diff mbox series

[v4,12/17] remoteproc: Introduce function rproc_detach()

Message ID 20201218173228.2277032-13-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 enable the remoteproc
core to release the resources associated with a remote processor
without stopping its operation.

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

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

---
 drivers/remoteproc/remoteproc_core.c | 71 +++++++++++++++++++++++++++-
 include/linux/remoteproc.h           |  2 +
 2 files changed, 72 insertions(+), 1 deletion(-)

-- 
2.25.1

Comments

Arnaud POULIQUEN Jan. 27, 2021, 8:50 a.m. UTC | #1
On 12/18/20 6:32 PM, Mathieu Poirier wrote:
> Introduce function rproc_detach() to enable the remoteproc

> core to release the resources associated with a remote processor

> without stopping its operation.

> 

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

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

> ---

>  drivers/remoteproc/remoteproc_core.c | 71 +++++++++++++++++++++++++++-

>  include/linux/remoteproc.h           |  2 +

>  2 files changed, 72 insertions(+), 1 deletion(-)

> 

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

> index e665ed4776c3..ece3f15070b9 100644

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

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

> @@ -1673,7 +1673,7 @@ static int rproc_stop(struct rproc *rproc, bool crashed)

>  /*

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

>   */

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

> +static int __rproc_detach(struct rproc *rproc)

>  {

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

>  	int ret;

> @@ -1927,6 +1927,75 @@ void rproc_shutdown(struct rproc *rproc)

>  }

>  EXPORT_SYMBOL(rproc_shutdown);

>  

> +/**

> + * rproc_detach() - Detach the remote processor from the

> + * remoteproc core

> + *

> + * @rproc: the remote processor

> + *

> + * Detach a remote processor (previously attached to with rproc_actuate()).


You rename the function to rproc_attach in you patch 04/17.

Then Reviewed-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>

Thanks,
Arnaud

> + *

> + * In case @rproc is still being used by an additional user(s), then

> + * this function will just decrement the power refcount and exit,

> + * without disconnecting the device.

> + *

> + * Function rproc_detach() calls __rproc_detach() in order to let a remote

> + * processor know that services provided by the application processor are

> + * no longer available.  From there it should be possible to remove the

> + * platform driver and even power cycle the application processor (if the HW

> + * supports it) without needing to switch off the remote processor.

> + */

> +int rproc_detach(struct rproc *rproc)

> +{

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

> +	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) {

> +		ret = -EPERM;

> +		goto out;

> +	}

> +

> +	/* if the remote proc is still needed, bail out */

> +	if (!atomic_dec_and_test(&rproc->power)) {

> +		ret = -EBUSY;

> +		goto out;

> +	}

> +

> +	ret = __rproc_detach(rproc);

> +	if (ret) {

> +		atomic_inc(&rproc->power);

> +		goto out;

> +	}

> +

> +	/* clean up all acquired resources */

> +	rproc_resource_cleanup(rproc);

> +

> +	rproc_disable_iommu(rproc);

> +

> +	/*

> +	 * If the remote processor was booted by the core the cached table needs

> +	 * to be freed and ->table_ptr set to NULL because it will be

> +	 * invalidated by rproc_resource_cleanup().  If the remote processor was

> +	 * attached to ->cached_table is NULL and kfree() returns right away.

> +	 *

> +	 * In either case ->table_ptr has to be set to NULL.  It will be set

> +	 * again when the remote processor is re-attached to.

> +	 */

> +	kfree(rproc->cached_table);

> +	rproc->cached_table = NULL;

> +	rproc->table_ptr = NULL;

> +out:

> +	mutex_unlock(&rproc->lock);

> +	return ret;

> +}

> +EXPORT_SYMBOL(rproc_detach);

> +

