Эх сурвалжийг харах

TEMP: remoteproc: add "late attach" support

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>
Robert Tivy 6 жил өмнө
parent
commit
15dfdff538

+ 39 - 19
drivers/remoteproc/remoteproc_core.c

@@ -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);
 

+ 2 - 0
include/linux/remoteproc.h

@@ -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;
 };