diff mbox

[1/4] remoteproc: Introduce always-on flag

Message ID 1470077883-7419-1-git-send-email-bjorn.andersson@linaro.org
State New
Headers show

Commit Message

Bjorn Andersson Aug. 1, 2016, 6:58 p.m. UTC
Introduce an "always-on" flag on rprocs to make it possible to flag
remote processors without vdevs to automatically boot once the firmware
is found.

Cc: Lee Jones <lee.jones@linaro.org>
Cc: Loic Pallardy <loic.pallardy@st.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

---
 drivers/remoteproc/remoteproc_core.c   | 27 ++++++++++++++++++++++++++-
 drivers/remoteproc/remoteproc_virtio.c | 13 -------------
 include/linux/remoteproc.h             |  1 +
 3 files changed, 27 insertions(+), 14 deletions(-)

-- 
2.5.0

Comments

Loic Pallardy Aug. 2, 2016, 3:17 p.m. UTC | #1
Hi Bjorn,

On 08/01/2016 08:58 PM, Bjorn Andersson wrote:
> Introduce an "always-on" flag on rprocs to make it possible to flag

> remote processors without vdevs to automatically boot once the firmware

> is found.

>

Should this flag rather be named "auto-boot"? From my pov, "always-on" 
means coprocessor can't be shutdown.

> Cc: Lee Jones <lee.jones@linaro.org>

> Cc: Loic Pallardy <loic.pallardy@st.com>

> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

> ---

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

>   drivers/remoteproc/remoteproc_virtio.c | 13 -------------

>   include/linux/remoteproc.h             |  1 +

>   3 files changed, 27 insertions(+), 14 deletions(-)

>

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

> index fe0539ed9cb5..7e7f24fcac69 100644

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

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

> @@ -933,6 +933,10 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)

>   	/* look for virtio devices and register them */

>   	ret = rproc_handle_resources(rproc, tablesz, rproc_vdev_handler);

>

> +	/* if rproc is marked always-on, request it to boot */

> +	if (rproc->always_on)

> +		rproc_boot_nowait(rproc);

> +

>   out:

>   	release_firmware(fw);

>   	/* allow rproc_del() contexts, if any, to proceed */

> @@ -978,11 +982,16 @@ static int rproc_add_virtio_devices(struct rproc *rproc)

>   int rproc_trigger_recovery(struct rproc *rproc)

>   {

>   	struct rproc_vdev *rvdev, *rvtmp;

> +	int ret;

>

>   	dev_err(&rproc->dev, "recovering %s\n", rproc->name);

>

>   	init_completion(&rproc->crash_comp);

>

> +	/* shut down the remote */

> +	/* TODO: make sure this works with rproc->power > 1 */

> +	rproc_shutdown(rproc);

> +

>   	/* clean up remote vdev entries */

>   	list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)

>   		rproc_remove_virtio_dev(rvdev);

> @@ -993,7 +1002,17 @@ int rproc_trigger_recovery(struct rproc *rproc)

>   	/* Free the copy of the resource table */

>   	kfree(rproc->cached_table);

>

> -	return rproc_add_virtio_devices(rproc);

> +	ret = rproc_add_virtio_devices(rproc);

> +	if (ret)

> +		return ret;

> +

> +	/*

> +	 * boot the remote processor up again, waiting for the async fw load to

> +	 * finish

> +	 */

> +	rproc_boot(rproc);

You are changing current behavior by forcing rproc boot whatever 
"always-on". Moreover coprocessor already rebooted by 
rproc_add_virtio_device if "always-on" flag is set, doesn't it?
If yes, rproc->power will be equal to 2 and rproc_shutdown call will 
failed as this second rproc_boot call is unknown from customer pov.

Regards,
Loic

> +

> +	return 0;

>   }

>

