Re: [PATCH v4 3/5] remoteproc: Add prepare/unprepare callbacks
From: Fabien DESSENNE
Date: Tue Dec 17 2019 - 05:22:17 EST
Hi Paul
On 14/12/2019 11:30 PM, Paul Cercueil wrote:
> Hi Fabien,
>
>
> Le jeu., dÃc. 12, 2019 at 10:03, Fabien DESSENNE
> <fabien.dessenne@xxxxxx> a Ãcrit :
>> Hi Paul
>>
>>
>> On 10/12/2019 5:40 PM, Paul Cercueil wrote:
>>> ÂThe .prepare() callback is called before the firmware is loaded to
>>> Âmemory. This is useful for instance in the case where some setup is
>>> Ârequired for the memory to be accessible.
>>
>>
>> I am trying to figure out what king of 'setup' may be required. From the
>> ingenic driver I understand that you need to enable clocks to allow some
>> memory access.
>>
>> Instead of adding this new ops, why not enabling clocks in probe()?
>
> Enabling the clocks in the probe means that the clocks will be
> unconditionally enabled until the driver is removed, even if the
> remote processor end up being unused. That would be a waste of power.
OK I understand.
Nevertheless I think that you may need to call .prepare() from
rproc_fw_boot() since you may need to access some memories from the
point rproc_handle_resources() is called (this sets up virtio which is
used if you have a resource table defining vdev).
And rproc_fw_boot() calls rproc_enable_iommu(), which sounds like
"prepare memory", so this may be the right place to call .prepare()
BR
Fabien
>
> Cheers,
> -Paul
>
>
>>
>> BR
>>
>> Fabien
>>
>>
>>>
>>> ÂSigned-off-by: Paul Cercueil <paul@xxxxxxxxxxxxxxx>
>>> Â---
>>>
>>> ÂNotes:
>>> ÂÂÂÂÂ v2-v4: No change
>>>
>>> ÂÂ drivers/remoteproc/remoteproc_core.c | 16 +++++++++++++++-
>>> ÂÂ include/linux/remoteproc.hÂÂÂÂÂÂÂÂÂÂ |Â 4 ++++
>>> ÂÂ 2 files changed, 19 insertions(+), 1 deletion(-)
>>>
>>> Âdiff --git a/drivers/remoteproc/remoteproc_core.c
>>> b/drivers/remoteproc/remoteproc_core.c
>>> Âindex 0a9fc7fdd1c3..3ea5f675a148 100644
>>> Â--- a/drivers/remoteproc/remoteproc_core.c
>>> Â+++ b/drivers/remoteproc/remoteproc_core.c
>>> Â@@ -1299,11 +1299,19 @@ static int rproc_start(struct rproc *rproc,
>>> const struct firmware *fw)
>>> ÂÂÂÂÂÂ struct device *dev = &rproc->dev;
>>> ÂÂÂÂÂÂ int ret;
>>>
>>> Â+ÂÂÂ if (rproc->ops->prepare) {
>>> Â+ÂÂÂÂÂÂÂ ret = rproc->ops->prepare(rproc);
>>> Â+ÂÂÂÂÂÂÂ if (ret) {
>>> Â+ÂÂÂÂÂÂÂÂÂÂÂ dev_err(dev, "Failed to prepare rproc: %d\n", ret);
>>> Â+ÂÂÂÂÂÂÂÂÂÂÂ return ret;
>>> Â+ÂÂÂÂÂÂÂ }
>>> Â+ÂÂÂ }
>>> Â+
>>> ÂÂÂÂÂÂ /* load the ELF segments to memory */
>>> ÂÂÂÂÂÂ ret = rproc_load_segments(rproc, fw);
>>> ÂÂÂÂÂÂ if (ret) {
>>> ÂÂÂÂÂÂÂÂÂÂ dev_err(dev, "Failed to load program segments: %d\n", ret);
>>> Â-ÂÂÂÂÂÂÂ return ret;
>>> Â+ÂÂÂÂÂÂÂ goto unprepare_rproc;
>>> ÂÂÂÂÂÂ }
>>>
>>> ÂÂÂÂÂÂ /*
>>> Â@@ -1354,6 +1362,9 @@ static int rproc_start(struct rproc *rproc,
>>> const struct firmware *fw)
>>> ÂÂÂÂÂÂ rproc_unprepare_subdevices(rproc);
>>> ÂÂ reset_table_ptr:
>>> ÂÂÂÂÂÂ rproc->table_ptr = rproc->cached_table;
>>> Â+unprepare_rproc:
>>> Â+ÂÂÂ if (rproc->ops->unprepare)
>>> Â+ÂÂÂÂÂÂÂ rproc->ops->unprepare(rproc);
>>>
>>> ÂÂÂÂÂÂ return ret;
>>> ÂÂ }
>>> Â@@ -1483,6 +1494,9 @@ static int rproc_stop(struct rproc *rproc,
>>> bool crashed)
>>>
>>> ÂÂÂÂÂÂ rproc->state = RPROC_OFFLINE;
>>>
>>> Â+ÂÂÂ if (rproc->ops->unprepare)
>>> Â+ÂÂÂÂÂÂÂ rproc->ops->unprepare(rproc);
>>> Â+
>>> ÂÂÂÂÂÂ dev_info(dev, "stopped remote processor %s\n", rproc->name);
>>>
>>> ÂÂÂÂÂÂ return 0;
>>> Âdiff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
>>> Âindex 5f201f0c86c3..a6272d1ba384 100644
>>> Â--- a/include/linux/remoteproc.h
>>> Â+++ b/include/linux/remoteproc.h
>>> Â@@ -355,6 +355,8 @@ enum rsc_handling_status {
>>>
>>> ÂÂ /**
>>> ÂÂÂ * struct rproc_ops - platform-specific device handlers
>>> Â+ * @prepare:ÂÂÂ prepare the device for power up (before the
>>> firmware is loaded)
>>> Â+ * @unprepare:ÂÂÂ unprepare the device after it is stopped
>>> ÂÂÂ * @start:ÂÂÂ power on the device and boot it
>>> ÂÂÂ * @stop:ÂÂÂ power off the device
>>> ÂÂÂ * @kick:ÂÂÂ kick a virtqueue (virtqueue id given as a parameter)
>>> Â@@ -371,6 +373,8 @@ enum rsc_handling_status {
>>> ÂÂÂ * @get_boot_addr:ÂÂÂ get boot address to entry point specified
>>> in firmware
>>> ÂÂÂ */
>>> ÂÂ struct rproc_ops {
>>> Â+ÂÂÂ int (*prepare)(struct rproc *rproc);
>>> Â+ÂÂÂ void (*unprepare)(struct rproc *rproc);
>>> ÂÂÂÂÂÂ int (*start)(struct rproc *rproc);
>>> ÂÂÂÂÂÂ int (*stop)(struct rproc *rproc);
>>> ÂÂÂÂÂÂ void (*kick)(struct rproc *rproc, int vqid);
>
>