lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 15 Mar 2013 10:29:55 +0100
From:	Erwan Yvin <erwan.yvin@...ricsson.com>
To:	Ohad Ben-Cohen <ohad@...ery.com>,
	Rusty Russel <rusty@...corp.com.au>, Ido Yariv <ido@...ery.com>
Cc:	Sjur Braendeland <sjur.brandeland@...ricsson.com>,
	Linus Walleij <linus.walleij@...ricsson.com>,
	virtualization <virtualization@...ts.linux-foundation.org>,
	lkml <linux-kernel@...r.kernel.org>,
	Erwan YVIN <erwan.yvin@...ricsson.com>
Subject: [PATCH 1/2] remoteproc: refactor find_vqs to prepare for vringh

From: Erwan YVIN <erwan.yvin@...ricsson.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@...ricsson.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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