]> Pileus Git - ~andy/linux/blobdiff - drivers/lguest/lguest_device.c
Merge git://git.infradead.org/mtd-2.6
[~andy/linux] / drivers / lguest / lguest_device.c
index df44d962626d327ba26a3b1a2aa83a2bba383390..e082cdac88b4bb283f41ebb611671d583ca78ecb 100644 (file)
@@ -228,7 +228,8 @@ extern void lguest_setup_irq(unsigned int irq);
  * function. */
 static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
                                    unsigned index,
-                                   void (*callback)(struct virtqueue *vq))
+                                   void (*callback)(struct virtqueue *vq),
+                                   const char *name)
 {
        struct lguest_device *ldev = to_lgdev(vdev);
        struct lguest_vq_info *lvq;
@@ -263,7 +264,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
        /* OK, tell virtio_ring.c to set up a virtqueue now we know its size
         * and we've got a pointer to its pages. */
        vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN,
-                                vdev, lvq->pages, lg_notify, callback);
+                                vdev, lvq->pages, lg_notify, callback, name);
        if (!vq) {
                err = -ENOMEM;
                goto unmap;
@@ -312,6 +313,38 @@ static void lg_del_vq(struct virtqueue *vq)
        kfree(lvq);
 }
 
+static void lg_del_vqs(struct virtio_device *vdev)
+{
+       struct virtqueue *vq, *n;
+
+       list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+               lg_del_vq(vq);
+}
+
+static int lg_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+                      struct virtqueue *vqs[],
+                      vq_callback_t *callbacks[],
+                      const char *names[])
+{
+       struct lguest_device *ldev = to_lgdev(vdev);
+       int i;
+
+       /* We must have this many virtqueues. */
+       if (nvqs > ldev->desc->num_vq)
+               return -ENOENT;
+
+       for (i = 0; i < nvqs; ++i) {
+               vqs[i] = lg_find_vq(vdev, i, callbacks[i], names[i]);
+               if (IS_ERR(vqs[i]))
+                       goto error;
+       }
+       return 0;
+
+error:
+       lg_del_vqs(vdev);
+       return PTR_ERR(vqs[i]);
+}
+
 /* The ops structure which hooks everything together. */
 static struct virtio_config_ops lguest_config_ops = {
        .get_features = lg_get_features,
@@ -321,8 +354,8 @@ static struct virtio_config_ops lguest_config_ops = {
        .get_status = lg_get_status,
        .set_status = lg_set_status,
        .reset = lg_reset,
-       .find_vq = lg_find_vq,
-       .del_vq = lg_del_vq,
+       .find_vqs = lg_find_vqs,
+       .del_vqs = lg_del_vqs,
 };
 
 /* The root device for the lguest virtio devices.  This makes them appear as