diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 899d2058bc45..1ed406714849 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -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);