If a subdevice fails to stop, it indicates broken communication with the DSP. Continuing to stop further subdevices against an unresponsive remote processor could close rpmsg devices that could remove the memory mapping from HLOS and in case if remote processor touches those memory can result in SMMU fault.
Change rproc_stop_subdevices() to return int and abort on the first failing subdev. Propagate the error through rproc_stop() and __rproc_detach() so callers are aware the teardown did not complete cleanly. Signed-off-by: Mukesh Ojha <[email protected]> --- drivers/remoteproc/remoteproc_core.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 21127d972bff..77c4f09c7604 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1110,7 +1110,7 @@ static int rproc_start_subdevices(struct rproc *rproc) return ret; } -static void rproc_stop_subdevices(struct rproc *rproc, bool crashed) +static int rproc_stop_subdevices(struct rproc *rproc, bool crashed) { struct rproc_subdev *subdev; int ret; @@ -1118,10 +1118,14 @@ static void rproc_stop_subdevices(struct rproc *rproc, bool crashed) list_for_each_entry_reverse(subdev, &rproc->subdevs, node) { if (subdev->stop) { ret = subdev->stop(subdev, crashed); - if (ret) - dev_warn(&rproc->dev, "subdev stop failed: %d\n", ret); + if (ret) { + dev_err(&rproc->dev, "subdev stop failed: %d\n", ret); + return ret; + } } } + + return 0; } static void rproc_unprepare_subdevices(struct rproc *rproc) @@ -1712,7 +1716,12 @@ static int rproc_stop(struct rproc *rproc, bool crashed) return -EINVAL; /* Stop any subdevices for the remote processor */ - rproc_stop_subdevices(rproc, crashed); + ret = rproc_stop_subdevices(rproc, crashed); + if (ret) { + dev_err(dev, "failed to stop subdevices for %s: %d\n", + rproc->name, ret); + return ret; + } /* the installed resource table is no longer accessible */ ret = rproc_reset_rsc_table_on_stop(rproc); @@ -1751,7 +1760,12 @@ static int __rproc_detach(struct rproc *rproc) return -EINVAL; /* Stop any subdevices for the remote processor */ - rproc_stop_subdevices(rproc, false); + ret = rproc_stop_subdevices(rproc, false); + if (ret) { + dev_err(dev, "failed to stop subdevices for %s: %d\n", + rproc->name, ret); + return ret; + } /* the installed resource table is no longer accessible */ ret = rproc_reset_rsc_table_on_detach(rproc); -- 2.53.0

