]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - rpmsg/rpmsg.git/commitdiff
TEMP: remoteproc: add "late attach" support
authorRobert Tivy <rtivy@ti.com>
Thu, 12 Sep 2019 17:45:08 +0000 (17:45 +0000)
committerSuman Anna <s-anna@ti.com>
Mon, 23 Sep 2019 01:46:54 +0000 (20:46 -0500)
The remoteproc driver core is, in general, responsible for allocating
the memory for firmware segments, parsing and loading the firmware
segments into the allocated memory regions, mapping these memory
regions into associated IOMMUs, starting/releasing the processors
from reset, and finally establishing IPC between the host and the
remote processors.

The "late attach" feature refers to a model wherein a remote processor
has already been configured, loaded and started by some external entity
prior to kernel boot (u-boot, for example), and the remoteproc driver
needs to be configured to 'attach' or establish a connection with the
currently running code on the remote processor without resetting or
reconfiguring the device and associated peripherals. The feature is
being added to support specific use-cases (eg: "early camera" or "early
video"), requiring certain KPI criteria. The feature is currently based
on having a remote processor perform all the necessary activities to
achieve the required KPI in a stand-alone mode without having to rely
on communicating with the MPU or perform any IPC activities until the
remoteproc driver is up.

The "late attach" support in the remoteproc driver core is currently
designed to not perform the loading of the firmware segments, or
programming of the IOMMUs. The driver though still goes through the
sequence of processing the firmware to set up the correct virtio
based IPC transports, and allocating the required memory segments
to mark these memory regions as used/reserved from kernel in the
corresponding rproc device's CMA pools. The driver expects the
allocator to not perform any memory initialization, to avoid wiping
out the pre-loaded code. Virtio-based IPC with the remote processors
is established once the driver completes processing the firmware,
just as in a regular boot.

Signed-off-by: Robert Tivy <rtivy@ti.com>
Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Amarinder Bindra <a-bindra@ti.com>
Signed-off-by: Venkateswara Rao Mandela <venkat.mandela@ti.com>
Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
drivers/remoteproc/remoteproc_core.c
include/linux/remoteproc.h

index 9e33dbee6e2045c1ed4755f8356ee65de0e62a2c..aba45c21ea473aa5640fa864512373e369b067d0 100644 (file)
@@ -715,10 +715,13 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc,
        if (!mapping)
                return -ENOMEM;
 
-       ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len, rsc->flags);
-       if (ret) {
-               dev_err(dev, "failed to map devmem: %d\n", ret);
-               goto out;
+       if (!rproc->late_attach) {
+               ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len,
+                               rsc->flags);
+               if (ret) {
+                       dev_err(dev, "failed to map devmem: %d\n", ret);
+                       goto out;
+               }
        }
 
        /*
@@ -733,8 +736,12 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc,
        mapping->len = rsc->len;
        list_add_tail(&mapping->node, &rproc->mappings);
 
-       dev_dbg(dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n",
-               rsc->pa, rsc->da, rsc->len);
+       if (!rproc->late_attach)
+               dev_dbg(dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n",
+                       rsc->pa, rsc->da, rsc->len);
+       else
+               dev_dbg(dev, "late-attach: processed devmem pa 0x%x, da 0x%x, len 0x%x\n",
+                       rsc->pa, rsc->da, rsc->len);
 
        return 0;
 
@@ -824,11 +831,13 @@ static int rproc_handle_carveout(struct rproc *rproc,
                        goto dma_free;
                }
 
-               ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len,
-                               rsc->flags);
-               if (ret) {
-                       dev_err(dev, "iommu_map failed: %d\n", ret);
-                       goto free_mapping;
+               if (!rproc->late_attach) {
+                       ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len,
+                                       rsc->flags);
+                       if (ret) {
+                               dev_err(dev, "iommu_map failed: %d\n", ret);
+                               goto free_mapping;
+                       }
                }
 
                /*
@@ -842,8 +851,13 @@ static int rproc_handle_carveout(struct rproc *rproc,
                mapping->len = rsc->len;
                list_add_tail(&mapping->node, &rproc->mappings);
 
-               dev_dbg(dev, "carveout mapped 0x%x to %pad\n",
-                       rsc->da, &dma);
+               if (!rproc->late_attach)
+                       dev_dbg(dev, "carveout mapped 0x%x to %pad\n",
+                               rsc->da, &dma);
+               else
+                       dev_dbg(dev, "late-attach: carveout processed 0x%x to %pad\n",
+                               rsc->da, &dma);
+
        }
 
        /*
@@ -1116,11 +1130,14 @@ static void rproc_resource_cleanup(struct rproc *rproc)
        list_for_each_entry_safe(entry, tmp, &rproc->mappings, node) {
                size_t unmapped;
 
-               unmapped = iommu_unmap(rproc->domain, entry->da, entry->len);
-               if (unmapped != entry->len) {
-                       /* nothing much to do besides complaining */
-                       dev_err(dev, "failed to unmap %u/%zu\n", entry->len,
-                               unmapped);
+               if (!rproc->late_attach) {
+                       unmapped = iommu_unmap(rproc->domain, entry->da,
+                                              entry->len);
+                       if (unmapped != entry->len) {
+                               /* nothing much to do besides complaining */
+                               dev_err(dev, "failed to unmap %u/%zu\n",
+                                       entry->len, unmapped);
+                       }
                }
 
                list_del(&entry->node);
@@ -1189,7 +1206,7 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
                goto clean_up_resources;
        }
 
-       if (!rproc->skip_load) {
+       if (!rproc->skip_load && !rproc->late_attach) {
                /* load the ELF segments to memory */
                ret = rproc_load_segments(rproc, fw);
                if (ret) {
@@ -1197,6 +1214,8 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
                                ret);
                        goto clean_up_resources;
                }
+       } else {
+               dev_dbg(dev, "Skipped program segments load for pre-booted rproc\n");
        }
 
        /*
@@ -1640,6 +1659,7 @@ void rproc_shutdown(struct rproc *rproc)
                complete_all(&rproc->crash_comp);
 
        rproc->state = RPROC_OFFLINE;
+       rproc->late_attach = 0;
 
        dev_info(dev, "stopped remote processor %s\n", rproc->name);
 
index 5c9519283fea31df6c069eebed212feeafcb8d6e..4474ee494f787f3ad60c68cbe5b77d0261741e68 100644 (file)
@@ -489,6 +489,7 @@ struct rproc_dump_segment {
  * @deny_sysfs_ops: flag to not permit sysfs operations on state and firmware
  * @skip_firmware_request: flag to skip requesting the firmware
  * @skip_load: flag to skip the loading of firmware segments
+ * @late_attach: flag indicating remote core has been externally pre-booted
  * @dump_segments: list of segments in the firmware
  */
 struct rproc {
@@ -527,6 +528,7 @@ struct rproc {
        unsigned int deny_sysfs_ops             : 1;
        unsigned int skip_firmware_request      : 1;
        unsigned int skip_load                  : 1;
+       unsigned int late_attach                : 1;
        struct list_head dump_segments;
 };