linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/5] remoteproc: Support bi-directional vdev config space.
@ 2012-12-06 19:35 Sjur Brændeland
  2012-12-06 19:35 ` [RFC 1/5] remoteproc: Refactor function rproc_elf_find_rsc_table Sjur Brændeland
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Sjur Brændeland @ 2012-12-06 19:35 UTC (permalink / raw)
  To: Ohad Ben-Cohen
  Cc: Linus Walleij, linux-kernel, sjurbren, Sjur Brændeland

From: Sjur Brændeland <sjur@brendeland.net>

This patch-set adds support for shared resource table between
Linux kernel and remote devices. 
Features:
1. dynamically-allocated address of the vrings can be communicated
2. vdev statuses can be communicated
3. virtio config space becomes bi-directional
4. virtio feature negotiation is two-way 

This is done by loading firmware once. First pass parsing of the
resource table will allocate carveouts. Then the firmware
is loaded into device memory. After this the address
of the resource table in shared memory is located. This address
is used in the second pass of parsing of the resource
table. This time the virtio devices are created. When the
virtio device are created the virto feature bits, status,
and configuration-space is shared with the remote device.

NOTE: This change will probably break existing device firmware!
The device memory allocation will change. Virtio Rings are no
longer located at start of device memory. But Ring Address in
resource table is supported.

Thanks,
Sjur

Sjur Brændeland (5):
  remoteproc: Refactor function rproc_elf_find_rsc_table
  remoteproc: Add operation to find resource table in memory
  remoteproc: Add state RPROC_LOADED
  remoteproc: Load firmware to device memory once.
  remoteproc: Support virtio config space.

 drivers/remoteproc/remoteproc_core.c       |  226 ++++++++++++----------------
 drivers/remoteproc/remoteproc_debugfs.c    |    1 +
 drivers/remoteproc/remoteproc_elf_loader.c |   99 ++++++++----
 drivers/remoteproc/remoteproc_internal.h   |   13 ++
 drivers/remoteproc/remoteproc_virtio.c     |   30 +++-
 drivers/remoteproc/ste_modem_rproc.c       |   43 ++++--
 include/linux/remoteproc.h                 |    6 +-
 7 files changed, 232 insertions(+), 186 deletions(-)

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC 1/5] remoteproc: Refactor function rproc_elf_find_rsc_table
  2012-12-06 19:35 [RFC 0/5] remoteproc: Support bi-directional vdev config space Sjur Brændeland
@ 2012-12-06 19:35 ` Sjur Brændeland
  2012-12-06 19:35 ` [RFC 2/5] remoteproc: Add operation to find resource table in memory Sjur Brændeland
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sjur Brændeland @ 2012-12-06 19:35 UTC (permalink / raw)
  To: Ohad Ben-Cohen
  Cc: Linus Walleij, linux-kernel, sjurbren, Sjur Brændeland

Refatcor rproc_elf_find_rsc_table and split out the scanning
for the section header named resource table. This is done to
prepare for loading firmware once when rproc is registered.

Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
---
 drivers/remoteproc/remoteproc_elf_loader.c |   83 +++++++++++++++++-----------
 1 file changed, 51 insertions(+), 32 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index e1f89d6..69832d9 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -208,38 +208,19 @@ rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 	return ret;
 }
 
-/**
- * rproc_elf_find_rsc_table() - find the resource table
- * @rproc: the rproc handle
- * @fw: the ELF firmware image
- * @tablesz: place holder for providing back the table size
- *
- * This function finds the resource table inside the remote processor's
- * firmware. It is used both upon the registration of @rproc (in order
- * to look for and register the supported virito devices), and when the
- * @rproc is booted.
- *
- * Returns the pointer to the resource table if it is found, and write its
- * size into @tablesz. If a valid table isn't found, NULL is returned
- * (and @tablesz isn't set).
- */
-static struct resource_table *
-rproc_elf_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
-							int *tablesz)
+static struct elf32_shdr *
+find_rsc_shdr(struct device *dev, struct elf32_hdr *ehdr)
 {
-	struct elf32_hdr *ehdr;
 	struct elf32_shdr *shdr;
+	int i;
 	const char *name_table;
-	struct device *dev = &rproc->dev;
 	struct resource_table *table = NULL;
-	int i;
-	const u8 *elf_data = fw->data;
+	const u8 *elf_data = (void *)ehdr;
 
-	ehdr = (struct elf32_hdr *)elf_data;
+	/* look for the resource table and handle it */
 	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
 	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
 
-	/* look for the resource table and handle it */
 	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
 		int size = shdr->sh_size;
 		int offset = shdr->sh_offset;
@@ -249,12 +230,6 @@ rproc_elf_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
 
 		table = (struct resource_table *)(elf_data + offset);
 
-		/* make sure we have the entire table */
-		if (offset + size > fw->size) {
-			dev_err(dev, "resource table truncated\n");
-			return NULL;
-		}
-
 		/* make sure table has at least the header */
 		if (sizeof(struct resource_table) > size) {
 			dev_err(dev, "header-less resource table\n");
@@ -280,10 +255,54 @@ rproc_elf_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
 			return NULL;
 		}
 
-		*tablesz = shdr->sh_size;
-		break;
+		return shdr;
+	}
+
+	return NULL;
+}
+
+/**
+ * rproc_elf_find_rsc_table() - find the resource table
+ * @rproc: the rproc handle
+ * @fw: the ELF firmware image
+ * @tablesz: place holder for providing back the table size
+ *
+ * This function finds the resource table inside the remote processor's
+ * firmware. It is used both upon the registration of @rproc (in order
+ * to look for and register the supported virito devices), and when the
+ * @rproc is booted.
+ *
+ * Returns the pointer to the resource table if it is found, and write its
+ * size into @tablesz. If a valid table isn't found, NULL is returned
+ * (and @tablesz isn't set).
+ */
+static struct resource_table *
+rproc_elf_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
+							int *tablesz)
+{
+	struct elf32_hdr *ehdr;
+	struct elf32_shdr *shdr;
+
+	struct device *dev = &rproc->dev;
+	struct resource_table *table = NULL;
+
+	const u8 *elf_data = fw->data;
+
+	ehdr = (struct elf32_hdr *)elf_data;
+
+	shdr = find_rsc_shdr(dev, ehdr);
+	if (!shdr)
+		return NULL;
+
+	/* make sure we have the entire table */
+	if (shdr->sh_offset + shdr->sh_size > fw->size) {
+		dev_err(dev, "resource table truncated\n");
+		return NULL;
 	}
 
+	table = (struct resource_table *)(elf_data + shdr->sh_offset);
+	*tablesz = shdr->sh_size;
+
 	return table;
 }
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 2/5] remoteproc: Add operation to find resource table in memory
  2012-12-06 19:35 [RFC 0/5] remoteproc: Support bi-directional vdev config space Sjur Brændeland
  2012-12-06 19:35 ` [RFC 1/5] remoteproc: Refactor function rproc_elf_find_rsc_table Sjur Brændeland
