1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

remoteproc updates for v6.14

Correct error path in rproc_alloc(), with regards to put_device() and
 freeing of the rproc index ida. The Mediatek SCP remoteproc driver is
 returned to only creating child devices from specific DeviceTree nodes.
 OMAP remoteproc driver is updated to match the cleanups in the OMAP
 iommu driver.
 
 In addition to this, a number of conversions to devres and other small,
 mostly stylistic, code cleanups.
 -----BEGIN PGP SIGNATURE-----
 
 iQJJBAABCAAzFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmeVIZEVHGFuZGVyc3Nv
 bkBrZXJuZWwub3JnAAoJEAsfOT8Nma3FwaMP/10U35ZG0iFhjmMTWusMMS/j/FMv
 ufD1wXCibAROf/Kj3JhITVjUyOVNYisyGKi8gUPmWn9Ti5nMjUFvYDXtUfrBegLf
 Kl1rYIFuXCeldQQbZDbtHXnXTtosneQSqLSoj1lQSiQgC8R0SuQCwm3KyhSBJs1P
 sxXz6B+ewW67U7hpaRI/hzKOzq3ANK7NqMzTxVkage+VRfEcc1xeH+iwTUUseiYR
 GkECXTogol+btjUyAM7QVkVUAA+DqjJoFinWW6kXzOP1Z+L6T4lqcqXVoakItR8K
 hJ2IP5ktoShDtQ1IdXOLXcdS9IL6YPvLjkY5YPv9/fSEyiKBOC3k49ED1tkLuFa4
 0/CDamFLeuAZm3yvnsH2sgpLYrUOdVbm6nkqicBq2BGngJxWr1crVeXclON39TgU
 7wa0jLWW2P1B649NGNRrM+6vsxrZPRRYVdpoT7L6EItdQfUKOo5ra1Min9SIeAjy
 edsAaM7UogOyewYTWW///3ecjS1UDEW2gOzrRnAyxUWd+6yzBxnMsxY+0h1idXPt
 Wbf9PP0YDd4HtbXrCH96t1FtMJJ9TClh7vxCLqpMSS1H508uFpSkMmOpw13FnODu
 evvucZ3QjOs+eujiuZWzbJyjXIqMSfU0wDYz2xSVOJxvctsUkASQzlvirqQZe0uy
 Oe9jfkgPMRdW9jQ9
 =QA3V
 -----END PGP SIGNATURE-----

Merge tag 'rproc-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux

Pull remoteproc updates from Bjorn Andersson:

 - Correct error path in rproc_alloc(), with regards to put_device() and
   freeing of the rproc index ida

 - The Mediatek SCP remoteproc driver is returned to only creating child
   devices from specific DeviceTree nodes

 - Update the OMAP remoteproc driver to match the cleanups in the OMAP
   iommu driver

In addition to this, a number of conversions to devres and other small,
mostly stylistic, code cleanups

* tag 'rproc-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux:
  remoteproc: st: Use syscon_regmap_lookup_by_phandle_args
  remoteproc: keystone: Use syscon_regmap_lookup_by_phandle_args
  remoteproc: st: Simplify with dev_err_probe
  remoteproc: omap: Simplify returning syscon PTR_ERR
  remoteproc: keystone: Simplify returning syscon PTR_ERR
  remoteproc: k3-r5: Add devm action to release tsp
  remoteproc: k3-r5: Use devm_rproc_add() helper
  remoteproc: k3-r5: Use devm_ioremap_wc() helper
  remoteproc: k3-r5: Use devm_kcalloc() helper
  remoteproc: k3-r5: Add devm action to release reserved memory
  remoteproc: mtk_scp: Only populate devices for SCP cores
  remoteproc: omap: Handle ARM dma_iommu_mapping
  remoteproc: core: Fix ida_free call while not allocated
This commit is contained in:
Linus Torvalds 2025-01-25 16:23:38 -08:00
commit aa22f4da2a
6 changed files with 97 additions and 112 deletions

View file