>   /**

> @@ -1374,6 +1393,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,

>   	rproc->name = name;

>   	rproc->ops = ops;

>   	rproc->priv = &rproc[1];

> +	rproc->always_on = true;

>

>   	device_initialize(&rproc->dev);

>   	rproc->dev.parent = dev;

> @@ -1452,6 +1472,11 @@ int rproc_del(struct rproc *rproc)

>   	/* if rproc is just being registered, wait */

>   	wait_for_completion(&rproc->firmware_loading_complete);

>

> +	/* if rproc is marked always-on, rproc_add() booted it */

> +	/* TODO: make sure this works with rproc->power > 1 */

> +	if (rproc->always_on)

> +		rproc_shutdown(rproc);

> +

>   	/* clean up remote vdev entries */

>   	list_for_each_entry_safe(rvdev, tmp, &rproc->rvdevs, node)

>   		rproc_remove_virtio_dev(rvdev);

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

> index cc91556313e1..574c90ce07f7 100644

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

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

> @@ -136,11 +136,6 @@ static void __rproc_virtio_del_vqs(struct virtio_device *vdev)

>

>   static void rproc_virtio_del_vqs(struct virtio_device *vdev)

>   {

> -	struct rproc *rproc = vdev_to_rproc(vdev);

> -

> -	/* power down the remote processor before deleting vqs */

> -	rproc_shutdown(rproc);

> -

>   	__rproc_virtio_del_vqs(vdev);

>   }

>

> @@ -149,7 +144,6 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,

>   		       vq_callback_t *callbacks[],

>   		       const char * const names[])

>   {

> -	struct rproc *rproc = vdev_to_rproc(vdev);

>   	int i, ret;

>

>   	for (i = 0; i < nvqs; ++i) {

> @@ -160,13 +154,6 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,

>   		}

>   	}

>

> -	/* now that the vqs are all set, boot the remote processor */

> -	ret = rproc_boot_nowait(rproc);

> -	if (ret) {

> -		dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret);

> -		goto error;

> -	}

> -

>   	return 0;

>

>   error:

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

> index 1c457a8dd5a6..bd1cfcbb57b9 100644

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

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

> @@ -443,6 +443,7 @@ struct rproc {

>   	struct resource_table *cached_table;

>   	u32 table_csum;

>   	bool has_iommu;

> +	bool always_on;

>   };

>

>   /* we currently support only two vrings per rvdev */

>
Bjorn Andersson Aug. 3, 2016, 10:02 p.m. UTC | #2
On Tue 02 Aug 08:17 PDT 2016, loic pallardy wrote:

> Hi Bjorn,

> 

> On 08/01/2016 08:58 PM, Bjorn Andersson wrote:

> >Introduce an "always-on" flag on rprocs to make it possible to flag

> >remote processors without vdevs to automatically boot once the firmware

> >is found.

> >

> Should this flag rather be named "auto-boot"? From my pov, "always-on" means

> coprocessor can't be shutdown.

> 


I saw it from the view of the remoteproc driver, in which case it's
always-on. But I'm fine with naming it "auto-boot" instead.

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

[..]
> >@@ -978,11 +982,16 @@ static int rproc_add_virtio_devices(struct rproc *rproc)

> >  int rproc_trigger_recovery(struct rproc *rproc)

> >  {

> >  	struct rproc_vdev *rvdev, *rvtmp;

> >+	int ret;

> >

> >  	dev_err(&rproc->dev, "recovering %s\n", rproc->name);

> >

> >  	init_completion(&rproc->crash_comp);

> >

> >+	/* shut down the remote */

> >+	/* TODO: make sure this works with rproc->power > 1 */

> >+	rproc_shutdown(rproc);

> >+

> >  	/* clean up remote vdev entries */

> >  	list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)

> >  		rproc_remove_virtio_dev(rvdev);

> >@@ -993,7 +1002,17 @@ int rproc_trigger_recovery(struct rproc *rproc)

> >  	/* Free the copy of the resource table */

> >  	kfree(rproc->cached_table);