@ 2012-12-06 19:35 ` Sjur Brændeland
  2012-12-06 19:35 ` [RFC 3/5] remoteproc: Add state RPROC_LOADED Sjur Brændeland
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Sjur Brændeland @ 2012-12-06 19:35 UTC (permalink / raw)
  To: Ohad Ben-Cohen
  Cc: Linus Walleij, linux-kernel, sjurbren, Sjur Brændeland

Add function find_rsc_table_va to firmware ops. This function
returns the location of the resource table in device memory
after the firmware is loaded.

Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
---
 drivers/remoteproc/remoteproc_elf_loader.c |   16 ++++++++++-
 drivers/remoteproc/remoteproc_internal.h   |   13 +++++++++
 drivers/remoteproc/ste_modem_rproc.c       |   43 +++++++++++++++++++---------
 3 files changed, 57 insertions(+), 15 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 69832d9..3f6e315 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -306,9 +306,23 @@ rproc_elf_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
 	return table;
 }
 
+struct resource_table *rproc_elf_get_rsctab_addr(struct rproc *rproc,
+						 const struct firmware *fw)
+{
+	struct elf32_shdr *shdr;
+
+	shdr = find_rsc_shdr(&rproc->dev, (struct elf32_hdr *)fw->data);
+	if (!shdr)
+		return NULL;
+
+	/* Find resource table in loaded segments */
+	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
+}
+
 const struct rproc_fw_ops rproc_elf_fw_ops = {
 	.load = rproc_elf_load_segments,
 	.find_rsc_table = rproc_elf_find_rsc_table,
 	.sanity_check = rproc_elf_sanity_check,
-	.get_boot_addr = rproc_elf_get_boot_addr
+	.get_boot_addr = rproc_elf_get_boot_addr,
+	.get_rsctab_addr = rproc_elf_get_rsctab_addr
 };
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 7bb6648..3a5cb7d 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -32,6 +32,7 @@ struct rproc;
  *			expects to find it
  * @sanity_check:	sanity check the fw image
  * @get_boot_addr:	get boot address to entry point specified in firmware
