tools/virtio: add vring_test.
[linux-3.10.git] / tools / virtio / virtio_test.c
index 0740284..814ae80 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <linux/vhost.h>
 #include <linux/virtio.h>
 #include <linux/virtio_ring.h>
 #include "../../drivers/vhost/test.h"
 
+/* Unused */
+void *__kmalloc_fake, *__kfree_ignore_start, *__kfree_ignore_end;
+
 struct vq_info {
        int kick;
        int call;
@@ -92,7 +96,8 @@ static void vq_info_add(struct vdev_info *dev, int num)
        assert(r >= 0);
        memset(info->ring, 0, vring_size(num, 4096));
        vring_init(&info->vring, num, info->ring, 4096);
-       info->vq = vring_new_virtqueue(info->vring.num, 4096, &dev->vdev,
+       info->vq = vring_new_virtqueue(info->idx,
+                                      info->vring.num, 4096, &dev->vdev,
                                       true, info->ring,
                                       vq_notify, vq_callback, "test");
        assert(info->vq);
@@ -144,7 +149,8 @@ static void wait_for_interrupt(struct vdev_info *dev)
                }
 }
 
-static void run_test(struct vdev_info *dev, struct vq_info *vq, int bufs)
+static void run_test(struct vdev_info *dev, struct vq_info *vq,
+                    bool delayed, int bufs)
 {
        struct scatterlist sl;
        long started = 0, completed = 0;
@@ -161,8 +167,9 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq, int bufs)
                        if (started < bufs) {
                                sg_init_one(&sl, dev->buf, dev->buf_size);
                                r = virtqueue_add_buf(vq->vq, &sl, 1, 0,
-                                                     dev->buf + started);
-                               if (likely(r >= 0)) {
+                                                     dev->buf + started,
+                                                     GFP_ATOMIC);
+                               if (likely(r == 0)) {
                                        ++started;
                                        virtqueue_kick(vq->vq);
                                }
@@ -175,15 +182,19 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq, int bufs)
                                r = 0;
                        }
 
-               } while (r >= 0);
+               } while (r == 0);
                if (completed == completed_before)
                        ++spurious;
                assert(completed <= bufs);
                assert(started <= bufs);
                if (completed == bufs)
                        break;
-               if (virtqueue_enable_cb(vq->vq)) {
-                       wait_for_interrupt(dev);
+               if (delayed) {
+                       if (virtqueue_enable_cb_delayed(vq->vq))
+                               wait_for_interrupt(dev);
+               } else {
+                       if (virtqueue_enable_cb(vq->vq))
+                               wait_for_interrupt(dev);
                }
        }
        test = 0;
@@ -215,14 +226,23 @@ const struct option longopts[] = {
                .val = 'i',
        },
        {
+               .name = "delayed-interrupt",
+               .val = 'D',
+       },
+       {
+               .name = "no-delayed-interrupt",
+               .val = 'd',
+       },
+       {
        }
 };
 
-static void help()
+static void help(void)
 {
        fprintf(stderr, "Usage: virtio_test [--help]"
                " [--no-indirect]"
                " [--no-event-idx]"
+               " [--delayed-interrupt]"
                "\n");
 }
 
@@ -232,6 +252,7 @@ int main(int argc, char **argv)
        unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
                (1ULL << VIRTIO_RING_F_EVENT_IDX);
        int o;
+       bool delayed = false;
 
        for (;;) {
                o = getopt_long(argc, argv, optstring, longopts, NULL);
@@ -250,6 +271,9 @@ int main(int argc, char **argv)
                case 'i':
                        features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC);
                        break;
+               case 'D':
+                       delayed = true;
+                       break;
                default:
                        assert(0);
                        break;
@@ -259,6 +283,6 @@ int main(int argc, char **argv)
 done:
        vdev_info_init(&dev, features);
        vq_info_add(&dev, 256);
-       run_test(&dev, &dev.vqs[0], 0x100000);
+       run_test(&dev, &dev.vqs[0], delayed, 0x100000);
        return 0;
 }