> >

> >-	return rproc_add_virtio_devices(rproc);

> >+	ret = rproc_add_virtio_devices(rproc);

> >+	if (ret)

> >+		return ret;

> >+

> >+	/*

> >+	 * boot the remote processor up again, waiting for the async fw load to

> >+	 * finish

> >+	 */

> >+	rproc_boot(rproc);

> You are changing current behavior by forcing rproc boot whatever

> "always-on". Moreover coprocessor already rebooted by

> rproc_add_virtio_device if "always-on" flag is set, doesn't it?

> If yes, rproc->power will be equal to 2 and rproc_shutdown call will failed

> as this second rproc_boot call is unknown from customer pov.

> 


rproc_add_virtio_devices() does no longer call rproc_boot(), this patch
moves that call. So for always-on rprocs "power" will go 1 -> 0 -> 1 in
this function.

What does change is that for a non-always-on case.

If we have 1 client that has requested rproc_boot() then the current
implementation will bring "power" down to 1 and we will wait until the
client for some reason calls rproc_shutdown(). After that we might boot
the system again, if there are any vdevs in the resource table.

Here we will bring "power" from 1 -> 0 -> 1, without regarding who's
holding references.

> >+

> >+	return 0;

> >  }


Regards,
Bjorn
Loic Pallardy Aug. 4, 2016, 9:44 a.m. UTC | #3
On 08/04/2016 12:02 AM, Bjorn Andersson wrote:
> On Tue 02 Aug 08:17 PDT 2016, loic pallardy wrote:

>

>> Hi Bjorn,

>>

>> On 08/01/2016 08:58 PM, Bjorn Andersson wrote:

>>> Introduce an "always-on" flag on rprocs to make it possible to flag

>>> remote processors without vdevs to automatically boot once the firmware

>>> is found.

>>>

>> Should this flag rather be named "auto-boot"? From my pov, "always-on" means

>> coprocessor can't be shutdown.

>>

>

> I saw it from the view of the remoteproc driver, in which case it's

> always-on. But I'm fine with naming it "auto-boot" instead.

>

> [..]

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

> [..]

>>> @@ -978,11 +982,16 @@ static int rproc_add_virtio_devices(struct rproc *rproc)

>>>   int rproc_trigger_recovery(struct rproc *rproc)

>>>   {

>>>   	struct rproc_vdev *rvdev, *rvtmp;

>>> +	int ret;

>>>

>>>   	dev_err(&rproc->dev, "recovering %s\n", rproc->name);

>>>

>>>   	init_completion(&rproc->crash_comp);

>>>

>>> +	/* shut down the remote */

>>> +	/* TODO: make sure this works with rproc->power > 1 */

>>> +	rproc_shutdown(rproc);

>>> +

>>>   	/* clean up remote vdev entries */

>>>   	list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)

>>>   		rproc_remove_virtio_dev(rvdev);

>>> @@ -993,7 +1002,17 @@ int rproc_trigger_recovery(struct rproc *rproc)

>>>   	/* Free the copy of the resource table */

>>>   	kfree(rproc->cached_table);

>>>

>>> -	return rproc_add_virtio_devices(rproc);

>>> +	ret = rproc_add_virtio_devices(rproc);

>>> +	if (ret)

>>> +		return ret;

>>> +

>>> +	/*

>>> +	 * boot the remote processor up again, waiting for the async fw load to

>>> +	 * finish

>>> +	 */

>>> +	rproc_boot(rproc);

>> You are changing current behavior by forcing rproc boot whatever

>> "always-on". Moreover coprocessor already rebooted by

>> rproc_add_virtio_device if "always-on" flag is set, doesn't it?

>> If yes, rproc->power will be equal to 2 and rproc_shutdown call will failed

>> as this second rproc_boot call is unknown from customer pov.

>>

>

> rproc_add_virtio_devices() does no longer call rproc_boot(), this patch

