mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
remoteproc: Force shutdown during device removal
rproc_del() is subjected to the reference counted shutdown path, as such a remoteproc with more than one reference will be left running as its resources are released underneath it. Refactor the shutdown path such that the reference count value is ignored when called from rproc_del(). Assisted-by: OpenCode:GPT-5.5 Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com> Reviewed-by: Pradnya Dahiwale <pradnya.dahiwale@oss.qualcomm.com> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Link: https://lore.kernel.org/r/20260723-rproc-rmmod-not-crashing-v1-3-546dfd5de0e6@oss.qualcomm.com Signed-off-by: Bjorn Andersson <andersson@kernel.org>
This commit is contained in:
parent
74ee3b2f57
commit
4059c64d78
|
|
@ -1988,6 +1988,54 @@ int rproc_boot(struct rproc *rproc)
|
|||
}
|
||||
EXPORT_SYMBOL(rproc_boot);
|
||||
|
||||
static int __rproc_shutdown(struct rproc *rproc, bool force)
|
||||
{
|
||||
struct device *dev = &rproc->dev;
|
||||
bool crashed;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&rproc->lock);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rproc->state != RPROC_RUNNING &&
|
||||
rproc->state != RPROC_ATTACHED &&
|
||||
rproc->state != RPROC_CRASHED) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
crashed = rproc->state == RPROC_CRASHED;
|
||||
|
||||
if (!atomic_dec_and_test(&rproc->power) && !force) {
|
||||
/* The remote processor is still needed by another user. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = rproc_stop(rproc, crashed);
|
||||
if (ret) {
|
||||
atomic_inc(&rproc->power);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* clean up all acquired resources */
|
||||
rproc_resource_cleanup(rproc);
|
||||
|
||||
/* release HW resources if needed */
|
||||
rproc_unprepare_device(rproc);
|
||||
|
||||
rproc_disable_iommu(rproc);
|
||||
|
||||
/* Free the copy of the resource table */
|
||||
kfree(rproc->cached_table);
|
||||
rproc->cached_table = NULL;
|
||||
rproc->table_ptr = NULL;
|
||||
out:
|
||||
mutex_unlock(&rproc->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* rproc_shutdown() - power off the remote processor
|
||||
* @rproc: the remote processor
|
||||
|
|
@ -2011,49 +2059,7 @@ EXPORT_SYMBOL(rproc_boot);
|
|||
*/
|
||||
int rproc_shutdown(struct rproc *rproc)
|
||||
{
|
||||
struct device *dev = &rproc->dev;
|
||||
bool crashed;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&rproc->lock);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rproc->state != RPROC_RUNNING &&
|
||||
rproc->state != RPROC_ATTACHED &&
|
||||
rproc->state != RPROC_CRASHED) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
crashed = rproc->state == RPROC_CRASHED;
|
||||
|
||||
/* if the remote proc is still needed, bail out */
|
||||
if (!atomic_dec_and_test(&rproc->power))
|
||||
goto out;
|
||||
|
||||
ret = rproc_stop(rproc, crashed);
|
||||
if (ret) {
|
||||
atomic_inc(&rproc->power);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* clean up all acquired resources */
|
||||
rproc_resource_cleanup(rproc);
|
||||
|
||||
/* release HW resources if needed */
|
||||
rproc_unprepare_device(rproc);
|
||||
|
||||
rproc_disable_iommu(rproc);
|
||||
|
||||
/* Free the copy of the resource table */
|
||||
kfree(rproc->cached_table);
|
||||
rproc->cached_table = NULL;
|
||||
rproc->table_ptr = NULL;
|
||||
out:
|
||||
mutex_unlock(&rproc->lock);
|
||||
return ret;
|
||||
return __rproc_shutdown(rproc, false);
|
||||
}
|
||||
EXPORT_SYMBOL(rproc_shutdown);
|
||||
|
||||
|
|
@ -2621,8 +2627,7 @@ int rproc_del(struct rproc *rproc)
|
|||
if (cancel_work_sync(&rproc->crash_handler))
|
||||
pm_relax(rproc->dev.parent);
|
||||
|
||||
/* TODO: make sure this works with rproc->power > 1 */
|
||||
rproc_shutdown(rproc);
|
||||
__rproc_shutdown(rproc, true);
|
||||
|
||||
rproc_delete_debug_dir(rproc);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user