diff mbox series

[v4,11/17] remoteproc: Introduce function __rproc_detach()

Message ID 20201218173228.2277032-12-mathieu.poirier@linaro.org
State New
Headers show
Series remoteproc: Add support for detaching a rproc | expand

Commit Message

Mathieu Poirier Dec. 18, 2020, 5:32 p.m. UTC
Introduce function __rproc_detach() to perform the same kind of
operation as rproc_stop(), but instead of switching off the
remote processor using rproc->ops->stop(), it uses
rproc->ops->detach().  That way it is possible for the core
to release the resources associated with a remote processor while
the latter is kept operating.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>

Reviewed-by: Peng Fan <peng.fan@nxp.com>

---
 drivers/remoteproc/remoteproc_core.c | 42 ++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

-- 
2.25.1

Comments

Arnaud POULIQUEN Jan. 27, 2021, 8:46 a.m. UTC | #1
On 12/18/20 6:32 PM, Mathieu Poirier wrote:
> Introduce function __rproc_detach() to perform the same kind of

> operation as rproc_stop(), but instead of switching off the

> remote processor using rproc->ops->stop(), it uses

> rproc->ops->detach().  That way it is possible for the core

> to release the resources associated with a remote processor while

> the latter is kept operating.

> 

> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>

> Reviewed-by: Peng Fan <peng.fan@nxp.com>

> ---

>  drivers/remoteproc/remoteproc_core.c | 42 ++++++++++++++++++++++++++++

>  1 file changed, 42 insertions(+)

> 

> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c

> index fc28053c7f89..e665ed4776c3 100644

> --- a/drivers/remoteproc/remoteproc_core.c

> +++ b/drivers/remoteproc/remoteproc_core.c

> @@ -1670,6 +1670,48 @@ static int rproc_stop(struct rproc *rproc, bool crashed)

>  	return 0;

>  }

>  

> +/*

> + * __rproc_detach(): Does the opposite of rproc_attach()

> + */

> +static int __maybe_unused __rproc_detach(struct rproc *rproc)

> +{

> +	struct device *dev = &rproc->dev;

> +	int ret;

> +

> +	/* No need to continue if a detach() operation has not been provided */

> +	if (!rproc->ops->detach)

> +		return -EINVAL;


I wonder if this ops should be optional.

> +

> +	/* Stop any subdevices for the remote processor */

> +	rproc_stop_subdevices(rproc, false);

> +

> +	/*

> +	 * If the remote processors was started by the core then a cached_table

> +	 * is present and we must follow the same cleanup sequence as we would

> +	 * for a shutdown().  As it is in rproc_stop(), use the cached resource

> +	 * table for the rest of the detach process since ->table_ptr will

> +	 * become invalid as soon as carveouts are released in

> +	 * rproc_resource_cleanup().

> +	 */

> +	if (rproc->cached_table)

> +		rproc->table_ptr = rproc->cached_table;

> +

> +	/* Tell the remote processor the core isn't available anymore */

> +	ret = rproc->ops->detach(rproc);

> +	if (ret) {

> +		dev_err(dev, "can't detach from rproc: %d\n", ret);

> +		rproc_start_subdevices(rproc);


Not sure that this would be possible in all cases, without a unprepare and
prepare. What about having the same behavior as the rproc_stop failure?

Thanks
Arnaud.

> +		return ret;

> +	}

> +

> +	rproc_unprepare_subdevices(rproc);

> +

> +	rproc->state = RPROC_DETACHED;

> +

> +	dev_info(dev, "detached remote processor %s\n", rproc->name);

> +

> +	return 0;

> +}

>  

>  /**

>   * rproc_trigger_recovery() - recover a remoteproc

>
Mathieu Poirier Jan. 29, 2021, 10:17 p.m. UTC | #2
On Wed, Jan 27, 2021 at 09:46:58AM +0100, Arnaud POULIQUEN wrote:
> 

> 

> On 12/18/20 6:32 PM, Mathieu Poirier wrote:

> > Introduce function __rproc_detach() to perform the same kind of

> > operation as rproc_stop(), but instead of switching off the

> > remote processor using rproc->ops->stop(), it uses

> > rproc->ops->detach().  That way it is possible for the core

> > to release the resources associated with a remote processor while

> > the latter is kept operating.

> > 

> > Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>

> > Reviewed-by: Peng Fan <peng.fan@nxp.com>

> > ---

> >  drivers/remoteproc/remoteproc_core.c | 42 ++++++++++++++++++++++++++++

> >  1 file changed, 42 insertions(+)

> > 

> > diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c

> > index fc28053c7f89..e665ed4776c3 100644

> > --- a/drivers/remoteproc/remoteproc_core.c

> > +++ b/drivers/remoteproc/remoteproc_core.c

> > @@ -1670,6 +1670,48 @@ static int rproc_stop(struct rproc *rproc, bool crashed)

> >  	return 0;

> >  }

> >  

> > +/*

> > + * __rproc_detach(): Does the opposite of rproc_attach()

> > + */