+ * @get_rsctab_addr:	get resouce table address as specified in firmware
  */
 struct rproc_fw_ops {
 	struct resource_table *(*find_rsc_table) (struct rproc *rproc,
@@ -40,6 +41,8 @@ struct rproc_fw_ops {
 	int (*load)(struct rproc *rproc, const struct firmware *fw);
 	int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
 	u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
+	struct resource_table *(*get_rsctab_addr)(struct rproc *rproc,
+						const struct firmware *fw);
 };
 
 /* from remoteproc_core.c */
@@ -102,6 +105,16 @@ struct resource_table *rproc_find_rsc_table(struct rproc *rproc,
 	return NULL;
 }
 
+static inline
+struct resource_table *rproc_get_rsctab_addr(struct rproc *rproc,
+				const struct firmware *fw)
+{
+	if (rproc->fw_ops->get_rsctab_addr)
+		return rproc->fw_ops->get_rsctab_addr(rproc, fw);
+
+	return NULL;
+}
+
 extern const struct rproc_fw_ops rproc_elf_fw_ops;
 
 #endif /* REMOTEPROC_INTERNAL_H */
diff --git a/drivers/remoteproc/ste_modem_rproc.c b/drivers/remoteproc/ste_modem_rproc.c
index a7743c0..59e99f1 100644
--- a/drivers/remoteproc/ste_modem_rproc.c
+++ b/drivers/remoteproc/ste_modem_rproc.c
@@ -64,26 +64,18 @@ static int sproc_load_segments(struct rproc *rproc, const struct firmware *fw)
 }
 
 /* Find the entry for resource table in the Table of Content */
-static struct ste_toc_entry *sproc_find_rsc_entry(const struct firmware *fw)
+static const struct ste_toc_entry *sproc_find_rsc_entry(const void *data)
 {
 	int i;
-	struct ste_toc *toc;
-
-	if (!fw)
-		return NULL;
-
-	toc = (void *)fw->data;
+	const struct ste_toc *toc;
+	toc = data;
 
 	/* Search the table for the resource table */
 	for (i = 0; i < SPROC_MAX_TOC_ENTRIES &&
 		    toc->table[i].start != 0xffffffff; i++) {
-
 		if (!strncmp(toc->table[i].name, SPROC_RESOURCE_NAME,
-			     sizeof(toc->table[i].name))) {
-			if (toc->table[i].start > fw->size)
-				return NULL;
+			     sizeof(toc->table[i].name)))
 			return &toc->table[i];
-		}
 	}
 
 	return NULL;
