diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-05-01 08:47:44 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-05-01 08:47:44 -0700 |
commit | bf61c8840efe60fd8f91446860b63338fb424158 (patch) | |
tree | 7a71832407a4f0d6346db773343f4c3ae2257b19 /drivers/vhost/vhost.c | |
parent | 5846115b30f3a881e542c8bfde59a699c1c13740 (diff) | |
parent | 0c6a61657da78098472fd0eb71cc01f2387fa1bb (diff) |
Merge branch 'next' into for-linus
Prepare first set of updates for 3.10 merge window.
Diffstat (limited to 'drivers/vhost/vhost.c')
-rw-r--r-- | drivers/vhost/vhost.c | 79 |
1 files changed, 26 insertions, 53 deletions
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 99ac2cb08b43..9759249e6d90 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -26,10 +26,6 @@ #include <linux/kthread.h> #include <linux/cgroup.h> -#include <linux/net.h> -#include <linux/if_packet.h> -#include <linux/if_arp.h> - #include "vhost.h" enum { @@ -81,26 +77,38 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, init_poll_funcptr(&poll->table, vhost_poll_func); poll->mask = mask; poll->dev = dev; + poll->wqh = NULL; vhost_work_init(&poll->work, fn); } /* Start polling a file. We add ourselves to file's wait queue. The caller must * keep a reference to a file until after vhost_poll_stop is called. */ -void vhost_poll_start(struct vhost_poll *poll, struct file *file) +int vhost_poll_start(struct vhost_poll *poll, struct file *file) { unsigned long mask; + int ret = 0; mask = file->f_op->poll(file, &poll->table); if (mask) vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); + if (mask & POLLERR) { + if (poll->wqh) + remove_wait_queue(poll->wqh, &poll->wait); + ret = -EINVAL; + } + + return ret; } /* Stop polling a file. After this function returns, it becomes safe to drop the * file reference. You must also flush afterwards. */ void vhost_poll_stop(struct vhost_poll *poll) { - remove_wait_queue(poll->wqh, &poll->wait); + if (poll->wqh) { + remove_wait_queue(poll->wqh, &poll->wait); + poll->wqh = NULL; + } } static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, @@ -414,28 +422,16 @@ long vhost_dev_reset_owner(struct vhost_dev *dev) return 0; } -/* In case of DMA done not in order in lower device driver for some reason. - * upend_idx is used to track end of used idx, done_idx is used to track head - * of used idx. Once lower device DMA done contiguously, we will signal KVM - * guest used idx. - */ -int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq) +void vhost_dev_stop(struct vhost_dev *dev) { int i; - int j = 0; - - for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) { - if ((vq->heads[i].len == VHOST_DMA_DONE_LEN)) { - vq->heads[i].len = VHOST_DMA_CLEAR_LEN; - vhost_add_used_and_signal(vq->dev, vq, - vq->heads[i].id, 0); - ++j; - } else - break; + + for (i = 0; i < dev->nvqs; ++i) { + if (dev->vqs[i].kick && dev->vqs[i].handle_kick) { + vhost_poll_stop(&dev->vqs[i].poll); + vhost_poll_flush(&dev->vqs[i].poll); + } } - if (j) - vq->done_idx = i; - return j; } /* Caller should have device mutex if and only if locked is set */ @@ -444,17 +440,6 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked) int i; for (i = 0; i < dev->nvqs; ++i) { - if (dev->vqs[i].kick && dev->vqs[i].handle_kick) { - vhost_poll_stop(&dev->vqs[i].poll); - vhost_poll_flush(&dev->vqs[i].poll); - } - /* Wait for all lower device DMAs done. */ - if (dev->vqs[i].ubufs) - vhost_ubuf_put_and_wait(dev->vqs[i].ubufs); - - /* Signal guest as appropriate. */ - vhost_zerocopy_signal_used(&dev->vqs[i]); - if (dev->vqs[i].error_ctx) eventfd_ctx_put(dev->vqs[i].error_ctx); if (dev->vqs[i].error) @@ -634,7 +619,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) return 0; } -static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) +long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) { struct file *eventfp, *filep = NULL; bool pollstart = false, pollstop = false; @@ -819,7 +804,7 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) fput(filep); if (pollstart && vq->handle_kick) - vhost_poll_start(&vq->poll, vq->kick); + r = vhost_poll_start(&vq->poll, vq->kick); mutex_unlock(&vq->mutex); @@ -829,9 +814,8 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) } /* Caller must have device mutex */ -long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg) +long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) { - void __user *argp = (void __user *)arg; struct file *eventfp, *filep = NULL; struct eventfd_ctx *ctx = NULL; u64 p; @@ -902,7 +886,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg) fput(filep); break; default: - r = vhost_set_vring(d, ioctl, argp); + r = -ENOIOCTLCMD; break; } done: @@ -1076,7 +1060,7 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, } _iov = iov + ret; size = reg->memory_size - addr + reg->guest_phys_addr; - _iov->iov_len = min((u64)len, size); + _iov->iov_len = min((u64)len - s, size); _iov->iov_base = (void __user *)(unsigned long) (reg->userspace_addr + addr - reg->guest_phys_addr); s += size; @@ -1599,14 +1583,3 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs) wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount)); kfree(ubufs); } - -void vhost_zerocopy_callback(struct ubuf_info *ubuf) -{ - struct vhost_ubuf_ref *ubufs = ubuf->ctx; - struct vhost_virtqueue *vq = ubufs->vq; - - vhost_poll_queue(&vq->poll); - /* set len = 1 to mark this desc buffers done DMA */ - vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN; - kref_put(&ubufs->kref, vhost_zerocopy_done_signal); -} |