]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'virtio/virtio-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Wed, 14 Nov 2012 02:14:10 +0000 (13:14 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 14 Nov 2012 02:14:10 +0000 (13:14 +1100)
15 files changed:
drivers/char/virtio_console.c
drivers/lguest/core.c
drivers/net/virtio_net.c
drivers/rpmsg/virtio_rpmsg_bus.c
drivers/scsi/virtio_scsi.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci.c
drivers/virtio/virtio_ring.c
include/linux/virtio.h
include/linux/virtio_scsi.h
mm/highmem.c
net/9p/trans_virtio.c
tools/lguest/lguest.c
tools/virtio/virtio_test.c

index 8ab9c3d4bf134c23bda43adafc688485a1c9e764..4ad8aca39b2ae86eda32d9804224321bad29a7f2 100644 (file)
@@ -349,7 +349,7 @@ static struct port_buffer *alloc_buf(size_t buf_size)
        buf = kmalloc(sizeof(*buf), GFP_KERNEL);
        if (!buf)
                goto fail;
-       buf->buf = kzalloc(buf_size, GFP_KERNEL);
+       buf->buf = kmalloc(buf_size, GFP_KERNEL);
        if (!buf->buf)
                goto free_buf;
        buf->len = 0;
@@ -459,7 +459,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
        vq = portdev->c_ovq;
 
        sg_init_one(sg, &cpkt, sizeof(cpkt));
-       if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) {
+       if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) {
                virtqueue_kick(vq);
                while (!virtqueue_get_buf(vq, &len))
                        cpu_relax();
@@ -524,7 +524,7 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
                              struct buffer_token *tok, bool nonblock)
 {
        struct virtqueue *out_vq;
-       ssize_t ret;
+       int err;
        unsigned long flags;
        unsigned int len;
 
@@ -534,17 +534,17 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
 
        reclaim_consumed_buffers(port);
 
-       ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
+       err = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
 
        /* Tell Host to go! */
        virtqueue_kick(out_vq);
 
-       if (ret < 0) {
+       if (err) {
                in_count = 0;
                goto done;
        }
 
-       if (ret == 0)
+       if (out_vq->num_free == 0)
                port->outvq_full = true;
 
        if (nonblock)
@@ -879,6 +879,8 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
        if (likely(ret > 0))
                ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true);
 
+       if (unlikely(ret <= 0))
+               kfree(sgl.sg);
        return ret;
 }
 
index b5fdcb78a75b8620e61288c5717f450b2c588592..a5ebc0083d87ad02e03f23ed8be7e66267c5d97e 100644 (file)
@@ -225,7 +225,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
                         * eventfd (ie. the appropriate virtqueue thread)?
                         */
                        if (!send_notify_to_eventfd(cpu)) {
-                               /* OK, we tell the main Laucher. */
+                               /* OK, we tell the main Launcher. */
                                if (put_user(cpu->pending_notify, user))
                                        return -EFAULT;
                                return sizeof(cpu->pending_notify);
index 26c502e4b871f4168b021739a9497f9dd8b6f640..97f4ff8cdd5dada88c26faa4699681323d5910ca 100644 (file)
@@ -95,7 +95,6 @@ struct skb_vnet_hdr {
                struct virtio_net_hdr hdr;
                struct virtio_net_hdr_mrg_rxbuf mhdr;
        };
-       unsigned int num_sg;
 };
 
 struct padded_vnet_hdr {
@@ -468,10 +467,11 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
                        err = add_recvbuf_small(vi, gfp);
 
                oom = err == -ENOMEM;
-               if (err < 0)
+               if (err)
                        break;
                ++vi->num;
-       } while (err > 0);
+       } while (vi->rvq->num_free);
+
        if (unlikely(vi->num > vi->max))
                vi->max = vi->num;
        virtqueue_kick(vi->rvq);
@@ -553,10 +553,10 @@ again:
        return received;
 }
 