@@ -96,9 +88,12 @@ sproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
 {
 	struct sproc *sproc = rproc->priv;
 	struct resource_table *table;
-	struct ste_toc_entry *entry;
+	const struct ste_toc_entry *entry;
 
-	entry = sproc_find_rsc_entry(fw);
+	if (!fw)
+		return NULL;
+
+	entry = sproc_find_rsc_entry(fw->data);
 	if (!entry) {
 		sproc_err(sproc, "resource table not found in fw\n");
 		return NULL;
@@ -149,10 +144,30 @@ sproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
 	return table;
 }
 
+/* Find the resource table inside the remote processor's firmware. */
+static struct resource_table *
+sproc_get_rsctab_addr(struct rproc *rproc, const struct firmware *fw)
+{
+	struct sproc *sproc = rproc->priv;
+	const struct ste_toc_entry *entry;
+
+	if (!fw || !sproc->fw_addr)
+		return NULL;
+
+	entry = sproc_find_rsc_entry(sproc->fw_addr);
+	if (!entry) {
+		sproc_err(sproc, "resource table not found in fw\n");
+		return NULL;
+	}
+
+	return sproc->fw_addr + entry->start;
+}
+
 /* STE modem firmware handler operations */
 const struct rproc_fw_ops sproc_fw_ops = {
 	.load = sproc_load_segments,
 	.find_rsc_table = sproc_find_rsc_table,
+	.get_rsctab_addr = sproc_get_rsctab_addr,
 };
 
 /* Kick the modem with specified notification id */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 3/5] remoteproc: Add state RPROC_LOADED
  2012-12-06 19:35 [RFC 0/5] remoteproc: Support bi-directional vdev config space Sjur Brændeland
  2012-12-06 19:35 ` [RFC 1/5] remoteproc: Refactor function rproc_elf_find_rsc_table Sjur Brændeland
  2012-12-06 19:35 ` [RFC 2/5] remoteproc: Add operation to find resource table in memory Sjur Brændeland