> moves that call. So for always-on rprocs "power" will go 1 -> 0 -> 1 in

> this function.

>

> What does change is that for a non-always-on case.

>

> If we have 1 client that has requested rproc_boot() then the current

> implementation will bring "power" down to 1 and we will wait until the

> client for some reason calls rproc_shutdown(). After that we might boot

> the system again, if there are any vdevs in the resource table.

>

> Here we will bring "power" from 1 -> 0 -> 1, without regarding who's

> holding references.


I'm fine with the final sequence in which only rproc_shutdown and 
rproc_boot are called (with patch 3 modifications).

But having a look only to this patch, we have the following function call:

rproc_trigger_recovery
   |__ rproc_shutdown --> power from 1 -> 0
   |__ rproc_add_virtio_devices
	|__ rproc_fw_config_virtio
		|__ (if always_on == 1) rproc_boot_nowait --> power from 0 --> 1
   |__ rproc_boot
	if always_on == 1 power from 1 --> 2
	else power from 0 --> 1

on this patch rproc_boot should be called only is always_on flag is not set.

With patch 3, call to rproc_add_virtio_devices is suppressed and 
behavior is ok.

Regards,
Loic
>

>>> +

>>> +	return 0;

>>>   }

>

> Regards,

> Bjorn

>
Bjorn Andersson Aug. 4, 2016, 5:23 p.m. UTC | #4
On Thu 04 Aug 02:44 PDT 2016, loic pallardy wrote:

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

[..]
> >>>@@ -993,7 +1002,17 @@ int rproc_trigger_recovery(struct rproc *rproc)

> >>>  	/* Free the copy of the resource table */

> >>>  	kfree(rproc->cached_table);

> >>>

> >>>-	return rproc_add_virtio_devices(rproc);

> >>>+	ret = rproc_add_virtio_devices(rproc);

> >>>+	if (ret)

> >>>+		return ret;

> >>>+

> >>>+	/*

> >>>+	 * boot the remote processor up again, waiting for the async fw load to

> >>>+	 * finish

> >>>+	 */

> >>>+	rproc_boot(rproc);

> >>You are changing current behavior by forcing rproc boot whatever

> >>"always-on". Moreover coprocessor already rebooted by

> >>rproc_add_virtio_device if "always-on" flag is set, doesn't it?

> >>If yes, rproc->power will be equal to 2 and rproc_shutdown call will failed

> >>as this second rproc_boot call is unknown from customer pov.

> >>

> >

> >rproc_add_virtio_devices() does no longer call rproc_boot(), this patch

> >moves that call. So for always-on rprocs "power" will go 1 -> 0 -> 1 in

> >this function.

> >

> >What does change is that for a non-always-on case.

> >

> >If we have 1 client that has requested rproc_boot() then the current

> >implementation will bring "power" down to 1 and we will wait until the

> >client for some reason calls rproc_shutdown(). After that we might boot

> >the system again, if there are any vdevs in the resource table.

> >

> >Here we will bring "power" from 1 -> 0 -> 1, without regarding who's

> >holding references.

> 

> I'm fine with the final sequence in which only rproc_shutdown and rproc_boot

> are called (with patch 3 modifications).

> 

> But having a look only to this patch, we have the following function call:

> 

> rproc_trigger_recovery

>   |__ rproc_shutdown --> power from 1 -> 0

>   |__ rproc_add_virtio_devices

> 	|__ rproc_fw_config_virtio

> 		|__ (if always_on == 1) rproc_boot_nowait --> power from 0 --> 1

>   |__ rproc_boot

> 	if always_on == 1 power from 1 --> 2

> 	else power from 0 --> 1

> 

> on this patch rproc_boot should be called only is always_on flag is not set.

> 

> With patch 3, call to rproc_add_virtio_devices is suppressed and behavior is

> ok.

> 


Doh! Thanks for the explanation, you're of course correct.