@ -335,25 +335,16 @@ static int keystone_rproc_of_get_dev_syscon(struct platform_device *pdev,
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int ret;
if (!of_property_read_bool(np, "ti,syscon-dev")) { if (!of_property_read_bool(np, "ti,syscon-dev")) {
dev_err(dev, "ti,syscon-dev property is absent\n"); dev_err(dev, "ti,syscon-dev property is absent\n");
return -EINVAL; return -EINVAL;
} }
ksproc->dev_ctrl = ksproc->dev_ctrl = syscon_regmap_lookup_by_phandle_args(np, "ti,syscon-dev",
syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev"); 1, &ksproc->boot_offset);
if (IS_ERR(ksproc->dev_ctrl)) { if (IS_ERR(ksproc->dev_ctrl))
ret = PTR_ERR(ksproc->dev_ctrl); return PTR_ERR(ksproc->dev_ctrl);
return ret;
}
if (of_property_read_u32_index(np, "ti,syscon-dev", 1,
&ksproc->boot_offset)) {
dev_err(dev, "couldn't read the boot register offset\n");
return -EINVAL;
}
return 0; return 0;
} }

View file

@ -1326,6 +1326,11 @@ static int scp_cluster_init(struct platform_device *pdev, struct mtk_scp_of_clus
return ret; return ret;
} }
static const struct of_device_id scp_core_match[] = {
{ .compatible = "mediatek,scp-core" },
{}
};
static int scp_probe(struct platform_device *pdev) static int scp_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@ -1357,13 +1362,15 @@ static int scp_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&scp_cluster->mtk_scp_list); INIT_LIST_HEAD(&scp_cluster->mtk_scp_list);
mutex_init(&scp_cluster->cluster_lock); mutex_init(&scp_cluster->cluster_lock);
ret = devm_of_platform_populate(dev); ret = of_platform_populate(dev_of_node(dev), scp_core_match, NULL, dev);
if (ret) if (ret)
return dev_err_probe(dev, ret, "Failed to populate platform devices\n"); return dev_err_probe(dev, ret, "Failed to populate platform devices\n");
ret = scp_cluster_init(pdev, scp_cluster); ret = scp_cluster_init(pdev, scp_cluster);
if (ret) if (ret) {
of_platform_depopulate(dev);
return ret; return ret;
}
return 0; return 0;
} }
@ -1379,6 +1386,7 @@ static void scp_remove(struct platform_device *pdev)
rproc_del(scp->rproc); rproc_del(scp->rproc);
scp_free(scp); scp_free(scp);
} }
of_platform_depopulate(&pdev->dev);
mutex_destroy(&scp_cluster->cluster_lock); mutex_destroy(&scp_cluster->cluster_lock);
} }

View file