@ 2012-12-06 19:35 ` Sjur Brændeland
  2012-12-06 19:35 ` [RFC 4/5] remoteproc: Load firmware to device memory once Sjur Brændeland
  2012-12-06 19:35 ` [RFC 5/5] remoteproc: Support virtio config space Sjur Brændeland
  4 siblings, 0 replies; 6+ messages in thread
From: Sjur Brændeland @ 2012-12-06 19:35 UTC (permalink / raw)
  To: Ohad Ben-Cohen
  Cc: Linus Walleij, linux-kernel, sjurbren, Sjur Brændeland,
	Sjur Brændeland

Add state RPROC_LOADED. Prepare for the state when the firmware
is loaded, but remote device is not started.

Signed-off-by: Sjur Brændeland <sjur.brandeland@steicsson.com>
---
 drivers/remoteproc/remoteproc_debugfs.c |    1 +
 include/linux/remoteproc.h              |    3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c
index 157a573..a026359 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -68,6 +68,7 @@ static const char * const rproc_state_string[] = {
 	"suspended",
 	"running",
 	"crashed",
+	"loaded",
 	"invalid",
 };
 
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index faf3332..17b8120 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -357,7 +357,8 @@ enum rproc_state {
 	RPROC_SUSPENDED	= 1,
 	RPROC_RUNNING	= 2,
 	RPROC_CRASHED	= 3,
-	RPROC_LAST	= 4,
+	RPROC_LOADED    = 4,
+	RPROC_LAST	= 5,
 };
 
 /**
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 4/5] remoteproc: Load firmware to device memory once.
  2012-12-06 19:35 [RFC 0/5] remoteproc: Support bi-directional vdev config space Sjur Brændeland
                   ` (2 preceding siblings ...)
  2012-12-06 19:35 ` [RFC 3/5] remoteproc: Add state RPROC_LOADED Sjur Brændeland
@ 2012-12-06 19:35 ` Sjur Brændeland
  2012-12-06 19:35 ` [RFC 5/5] remoteproc: Support virtio config space Sjur Brændeland
  4 siblings, 0 replies; 6+ messages in thread
From: Sjur Brændeland @ 2012-12-06 19:35 UTC (permalink / raw)
  To: Ohad Ben-Cohen
  Cc: Linus Walleij, linux-kernel, sjurbren, Sjur Brændeland

Note: This patch changes device memory layout!!
      Virtio Rings are no longer located at start of device memory.
      But Ring Address in resource table is now supported.

Load firmware into device memory before virtio devices are added,
and use resource table located in device memory when crating
virtio devices. This enables dynamically-allocated address and
kick-ids of vrings to be communicated to the remote device.
This also pave the way for implementing bi-directional virtio
config-space and virtio feature negotiation.

Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
---
 drivers/remoteproc/remoteproc_core.c |  222 ++++++++++++++--------------------
 1 file changed, 91 insertions(+), 131 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index dd3bfaf..e407197 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -681,16 +681,36 @@ static rproc_handle_resource_t rproc_handle_rsc[] = {
 	[RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout,
 	[RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem,
 	[RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace,
-	[RSC_VDEV] = NULL, /* VDEVs were handled upon registrarion */
+	[RSC_VDEV] = (rproc_handle_resource_t)rproc_handle_vdev,
 };
 
-/* handle firmware resource entries before booting the remote processor */
+static bool
+is_mem_resource(int rsc_type)
+{
+	/* Handle memory configurations only */
+	switch (rsc_type) {
+	case RSC_CARVEOUT:
+	case RSC_DEVMEM:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline bool
+isnt_mem_resource(int rsc_type)
+{
+	return !is_mem_resource(rsc_type);
+}
+
+/* handle firmware resource entries */
 static int
-rproc_handle_boot_rsc(struct rproc *rproc, struct resource_table *table, int len)
+rproc_handle_resouce(struct rproc *rproc, struct resource_table *table, int len,
+					bool (*rsc_filter)(int type))
 {
 	struct device *dev = &rproc->dev;
-	rproc_handle_resource_t handler;
 	int ret = 0, i;
+	rproc_handle_resource_t handler;
 
 	for (i = 0; i < table->num; i++) {
 		int offset = table->offset[i];
@@ -698,58 +718,27 @@ rproc_handle_boot_rsc(struct rproc *rproc, struct resource_table *table, int len
 		int avail = len - offset - sizeof(*hdr);
 		void *rsc = (void *)hdr + sizeof(*hdr);
 
-		/* make sure table isn't truncated */
-		if (avail < 0) {
-			dev_err(dev, "rsc table is truncated\n");
-			return -EINVAL;
-		}
-
-		dev_dbg(dev, "rsc: type %d\n", hdr->type);
-
 		if (hdr->type >= RSC_LAST) {
 			dev_warn(dev, "unsupported resource %d\n", hdr->type);
 			continue;
 		}
 
-		handler = rproc_handle_rsc[hdr->type];
-		if (!handler)
-			continue;
-
-		ret = handler(rproc, rsc, avail);
-		if (ret)
-			break;
-	}
-
-	return ret;
-}
-
-/* handle firmware resource entries while registering the remote processor */
-static int
-rproc_handle_virtio_rsc(struct rproc *rproc, struct resource_table *table, int len)
-{
-	struct device *dev = &rproc->dev;
-	int ret = 0, i;
-
-	for (i = 0; i < table->num; i++) {
-		int offset = table->offset[i];
-		struct fw_rsc_hdr *hdr = (void *)table + offset;
-		int avail = len - offset - sizeof(*hdr);
-		struct fw_rsc_vdev *vrsc;
-
 		/* make sure table isn't truncated */
 		if (avail < 0) {
 			dev_err(dev, "rsc table is truncated\n");
 			return -EINVAL;
 		}
 
+		if (!rsc_filter(hdr->type))
+			continue;
+
 		dev_dbg(dev, "%s: rsc type %d\n", __func__, hdr->type);
 
-		if (hdr->type != RSC_VDEV)
+		handler = rproc_handle_rsc[hdr->type];
+		if (!handler)
 			continue;
 
-		vrsc = (struct fw_rsc_vdev *)hdr->data;
-
-		ret = rproc_handle_vdev(rproc, vrsc, avail);
+		ret = handler(rproc, rsc, avail);
 		if (ret)
 			break;
 	}
@@ -801,20 +790,40 @@ static void rproc_resource_cleanup(struct rproc *rproc)
 }
 
 /*
- * take a firmware and boot a remote processor with it.
+ * take a firmware parse the resouce table and load it
+ *
+ * Note: this function is called asynchronously upon registration of the
+ * remote processor (so we must wait until it completes before we try
+ * to unregister the device. one other option is just to use kref here,
+ * that might be cleaner).
  */
-static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
+static void rproc_fw_load(const struct firmware *fw, void *context)
 {
+	struct rproc *rproc = context;
 	struct device *dev = &rproc->dev;
-	const char *name = rproc->firmware;
 	struct resource_table *table;
 	int ret, tablesz;
 
-	ret = rproc_fw_sanity_check(rproc, fw);
+	if (!fw)
+		goto nofw;
+
+	if (rproc_fw_sanity_check(rproc, fw) < 0)
+		goto cleanup;
+
+	/* look for the resource table */
+	table = rproc_find_rsc_table(rproc, fw,  &tablesz);
+	if (!table)
+		goto cleanup;
+
+	/* Handle carveout and devmem resouces so we have memory to load into */
+	ret = rproc_handle_resouce(rproc, table, tablesz, is_mem_resource);
 	if (ret)
-		return ret;
+		goto cleanup;
 
-	dev_info(dev, "Booting fw image %s, size %zd\n", name, fw->size);
+	/* load the firmware into memory before handling the virtio devices*/
+	ret = rproc_load_segments(rproc, fw);
+	if (ret)
+		goto cleanup;
 
 	/*
 	 * if enabling an IOMMU isn't relevant for this rproc, this is
@@ -823,80 +832,35 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
 	ret = rproc_enable_iommu(rproc);
 	if (ret) {
 		dev_err(dev, "can't enable iommu: %d\n", ret);
-		return ret;
+		goto cleanup;
 	}
 
-	rproc->bootaddr = rproc_get_boot_addr(rproc, fw);
+	/* Find the new location of the resource table in device memory */
+	table  = rproc_get_rsctab_addr(rproc, fw);
 
-	/* look for the resource table */
-	table = rproc_find_rsc_table(rproc, fw, &tablesz);
-	if (!table) {
-		ret = -EINVAL;
-		goto clean_up;
-	}
-
-	/* handle fw resources which are required to boot rproc */
-	ret = rproc_handle_boot_rsc(rproc, table, tablesz);
-	if (ret) {
-		dev_err(dev, "Failed to process resources: %d\n", ret);
-		goto clean_up;
-	}
-
-	/* 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);
-		goto clean_up;
-	}
-
-	/* power up the remote processor */
-	ret = rproc->ops->start(rproc);
-	if (ret) {
-		dev_err(dev, "can't start rproc %s: %d\n", rproc->name, ret);
-		goto clean_up;
-	}
+	/*
+	 * Handle virtio devices with resource entries in shared memory.
+	 * This enables proper configuration space handling for virtio.
+	 */
+	ret = rproc_handle_resouce(rproc, table, tablesz,
+				   isnt_mem_resource);
+	if (ret)
+		goto disable_iommu;
 
-	rproc->state = RPROC_RUNNING;
+	rproc->bootaddr = rproc_get_boot_addr(rproc, fw);
 
-	dev_info(dev, "remote processor %s is now up\n", rproc->name);
+	rproc->state = RPROC_LOADED;
 
-	return 0;
+	dev_info(dev, "remote processor %s is loaded to memory\n", rproc->name);
+	complete_all(&rproc->firmware_loading_complete);
 
-clean_up:
-	rproc_resource_cleanup(rproc);
+	return;
+disable_iommu:
 	rproc_disable_iommu(rproc);
-	return ret;
-}
-
-/*
- * take a firmware and look for virtio devices to register.
- *
- * Note: this function is called asynchronously upon registration of the
- * remote processor (so we must wait until it completes before we try
- * to unregister the device. one other option is just to use kref here,
- * that might be cleaner).
- */
-static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
-{
-	struct rproc *rproc = context;
-	struct resource_table *table;
-	int ret, tablesz;
-
-	if (rproc_fw_sanity_check(rproc, fw) < 0)
-		goto out;
-
-	/* look for the resource table */
-	table = rproc_find_rsc_table(rproc, fw,  &tablesz);
-	if (!table)
-		goto out;
-
-	/* look for virtio devices and register them */
-	ret = rproc_handle_virtio_rsc(rproc, table, tablesz);
-	if (ret)
-		goto out;
-
-out:
+cleanup:
+	rproc_resource_cleanup(rproc);
 	release_firmware(fw);
+nofw:
 	/* allow rproc_del() contexts, if any, to proceed */
 	complete_all(&rproc->firmware_loading_complete);
 }
@@ -905,6 +869,12 @@ static int rproc_add_virtio_devices(struct rproc *rproc)
 {
 	int ret;
 
+	/* loading a firmware is required */
+	if (!rproc->firmware) {
+		dev_err(&rproc->dev, "%s: no firmware to load\n", __func__);
+		return -EINVAL;
+	}
+
 	/* rproc_del() calls must wait until async loader completes */
 	init_completion(&rproc->firmware_loading_complete);
 
@@ -918,7 +888,7 @@ static int rproc_add_virtio_devices(struct rproc *rproc)
 	 */
 	ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
 				      rproc->firmware, &rproc->dev, GFP_KERNEL,
-				      rproc, rproc_fw_config_virtio);
+				      rproc, rproc_fw_load);
 	if (ret < 0) {
 		dev_err(&rproc->dev, "request_firmware_nowait err: %d\n", ret);
 		complete_all(&rproc->firmware_loading_complete);
@@ -999,13 +969,12 @@ static void rproc_crash_handler_work(struct work_struct *work)
  */
 int rproc_boot(struct rproc *rproc)
 {
-	const struct firmware *firmware_p;
 	struct device *dev;
 	int ret;
 
 	if (!rproc) {
 		pr_err("invalid rproc handle\n");
-		return -EINVAL;
+
 	}
 
 	dev = &rproc->dev;
@@ -1016,13 +985,6 @@ int rproc_boot(struct rproc *rproc)
 		return ret;
 	}
 
-	/* loading a firmware is required */
-	if (!rproc->firmware) {
-		dev_err(dev, "%s: no firmware to load\n", __func__);
-		ret = -EINVAL;
-		goto unlock_mutex;
-	}
-
 	/* prevent underlying implementation from being removed */
 	if (!try_module_get(dev->parent->driver->owner)) {
 		dev_err(dev, "%s: can't get owner\n", __func__);
@@ -1036,18 +998,15 @@ int rproc_boot(struct rproc *rproc)
 		goto unlock_mutex;
 	}
 
-	dev_info(dev, "powering up %s\n", rproc->name);
-
-	/* load firmware */
-	ret = request_firmware(&firmware_p, rproc->firmware, dev);
-	if (ret < 0) {
-		dev_err(dev, "request_firmware failed: %d\n", ret);
+	/* power up the remote processor */
+	ret = rproc->ops->start(rproc);
+	if (ret) {
+		dev_err(dev, "can't start rproc %s: %d\n", rproc->name, ret);
 		goto downref_rproc;
 	}
 
-	ret = rproc_fw_boot(rproc, firmware_p);
-
-	release_firmware(firmware_p);
+	rproc->state = RPROC_RUNNING;
+	dev_info(dev, "powering up %s\n", rproc->name);
 
 downref_rproc:
 	if (ret) {
@@ -1160,6 +1119,7 @@ int rproc_add(struct rproc *rproc)
 	rproc_create_debug_dir(rproc);
 
 	return rproc_add_virtio_devices(rproc);
+
 }
 EXPORT_SYMBOL(rproc_add);
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 5/5] remoteproc: Support virtio config space.
  2012-12-06 19:35 [RFC 0/5] remoteproc: Support bi-directional vdev config space Sjur Brændeland
                   ` (3 preceding siblings ...)
  2012-12-06 19:35 ` [RFC 4/5] remoteproc: Load firmware to device memory once Sjur Brændeland
@ 2012-12-06 19:35 ` Sjur Brændeland
  4 siblings, 0 replies; 6+ messages in thread