> > +static int __maybe_unused __rproc_detach(struct rproc *rproc)

> > +{

> > +	struct device *dev = &rproc->dev;

> > +	int ret;

> > +

> > +	/* No need to continue if a detach() operation has not been provided */

> > +	if (!rproc->ops->detach)

> > +		return -EINVAL;

> 

> I wonder if this ops should be optional.


Function rproc_validate() doesn't check for it so it is optional.  Returning an
error is to indicate to sysfs the operation is not supported if someone tries to
do a "detach" when rproc::ops doesn't provide it.

> 

> > +

> > +	/* Stop any subdevices for the remote processor */

> > +	rproc_stop_subdevices(rproc, false);

> > +

> > +	/*

> > +	 * If the remote processors was started by the core then a cached_table

> > +	 * is present and we must follow the same cleanup sequence as we would

> > +	 * for a shutdown().  As it is in rproc_stop(), use the cached resource

> > +	 * table for the rest of the detach process since ->table_ptr will

> > +	 * become invalid as soon as carveouts are released in

> > +	 * rproc_resource_cleanup().

> > +	 */

> > +	if (rproc->cached_table)

> > +		rproc->table_ptr = rproc->cached_table;

> > +

> > +	/* Tell the remote processor the core isn't available anymore */

> > +	ret = rproc->ops->detach(rproc);

> > +	if (ret) {

> > +		dev_err(dev, "can't detach from rproc: %d\n", ret);

> > +		rproc_start_subdevices(rproc);

> 

> Not sure that this would be possible in all cases, without a unprepare and

> prepare. What about having the same behavior as the rproc_stop failure?


I thought rproc_stop()'s failure path was buggy and could be improved but as you
say, there might be other ramifications to take into account.  I agree that it
is more prudent to follow the current behavior from rproc_stop() and leave
enhancements for another patchset.

> 

> Thanks

> Arnaud.

> 

> > +		return ret;

> > +	}

> > +

> > +	rproc_unprepare_subdevices(rproc);

> > +

> > +	rproc->state = RPROC_DETACHED;

> > +

> > +	dev_info(dev, "detached remote processor %s\n", rproc->name);

> > +

> > +	return 0;

> > +}

> >  

> >  /**

> >   * rproc_trigger_recovery() - recover a remoteproc

> >
diff mbox series

Patch

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index fc28053c7f89..e665ed4776c3 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1670,6 +1670,48 @@  static int rproc_stop(struct rproc *rproc, bool crashed)
 	return 0;
 }
 
+/*
+ * __rproc_detach(): Does the opposite of rproc_attach()
+ */
+static int __maybe_unused __rproc_detach(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	int ret;
+
+	/* No need to continue if a detach() operation has not been provided */
+	if (!rproc->ops->detach)
+		return -EINVAL;
+
+	/* Stop any subdevices for the remote processor */
+	rproc_stop_subdevices(rproc, false);
+
+	/*
+	 * If the remote processors was started by the core then a cached_table
+	 * is present and we must follow the same cleanup sequence as we would
+	 * for a shutdown().  As it is in rproc_stop(), use the cached resource
+	 * table for the rest of the detach process since ->table_ptr will
+	 * become invalid as soon as carveouts are released in
+	 * rproc_resource_cleanup().
+	 */
+	if (rproc->cached_table)
+		rproc->table_ptr = rproc->cached_table;
+
+	/* Tell the remote processor the core isn't available anymore */
+	ret = rproc->ops->detach(rproc);
+	if (ret) {
+		dev_err(dev, "can't detach from rproc: %d\n", ret);
+		rproc_start_subdevices(rproc);
+		return ret;
+	}
+
+	rproc_unprepare_subdevices(rproc);
+
+	rproc->state = RPROC_DETACHED;
+
+	dev_info(dev, "detached remote processor %s\n", rproc->name);
+
+	return 0;
+}
 
 /**
  * rproc_trigger_recovery() - recover a remoteproc