@ -37,6 +37,10 @@
#include <linux/platform_data/dmtimer-omap.h> #include <linux/platform_data/dmtimer-omap.h>
#ifdef CONFIG_ARM_DMA_USE_IOMMU
#include <asm/dma-iommu.h>
#endif
#include "omap_remoteproc.h" #include "omap_remoteproc.h"
#include "remoteproc_internal.h" #include "remoteproc_internal.h"
@ -1133,7 +1137,6 @@ static int omap_rproc_get_boot_data(struct platform_device *pdev,
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct omap_rproc *oproc = rproc->priv; struct omap_rproc *oproc = rproc->priv;
const struct omap_rproc_dev_data *data; const struct omap_rproc_dev_data *data;
int ret;
data = of_device_get_match_data(&pdev->dev); data = of_device_get_match_data(&pdev->dev);
if (!data) if (!data)
@ -1149,10 +1152,8 @@ static int omap_rproc_get_boot_data(struct platform_device *pdev,
oproc->boot_data->syscon = oproc->boot_data->syscon =
syscon_regmap_lookup_by_phandle(np, "ti,bootreg"); syscon_regmap_lookup_by_phandle(np, "ti,bootreg");
if (IS_ERR(oproc->boot_data->syscon)) { if (IS_ERR(oproc->boot_data->syscon))
ret = PTR_ERR(oproc->boot_data->syscon); return PTR_ERR(oproc->boot_data->syscon);
return ret;
}
if (of_property_read_u32_index(np, "ti,bootreg", 1, if (of_property_read_u32_index(np, "ti,bootreg", 1,
&oproc->boot_data->boot_reg)) { &oproc->boot_data->boot_reg)) {
@ -1323,6 +1324,19 @@ static int omap_rproc_probe(struct platform_device *pdev)
/* All existing OMAP IPU and DSP processors have an MMU */ /* All existing OMAP IPU and DSP processors have an MMU */
rproc->has_iommu = true; rproc->has_iommu = true;
#ifdef CONFIG_ARM_DMA_USE_IOMMU
/*
* Throw away the ARM DMA mapping that we'll never use, so it doesn't
* interfere with the core rproc->domain and we get the right DMA ops.
*/
if (pdev->dev.archdata.mapping) {
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(&pdev->dev);
arm_iommu_detach_device(&pdev->dev);
arm_iommu_release_mapping(mapping);
}
#endif
ret = omap_rproc_of_get_internal_memories(pdev, rproc); ret = omap_rproc_of_get_internal_memories(pdev, rproc);
if (ret) if (ret)
return ret; return ret;

View file

@ -2486,6 +2486,13 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
rproc->dev.driver_data = rproc; rproc->dev.driver_data = rproc;
idr_init(&rproc->notifyids); idr_init(&rproc->notifyids);
/* Assign a unique device index and name */
rproc->index = ida_alloc(&rproc_dev_index, GFP_KERNEL);
if (rproc->index < 0) {
dev_err(dev, "ida_alloc failed: %d\n", rproc->index);
goto put_device;
}
rproc->name = kstrdup_const(name, GFP_KERNEL); rproc->name = kstrdup_const(name, GFP_KERNEL);
if (!rproc->name) if (!rproc->name)
goto put_device; goto put_device;
@ -2496,13 +2503,6 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
if (rproc_alloc_ops(rproc, ops)) if (rproc_alloc_ops(rproc, ops))
goto put_device; goto put_device;
/* Assign a unique device index and name */
rproc->index = ida_alloc(&rproc_dev_index, GFP_KERNEL);
if (rproc->index < 0) {
dev_err(dev, "ida_alloc failed: %d\n", rproc->index);
goto put_device;
}
dev_set_name(&rproc->dev, "remoteproc%d", rproc->index); dev_set_name(&rproc->dev, "remoteproc%d", rproc->index);
atomic_set(&rproc->power, 0); atomic_set(&rproc->power, 0);

View file

@ -290,26 +290,23 @@ static int st_rproc_parse_dt(struct platform_device *pdev)
if (ddata->config->sw_reset) { if (ddata->config->sw_reset) {
ddata->sw_reset = devm_reset_control_get_exclusive(dev, ddata->sw_reset = devm_reset_control_get_exclusive(dev,
"sw_reset"); "sw_reset");
if (IS_ERR(ddata->sw_reset)) { if (IS_ERR(ddata->sw_reset))
dev_err(dev, "Failed to get S/W Reset\n"); return dev_err_probe(dev, PTR_ERR(ddata->sw_reset),
return PTR_ERR(ddata->sw_reset); "Failed to get S/W Reset\n");
}
} }
if (ddata->config->pwr_reset) { if (ddata->config->pwr_reset) {
ddata->pwr_reset = devm_reset_control_get_exclusive(dev, ddata->pwr_reset = devm_reset_control_get_exclusive(dev,
"pwr_reset"); "pwr_reset");
if (IS_ERR(ddata->pwr_reset)) { if (IS_ERR(ddata->pwr_reset))
dev_err(dev, "Failed to get Power Reset\n"); return dev_err_probe(dev, PTR_ERR(ddata->pwr_reset),
return PTR_ERR(ddata->pwr_reset); "Failed to get Power Reset\n");
}
} }
ddata->clk = devm_clk_get(dev, NULL); ddata->clk = devm_clk_get(dev, NULL);
if (IS_ERR(ddata->clk)) { if (IS_ERR(ddata->clk))
dev_err(dev, "Failed to get clock\n"); return dev_err_probe(dev, PTR_ERR(ddata->clk),
return PTR_ERR(ddata->clk); "Failed to get clock\n");
}
err = of_property_read_u32(np, "clock-frequency", &ddata->clk_rate); err = of_property_read_u32(np, "clock-frequency", &ddata->clk_rate);
if (err) { if (err) {
@ -317,18 +314,11 @@ static int st_rproc_parse_dt(struct platform_device *pdev)
return err; return err;
} }
ddata->boot_base = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); ddata->boot_base = syscon_regmap_lookup_by_phandle_args(np, "st,syscfg",
if (IS_ERR(ddata->boot_base)) { 1, &ddata->boot_offset);
dev_err(dev, "Boot base not found\n"); if (IS_ERR(ddata->boot_base))
return PTR_ERR(ddata->boot_base); return dev_err_probe(dev, PTR_ERR(ddata->boot_base),
} "Boot base not found\n");
err = of_property_read_u32_index(np, "st,syscfg", 1,
&ddata->boot_offset);
if (err) {
dev_err(dev, "Boot offset not found\n");
return -EINVAL;
}
err = clk_prepare(ddata->clk); err = clk_prepare(ddata->clk);
if (err) if (err)
@ -395,32 +385,32 @@ static int st_rproc_probe(struct platform_device *pdev)
*/ */
chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_rx"); chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_rx");
if (IS_ERR(chan)) { if (IS_ERR(chan)) {
dev_err(&rproc->dev, "failed to request mbox chan 0\n"); ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
ret = PTR_ERR(chan); "failed to request mbox chan 0\n");
goto free_clk; goto free_clk;
} }
ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_RX] = chan; ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_RX] = chan;
chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_tx"); chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_tx");
if (IS_ERR(chan)) { if (IS_ERR(chan)) {
dev_err(&rproc->dev, "failed to request mbox chan 0\n"); ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
ret = PTR_ERR(chan); "failed to request mbox chan 0\n");
goto free_mbox; goto free_mbox;
} }
ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_TX] = chan; ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_TX] = chan;
chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_rx"); chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_rx");
if (IS_ERR(chan)) { if (IS_ERR(chan)) {
dev_err(&rproc->dev, "failed to request mbox chan 1\n"); ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
ret = PTR_ERR(chan); "failed to request mbox chan 1\n");
goto free_mbox; goto free_mbox;
} }
ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_RX] = chan; ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_RX] = chan;
chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_tx"); chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_tx");
if (IS_ERR(chan)) { if (IS_ERR(chan)) {
dev_err(&rproc->dev, "failed to request mbox chan 1\n"); ret = dev_err_probe(&rproc->dev, PTR_ERR(chan),
ret = PTR_ERR(chan); "failed to request mbox chan 1\n");
goto free_mbox; goto free_mbox;
} }
ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_TX] = chan; ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_TX] = chan;