From: Sjur Brændeland @ 2012-12-06 19:35 UTC (permalink / raw)
  To: Ohad Ben-Cohen
  Cc: Linus Walleij, linux-kernel, sjurbren, Sjur Brændeland

Add support for bi-directional virtio configuration space,
visibility of device status to remote processor and
device feature-bit negotiation with remote device.

Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
---
 drivers/remoteproc/remoteproc_core.c   |    4 ++--
 drivers/remoteproc/remoteproc_virtio.c |   30 +++++++++++++++++++++++++++---
 include/linux/remoteproc.h             |    3 +--
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index e407197..5f99587 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -362,8 +362,8 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
 			goto free_rvdev;
 	}
 
-	/* remember the device features */
-	rvdev->dfeatures = rsc->dfeatures;
+	/* remember the vring resource address */
+	rvdev->rsc = rsc;
 
 	list_add_tail(&rvdev->node, &rproc->rvdevs);
 
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index e7a4780..9ebc5d9 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -176,16 +176,21 @@ error:
  */
 static u8 rproc_virtio_get_status(struct virtio_device *vdev)
 {
-	return 0;
+	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+	return rvdev->rsc->status;
 }
 
 static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status)
 {
+	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+	rvdev->rsc->status = status;
 	dev_dbg(&vdev->dev, "status: %d\n", status);
 }
 
 static void rproc_virtio_reset(struct virtio_device *vdev)
 {
+	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+	rvdev->rsc->status = 0;
 	dev_dbg(&vdev->dev, "reset !\n");
 }
 
