diff options
Diffstat (limited to 'drivers/virtio/virtio_ring.c')
-rw-r--r-- | drivers/virtio/virtio_ring.c | 46 |
1 files changed, 19 insertions, 27 deletions
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index e639584b2dbd..ffd7e7da5d3b 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -93,8 +93,6 @@ struct vring_virtqueue | |||
93 | /* Host publishes avail event idx */ | 93 | /* Host publishes avail event idx */ |
94 | bool event; | 94 | bool event; |
95 | 95 | ||
96 | /* Number of free buffers */ | ||
97 | unsigned int num_free; | ||
98 | /* Head of free buffer list. */ | 96 | /* Head of free buffer list. */ |
99 | unsigned int free_head; | 97 | unsigned int free_head; |
100 | /* Number we've added since last sync. */ | 98 | /* Number we've added since last sync. */ |
@@ -106,9 +104,6 @@ struct vring_virtqueue | |||
106 | /* How to notify other side. FIXME: commonalize hcalls! */ | 104 | /* How to notify other side. FIXME: commonalize hcalls! */ |
107 | void (*notify)(struct virtqueue *vq); | 105 | void (*notify)(struct virtqueue *vq); |
108 | 106 | ||
109 | /* Index of the queue */ | ||
110 | int queue_index; | ||
111 | |||
112 | #ifdef DEBUG | 107 | #ifdef DEBUG |
113 | /* They're supposed to lock for us. */ | 108 | /* They're supposed to lock for us. */ |
114 | unsigned int in_use; | 109 | unsigned int in_use; |
@@ -135,6 +130,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq, | |||
135 | unsigned head; | 130 | unsigned head; |
136 | int i; | 131 | int i; |
137 | 132 | ||
133 | /* | ||
134 | * We require lowmem mappings for the descriptors because | ||
135 | * otherwise virt_to_phys will give us bogus addresses in the | ||
136 | * virtqueue. | ||
137 | */ | ||
138 | gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH); | ||
139 | |||
138 | desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); | 140 | desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); |
139 | if (!desc) | 141 | if (!desc) |
140 | return -ENOMEM; | 142 | return -ENOMEM; |
@@ -160,7 +162,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq, | |||
160 | desc[i-1].next = 0; | 162 | desc[i-1].next = 0; |
161 | 163 | ||
162 | /* We're about to use a buffer */ | 164 | /* We're about to use a buffer */ |
163 | vq->num_free--; | 165 | vq->vq.num_free--; |
164 | 166 | ||
165 | /* Use a single buffer which doesn't continue */ | 167 | /* Use a single buffer which doesn't continue */ |
166 | head = vq->free_head; | 168 | head = vq->free_head; |
@@ -174,13 +176,6 @@ static int vring_add_indirect(struct vring_virtqueue *vq, | |||
174 | return head; | 176 | return head; |
175 | } | 177 | } |
176 | 178 | ||
177 | int virtqueue_get_queue_index(struct virtqueue *_vq) | ||
178 | { | ||
179 | struct vring_virtqueue *vq = to_vvq(_vq); | ||
180 | return vq->queue_index; | ||
181 | } | ||
182 | EXPORT_SYMBOL_GPL(virtqueue_get_queue_index); | ||
183 | |||
184 | /** | 179 | /** |
185 | * virtqueue_add_buf - expose buffer to other end | 180 | * virtqueue_add_buf - expose buffer to other end |
186 | * @vq: the struct virtqueue we're talking about. | 181 | * @vq: the struct virtqueue we're talking about. |
@@ -193,10 +188,7 @@ EXPORT_SYMBOL_GPL(virtqueue_get_queue_index); | |||
193 | * Caller must ensure we don't call this with other virtqueue operations | 188 | * Caller must ensure we don't call this with other virtqueue operations |
194 | * at the same time (except where noted). | 189 | * at the same time (except where noted). |
195 | * | 190 | * |
196 | * Returns remaining capacity of queue or a negative error | 191 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM). |
197 | * (ie. ENOSPC). Note that it only really makes sense to treat all | ||
198 | * positive return values as "available": indirect buffers mean that | ||
199 | * we can put an entire sg[] array inside a single queue entry. | ||
200 | */ | 192 | */ |
201 | int virtqueue_add_buf(struct virtqueue *_vq, | 193 | int virtqueue_add_buf(struct virtqueue *_vq, |
202 | struct scatterlist sg[], | 194 | struct scatterlist sg[], |
@@ -228,7 +220,7 @@ int virtqueue_add_buf(struct virtqueue *_vq, | |||
228 | 220 | ||
229 | /* If the host supports indirect descriptor tables, and we have multiple | 221 | /* If the host supports indirect descriptor tables, and we have multiple |
230 | * buffers, then go indirect. FIXME: tune this threshold */ | 222 | * buffers, then go indirect. FIXME: tune this threshold */ |
231 | if (vq->indirect && (out + in) > 1 && vq->num_free) { | 223 | if (vq->indirect && (out + in) > 1 && vq->vq.num_free) { |
232 | head = vring_add_indirect(vq, sg, out, in, gfp); | 224 | head = vring_add_indirect(vq, sg, out, in, gfp); |
233 | if (likely(head >= 0)) | 225 | if (likely(head >= 0)) |
234 | goto add_head; | 226 | goto add_head; |
@@ -237,9 +229,9 @@ int virtqueue_add_buf(struct virtqueue *_vq, | |||
237 | BUG_ON(out + in > vq->vring.num); | 229 | BUG_ON(out + in > vq->vring.num); |
238 | BUG_ON(out + in == 0); | 230 | BUG_ON(out + in == 0); |
239 | 231 | ||
240 | if (vq->num_free < out + in) { | 232 | if (vq->vq.num_free < out + in) { |
241 | pr_debug("Can't add buf len %i - avail = %i\n", | 233 | pr_debug("Can't add buf len %i - avail = %i\n", |
242 | out + in, vq->num_free); | 234 | out + in, vq->vq.num_free); |
243 | /* FIXME: for historical reasons, we force a notify here if | 235 | /* FIXME: for historical reasons, we force a notify here if |
244 | * there are outgoing parts to the buffer. Presumably the | 236 | * there are outgoing parts to the buffer. Presumably the |
245 | * host should service the ring ASAP. */ | 237 | * host should service the ring ASAP. */ |
@@ -250,7 +242,7 @@ int virtqueue_add_buf(struct virtqueue *_vq, | |||
250 | } | 242 | } |
251 | 243 | ||
252 | /* We're about to use some buffers from the free list. */ | 244 | /* We're about to use some buffers from the free list. */ |
253 | vq->num_free -= out + in; | 245 | vq->vq.num_free -= out + in; |
254 | 246 | ||
255 | head = vq->free_head; | 247 | head = vq->free_head; |
256 | for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) { | 248 | for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) { |
@@ -296,7 +288,7 @@ add_head: | |||
296 | pr_debug("Added buffer head %i to %p\n", head, vq); | 288 | pr_debug("Added buffer head %i to %p\n", head, vq); |
297 | END_USE(vq); | 289 | END_USE(vq); |
298 | 290 | ||
299 | return vq->num_free; | 291 | return 0; |
300 | } | 292 | } |
301 | EXPORT_SYMBOL_GPL(virtqueue_add_buf); | 293 | EXPORT_SYMBOL_GPL(virtqueue_add_buf); |
302 | 294 | ||
@@ -393,13 +385,13 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head) | |||
393 | 385 | ||
394 | while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) { | 386 | while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) { |
395 | i = vq->vring.desc[i].next; | 387 | i = vq->vring.desc[i].next; |
396 | vq->num_free++; | 388 | vq->vq.num_free++; |
397 | } | 389 | } |
398 | 390 | ||
399 | vq->vring.desc[i].next = vq->free_head; | 391 | vq->vring.desc[i].next = vq->free_head; |
400 | vq->free_head = head; | 392 | vq->free_head = head; |
401 | /* Plus final descriptor */ | 393 | /* Plus final descriptor */ |
402 | vq->num_free++; | 394 | vq->vq.num_free++; |
403 | } | 395 | } |
404 | 396 | ||
405 | static inline bool more_used(const struct vring_virtqueue *vq) | 397 | static inline bool more_used(const struct vring_virtqueue *vq) |
@@ -599,7 +591,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq) | |||
599 | return buf; | 591 | return buf; |
600 | } | 592 | } |
601 | /* That should have freed everything. */ | 593 | /* That should have freed everything. */ |
602 | BUG_ON(vq->num_free != vq->vring.num); | 594 | BUG_ON(vq->vq.num_free != vq->vring.num); |
603 | 595 | ||
604 | END_USE(vq); | 596 | END_USE(vq); |
605 | return NULL; | 597 | return NULL; |
@@ -653,12 +645,13 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
653 | vq->vq.callback = callback; | 645 | vq->vq.callback = callback; |
654 | vq->vq.vdev = vdev; | 646 | vq->vq.vdev = vdev; |
655 | vq->vq.name = name; | 647 | vq->vq.name = name; |
648 | vq->vq.num_free = num; | ||
649 | vq->vq.index = index; | ||
656 | vq->notify = notify; | 650 | vq->notify = notify; |
657 | vq->weak_barriers = weak_barriers; | 651 | vq->weak_barriers = weak_barriers; |
658 | vq->broken = false; | 652 | vq->broken = false; |
659 | vq->last_used_idx = 0; | 653 | vq->last_used_idx = 0; |
660 | vq->num_added = 0; | 654 | vq->num_added = 0; |
661 | vq->queue_index = index; | ||
662 | list_add_tail(&vq->vq.list, &vdev->vqs); | 655 | list_add_tail(&vq->vq.list, &vdev->vqs); |
663 | #ifdef DEBUG | 656 | #ifdef DEBUG |
664 | vq->in_use = false; | 657 | vq->in_use = false; |
@@ -673,7 +666,6 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
673 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; | 666 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; |
674 | 667 | ||
675 | /* Put everything in free lists. */ | 668 | /* Put everything in free lists. */ |
676 | vq->num_free = num; | ||
677 | vq->free_head = 0; | 669 | vq->free_head = 0; |
678 | for (i = 0; i < num-1; i++) { | 670 | for (i = 0; i < num-1; i++) { |
679 | vq->vring.desc[i].next = i+1; | 671 | vq->vring.desc[i].next = i+1; |