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; |
