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


Reply via email to