-static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
+static void free_old_xmit_skbs(struct virtnet_info *vi)
 {
        struct sk_buff *skb;
-       unsigned int len, tot_sgs = 0;
+       unsigned int len;
        struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 
        while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
@@ -567,16 +567,15 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
                stats->tx_packets++;
                u64_stats_update_end(&stats->tx_syncp);
 
-               tot_sgs += skb_vnet_hdr(skb)->num_sg;
                dev_kfree_skb_any(skb);
        }
-       return tot_sgs;
 }
 
 static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
 {
        struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
        const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
+       unsigned num_sg;
 
        pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
 
@@ -615,35 +614,28 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
        else
                sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr);
 
-       hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
-       return virtqueue_add_buf(vi->svq, vi->tx_sg, hdr->num_sg,
+       num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
+       return virtqueue_add_buf(vi->svq, vi->tx_sg, num_sg,
                                 0, skb, GFP_ATOMIC);
 }
 
 static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
-       int capacity;
+       int err;
 
        /* Free up any pending old buffers before queueing new ones. */
        free_old_xmit_skbs(vi);
 
        /* Try to transmit */
-       capacity = xmit_skb(vi, skb);
-
-       /* This can happen with OOM and indirect buffers. */
-       if (unlikely(capacity < 0)) {
-               if (likely(capacity == -ENOMEM)) {
-                       if (net_ratelimit())
-                               dev_warn(&dev->dev,
-                                        "TX queue failure: out of memory\n");
-               } else {
-                       dev->stats.tx_fifo_errors++;
-                       if (net_ratelimit())
-                               dev_warn(&dev->dev,
-                                        "Unexpected TX queue failure: %d\n",
-                                        capacity);
-               }
+       err = xmit_skb(vi, skb);
+
+       /* This should not happen! */
+       if (unlikely(err)) {
+               dev->stats.tx_fifo_errors++;
+               if (net_ratelimit())
+                       dev_warn(&dev->dev,
+                                "Unexpected TX queue failure: %d\n", err);
                dev->stats.tx_dropped++;
                kfree_skb(skb);
                return NETDEV_TX_OK;
@@ -656,12 +648,12 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Apparently nice girls don't return TX_BUSY; stop the queue
         * before it gets out of hand.  Naturally, this wastes entries. */
-       if (capacity < 2+MAX_SKB_FRAGS) {
+       if (vi->svq->num_free < 2+MAX_SKB_FRAGS) {
                netif_stop_queue(dev);
                if (unlikely(!virtqueue_enable_cb_delayed(vi->svq))) {
                        /* More just got used, free them then recheck. */
-                       capacity += free_old_xmit_skbs(vi);
-                       if (capacity >= 2+MAX_SKB_FRAGS) {
+                       free_old_xmit_skbs(vi);
+                       if (vi->svq->num_free >= 2+MAX_SKB_FRAGS) {
                                netif_start_queue(dev);
                                virtqueue_disable_cb(vi->svq);
                        }
index 1859f71372e24912203dca245f3d60c71c80a35d..027096fe6a124dc9edde55da90517c5daac38747 100644 (file)
@@ -764,7 +764,7 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
 
        /* add message to the remote processor's virtqueue */
        err = virtqueue_add_buf(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL);
-       if (err < 0) {
+       if (err) {
                /*
                 * need to reclaim the buffer here, otherwise it's lost
                 * (memory won't leak, but rpmsg won't use it again for TX).
@@ -776,8 +776,6 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
 
        /* tell the remote processor it has a pending message to read */
        virtqueue_kick(vrp->svq);
-
-       err = 0;
 out:
        mutex_unlock(&vrp->tx_lock);
        return err;
@@ -980,7 +978,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
 
                err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr,
                                                                GFP_KERNEL);
-               WARN_ON(err < 0); /* sanity check; this can't really happen */
+               WARN_ON(err); /* sanity check; this can't really happen */
        }
 
        /* suppress "tx-complete" interrupts */
index 595af1ae4421937ba1b157d79b84d081866e8355..d5f9f4516d887f0e31cc94a2a35057c84651ddea 100644 (file)
@@ -215,7 +215,7 @@ static void virtscsi_ctrl_done(struct virtqueue *vq)
 static int virtscsi_kick_event(struct virtio_scsi *vscsi,
                               struct virtio_scsi_event_node *event_node)
 {
-       int ret;
+       int err;
        struct scatterlist sg;
        unsigned long flags;
 
@@ -223,13 +223,14 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi,
 
        spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
 
-       ret = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node, GFP_ATOMIC);
-       if (ret >= 0)
+       err = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node,
+                               GFP_ATOMIC);
+       if (!err)
                virtqueue_kick(vscsi->event_vq.vq);
 
        spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
 
-       return ret;
+       return err;
 }
 
 static int virtscsi_kick_event_all(struct virtio_scsi *vscsi)
@@ -410,22 +411,23 @@ static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt,
 {
        unsigned int out_num, in_num;
        unsigned long flags;
-       int ret;
+       int err;
+       bool needs_kick = false;
 
        spin_lock_irqsave(&tgt->tgt_lock, flags);
        virtscsi_map_cmd(tgt, cmd, &out_num, &in_num, req_size, resp_size);
 
        spin_lock(&vq->vq_lock);
-       ret = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
+       err = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
        spin_unlock(&tgt->tgt_lock);
-       if (ret >= 0)
-               ret = virtqueue_kick_prepare(vq->vq);
+       if (!err)
+               needs_kick = virtqueue_kick_prepare(vq->vq);
 
        spin_unlock_irqrestore(&vq->vq_lock, flags);
 
-       if (ret > 0)
+       if (needs_kick)
                virtqueue_notify(vq->vq);
-       return ret;
+       return err;
 }
 
 static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
@@ -467,7 +469,7 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
 
        if (virtscsi_kick_cmd(tgt, &vscsi->req_vq, cmd,
                              sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
-                             GFP_ATOMIC) >= 0)
+                             GFP_ATOMIC) == 0)
                ret = 0;
 
 out:
index 0908e604433303d605b9a7cd6ab4ffe36087f96f..586395cca5fe129b4e2ecd4706e395ee567f5adb 100644 (file)
@@ -130,10 +130,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
                struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY |
                                        __GFP_NOMEMALLOC | __GFP_NOWARN);
                if (!page) {
-                       if (printk_ratelimit())
-                               dev_printk(KERN_INFO, &vb->vdev->dev,
-                                          "Out of puff! Can't get %zu pages\n",
-                                          num);
+                       dev_info_ratelimited(&vb->vdev->dev,
+                                            "Out of puff! Can't get %zu pages\n",
+                                            num);
                        /* Sleep for at least 1/5 of a second before retry. */
                        msleep(200);
                        break;
index 6b1b7e1849396d8183c6ae326b0ab1dc4c66ead2..5a0e1d32ce133a5c7305b966cddcfdc701edbe53 100644 (file)
@@ -225,7 +225,7 @@ static void vm_notify(struct virtqueue *vq)
 
        /* We write the queue's selector into the notification register to
         * signal the other end */
-       writel(virtqueue_get_queue_index(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
+       writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY);
 }
 
 /* Notify all virtqueues on an interrupt. */
@@ -266,7 +266,7 @@ static void vm_del_vq(struct virtqueue *vq)
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev);
        struct virtio_mmio_vq_info *info = vq->priv;
        unsigned long flags, size;
-       unsigned int index = virtqueue_get_queue_index(vq);
+       unsigned int index = vq->index;
 
        spin_lock_irqsave(&vm_dev->lock, flags);
        list_del(&info->node);
index c33aea36598aa2b6133147756956439f65a84f7f..e3ecc94591ad29defa2b572d54eab60a223cb3aa 100644 (file)
@@ -203,8 +203,7 @@ static void vp_notify(struct virtqueue *vq)
 
        /* we write the queue's selector into the notification register to
         * signal the other end */
-       iowrite16(virtqueue_get_queue_index(vq),
-                 vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
+       iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
 }
 
 /* Handle a configuration change: Tell driver if it wants to know. */
@@ -479,8 +478,7 @@ static void vp_del_vq(struct virtqueue *vq)
        list_del(&info->node);
        spin_unlock_irqrestore(&vp_dev->lock, flags);
 
-       iowrite16(virtqueue_get_queue_index(vq),
-               vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
+       iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
 
        if (vp_dev->msix_enabled) {
                iowrite16(VIRTIO_MSI_NO_VECTOR,
@@ -830,16 +828,4 @@ static struct pci_driver virtio_pci_driver = {
 #endif
 };
 
-static int __init virtio_pci_init(void)
-{
-       return pci_register_driver(&virtio_pci_driver);
-}
-
-module_init(virtio_pci_init);
-
-static void __exit virtio_pci_exit(void)
-{
-       pci_unregister_driver(&virtio_pci_driver);
-}
-
-module_exit(virtio_pci_exit);
+module_pci_driver(virtio_pci_driver);
index e639584b2dbd1c24e36017db1978009b73f8e33f..ffd7e7da5d3b1753316f633fbbb38935e5dc27de 100644 (file)
@@ -93,8 +93,6 @@ struct vring_virtqueue
        /* Host publishes avail event idx */
        bool event;
 
-       /* Number of free buffers */
-       unsigned int num_free;
        /* Head of free buffer list. */
        unsigned int free_head;
        /* Number we've added since last sync. */
@@ -106,9 +104,6 @@ struct vring_virtqueue
        /* How to notify other side. FIXME: commonalize hcalls! */
        void (*notify)(struct virtqueue *vq);
 
-       /* Index of the queue */
-       int queue_index;
-
 #ifdef DEBUG
        /* They're supposed to lock for us. */
        unsigned int in_use;
@@ -135,6 +130,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
        unsigned head;
        int i;
 
+       /*
+        * We require lowmem mappings for the descriptors because
+        * otherwise virt_to_phys will give us bogus addresses in the
+        * virtqueue.
+        */
+       gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH);
+
        desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
        if (!desc)
                return -ENOMEM;
@@ -160,7 +162,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
        desc[i-1].next = 0;
 
        /* We're about to use a buffer */
-       vq->num_free--;
+       vq->vq.num_free--;
 
        /* Use a single buffer which doesn't continue */
        head = vq->free_head;
@@ -174,13 +176,6 @@ static int vring_add_indirect(struct vring_virtqueue *vq,
        return head;
 }
 
-int virtqueue_get_queue_index(struct virtqueue *_vq)
-{
-       struct vring_virtqueue *vq = to_vvq(_vq);
-       return vq->queue_index;
-}
-EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
-
 /**
  * virtqueue_add_buf - expose buffer to other end
  * @vq: the struct virtqueue we're talking about.
@@ -193,10 +188,7 @@ EXPORT_SYMBOL_GPL(virtqueue_get_queue_index);
  * Caller must ensure we don't call this with other virtqueue operations
  * at the same time (except where noted).
  *
- * Returns remaining capacity of queue or a negative error
- * (ie. ENOSPC).  Note that it only really makes sense to treat all
- * positive return values as "available": indirect buffers mean that
- * we can put an entire sg[] array inside a single queue entry.
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM).
  */
 int virtqueue_add_buf(struct virtqueue *_vq,
                      struct scatterlist sg[],
@@ -228,7 +220,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
 
        /* If the host supports indirect descriptor tables, and we have multiple
         * buffers, then go indirect. FIXME: tune this threshold */
-       if (vq->indirect && (out + in) > 1 && vq->num_free) {
+       if (vq->indirect && (out + in) > 1 && vq->vq.num_free) {
                head = vring_add_indirect(vq, sg, out, in, gfp);
                if (likely(head >= 0))
                        goto add_head;
@@ -237,9 +229,9 @@ int virtqueue_add_buf(struct virtqueue *_vq,
        BUG_ON(out + in > vq->vring.num);
        BUG_ON(out + in == 0);
 
-       if (vq->num_free < out + in) {
+       if (vq->vq.num_free < out + in) {
                pr_debug("Can't add buf len %i - avail = %i\n",
-                        out + in, vq->num_free);
+                        out + in, vq->vq.num_free);
                /* FIXME: for historical reasons, we force a notify here if
                 * there are outgoing parts to the buffer.  Presumably the
                 * host should service the ring ASAP. */
@@ -250,7 +242,7 @@ int virtqueue_add_buf(struct virtqueue *_vq,
        }
 
        /* We're about to use some buffers from the free list. */
-       vq->num_free -= out + in;
+       vq->vq.num_free -= out + in;
 
        head = vq->free_head;
        for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
@@ -296,7 +288,7 @@ add_head:
        pr_debug("Added buffer head %i to %p\n", head, vq);
        END_USE(vq);
 
-       return vq->num_free;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(virtqueue_add_buf);
 
@@ -393,13 +385,13 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
 
        while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) {
                i = vq->vring.desc[i].next;
-               vq->num_free++;
+               vq->vq.num_free++;
        }
 
        vq->vring.desc[i].next = vq->free_head;
        vq->free_head = head;
        /* Plus final descriptor */
-       vq->num_free++;
+       vq->vq.num_free++;
 }
 
 static inline bool more_used(const struct vring_virtqueue *vq)
@@ -599,7 +591,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
                return buf;
        }
        /* That should have freed everything. */
-       BUG_ON(vq->num_free != vq->vring.num);
+       BUG_ON(vq->vq.num_free != vq->vring.num);
 
        END_USE(vq);
        return NULL;
@@ -653,12 +645,13 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
        vq->vq.callback = callback;
        vq->vq.vdev = vdev;
        vq->vq.name = name;
+       vq->vq.num_free = num;
+       vq->vq.index = index;
        vq->notify = notify;
        vq->weak_barriers = weak_barriers;
        vq->broken = false;
        vq->last_used_idx = 0;
        vq->num_added = 0;
-       vq->queue_index = index;
        list_add_tail(&vq->vq.list, &vdev->vqs);
 #ifdef DEBUG
        vq->in_use = false;
@@ -673,7 +666,6 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
                vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
 
        /* Put everything in free lists. */
-       vq->num_free = num;
        vq->free_head = 0;
        for (i = 0; i < num-1; i++) {
                vq->vring.desc[i].next = i+1;
index 533b1157f22e675cf858c40d6e4b4a5ed17ee5ec..25fa1a63fc2e1b4af3a41273fd4c9c7e79e8ecd2 100644 (file)
  * @name: the name of this virtqueue (mainly for debugging)
  * @vdev: the virtio device this queue was created for.
  * @priv: a pointer for the virtqueue implementation to use.
+ * @index: the zero-based ordinal number for this queue.
+ * @num_free: number of elements we expect to be able to fit.
+ *
+ * A note on @num_free: with indirect buffers, each buffer needs one
+ * element in the queue, otherwise a buffer will need one element per
+ * sg element.
  */
 struct virtqueue {
        struct list_head list;
        void (*callback)(struct virtqueue *vq);
        const char *name;
        struct virtio_device *vdev;
+       unsigned int index;
+       unsigned int num_free;
        void *priv;
 };
 
@@ -50,8 +58,6 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
 unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
 
-int virtqueue_get_queue_index(struct virtqueue *vq);
-
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
index d6b4440387b70a336d9da8af35e1224a20af04ba..4195b97a3def6a84574519da4a6fe37b7e954406 100644 (file)
@@ -1,7 +1,31 @@
+/*
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
 #ifndef _LINUX_VIRTIO_SCSI_H
 #define _LINUX_VIRTIO_SCSI_H
-/* This header is BSD licensed so anyone can use the definitions to implement
- * compatible drivers/servers. */
 
 #define VIRTIO_SCSI_CDB_SIZE   32
 #define VIRTIO_SCSI_SENSE_SIZE 96
index d517cd16a6eb91e8df18f3cbd79cd67621b27d3f..2a07f97dabf11bceb05e69be4143d6cc06a7bd12 100644 (file)
@@ -105,6 +105,7 @@ struct page *kmap_to_page(void *vaddr)
 
        return virt_to_page(addr);
 }
+EXPORT_SYMBOL(kmap_to_page);
 
 static void flush_all_zero_pkmaps(void)
 {
index 35b8911b1c8e5de48c5e6bab97e411ca55302ece..fd05c81cb348fe04a0701aad70d672a7f17f238e 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/inet.h>
 #include <linux/idr.h>
 #include <linux/file.h>
+#include <linux/highmem.h>
 #include <linux/slab.h>
 #include <net/9p/9p.h>
 #include <linux/parser.h>
@@ -325,7 +326,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
                int count = nr_pages;
                while (nr_pages) {
                        s = rest_of_page(data);
-                       pages[index++] = virt_to_page(data);
+                       pages[index++] = kmap_to_page(data);
                        data += s;
                        nr_pages--;
                }
index fd2f9221b24120e25d32c2c8d8b4849d8d24569a..07a03452c227e3804a04661f26e7ca8cc73bec35 100644 (file)
@@ -179,29 +179,6 @@ static struct termios orig_term;
 #define wmb() __asm__ __volatile__("" : : : "memory")
 #define mb() __asm__ __volatile__("" : : : "memory")
 
-/*
- * Convert an iovec element to the given type.
- *
- * This is a fairly ugly trick: we need to know the size of the type and
- * alignment requirement to check the pointer is kosher.  It's also nice to
- * have the name of the type in case we report failure.
- *
- * Typing those three things all the time is cumbersome and error prone, so we
- * have a macro which sets them all up and passes to the real function.
- */
-#define convert(iov, type) \
-       ((type *)_convert((iov), sizeof(type), __alignof__(type), #type))
-
-static void *_convert(struct iovec *iov, size_t size, size_t align,
-                     const char *name)
-{
-       if (iov->iov_len != size)
-               errx(1, "Bad iovec size %zu for %s", iov->iov_len, name);
-       if ((unsigned long)iov->iov_base % align != 0)
-               errx(1, "Bad alignment %p for %s", iov->iov_base, name);
-       return iov->iov_base;
-}
-
 /* Wrapper for the last available index.  Makes it easier to change. */
 #define lg_last_avail(vq)      ((vq)->last_avail_idx)
 
@@ -228,7 +205,8 @@ static bool iov_empty(const struct iovec iov[], unsigned int num_iov)
 }
 
 /* Take len bytes from the front of this iovec. */
-static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
+static void iov_consume(struct iovec iov[], unsigned num_iov,
+                       void *dest, unsigned len)
 {
        unsigned int i;
 
@@ -236,11 +214,16 @@ static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
                unsigned int used;
 
                used = iov[i].iov_len < len ? iov[i].iov_len : len;
+               if (dest) {
+                       memcpy(dest, iov[i].iov_base, used);
+                       dest += used;
+               }
                iov[i].iov_base += used;
                iov[i].iov_len -= used;
                len -= used;
        }
-       assert(len == 0);
+       if (len != 0)
+               errx(1, "iovec too short!");
 }
 
 /* The device virtqueue descriptors are followed by feature bitmasks. */
@@ -864,7 +847,7 @@ static void console_output(struct virtqueue *vq)
                        warn("Write to stdout gave %i (%d)", len, errno);
                        break;
                }
-               iov_consume(iov, out, len);
+               iov_consume(iov, out, NULL, len);
        }
 
        /*
@@ -1591,9 +1574,9 @@ static void blk_request(struct virtqueue *vq)
 {
        struct vblk_info *vblk = vq->dev->priv;
        unsigned int head, out_num, in_num, wlen;
-       int ret;
+       int ret, i;
        u8 *in;
-       struct virtio_blk_outhdr *out;
+       struct virtio_blk_outhdr out;
        struct iovec iov[vq->vring.num];
        off64_t off;
 
@@ -1603,32 +1586,36 @@ static void blk_request(struct virtqueue *vq)
         */
        head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
 
-       /*
-        * Every block request should contain at least one output buffer
-        * (detailing the location on disk and the type of request) and one
-        * input buffer (to hold the result).
-        */
-       if (out_num == 0 || in_num == 0)
-               errx(1, "Bad virtblk cmd %u out=%u in=%u",
-                    head, out_num, in_num);
+       /* Copy the output header from the front of the iov (adjusts iov) */
+       iov_consume(iov, out_num, &out, sizeof(out));
+
+       /* Find and trim end of iov input array, for our status byte. */
+       in = NULL;
+       for (i = out_num + in_num - 1; i >= out_num; i--) {
+               if (iov[i].iov_len > 0) {
+                       in = iov[i].iov_base + iov[i].iov_len - 1;
+                       iov[i].iov_len--;
+                       break;
+               }
+       }
+       if (!in)
+               errx(1, "Bad virtblk cmd with no room for status");
 
-       out = convert(&iov[0], struct virtio_blk_outhdr);
-       in = convert(&iov[out_num+in_num-1], u8);
        /*
         * For historical reasons, block operations are expressed in 512 byte
         * "sectors".
         */
-       off = out->sector * 512;
+       off = out.sector * 512;
 
        /*
         * In general the virtio block driver is allowed to try SCSI commands.
         * It'd be nice if we supported eject, for example, but we don't.
         */
-       if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
+       if (out.type & VIRTIO_BLK_T_SCSI_CMD) {
                fprintf(stderr, "Scsi commands unsupported\n");
                *in = VIRTIO_BLK_S_UNSUPP;
                wlen = sizeof(*in);
-       } else if (out->type & VIRTIO_BLK_T_OUT) {
+       } else if (out.type & VIRTIO_BLK_T_OUT) {
                /*
                 * Write
                 *
@@ -1636,10 +1623,10 @@ static void blk_request(struct virtqueue *vq)
                 * if they try to write past end.
                 */
                if (lseek64(vblk->fd, off, SEEK_SET) != off)
-                       err(1, "Bad seek to sector %llu", out->sector);
+                       err(1, "Bad seek to sector %llu", out.sector);
 
-               ret = writev(vblk->fd, iov+1, out_num-1);
-               verbose("WRITE to sector %llu: %i\n", out->sector, ret);
+               ret = writev(vblk->fd, iov, out_num);
+               verbose("WRITE to sector %llu: %i\n", out.sector, ret);
 
                /*
                 * Grr... Now we know how long the descriptor they sent was, we
@@ -1655,7 +1642,7 @@ static void blk_request(struct virtqueue *vq)
 
                wlen = sizeof(*in);
                *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
-       } else if (out->type & VIRTIO_BLK_T_FLUSH) {
+       } else if (out.type & VIRTIO_BLK_T_FLUSH) {
                /* Flush */
                ret = fdatasync(vblk->fd);
                verbose("FLUSH fdatasync: %i\n", ret);
@@ -1669,10 +1656,9 @@ static void blk_request(struct virtqueue *vq)
                 * if they try to read past end.
                 */
                if (lseek64(vblk->fd, off, SEEK_SET) != off)
-                       err(1, "Bad seek to sector %llu", out->sector);
+                       err(1, "Bad seek to sector %llu", out.sector);
 
-               ret = readv(vblk->fd, iov+1, in_num-1);
-               verbose("READ from sector %llu: %i\n", out->sector, ret);
+               ret = readv(vblk->fd, iov + out_num, in_num);
                if (ret >= 0) {
                        wlen = sizeof(*in) + ret;
                        *in = VIRTIO_BLK_S_OK;
@@ -1758,7 +1744,7 @@ static void rng_input(struct virtqueue *vq)
                len = readv(rng_info->rfd, iov, in_num);
                if (len <= 0)
                        err(1, "Read from /dev/random gave %i", len);
-               iov_consume(iov, in_num, len);
+               iov_consume(iov, in_num, NULL, len);
                totlen += len;
        }
 
index e626fa553c5ae1b2db0f044fe0c987e13e5af9ec..a11028acf219915cfc81785e4b79a1555b400a44 100644 (file)
@@ -164,7 +164,7 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
                                r = virtqueue_add_buf(vq->vq, &sl, 1, 0,
                                                      dev->buf + started,
                                                      GFP_ATOMIC);
-                               if (likely(r >= 0)) {
+                               if (likely(r == 0)) {
                                        ++started;
                                        virtqueue_kick(vq->vq);
                                }
@@ -177,7 +177,7 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
                                r = 0;
                        }
 
-               } while (r >= 0);
+               } while (r == 0);
                if (completed == completed_before)
                        ++spurious;
                assert(completed <= bufs);