lkml.org 
[lkml]   [2013]   [Mar]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 1/2] remoteproc: refactor find_vqs to prepare for vringh
Date
From: Erwan YVIN <erwan.yvin@stericsson.com>

Refactor code for creating virtio queues and prepare
for accommodating the new host virtio rings.

This refactoring moves all handing of struct virtqueue
to a separate function __create_new_virtqueue().
A more generic function __rproc_virtio_find_rings()
allocates the virtio rings and ring IDs and calls the
virtqueue specific function when a virtio ring and the
ring IDs are allocated. Some type safety is sacrificed,
in order to make the code more generic.

Signed-off-by: Erwan Yvin <erwan.yvin@stericsson.com>
---
drivers/remoteproc/remoteproc_virtio.c | 138 +++++++++++++++++++-------------
1 file changed, 82 insertions(+), 56 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 9e198e5..ef5ec8a 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -67,50 +67,93 @@ irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid)
}
EXPORT_SYMBOL(rproc_vq_interrupt);

-static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
- unsigned id,
- void (*callback)(struct virtqueue *vq),
- const char *name)
+/*
+ * Allocate and intitialize the virtio rings. We downcast some types here
+ * in order to have common code between virtqueue and vringh.
+ */
+static int __rproc_virtio_find_rings(struct virtio_device *vdev,
+ unsigned nrings, void *rings[],
+ void *callbacks[], const char *name[],
+ void *create(struct rproc_vring *rvring,
+ unsigned int index,
+ void *callbacks,
+ const char *name))
{
struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
struct rproc *rproc = vdev_to_rproc(vdev);
struct device *dev = &rproc->dev;
struct rproc_vring *rvring;
- struct virtqueue *vq;
- void *addr;
- int len, size, ret;
+ /* Use resource entry fw_rsc_vdev.num_of_rings instead when available */
+ size_t max = ARRAY_SIZE(rvdev->vring);
+ const char *rng_name;
+ int rng, id, err;

/* we're temporarily limited to two virtqueues per rvdev */
- if (id >= ARRAY_SIZE(rvdev->vring))
- return ERR_PTR(-EINVAL);
+ if (nrings > max)
+ return -EINVAL;

- if (!name)
- return NULL;
+ /*
+ * We have two different arrays here:
+ * rvdev->vring[] holds the virtio rings in shared memory as
+ * specified by the resource table. It uses "rng" as index.
+ *
+ * The parameter rings[] is used for passing the requested
+ * virtio rings back to the caller. nrings is used by the
+ * caller to specify the number of rings to return.
+ */
+ for (id = rng = 0; id < nrings && rng < max; ++rng) {
+ rvring = &rvdev->vring[rng];
+ if (rvring->vq)
+ continue;
+
+ /* Allocate and initialize the virtio ring */
+ err = rproc_alloc_vring(rvdev, rng);
+ if (err)
+ return err;
+
+ memset(rvring->va, 0, vring_size(rvring->len, rvring->align));
+ rng_name = name ? name[id] : NULL;
+ rings[id] = create(rvring, id, callbacks[id], rng_name);
+ if (IS_ERR(rings[id])) {
+ rproc_free_vring(rvring);
+ return PTR_ERR(rings[id]);
+ }

- ret = rproc_alloc_vring(rvdev, id);
- if (ret)
- return ERR_PTR(ret);
+ dev_dbg(dev, "vring%d: va %p qsz %d notifyid %d\n",
+ rng, rvring->va, rvring->len, rvring->notifyid);
+ ++id;
+ }

- rvring = &rvdev->vring[id];
- addr = rvring->va;
- len = rvring->len;
+ if (id < nrings) {
+ dev_err(dev, "couldn't find the requested rings: %d\n", nrings);
+ return -ENOBUFS;
+ }

- /* zero vring */
- size = vring_size(len, rvring->align);
- memset(addr, 0, size);
+ /* now that the rings are all set, boot the remote processor */
+ return rproc_boot(rproc);
+}

- dev_dbg(dev, "vring%d: va %p qsz %d notifyid %d\n",
- id, addr, len, rvring->notifyid);
+/* Helper function that creates and initializes the virtqueue */
+static void *__create_new_virtqueue(struct rproc_vring *rvring,
+ unsigned int id,
+ void *callback,
+ const char *name)
+{
+ struct virtio_device *vdev = &rvring->rvdev->vdev;
+ struct virtqueue *vq;
+
+ if (!name)
+ return ERR_PTR(-EINVAL);

/*
* Create the new vq, and tell virtio we're not interested in
* the 'weak' smp barriers, since we're talking with a real device.
*/
- vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, addr,
- rproc_virtio_notify, callback, name);
+ vq = vring_new_virtqueue(id, rvring->len, rvring->align, vdev, false,
+ rvring->va, rproc_virtio_notify, callback,
+ name);
if (!vq) {
- dev_err(dev, "vring_new_virtqueue %s failed\n", name);
- rproc_free_vring(rvring);
+ dev_err(&vdev->dev, "vring_new_virtqueue %s failed\n", name);
return ERR_PTR(-ENOMEM);
}

@@ -133,44 +176,27 @@ static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
}
}

-static void rproc_virtio_del_vqs(struct virtio_device *vdev)
+static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+ struct virtqueue *vqs[],
+ vq_callback_t *callbacks[],
+ const char *names[])
{
- struct rproc *rproc = vdev_to_rproc(vdev);
-
- /* power down the remote processor before deleting vqs */
- rproc_shutdown(rproc);
-
- __rproc_virtio_del_vqs(vdev);
+ void *cbs = callbacks, *rings = vqs;
+ int err = __rproc_virtio_find_rings(vdev, nvqs, rings, cbs,
+ names, __create_new_virtqueue);
+ if (err)
+ __rproc_virtio_del_vqs(vdev);
+ return err;
}

-static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
- struct virtqueue *vqs[],
- vq_callback_t *callbacks[],
- const char *names[])
+static void rproc_virtio_del_vqs(struct virtio_device *vdev)
{
struct rproc *rproc = vdev_to_rproc(vdev);
- int i, ret;

- for (i = 0; i < nvqs; ++i) {
- vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
- if (IS_ERR(vqs[i])) {
- ret = PTR_ERR(vqs[i]);
- goto error;
- }
- }
-
- /* now that the vqs are all set, boot the remote processor */
- ret = rproc_boot(rproc);
- if (ret) {
- dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret);
- goto error;
- }
-
- return 0;
+ /* power down the remote processor before deleting vqs */
+ rproc_shutdown(rproc);

-error:
__rproc_virtio_del_vqs(vdev);
- return ret;
}

/*
--
1.7.9.2


\
 
 \ /
  Last update: 2013-03-15 11:22    [W:1.535 / U:0.004 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site