From 507f8f1f4ab8f6d61587c4cd00bf12729d5bb524 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 20 Nov 2014 18:00:24 -0600 Subject: iommu/omap: Fix a minor typo in debugfs output The second-level page table dump is being printed with a prefix value of 1, which is meant for Level-1 PTEs. This should have been a 2, so fix it. Fixes: 01b4456 (iommu/omap: Switch pagetable debugfs entry to use seq_file) Signed-off-by: Suman Anna --- drivers/iommu/omap-iommu-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index 0b7dfaa3767..5ef2cf7613d 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c @@ -118,7 +118,7 @@ static void dump_ioptable(struct seq_file *s) continue; da = (i << IOPGD_SHIFT) + (j << IOPTE_SHIFT); - seq_printf(s, "1: 0x%08x 0x%08x\n", da, *iopte); + seq_printf(s, "2: 0x%08x 0x%08x\n", da, *iopte); } } -- cgit v1.2.3 From 8b4274eb315e253698cb4fa45fa3f0ed5eac966c Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 15 Jan 2015 17:16:12 -0600 Subject: remoteproc/pruss: fix a crash with platform_device_unregister The following kernel crash is seen during the removal of a PRUSS device or during the removal of the PRUSS remoteproc module or during any early error exit during the probe of the PRUSS device: Unable to handle kernel NULL pointer dereference at virtual address 00000018 pgd = ec708000 [00000018] *pgd=ac6f8831, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] SMP ARM Modules linked in: pruss_remoteproc [last unloaded: virtio_rpmsg_bus] CPU: 0 PID: 1164 Comm: sh Not tainted 3.14.26-00002-g49b864ea1130 #2 task: ec320040 ti: ec6dc000 task.ti: ec6dc000 PC is at release_resource+0x1c/0x90 LR is at release_resource+0x18/0x90 ...[snip]... Backtrace: [] (release_resource) from [] (platform_device_del+0x74/0xa4) r4:00000001 r3:00000000 [] (platform_device_del) from [] (platform_device_unregister+0x14/0x20) r5:00000000 r4:ec1a4a00 [] (platform_device_unregister) from [] (pru_rproc_unregister+0x14/0x1c [pruss_remoteproc]) r4:00000000 r3:ec1a4a10 [] (pru_rproc_unregister [pruss_remoteproc]) from [] (device_for_each_child+0x3c/0x7c) [] (device_for_each_child) from [] (pruss_remove+0x40/0x84 [pruss_remoteproc]) r6:ec1a4410 r5:ec247400 r4:ec247410 [] (pruss_remove [pruss_remoteproc]) from [] (platform_drv_remove+0x1c/0x20) r7:0000000f r6:c08b8ac0 r5:bf00954c r4:ec247410 [] (platform_drv_remove) from [] (__device_release_driver+0x78/0xd0) [] (__device_release_driver) from [] (device_release_driver+0x24/0x30) r5:ec247410 r4:ec247444 [] (device_release_driver) from [] (unbind_store+0x60/0x98) r5:bf00954c r4:ec247410 [] (unbind_store) from [] (drv_attr_store+0x28/0x34) r7:0000000f r6:ec6ddf78 r5:ec6e8fc0 r4:ec70f900 [] (drv_attr_store) from [] (sysfs_kf_write+0x4c/0x50) [] (sysfs_kf_write) from [] (kernfs_fop_write+0xbc/0x154) r5:00000000 r4:00000000 [] (kernfs_fop_write) from [] (vfs_write+0xb0/0x188) r10:b6fbb000 r9:ec6dc000 r8:0000000f r7:ec6ddf78 r6:b6fbb000 r5:0000000f r4:ec701980 [] (vfs_write) from [] (SyS_write+0x44/0x90) r10:b6fbb000 r8:0000000f r7:ec701980 r6:ec701980 r5:00000000 r4:00000000 [] (SyS_write) from [] (ret_fast_syscall+0x0/0x30) r10:00000000 r8:c000eac4 r7:00000004 r6:0000000f r5:b6f945c8 r4:0000000f Code: e1a04000 e59f0074 eb16dea3 e5943010 (e5932018) ---[ end trace 77712d823a300402 ]--- The crash is due to the differences between how the resources are managed during the platform device creation path between of_platform_populate() and the traditional platform_device_add(). The of_platform_populate() uses of_device_add() instead of platform_device_add(), and as such does not add the resources. The PRUSS device removal logic currently uses the traditional platform_device_unregister() used to remove platform devices, and this crashes during the cleanup of the resources. Fix this error by using of_device_unregister(), the counterpart to of_device_add(). Signed-off-by: Suman Anna --- drivers/remoteproc/pruss_remoteproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/remoteproc/pruss_remoteproc.c b/drivers/remoteproc/pruss_remoteproc.c index abfe217cc16..c16da32fc07 100644 --- a/drivers/remoteproc/pruss_remoteproc.c +++ b/drivers/remoteproc/pruss_remoteproc.c @@ -1096,7 +1096,7 @@ static int pru_rproc_unregister(struct device *dev, void *data) { struct platform_device *pdev = to_platform_device(dev); - platform_device_unregister(pdev); + of_device_unregister(pdev); return 0; } -- cgit v1.2.3 From 3b0f876852c6ae3fc5389545ec311e2ee1a6d0dc Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 19 Jan 2015 17:27:55 -0600 Subject: remoteproc/pruss: use match data instead of platform data for PRUs The PRU platform devices are dynamically created during the probe of the corresponding parent PRUSS driver. Each of the PRU processors needs to have a unique id and load a separate image. This information is currently supplied through platform data supplied through a of_dev_auxdata structure to the of_platform_populate() API. The platform data though is causing a kernel crash during the device unregistration or during the PRUSS driver remove. The cause is attributed to the difference in the management of the platform data between the OF path and the traditional platform device creation path. Any platform_data supplied for the OF devices through auxdata lookup data is populated directly in the device's platform_data field, unlike those created using platform API. The device removal code (with either platform_device_unregister() or of_device_unregister()) exercises the standard platform code and results in a kernel oops due to an invalid kfree on this direct populated platform_data, similar to below: Unable to handle kernel paging request at virtual address 73007061 pgd = ec71c000 [73007061] *pgd=00000000 Internal error: Oops: 1 [#1] SMP ARM Modules linked in: pruss_remoteproc [last unloaded: virtio_rpmsg_bus] CPU: 0 PID: 1165 Comm: sh Not tainted 3.14.29-00170-gabe5c2536ffd #34 task: ec4084c0 ti: ec73c000 task.ti: ec73c000 PC is at kfree+0x70/0xec LR is at platform_device_release+0x18/0x34 ...[snip]... Backtrace: [] (kfree) from [] (platform_device_release+0x18/0x34) r6:ec1a1d80 r5:ec31a810 r4:ec31a810 r3:c03a7084 [] (platform_device_release) from [] (device_release+0x34/0x98) r4:ec31a818 r3:c03a7084 [] (device_release) from [] (kobject_release+0x98/0x1bc) r6:c093dbb0 r5:c0914968 r4:ec31a834 r3:c03a1728 [] (kobject_release) from [] (kobject_put+0x50/0x7c) r8:c03a1524 r7:00000001 r6:ec1a1d94 r5:ec73de40 r4:ec31a818 [] (kobject_put) from [] (put_device+0x1c/0x20) r4:ec1a1c14 [] (put_device) from [] (klist_children_put+0x14/0x18) [] (klist_children_put) from [] (klist_next+0xc0/0x13c) [] (klist_next) from [] (device_for_each_child+0x48/0x7c) r10:ec6f3cc0 r8:ec4fc700 r7:00000000 r6:bf0071c4 r5:00000000 r4:00000000 [] (device_for_each_child) from [] (pruss_remove+0x40/0x84 [pruss_remoteproc]) r6:ec31ac10 r5:ec24f400 r4:ec24f410 [] (pruss_remove [pruss_remoteproc]) from [] (platform_drv_remove+0x1c/0x20) r7:0000000f r6:c0914af0 r5:bf009714 r4:ec24f410 [] (platform_drv_remove) from [] (__device_release_driver+0x78/0xd0) [] (__device_release_driver) from [] (device_release_driver+0x24/0x30) r5:ec24f410 r4:ec24f444 Fix this by migrating away from using the platform data and instead supplying the same information to the PRU rproc driver through OF device match data. This approach is taken to align with the long-term upstream plan, where users are supposed to move off of the auxdata approach as it is only to be used as a temporary migration path. NOTE: The individual SoC-specific of_dev_auxdata structures could have been removed, but are retained for now for the benefit of having the PRU core device names show up with an identifier like xxxxxxxx.pru0 instead of a generic xxxxxxxx.pru. Signed-off-by: Suman Anna --- drivers/remoteproc/pruss_remoteproc.c | 132 ++++++++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 30 deletions(-) diff --git a/drivers/remoteproc/pruss_remoteproc.c b/drivers/remoteproc/pruss_remoteproc.c index c16da32fc07..da00a8048ef 100644 --- a/drivers/remoteproc/pruss_remoteproc.c +++ b/drivers/remoteproc/pruss_remoteproc.c @@ -126,15 +126,25 @@ enum pru_mem { }; /** - * struct pru_rproc_platform_data - PRU core platform data + * struct pru_private_data - PRU core private data * @id: PRU index * @fw_name: firmware name to be used for the PRU core */ -struct pru_rproc_platform_data { +struct pru_private_data { u32 id; const char *fw_name; }; +/** + * struct pru_match_private_data - match private data to handle multiple instances + * @device_name: device name of the PRU processor core instance + * @priv_data: PRU driver private data for this PRU processor core instance + */ +struct pru_match_private_data { + const char *device_name; + struct pru_private_data *priv_data; +}; + /** * struct pruss_private_data - PRUSS driver private data * @num_irqs: number of interrupts to MPU @@ -765,13 +775,34 @@ static struct rproc_ops pru_rproc_ops = { .da_to_va = pru_da_to_va, }; +static const struct of_device_id pru_rproc_match[]; + +static const struct pru_private_data *pru_rproc_get_private_data( + struct platform_device *pdev) +{ + const struct pru_match_private_data *data; + const struct of_device_id *match; + + match = of_match_device(pru_rproc_match, &pdev->dev); + if (!match) + return ERR_PTR(-ENODEV); + + data = match->data; + for (; data && data->device_name; data++) { + if (!strcmp(dev_name(&pdev->dev), data->device_name)) + return data->priv_data; + } + + return NULL; +} + static int pru_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct platform_device *ppdev = to_platform_device(dev->parent); struct pru_rproc *pru; - struct pru_rproc_platform_data *pdata = dev_get_platdata(dev); + const struct pru_private_data *pdata; struct rproc *rproc = NULL; struct mbox_client *client; struct resource *res; @@ -783,8 +814,9 @@ static int pru_rproc_probe(struct platform_device *pdev) return -ENODEV; } - if (!pdata || !pdata->fw_name) { - dev_err(dev, "platform data (PRU-private) missing\n"); + pdata = pru_rproc_get_private_data(pdev); + if (IS_ERR_OR_NULL(pdata) || !pdata->fw_name) { + dev_err(dev, "missing or incomplete PRU-private data\n"); return -ENODEV; } @@ -1118,73 +1150,113 @@ static int pruss_remove(struct platform_device *pdev) return 0; } -/* PRU0 core-specific platform data */ -static struct pru_rproc_platform_data pru0_rproc_pdata = { +/* PRU0 core-specific private data */ +static struct pru_private_data pru0_rproc_pdata = { .id = 0, .fw_name = "rproc-pru0-fw", }; -/* PRU1 core-specific platform data */ -static struct pru_rproc_platform_data pru1_rproc_pdata = { +/* PRU1 core-specific private data */ +static struct pru_private_data pru1_rproc_pdata = { .id = 1, .fw_name = "rproc-pru1-fw", }; -static struct pru_rproc_platform_data pru1_0_rproc_pdata = { +static struct pru_private_data pru1_0_rproc_pdata = { .id = 0, .fw_name = "am57xx-pru1_0-fw", }; -static struct pru_rproc_platform_data pru1_1_rproc_pdata = { +static struct pru_private_data pru1_1_rproc_pdata = { .id = 1, .fw_name = "am57xx-pru1_1-fw", }; -static struct pru_rproc_platform_data pru2_0_rproc_pdata = { +static struct pru_private_data pru2_0_rproc_pdata = { .id = 0, .fw_name = "am57xx-pru2_0-fw", }; -static struct pru_rproc_platform_data pru2_1_rproc_pdata = { +static struct pru_private_data pru2_1_rproc_pdata = { .id = 1, .fw_name = "am57xx-pru2_1-fw", }; /* platform data to be added when creating the PRU platform devices */ static struct of_dev_auxdata am335x_pru_rproc_auxdata_lookup[] = { - OF_DEV_AUXDATA("ti,pru-rproc", 0x4a334000, "4a334000.pru0", - &pru0_rproc_pdata), - OF_DEV_AUXDATA("ti,pru-rproc", 0x4a338000, "4a338000.pru1", - &pru1_rproc_pdata), + OF_DEV_AUXDATA("ti,pru-rproc", 0x4a334000, "4a334000.pru0", NULL), + OF_DEV_AUXDATA("ti,pru-rproc", 0x4a338000, "4a338000.pru1", NULL), { /* sentinel */ }, }; static struct of_dev_auxdata am4372_pru_rproc_auxdata_lookup[] = { - OF_DEV_AUXDATA("ti,pru-rproc", 0x54434000, "54434000.pru0", - &pru0_rproc_pdata), - OF_DEV_AUXDATA("ti,pru-rproc", 0x54438000, "54438000.pru1", - &pru1_rproc_pdata), + OF_DEV_AUXDATA("ti,pru-rproc", 0x54434000, "54434000.pru0", NULL), + OF_DEV_AUXDATA("ti,pru-rproc", 0x54438000, "54438000.pru1", NULL), { /* sentinel */ }, }; static struct of_dev_auxdata am5728_pruss1_rproc_auxdata_lookup[] = { - OF_DEV_AUXDATA("ti,pru-rproc", 0x4b234000, "4b234000.pru0", - &pru1_0_rproc_pdata), - OF_DEV_AUXDATA("ti,pru-rproc", 0x4b238000, "4b238000.pru1", - &pru1_1_rproc_pdata), + OF_DEV_AUXDATA("ti,pru-rproc", 0x4b234000, "4b234000.pru0", NULL), + OF_DEV_AUXDATA("ti,pru-rproc", 0x4b238000, "4b238000.pru1", NULL), { /* sentinel */ }, }; static struct of_dev_auxdata am5728_pruss2_rproc_auxdata_lookup[] = { - OF_DEV_AUXDATA("ti,pru-rproc", 0x4b2b4000, "4b2b4000.pru0", - &pru2_0_rproc_pdata), - OF_DEV_AUXDATA("ti,pru-rproc", 0x4b2b8000, "4b2b8000.pru1", - &pru2_1_rproc_pdata), + OF_DEV_AUXDATA("ti,pru-rproc", 0x4b2b4000, "4b2b4000.pru0", NULL), + OF_DEV_AUXDATA("ti,pru-rproc", 0x4b2b8000, "4b2b8000.pru1", NULL), { /* sentinel */ }, }; +/* + * A single match structure is used against a unified compatible + * string "ti,pru-rproc" as the addresses of the different PRU cores + * are unique across all the applicable SoCs. + * XXX: A SoC-specific compatible string is probably a better option + * for the future to allow more flexibility. + */ +static struct pru_match_private_data pru_match_data[] = { + /* AM33xx SoC-specific data */ + { + .device_name = "4a334000.pru0", + .priv_data = &pru0_rproc_pdata, + }, + { + .device_name = "4b280000.pru1", + .priv_data = &pru1_rproc_pdata, + }, + /* AM43xx SoC-specific data */ + { + .device_name = "54434000.pru0", + .priv_data = &pru0_rproc_pdata, + }, + { + .device_name = "54438000.pru1", + .priv_data = &pru1_rproc_pdata, + }, + /* AM57xx SoC-specific data */ + { + .device_name = "4b234000.pru0", + .priv_data = &pru1_0_rproc_pdata, + }, + { + .device_name = "4b238000.pru1", + .priv_data = &pru1_1_rproc_pdata, + }, + { + .device_name = "4b2b4000.pru0", + .priv_data = &pru2_0_rproc_pdata, + }, + { + .device_name = "4b2b8000.pru1", + .priv_data = &pru2_1_rproc_pdata, + }, + { + /* sentinel */ + }, +}; + static const struct of_device_id pru_rproc_match[] = { - { .compatible = "ti,pru-rproc", .data = NULL, }, + { .compatible = "ti,pru-rproc", .data = pru_match_data, }, {}, }; MODULE_DEVICE_TABLE(of, pru_rproc_match); -- cgit v1.2.3 From 1c59fb56bb8e03df2ec5ebcc73aa3a82c3cfcf47 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 30 Jan 2015 14:34:05 -0600 Subject: iommu/omap: Fix a sleeping function invocation in atomic context bug The kzalloc function in the omap_iommu_attach_init() function is invoked with GFP_KERNEL flag, but the function is called with a spinlock held (atomic context). This throws up the following warning with CONFIG_DEBUG_ATOMIC_SLEEP enabled: remoteproc0: powering up 58820000.ipu remoteproc0: Booting fw image dra7-ipu1-fw.xem4, size 6115639 BUG: sleeping function called from invalid context at mm/slab.c:2967 in_atomic(): 1, irqs_disabled(): 0, pid: 65, name: kworker/0:1 CPU: 0 PID: 65 Comm: kworker/0:1 Not tainted 3.14.30-00284-g46d15f7 #11 Workqueue: events request_firmware_work_func Backtrace: [] (dump_backtrace) from [] (show_stack+0x18/0x1c) r6:000080d0 r5:c0900e00 r4:00000000 r3:ec21a000 [] (show_stack) from [] (dump_stack+0x84/0xb8) [] (dump_stack) from [] (__might_sleep+0xcc/0xf8) r4:ec21a000 r3:40000013 [] (__might_sleep) from [] (__kmalloc+0xe4/0x124) r5:ec000080 r4:000080d0 [] (__kmalloc) from [] (omap_iommu_attach_dev+0xd0/0x3e0) r7:ec6f6800 r6:eb400994 r5:00000000 r4:ec25ad40 [] (omap_iommu_attach_dev) from [] (iommu_attach_device+0x20/0x2c) r10:ec247810 r9:eb40098c r8:ec6f6840 r7:eb400828 r6:eb400994 r5:00000000 r4:eb400800 [] (iommu_attach_device) from [] (rproc_boot+0x27c/0x4d4) [] (rproc_boot) from [] (rproc_virtio_find_vqs+0x1a8/0x204) r10:eb16e410 r9:bf001908 r8:ec21bca0 r7:ec21bc8c r6:ec21bc94 r5:ec21bc9c r4:00000002 .... .... [] (kthread) from [] (ret_from_fork+0x14/0x3c) r7:00000000 r6:00000000 r5:c0059e0c r4:ec1ecf40 omap-iommu 58882000.mmu: 58882000.mmu: version 2.1 remoteproc0: remote processor 58820000.ipu is now up Fix the same by using the appropriate GFP_ATOMIC flag. Note that the fix does not convert the spinlock into a mutex, even though the attach is done usually in a process context. This is done to keep the IOMMU API generic and allow them to be called from any context. Fixes: 6636390de ("iommu/omap: add support to program multiple iommus") Reported-by: Tomi Valkeinen Signed-off-by: Suman Anna --- drivers/iommu/omap-iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index c34e3ce5428..693f23c46a6 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -1187,13 +1187,13 @@ static int omap_iommu_attach_init(struct device *dev, return -EINVAL; odomain->iommus = kzalloc(odomain->num_iommus * sizeof(*iommu), - GFP_KERNEL); + GFP_ATOMIC); if (!odomain->iommus) return -ENOMEM; iommu = odomain->iommus; for (i = 0; i < odomain->num_iommus; i++, iommu++) { - iommu->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_KERNEL); + iommu->pgtable = kzalloc(IOPGD_TABLE_SIZE, GFP_ATOMIC); if (!iommu->pgtable) return -ENOMEM; -- cgit v1.2.3 From 33a427b820334985a108cf909a22d3b21b18ff0f Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 2 Feb 2015 17:08:46 -0600 Subject: remoteproc/pruss: fix the cleanup path in pru_rproc_probe() The PRU remoteproc driver can manually boot a processor if the corresponding firmware doesn't support virtio devices. However, the current cleanup code doesn't undo the operations performed by rproc_add() in case the manual boot fails. A successful rproc_add() requires the corresponding rproc_del() to be called during cleanup, so fix the same. Signed-off-by: Suman Anna --- drivers/remoteproc/pruss_remoteproc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/pruss_remoteproc.c b/drivers/remoteproc/pruss_remoteproc.c index da00a8048ef..c528efe6a88 100644 --- a/drivers/remoteproc/pruss_remoteproc.c +++ b/drivers/remoteproc/pruss_remoteproc.c @@ -890,7 +890,7 @@ static int pru_rproc_probe(struct platform_device *pdev) ret = rproc_boot(pru->rproc); if (ret) { dev_err(dev, "rproc_boot failed\n"); - goto put_mbox; + goto del_rproc; } } @@ -901,6 +901,8 @@ static int pru_rproc_probe(struct platform_device *pdev) return 0; +del_rproc: + rproc_del(pru->rproc); put_mbox: mbox_free_channel(pru->mbox); free_rproc: -- cgit v1.2.3 From e707094abaf42a3dfa27cc419db899e1c6d7b012 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 2 Feb 2015 15:42:51 -0600 Subject: remoteproc/pruss: fix shutdown for manually booted PRU cores The remoteproc infrastructure auto-boots the processors that have support for virtio transports. The remoteproc virtio layer also handles the shutdown for such remoteproc devices, but not for processors booted outside the remoteproc virtio layer. The current PRU remoteproc driver also provides support to manually boot a PRU processor if there are no virtio devices associated with the processor (standalone functionality without any communication with the MPU, usually used in a configuration where one of the PRU cores is used in a slave-mode and complements the functionality implemented on the other PRU core). The manual boot is done during the probe of the PRU rproc driver, but it isn't handling the shutdown of the PRU processor, so the same has been fixed. This also fixes an issue with the module reference count of the PRUSS remoteproc module. The rproc_boot() function holds a reference count to the module implementing the driver for the corresponding remoteproc device. The PRUSS remoteproc module implements two platform drivers - one for the PRUSS subsystem, and the other to deal with the individual PRU cores, and as such the module reference count module is incremented for every booted processor, and is decremented properly only when the corresponding processor is shutdown. Without the fix, the reference count is never decremented when the PRU rproc device or the parent PRUSS subsystem device is unbound from their corresponding drivers. NOTE: The rmmod of the PRUSS remoteproc module can only succeed when the PRU/PRUSS devices are unbound from their drivers, if there were any manually booted PRU cores. Ideally, the boot would have to be implemented in a different layer to avoid this issue. Signed-off-by: Suman Anna --- drivers/remoteproc/pruss_remoteproc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/remoteproc/pruss_remoteproc.c b/drivers/remoteproc/pruss_remoteproc.c index c528efe6a88..d498ee3b534 100644 --- a/drivers/remoteproc/pruss_remoteproc.c +++ b/drivers/remoteproc/pruss_remoteproc.c @@ -918,6 +918,11 @@ static int pru_rproc_remove(struct platform_device *pdev) dev_info(dev, "%s: removing rproc %s\n", __func__, rproc->name); + if (list_empty(&pru->rproc->rvdevs)) { + dev_info(dev, "stopping the manually booted PRU core\n"); + rproc_shutdown(pru->rproc); + } + mbox_free_channel(pru->mbox); rproc_del(rproc); -- cgit v1.2.3