summaryrefslogtreecommitdiff
path: root/drivers/remoteproc/remoteproc_virtio.c
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2012-05-17 11:23:59 (GMT)
committerOhad Ben-Cohen <ohad@wizery.com>2012-07-04 10:27:04 (GMT)
commit6db20ea8d85064175c7ef594c433c6c2e6bbab83 (patch)
tree6087ffde8501059bdfd578758fb05c53aba3d620 /drivers/remoteproc/remoteproc_virtio.c
parent485802a6c524e62b5924849dd727ddbb1497cc71 (diff)
downloadlinux-fsl-qoriq-6db20ea8d85064175c7ef594c433c6c2e6bbab83.tar.xz
remoteproc: allocate vrings on demand, free when not needed
Dynamically allocate the vrings' DMA when the remote processor is about to be powered on (i.e. when ->find_vqs() is invoked), and release them as soon as it is powered off (i.e. when ->del_vqs() is invoked). The obvious and immediate benefit is better memory utilization, since memory for the vrings is now only allocated when the relevant remote processor is used. Additionally, this approach also makes recovery of a (crashing) remote processor easier: one just needs to remove the relevant vdevs, and the entire vrings cleanup takes place automagically. Tested-by: Fernando Guzman Lugo <fernando.lugo@ti.com> Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Diffstat (limited to 'drivers/remoteproc/remoteproc_virtio.c')
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index ecf6121..26a7144 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -77,14 +77,17 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
struct rproc_vring *rvring;
struct virtqueue *vq;
void *addr;
- int len, size;
+ int len, size, ret;
/* we're temporarily limited to two virtqueues per rvdev */
if (id >= ARRAY_SIZE(rvdev->vring))
return ERR_PTR(-EINVAL);
- rvring = &rvdev->vring[id];
+ ret = rproc_alloc_vring(rvdev, id);
+ if (ret)
+ return ERR_PTR(ret);
+ rvring = &rvdev->vring[id];
addr = rvring->va;
len = rvring->len;
@@ -103,6 +106,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
rproc_virtio_notify, callback, name);
if (!vq) {
dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name);
+ rproc_free_vring(rvring);
return ERR_PTR(-ENOMEM);
}
@@ -125,6 +129,7 @@ static void rproc_virtio_del_vqs(struct virtio_device *vdev)
rvring = vq->priv;
rvring->vq = NULL;
vring_del_virtqueue(vq);
+ rproc_free_vring(rvring);
}
}
@@ -228,8 +233,12 @@ static struct virtio_config_ops rproc_virtio_config_ops = {
static void rproc_vdev_release(struct device *dev)
{
struct virtio_device *vdev = dev_to_virtio(dev);
+ struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
struct rproc *rproc = vdev_to_rproc(vdev);
+ list_del(&rvdev->node);
+ kfree(rvdev);
+
kref_put(&rproc->refcount, rproc_release);
}