@@ -194,7 +199,7 @@ static u32 rproc_virtio_get_features(struct virtio_device *vdev)
 {
 	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
 
-	return rvdev->dfeatures;
+	return rvdev->rsc->dfeatures;
 }
 
 static void rproc_virtio_finalize_features(struct virtio_device *vdev)
@@ -213,7 +218,23 @@ static void rproc_virtio_finalize_features(struct virtio_device *vdev)
 	 * fixed as part of a small resource table overhaul and then an
 	 * extension of the virtio resource entries.
 	 */
-	rvdev->gfeatures = vdev->features[0];
+	rvdev->rsc->gfeatures = vdev->features[0];
+}
+
+void rproc_virtio_get(struct virtio_device *vdev, unsigned offset,
+							void *buf, unsigned len)
+{
+	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+	void *cfg = &rvdev->rsc->vring[rvdev->rsc->num_of_vrings];
+	memcpy(buf, cfg + offset, len);
+}
+
+void rproc_virtio_set(struct virtio_device *vdev, unsigned offset,
+		      const void *buf, unsigned len)
+{
+	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+	void *cfg = &rvdev->rsc->vring[rvdev->rsc->num_of_vrings];
+	memcpy(cfg + offset, buf, len);
 }
 
 static struct virtio_config_ops rproc_virtio_config_ops = {
@@ -224,6 +245,9 @@ static struct virtio_config_ops rproc_virtio_config_ops = {
 	.reset		= rproc_virtio_reset,
 	.set_status	= rproc_virtio_set_status,
 	.get_status	= rproc_virtio_get_status,
+	.get		= rproc_virtio_get,
+	.set		= rproc_virtio_set,
+
 };
 
 /*
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 17b8120..39ce14e 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -471,8 +471,7 @@ struct rproc_vdev {
 	struct rproc *rproc;
 	struct virtio_device vdev;
 	struct rproc_vring vring[RVDEV_NUM_VRINGS];
-	unsigned long dfeatures;
-	unsigned long gfeatures;
+	struct fw_rsc_vdev *rsc;
 };
 
 struct rproc *rproc_alloc(struct device *dev, const char *name,
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-12-06 19:37 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-06 19:35 [RFC 0/5] remoteproc: Support bi-directional vdev config space Sjur Brændeland
2012-12-06 19:35 ` [RFC 1/5] remoteproc: Refactor function rproc_elf_find_rsc_table Sjur Brændeland
2012-12-06 19:35 ` [RFC 2/5] remoteproc: Add operation to find resource table in memory Sjur Brændeland
2012-12-06 19:35 ` [RFC 3/5] remoteproc: Add state RPROC_LOADED Sjur Brændeland
2012-12-06 19:35 ` [RFC 4/5] remoteproc: Load firmware to device memory once Sjur Brændeland
2012-12-06 19:35 ` [RFC 5/5] remoteproc: Support virtio config space Sjur Brændeland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).