View file

@ -955,6 +955,13 @@ out:
return ret; return ret;
} }
static void k3_r5_mem_release(void *data)
{
struct device *dev = data;
of_reserved_mem_device_release(dev);
}
static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc) static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
{ {
struct device *dev = kproc->dev; struct device *dev = kproc->dev;
@ -985,27 +992,25 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
return ret; return ret;
} }
ret = devm_add_action_or_reset(dev, k3_r5_mem_release, dev);
if (ret)
return ret;
num_rmems--; num_rmems--;
kproc->rmem = kcalloc(num_rmems, sizeof(*kproc->rmem), GFP_KERNEL); kproc->rmem = devm_kcalloc(dev, num_rmems, sizeof(*kproc->rmem), GFP_KERNEL);
if (!kproc->rmem) { if (!kproc->rmem)
ret = -ENOMEM; return -ENOMEM;
goto release_rmem;
}
/* use remaining reserved memory regions for static carveouts */ /* use remaining reserved memory regions for static carveouts */
for (i = 0; i < num_rmems; i++) { for (i = 0; i < num_rmems; i++) {
rmem_np = of_parse_phandle(np, "memory-region", i + 1); rmem_np = of_parse_phandle(np, "memory-region", i + 1);
if (!rmem_np) { if (!rmem_np)
ret = -EINVAL; return -EINVAL;
goto unmap_rmem;
}
rmem = of_reserved_mem_lookup(rmem_np); rmem = of_reserved_mem_lookup(rmem_np);
of_node_put(rmem_np); of_node_put(rmem_np);
if (!rmem) { if (!rmem)
ret = -EINVAL; return -EINVAL;
goto unmap_rmem;
}
kproc->rmem[i].bus_addr = rmem->base; kproc->rmem[i].bus_addr = rmem->base;
/* /*
@ -1020,12 +1025,11 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
*/ */
kproc->rmem[i].dev_addr = (u32)rmem->base; kproc->rmem[i].dev_addr = (u32)rmem->base;
kproc->rmem[i].size = rmem->size; kproc->rmem[i].size = rmem->size;
kproc->rmem[i].cpu_addr = ioremap_wc(rmem->base, rmem->size); kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
if (!kproc->rmem[i].cpu_addr) { if (!kproc->rmem[i].cpu_addr) {
dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n", dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
i + 1, &rmem->base, &rmem->size); i + 1, &rmem->base, &rmem->size);
ret = -ENOMEM; return -ENOMEM;
goto unmap_rmem;
} }
dev_dbg(dev, "reserved memory%d: bus addr %pa size 0x%zx va %pK da 0x%x\n", dev_dbg(dev, "reserved memory%d: bus addr %pa size 0x%zx va %pK da 0x%x\n",
@ -1036,25 +1040,6 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
kproc->num_rmems = num_rmems; kproc->num_rmems = num_rmems;
return 0; return 0;
unmap_rmem:
for (i--; i >= 0; i--)
iounmap(kproc->rmem[i].cpu_addr);
kfree(kproc->rmem);
release_rmem:
of_reserved_mem_device_release(dev);
return ret;
}
static void k3_r5_reserved_mem_exit(struct k3_r5_rproc *kproc)
{
int i;
for (i = 0; i < kproc->num_rmems; i++)
iounmap(kproc->rmem[i].cpu_addr);
kfree(kproc->rmem);
of_reserved_mem_device_release(kproc->dev);
} }
/* /*
@ -1281,10 +1266,10 @@ init_rmem:
goto out; goto out;
} }
ret = rproc_add(rproc); ret = devm_rproc_add(dev, rproc);
if (ret) { if (ret) {
dev_err(dev, "rproc_add failed, ret = %d\n", ret); dev_err_probe(dev, ret, "rproc_add failed\n");
goto err_add; goto out;
} }
/* create only one rproc in lockstep, single-cpu or /* create only one rproc in lockstep, single-cpu or
@ -1312,7 +1297,7 @@ init_rmem:
dev_err(dev, dev_err(dev,
"Timed out waiting for %s core to power up!\n", "Timed out waiting for %s core to power up!\n",
rproc->name); rproc->name);
goto err_powerup; goto out;
} }
} }
@ -1328,10 +1313,6 @@ err_split:
} }
} }
err_powerup:
rproc_del(rproc);
err_add:
k3_r5_reserved_mem_exit(kproc);
out: out:
/* undo core0 upon any failures on core1 in split-mode */ /* undo core0 upon any failures on core1 in split-mode */
if (cluster->mode == CLUSTER_MODE_SPLIT && core == core1) { if (cluster->mode == CLUSTER_MODE_SPLIT && core == core1) {
@ -1374,10 +1355,6 @@ static void k3_r5_cluster_rproc_exit(void *data)
} }
mbox_free_channel(kproc->mbox); mbox_free_channel(kproc->mbox);
rproc_del(rproc);
k3_r5_reserved_mem_exit(kproc);
} }
} }
@ -1510,6 +1487,13 @@ static int k3_r5_core_of_get_sram_memories(struct platform_device *pdev,
return 0; return 0;
} }
static void k3_r5_release_tsp(void *data)
{
struct ti_sci_proc *tsp = data;
ti_sci_proc_release(tsp);
}
static int k3_r5_core_of_init(struct platform_device *pdev) static int k3_r5_core_of_init(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@ -1603,6 +1587,10 @@ static int k3_r5_core_of_init(struct platform_device *pdev)
goto err; goto err;
} }
ret = devm_add_action_or_reset(dev, k3_r5_release_tsp, core->tsp);
if (ret)
goto err;
platform_set_drvdata(pdev, core); platform_set_drvdata(pdev, core);
devres_close_group(dev, k3_r5_core_of_init); devres_close_group(dev, k3_r5_core_of_init);
@ -1619,13 +1607,7 @@ err:
*/ */
static void k3_r5_core_of_exit(struct platform_device *pdev) static void k3_r5_core_of_exit(struct platform_device *pdev)
{ {
struct k3_r5_core *core = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int ret;
ret = ti_sci_proc_release(core->tsp);
if (ret)
dev_err(dev, "failed to release proc, ret = %d\n", ret);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
devres_release_group(dev, k3_r5_core_of_init); devres_release_group(dev, k3_r5_core_of_init);