>  /**

>   * rproc_get_by_phandle() - find a remote processor by phandle

>   * @phandle: phandle to the rproc

> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h

> index 9bb34c3eb847..65ece6f177b7 100644

> --- a/include/linux/remoteproc.h

> +++ b/include/linux/remoteproc.h

> @@ -659,6 +659,8 @@ rproc_of_resm_mem_entry_init(struct device *dev, u32 of_resm_idx, size_t len,

>  

>  int rproc_boot(struct rproc *rproc);

>  void rproc_shutdown(struct rproc *rproc);

> +int rproc_detach(struct rproc *rproc);

> +int rproc_set_firmware(struct rproc *rproc, const char *fw_name);

>  void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type);

>  int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size);

>  int rproc_coredump_add_custom_segment(struct rproc *rproc,

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

> 

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

> > Introduce function rproc_detach() to enable the remoteproc

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

> > without stopping its operation.

> > 

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

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

> > ---

> >  drivers/remoteproc/remoteproc_core.c | 71 +++++++++++++++++++++++++++-

> >  include/linux/remoteproc.h           |  2 +

> >  2 files changed, 72 insertions(+), 1 deletion(-)

> > 

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

> > index e665ed4776c3..ece3f15070b9 100644

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

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

> > @@ -1673,7 +1673,7 @@ static int rproc_stop(struct rproc *rproc, bool crashed)

> >  /*

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

> >   */

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

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

> >  {

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

> >  	int ret;

> > @@ -1927,6 +1927,75 @@ void rproc_shutdown(struct rproc *rproc)

> >  }

> >  EXPORT_SYMBOL(rproc_shutdown);

> >  

> > +/**

> > + * rproc_detach() - Detach the remote processor from the

> > + * remoteproc core

> > + *

> > + * @rproc: the remote processor

> > + *

> > + * Detach a remote processor (previously attached to with rproc_actuate()).

> 

> You rename the function to rproc_attach in you patch 04/17.

> 


Yes, good catch.

> Then Reviewed-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>

> 

> Thanks,

> Arnaud

> 

> > + *

> > + * In case @rproc is still being used by an additional user(s), then

> > + * this function will just decrement the power refcount and exit,

> > + * without disconnecting the device.

> > + *

> > + * Function rproc_detach() calls __rproc_detach() in order to let a remote

> > + * processor know that services provided by the application processor are

> > + * no longer available.  From there it should be possible to remove the

> > + * platform driver and even power cycle the application processor (if the HW

> > + * supports it) without needing to switch off the remote processor.

> > + */

> > +int rproc_detach(struct rproc *rproc)

> > +{

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

> > +	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) {

> > +		ret = -EPERM;

> > +		goto out;

> > +	}

> > +

> > +	/* if the remote proc is still needed, bail out */

> > +	if (!atomic_dec_and_test(&rproc->power)) {

> > +		ret = -EBUSY;

> > +		goto out;

> > +	}

> > +

> > +	ret = __rproc_detach(rproc);

> > +	if (ret) {

> > +		atomic_inc(&rproc->power);

> > +		goto out;

> > +	}

> > +

> > +	/* clean up all acquired resources */

> > +	rproc_resource_cleanup(rproc);

> > +

> > +	rproc_disable_iommu(rproc);

> > +

> > +	/*

> > +	 * If the remote processor was booted by the core the cached table needs

> > +	 * to be freed and ->table_ptr set to NULL because it will be

> > +	 * invalidated by rproc_resource_cleanup().  If the remote processor was

> > +	 * attached to ->cached_table is NULL and kfree() returns right away.

> > +	 *

> > +	 * In either case ->table_ptr has to be set to NULL.  It will be set

> > +	 * again when the remote processor is re-attached to.

> > +	 */

> > +	kfree(rproc->cached_table);

> > +	rproc->cached_table = NULL;

> > +	rproc->table_ptr = NULL;

> > +out:

> > +	mutex_unlock(&rproc->lock);

> > +	return ret;

> > +}

> > +EXPORT_SYMBOL(rproc_detach);

> > +