Regards,
Bjorn
diff mbox

Patch

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index fe0539ed9cb5..7e7f24fcac69 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -933,6 +933,10 @@  static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
 	/* look for virtio devices and register them */
 	ret = rproc_handle_resources(rproc, tablesz, rproc_vdev_handler);
 
+	/* if rproc is marked always-on, request it to boot */
+	if (rproc->always_on)
+		rproc_boot_nowait(rproc);
+
 out:
 	release_firmware(fw);
 	/* allow rproc_del() contexts, if any, to proceed */
@@ -978,11 +982,16 @@  static int rproc_add_virtio_devices(struct rproc *rproc)
 int rproc_trigger_recovery(struct rproc *rproc)
 {
 	struct rproc_vdev *rvdev, *rvtmp;
+	int ret;
 
 	dev_err(&rproc->dev, "recovering %s\n", rproc->name);
 
 	init_completion(&rproc->crash_comp);
 
+	/* shut down the remote */
+	/* TODO: make sure this works with rproc->power > 1 */
+	rproc_shutdown(rproc);
+
 	/* clean up remote vdev entries */
 	list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)
 		rproc_remove_virtio_dev(rvdev);
@@ -993,7 +1002,17 @@  int rproc_trigger_recovery(struct rproc *rproc)
 	/* Free the copy of the resource table */
 	kfree(rproc->cached_table);
 
-	return rproc_add_virtio_devices(rproc);
+	ret = rproc_add_virtio_devices(rproc);
+	if (ret)
+		return ret;
+
+	/*
+	 * boot the remote processor up again, waiting for the async fw load to
+	 * finish
+	 */
+	rproc_boot(rproc);
+
+	return 0;
 }
 
 /**
@@ -1374,6 +1393,7 @@  struct rproc *rproc_alloc(struct device *dev, const char *name,
 	rproc->name = name;
 	rproc->ops = ops;
 	rproc->priv = &rproc[1];
+	rproc->always_on = true;
 
 	device_initialize(&rproc->dev);
 	rproc->dev.parent = dev;
@@ -1452,6 +1472,11 @@  int rproc_del(struct rproc *rproc)
 	/* if rproc is just being registered, wait */
 	wait_for_completion(&rproc->firmware_loading_complete);
 
+	/* if rproc is marked always-on, rproc_add() booted it */
+	/* TODO: make sure this works with rproc->power > 1 */
+	if (rproc->always_on)
+		rproc_shutdown(rproc);
+
 	/* clean up remote vdev entries */
 	list_for_each_entry_safe(rvdev, tmp, &rproc->rvdevs, node)
 		rproc_remove_virtio_dev(rvdev);
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index cc91556313e1..574c90ce07f7 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -136,11 +136,6 @@  static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
 
 static void rproc_virtio_del_vqs(struct virtio_device *vdev)
 {
-	struct rproc *rproc = vdev_to_rproc(vdev);
-
-	/* power down the remote processor before deleting vqs */
-	rproc_shutdown(rproc);
-
 	__rproc_virtio_del_vqs(vdev);
 }
 
@@ -149,7 +144,6 @@  static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		       vq_callback_t *callbacks[],
 		       const char * const names[])
 {
-	struct rproc *rproc = vdev_to_rproc(vdev);
 	int i, ret;
 
 	for (i = 0; i < nvqs; ++i) {
@@ -160,13 +154,6 @@  static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		}
 	}
 
-	/* now that the vqs are all set, boot the remote processor */
-	ret = rproc_boot_nowait(rproc);
-	if (ret) {
-		dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret);
-		goto error;
-	}
-
 	return 0;
 
 error:
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 1c457a8dd5a6..bd1cfcbb57b9 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -443,6 +443,7 @@  struct rproc {
 	struct resource_table *cached_table;
 	u32 table_csum;
 	bool has_iommu;
+	bool always_on;
 };
 
 /* we currently support only two vrings per rvdev */