diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2011-07-17 23:48:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-18 13:42:32 -0400 |
commit | bab632d69ee48a106e779b60cc01adfe80a72807 (patch) | |
tree | 56b8bd3df85cfee8e425abe18963e5aad015e2fa /drivers/vhost/vhost.h | |
parent | 5c74501f76360ce6f410730b9b5e5976f38e8504 (diff) |
vhost: vhost TX zero-copy support
>From: Shirley Ma <mashirle@us.ibm.com>
This adds experimental zero copy support in vhost-net,
disabled by default. To enable, set
experimental_zcopytx module option to 1.
This patch maintains the outstanding userspace buffers in the
sequence it is delivered to vhost. The outstanding userspace buffers
will be marked as done once the lower device buffers DMA has finished.
This is monitored through last reference of kfree_skb callback. Two
buffer indices are used for this purpose.
The vhost-net device passes the userspace buffers info to lower device
skb through message control. DMA done status check and guest
notification are handled by handle_tx: in the worst case is all buffers
in the vq are in pending/done status, so we need to notify guest to
release DMA done buffers first before we get any new buffers from the
vq.
One known problem is that if the guest stops submitting
buffers, buffers might never get used until some
further action, e.g. device reset. This does not
seem to affect linux guests.
Signed-off-by: Shirley <xma@us.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/vhost/vhost.h')
-rw-r--r-- | drivers/vhost/vhost.h | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 8e03379dd30f..1544b782529b 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h | |||
@@ -13,6 +13,11 @@ | |||
13 | #include <linux/virtio_ring.h> | 13 | #include <linux/virtio_ring.h> |
14 | #include <asm/atomic.h> | 14 | #include <asm/atomic.h> |
15 | 15 | ||
16 | /* This is for zerocopy, used buffer len is set to 1 when lower device DMA | ||
17 | * done */ | ||
18 | #define VHOST_DMA_DONE_LEN 1 | ||
19 | #define VHOST_DMA_CLEAR_LEN 0 | ||
20 | |||
16 | struct vhost_device; | 21 | struct vhost_device; |
17 | 22 | ||
18 | struct vhost_work; | 23 | struct vhost_work; |
@@ -50,6 +55,18 @@ struct vhost_log { | |||
50 | u64 len; | 55 | u64 len; |
51 | }; | 56 | }; |
52 | 57 | ||
58 | struct vhost_virtqueue; | ||
59 | |||
60 | struct vhost_ubuf_ref { | ||
61 | struct kref kref; | ||
62 | wait_queue_head_t wait; | ||
63 | struct vhost_virtqueue *vq; | ||
64 | }; | ||
65 | |||
66 | struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy); | ||
67 | void vhost_ubuf_put(struct vhost_ubuf_ref *); | ||
68 | void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *); | ||
69 | |||
53 | /* The virtqueue structure describes a queue attached to a device. */ | 70 | /* The virtqueue structure describes a queue attached to a device. */ |
54 | struct vhost_virtqueue { | 71 | struct vhost_virtqueue { |
55 | struct vhost_dev *dev; | 72 | struct vhost_dev *dev; |
@@ -114,6 +131,16 @@ struct vhost_virtqueue { | |||
114 | /* Log write descriptors */ | 131 | /* Log write descriptors */ |
115 | void __user *log_base; | 132 | void __user *log_base; |
116 | struct vhost_log *log; | 133 | struct vhost_log *log; |
134 | /* vhost zerocopy support fields below: */ | ||
135 | /* last used idx for outstanding DMA zerocopy buffers */ | ||
136 | int upend_idx; | ||
137 | /* first used idx for DMA done zerocopy buffers */ | ||
138 | int done_idx; | ||
139 | /* an array of userspace buffers info */ | ||
140 | struct ubuf_info *ubuf_info; | ||
141 | /* Reference counting for outstanding ubufs. | ||
142 | * Protected by vq mutex. Writers must also take device mutex. */ | ||
143 | struct vhost_ubuf_ref *ubufs; | ||
117 | }; | 144 | }; |
118 | 145 | ||
119 | struct vhost_dev { | 146 | struct vhost_dev { |
@@ -160,6 +187,8 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *); | |||
160 | 187 | ||
161 | int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, | 188 | int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, |
162 | unsigned int log_num, u64 len); | 189 | unsigned int log_num, u64 len); |
190 | void vhost_zerocopy_callback(void *arg); | ||
191 | int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq); | ||
163 | 192 | ||
164 | #define vq_err(vq, fmt, ...) do { \ | 193 | #define vq_err(vq, fmt, ...) do { \ |
165 | pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \ | 194 | pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \ |
@@ -186,4 +215,6 @@ static inline int vhost_has_feature(struct vhost_dev *dev, int bit) | |||
186 | return acked_features & (1 << bit); | 215 | return acked_features & (1 << bit); |
187 | } | 216 | } |
188 | 217 | ||
218 | void vhost_enable_zcopy(int vq); | ||
219 | |||
189 | #endif | 220 | #endif |