> >  /**

> >   * rproc_get_by_phandle() - find a remote processor by phandle

> >   * @phandle: phandle to the rproc

> > diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h

> > index 9bb34c3eb847..65ece6f177b7 100644

> > --- a/include/linux/remoteproc.h

> > +++ b/include/linux/remoteproc.h

> > @@ -659,6 +659,8 @@ rproc_of_resm_mem_entry_init(struct device *dev, u32 of_resm_idx, size_t len,

> >  

> >  int rproc_boot(struct rproc *rproc);

> >  void rproc_shutdown(struct rproc *rproc);

> > +int rproc_detach(struct rproc *rproc);

> > +int rproc_set_firmware(struct rproc *rproc, const char *fw_name);

> >  void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type);

> >  int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size);

> >  int rproc_coredump_add_custom_segment(struct rproc *rproc,

> >
diff mbox series

Patch

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index e665ed4776c3..ece3f15070b9 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1673,7 +1673,7 @@  static int rproc_stop(struct rproc *rproc, bool crashed)
 /*
  * __rproc_detach(): Does the opposite of rproc_attach()
  */
-static int __maybe_unused __rproc_detach(struct rproc *rproc)
+static int __rproc_detach(struct rproc *rproc)
 {
 	struct device *dev = &rproc->dev;
 	int ret;
@@ -1927,6 +1927,75 @@  void rproc_shutdown(struct rproc *rproc)
 }
 EXPORT_SYMBOL(rproc_shutdown);
 
+/**
+ * rproc_detach() - Detach the remote processor from the
+ * remoteproc core
+ *
+ * @rproc: the remote processor
+ *
+ * Detach a remote processor (previously attached to with rproc_actuate()).
+ *
+ * In case @rproc is still being used by an additional user(s), then
+ * this function will just decrement the power refcount and exit,
+ * without disconnecting the device.
+ *
+ * Function rproc_detach() calls __rproc_detach() in order to let a remote
+ * processor know that services provided by the application processor are
+ * no longer available.  From there it should be possible to remove the
+ * platform driver and even power cycle the application processor (if the HW
+ * supports it) without needing to switch off the remote processor.
+ */
+int rproc_detach(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	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) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	/* if the remote proc is still needed, bail out */
+	if (!atomic_dec_and_test(&rproc->power)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = __rproc_detach(rproc);
+	if (ret) {
+		atomic_inc(&rproc->power);
+		goto out;
+	}
+
+	/* clean up all acquired resources */
+	rproc_resource_cleanup(rproc);
+
+	rproc_disable_iommu(rproc);
+
+	/*
+	 * If the remote processor was booted by the core the cached table needs
+	 * to be freed and ->table_ptr set to NULL because it will be
+	 * invalidated by rproc_resource_cleanup().  If the remote processor was
+	 * attached to ->cached_table is NULL and kfree() returns right away.
+	 *
+	 * In either case ->table_ptr has to be set to NULL.  It will be set
+	 * again when the remote processor is re-attached to.
+	 */
+	kfree(rproc->cached_table);
+	rproc->cached_table = NULL;
+	rproc->table_ptr = NULL;
+out:
+	mutex_unlock(&rproc->lock);
+	return ret;
+}
+EXPORT_SYMBOL(rproc_detach);
+
 /**
  * rproc_get_by_phandle() - find a remote processor by phandle
  * @phandle: phandle to the rproc
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 9bb34c3eb847..65ece6f177b7 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -659,6 +659,8 @@  rproc_of_resm_mem_entry_init(struct device *dev, u32 of_resm_idx, size_t len,
 
 int rproc_boot(struct rproc *rproc);
 void rproc_shutdown(struct rproc *rproc);
+int rproc_detach(struct rproc *rproc);
+int rproc_set_firmware(struct rproc *rproc, const char *fw_name);
 void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type);
 int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size);
 int rproc_coredump_add_custom_segment(struct rproc *rproc,