aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/block/virtio_blk.c10
-rw-r--r--drivers/char/virtio_console.c22
-rw-r--r--drivers/virtio/config.c12
-rw-r--r--drivers/virtio/virtio_balloon.c2
-rw-r--r--drivers/virtio/virtio_pci_legacy.c16
-rw-r--r--drivers/virtio/virtio_ring.c16
-rw-r--r--tools/virtio/ringtest/Makefile4
-rw-r--r--tools/virtio/ringtest/main.c20
-rw-r--r--tools/virtio/ringtest/main.h4
-rw-r--r--tools/virtio/ringtest/noring.c6
-rw-r--r--tools/virtio/ringtest/ptr_ring.c22
-rw-r--r--tools/virtio/ringtest/ring.c18
-rw-r--r--tools/virtio/ringtest/virtio_ring_0_9.c64
14 files changed, 96 insertions, 122 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 4012c2f98617..ccae35bb3904 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12783,6 +12783,7 @@ F: include/uapi/linux/virtio_console.h
12783 12783
12784VIRTIO CORE, NET AND BLOCK DRIVERS 12784VIRTIO CORE, NET AND BLOCK DRIVERS
12785M: "Michael S. Tsirkin" <mst@redhat.com> 12785M: "Michael S. Tsirkin" <mst@redhat.com>
12786M: Jason Wang <jasowang@redhat.com>
12786L: virtualization@lists.linux-foundation.org 12787L: virtualization@lists.linux-foundation.org
12787S: Maintained 12788S: Maintained
12788F: Documentation/devicetree/bindings/virtio/ 12789F: Documentation/devicetree/bindings/virtio/
@@ -12813,6 +12814,7 @@ F: include/uapi/linux/virtio_gpu.h
12813 12814
12814VIRTIO HOST (VHOST) 12815VIRTIO HOST (VHOST)
12815M: "Michael S. Tsirkin" <mst@redhat.com> 12816M: "Michael S. Tsirkin" <mst@redhat.com>
12817M: Jason Wang <jasowang@redhat.com>
12816L: kvm@vger.kernel.org 12818L: kvm@vger.kernel.org
12817L: virtualization@lists.linux-foundation.org 12819L: virtualization@lists.linux-foundation.org
12818L: netdev@vger.kernel.org 12820L: netdev@vger.kernel.org
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 2dc5c96c186a..5545a679abd8 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -376,7 +376,7 @@ static void virtblk_config_changed(struct virtio_device *vdev)
376 376
377static int init_vq(struct virtio_blk *vblk) 377static int init_vq(struct virtio_blk *vblk)
378{ 378{
379 int err = 0; 379 int err;
380 int i; 380 int i;
381 vq_callback_t **callbacks; 381 vq_callback_t **callbacks;
382 const char **names; 382 const char **names;
@@ -390,13 +390,13 @@ static int init_vq(struct virtio_blk *vblk)
390 if (err) 390 if (err)
391 num_vqs = 1; 391 num_vqs = 1;
392 392
393 vblk->vqs = kmalloc(sizeof(*vblk->vqs) * num_vqs, GFP_KERNEL); 393 vblk->vqs = kmalloc_array(num_vqs, sizeof(*vblk->vqs), GFP_KERNEL);
394 if (!vblk->vqs) 394 if (!vblk->vqs)
395 return -ENOMEM; 395 return -ENOMEM;
396 396
397 names = kmalloc(sizeof(*names) * num_vqs, GFP_KERNEL); 397 names = kmalloc_array(num_vqs, sizeof(*names), GFP_KERNEL);
398 callbacks = kmalloc(sizeof(*callbacks) * num_vqs, GFP_KERNEL); 398 callbacks = kmalloc_array(num_vqs, sizeof(*callbacks), GFP_KERNEL);
399 vqs = kmalloc(sizeof(*vqs) * num_vqs, GFP_KERNEL); 399 vqs = kmalloc_array(num_vqs, sizeof(*vqs), GFP_KERNEL);
400 if (!names || !callbacks || !vqs) { 400 if (!names || !callbacks || !vqs) {
401 err = -ENOMEM; 401 err = -ENOMEM;
402 goto out; 402 goto out;
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index d433b1db1fdd..5649234b7316 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1539,19 +1539,29 @@ static void remove_port_data(struct port *port)
1539 spin_lock_irq(&port->inbuf_lock); 1539 spin_lock_irq(&port->inbuf_lock);
1540 /* Remove unused data this port might have received. */ 1540 /* Remove unused data this port might have received. */
1541 discard_port_data(port); 1541 discard_port_data(port);
1542 spin_unlock_irq(&port->inbuf_lock);
1542 1543
1543 /* Remove buffers we queued up for the Host to send us data in. */ 1544 /* Remove buffers we queued up for the Host to send us data in. */
1544 while ((buf = virtqueue_detach_unused_buf(port->in_vq))) 1545 do {
1545 free_buf(buf, true); 1546 spin_lock_irq(&port->inbuf_lock);
1546 spin_unlock_irq(&port->inbuf_lock); 1547 buf = virtqueue_detach_unused_buf(port->in_vq);
1548 spin_unlock_irq(&port->inbuf_lock);
1549 if (buf)
1550 free_buf(buf, true);
1551 } while (buf);
1547 1552
1548 spin_lock_irq(&port->outvq_lock); 1553 spin_lock_irq(&port->outvq_lock);
1549 reclaim_consumed_buffers(port); 1554 reclaim_consumed_buffers(port);
1555 spin_unlock_irq(&port->outvq_lock);
1550 1556
1551 /* Free pending buffers from the out-queue. */ 1557 /* Free pending buffers from the out-queue. */
1552 while ((buf = virtqueue_detach_unused_buf(port->out_vq))) 1558 do {
1553 free_buf(buf, true); 1559 spin_lock_irq(&port->outvq_lock);
1554 spin_unlock_irq(&port->outvq_lock); 1560 buf = virtqueue_detach_unused_buf(port->out_vq);
1561 spin_unlock_irq(&port->outvq_lock);
1562 if (buf)
1563 free_buf(buf, true);
1564 } while (buf);
1555} 1565}
1556 1566
1557/* 1567/*
diff --git a/drivers/virtio/config.c b/drivers/virtio/config.c
deleted file mode 100644
index f70bcd2ff98f..000000000000
--- a/drivers/virtio/config.c
+++ /dev/null
@@ -1,12 +0,0 @@
1/* Configuration space parsing helpers for virtio.
2 *
3 * The configuration is [type][len][... len bytes ...] fields.
4 *
5 * Copyright 2007 Rusty Russell, IBM Corporation.
6 * GPL v2 or later.
7 */
8#include <linux/err.h>
9#include <linux/virtio.h>
10#include <linux/virtio_config.h>
11#include <linux/bug.h>
12
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 4e7003db12c4..181793f07852 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -577,6 +577,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
577 577
578 virtio_device_ready(vdev); 578 virtio_device_ready(vdev);
579 579
580 if (towards_target(vb))
581 virtballoon_changed(vdev);
580 return 0; 582 return 0;
581 583
582out_del_vqs: 584out_del_vqs:
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index 8c4e61783441..6d9e5173d5fa 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -212,10 +212,18 @@ int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev)
212 return -ENODEV; 212 return -ENODEV;
213 } 213 }
214 214
215 rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64)); 215 rc = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64));
216 if (rc) 216 if (rc) {
217 rc = dma_set_mask_and_coherent(&pci_dev->dev, 217 rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
218 DMA_BIT_MASK(32)); 218 } else {
219 /*
220 * The virtio ring base address is expressed as a 32-bit PFN,
221 * with a page size of 1 << VIRTIO_PCI_QUEUE_ADDR_SHIFT.
222 */
223 dma_set_coherent_mask(&pci_dev->dev,
224 DMA_BIT_MASK(32 + VIRTIO_PCI_QUEUE_ADDR_SHIFT));
225 }
226
219 if (rc) 227 if (rc)
220 dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n"); 228 dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n");
221 229
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ed9c9eeedfe5..489bfc61cf30 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -167,7 +167,7 @@ static bool vring_use_dma_api(struct virtio_device *vdev)
167 * making all of the arch DMA ops work on the vring device itself 167 * making all of the arch DMA ops work on the vring device itself
168 * is a mess. For now, we use the parent device for DMA ops. 168 * is a mess. For now, we use the parent device for DMA ops.
169 */ 169 */
170static struct device *vring_dma_dev(const struct vring_virtqueue *vq) 170static inline struct device *vring_dma_dev(const struct vring_virtqueue *vq)
171{ 171{
172 return vq->vq.vdev->dev.parent; 172 return vq->vq.vdev->dev.parent;
173} 173}
@@ -732,7 +732,8 @@ void virtqueue_disable_cb(struct virtqueue *_vq)
732 732
733 if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { 733 if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) {
734 vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; 734 vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
735 vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); 735 if (!vq->event)
736 vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
736 } 737 }
737 738
738} 739}
@@ -764,7 +765,8 @@ unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq)
764 * entry. Always do both to keep code simple. */ 765 * entry. Always do both to keep code simple. */
765 if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { 766 if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {
766 vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; 767 vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT;
767 vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); 768 if (!vq->event)
769 vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
768 } 770 }
769 vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx); 771 vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx);
770 END_USE(vq); 772 END_USE(vq);
@@ -832,10 +834,11 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
832 * more to do. */ 834 * more to do. */
833 /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to 835 /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to
834 * either clear the flags bit or point the event index at the next 836 * either clear the flags bit or point the event index at the next
835 * entry. Always do both to keep code simple. */ 837 * entry. Always update the event index to keep code simple. */
836 if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { 838 if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {
837 vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; 839 vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT;
838 vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); 840 if (!vq->event)
841 vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
839 } 842 }
840 /* TODO: tune this threshold */ 843 /* TODO: tune this threshold */
841 bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4; 844 bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4;
@@ -953,7 +956,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
953 /* No callback? Tell other side not to bother us. */ 956 /* No callback? Tell other side not to bother us. */
954 if (!callback) { 957 if (!callback) {
955 vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; 958 vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
956 vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow); 959 if (!vq->event)
960 vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow);
957 } 961 }
958 962
959 /* Put everything in free lists. */ 963 /* Put everything in free lists. */
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile
index 877a8a4721b6..c012edbdb13b 100644
--- a/tools/virtio/ringtest/Makefile
+++ b/tools/virtio/ringtest/Makefile
@@ -3,8 +3,8 @@ all:
3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder ptr_ring noring 3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder ptr_ring noring
4 4
5CFLAGS += -Wall 5CFLAGS += -Wall
6CFLAGS += -pthread -O2 -ggdb 6CFLAGS += -pthread -O2 -ggdb -flto -fwhole-program
7LDFLAGS += -pthread -O2 -ggdb 7LDFLAGS += -pthread -O2 -ggdb -flto -fwhole-program
8 8
9main.o: main.c main.h 9main.o: main.c main.h
10ring.o: ring.c main.h 10ring.o: ring.c main.h
diff --git a/tools/virtio/ringtest/main.c b/tools/virtio/ringtest/main.c
index 147abb452a6c..f31353fac541 100644
--- a/tools/virtio/ringtest/main.c
+++ b/tools/virtio/ringtest/main.c
@@ -96,7 +96,13 @@ void set_affinity(const char *arg)
96 assert(!ret); 96 assert(!ret);
97} 97}
98 98
99static void run_guest(void) 99void poll_used(void)
100{
101 while (used_empty())
102 busy_wait();
103}
104
105static void __attribute__((__flatten__)) run_guest(void)
100{ 106{
101 int completed_before; 107 int completed_before;
102 int completed = 0; 108 int completed = 0;
@@ -141,7 +147,7 @@ static void run_guest(void)
141 assert(completed <= bufs); 147 assert(completed <= bufs);
142 assert(started <= bufs); 148 assert(started <= bufs);
143 if (do_sleep) { 149 if (do_sleep) {
144 if (enable_call()) 150 if (used_empty() && enable_call())
145 wait_for_call(); 151 wait_for_call();
146 } else { 152 } else {
147 poll_used(); 153 poll_used();
@@ -149,7 +155,13 @@ static void run_guest(void)
149 } 155 }
150} 156}
151 157
152static void run_host(void) 158void poll_avail(void)
159{
160 while (avail_empty())
161 busy_wait();
162}
163
164static void __attribute__((__flatten__)) run_host(void)
153{ 165{
154 int completed_before; 166 int completed_before;
155 int completed = 0; 167 int completed = 0;
@@ -160,7 +172,7 @@ static void run_host(void)
160 172
161 for (;;) { 173 for (;;) {
162 if (do_sleep) { 174 if (do_sleep) {
163 if (enable_kick()) 175 if (avail_empty() && enable_kick())
164 wait_for_kick(); 176 wait_for_kick();
165 } else { 177 } else {
166 poll_avail(); 178 poll_avail();
diff --git a/tools/virtio/ringtest/main.h b/tools/virtio/ringtest/main.h
index 16917acb0ade..34e63cc4c572 100644
--- a/tools/virtio/ringtest/main.h
+++ b/tools/virtio/ringtest/main.h
@@ -56,15 +56,15 @@ void alloc_ring(void);
56int add_inbuf(unsigned, void *, void *); 56int add_inbuf(unsigned, void *, void *);
57void *get_buf(unsigned *, void **); 57void *get_buf(unsigned *, void **);
58void disable_call(); 58void disable_call();
59bool used_empty();
59bool enable_call(); 60bool enable_call();
60void kick_available(); 61void kick_available();
61void poll_used();
62/* host side */ 62/* host side */
63void disable_kick(); 63void disable_kick();
64bool avail_empty();
64bool enable_kick(); 65bool enable_kick();
65bool use_buf(unsigned *, void **); 66bool use_buf(unsigned *, void **);
66void call_used(); 67void call_used();
67void poll_avail();
68 68
69/* implemented by main */ 69/* implemented by main */
70extern bool do_sleep; 70extern bool do_sleep;
diff --git a/tools/virtio/ringtest/noring.c b/tools/virtio/ringtest/noring.c
index eda2f4824130..b8d1c1daac7c 100644
--- a/tools/virtio/ringtest/noring.c
+++ b/tools/virtio/ringtest/noring.c
@@ -24,8 +24,9 @@ void *get_buf(unsigned *lenp, void **bufp)
24 return "Buffer"; 24 return "Buffer";
25} 25}
26 26
27void poll_used(void) 27bool used_empty()
28{ 28{
29 return false;
29} 30}
30 31
31void disable_call() 32void disable_call()
@@ -54,8 +55,9 @@ bool enable_kick()
54 assert(0); 55 assert(0);
55} 56}
56 57
57void poll_avail(void) 58bool avail_empty()
58{ 59{
60 return false;
59} 61}
60 62
61bool use_buf(unsigned *lenp, void **bufp) 63bool use_buf(unsigned *lenp, void **bufp)
diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c
index bd2ad1d3b7a9..635b07b4fdd3 100644
--- a/tools/virtio/ringtest/ptr_ring.c
+++ b/tools/virtio/ringtest/ptr_ring.c
@@ -133,18 +133,9 @@ void *get_buf(unsigned *lenp, void **bufp)
133 return datap; 133 return datap;
134} 134}
135 135
136void poll_used(void) 136bool used_empty()
137{ 137{
138 void *b; 138 return (tailcnt == headcnt || __ptr_ring_full(&array));
139
140 do {
141 if (tailcnt == headcnt || __ptr_ring_full(&array)) {
142 b = NULL;
143 barrier();
144 } else {
145 b = "Buffer\n";
146 }
147 } while (!b);
148} 139}
149 140
150void disable_call() 141void disable_call()
@@ -173,14 +164,9 @@ bool enable_kick()
173 assert(0); 164 assert(0);
174} 165}
175 166
176void poll_avail(void) 167bool avail_empty()
177{ 168{
178 void *b; 169 return !__ptr_ring_peek(&array);
179
180 do {
181 barrier();
182 b = __ptr_ring_peek(&array);
183 } while (!b);
184} 170}
185 171
186bool use_buf(unsigned *lenp, void **bufp) 172bool use_buf(unsigned *lenp, void **bufp)
diff --git a/tools/virtio/ringtest/ring.c b/tools/virtio/ringtest/ring.c
index c25c8d248b6b..747c5dd47be8 100644
--- a/tools/virtio/ringtest/ring.c
+++ b/tools/virtio/ringtest/ring.c
@@ -163,12 +163,11 @@ void *get_buf(unsigned *lenp, void **bufp)
163 return datap; 163 return datap;
164} 164}
165 165
166void poll_used(void) 166bool used_empty()
167{ 167{
168 unsigned head = (ring_size - 1) & guest.last_used_idx; 168 unsigned head = (ring_size - 1) & guest.last_used_idx;
169 169
170 while (ring[head].flags & DESC_HW) 170 return (ring[head].flags & DESC_HW);
171 busy_wait();
172} 171}
173 172
174void disable_call() 173void disable_call()
@@ -180,13 +179,11 @@ void disable_call()
180 179
181bool enable_call() 180bool enable_call()
182{ 181{
183 unsigned head = (ring_size - 1) & guest.last_used_idx;
184
185 event->call_index = guest.last_used_idx; 182 event->call_index = guest.last_used_idx;
186 /* Flush call index write */ 183 /* Flush call index write */
187 /* Barrier D (for pairing) */ 184 /* Barrier D (for pairing) */
188 smp_mb(); 185 smp_mb();
189 return ring[head].flags & DESC_HW; 186 return used_empty();
190} 187}
191 188
192void kick_available(void) 189void kick_available(void)
@@ -213,20 +210,17 @@ void disable_kick()
213 210
214bool enable_kick() 211bool enable_kick()
215{ 212{
216 unsigned head = (ring_size - 1) & host.used_idx;
217
218 event->kick_index = host.used_idx; 213 event->kick_index = host.used_idx;
219 /* Barrier C (for pairing) */ 214 /* Barrier C (for pairing) */
220 smp_mb(); 215 smp_mb();
221 return !(ring[head].flags & DESC_HW); 216 return avail_empty();
222} 217}
223 218
224void poll_avail(void) 219bool avail_empty()
225{ 220{
226 unsigned head = (ring_size - 1) & host.used_idx; 221 unsigned head = (ring_size - 1) & host.used_idx;
227 222
228 while (!(ring[head].flags & DESC_HW)) 223 return !(ring[head].flags & DESC_HW);
229 busy_wait();
230} 224}
231 225
232bool use_buf(unsigned *lenp, void **bufp) 226bool use_buf(unsigned *lenp, void **bufp)
diff --git a/tools/virtio/ringtest/virtio_ring_0_9.c b/tools/virtio/ringtest/virtio_ring_0_9.c
index 761866212aac..bbc3043b2fb1 100644
--- a/tools/virtio/ringtest/virtio_ring_0_9.c
+++ b/tools/virtio/ringtest/virtio_ring_0_9.c
@@ -194,24 +194,16 @@ void *get_buf(unsigned *lenp, void **bufp)
194 return datap; 194 return datap;
195} 195}
196 196
197void poll_used(void) 197bool used_empty()
198{ 198{
199 unsigned short last_used_idx = guest.last_used_idx;
199#ifdef RING_POLL 200#ifdef RING_POLL
200 unsigned head = (ring_size - 1) & guest.last_used_idx; 201 unsigned short head = last_used_idx & (ring_size - 1);
202 unsigned index = ring.used->ring[head].id;
201 203
202 for (;;) { 204 return (index ^ last_used_idx ^ 0x8000) & ~(ring_size - 1);
203 unsigned index = ring.used->ring[head].id;
204
205 if ((index ^ guest.last_used_idx ^ 0x8000) & ~(ring_size - 1))
206 busy_wait();
207 else
208 break;
209 }
210#else 205#else
211 unsigned head = guest.last_used_idx; 206 return ring.used->idx == last_used_idx;
212
213 while (ring.used->idx == head)
214 busy_wait();
215#endif 207#endif
216} 208}
217 209
@@ -224,22 +216,11 @@ void disable_call()
224 216
225bool enable_call() 217bool enable_call()
226{ 218{
227 unsigned short last_used_idx; 219 vring_used_event(&ring) = guest.last_used_idx;
228
229 vring_used_event(&ring) = (last_used_idx = guest.last_used_idx);
230 /* Flush call index write */ 220 /* Flush call index write */
231 /* Barrier D (for pairing) */ 221 /* Barrier D (for pairing) */
232 smp_mb(); 222 smp_mb();
233#ifdef RING_POLL 223 return used_empty();
234 {
235 unsigned short head = last_used_idx & (ring_size - 1);
236 unsigned index = ring.used->ring[head].id;
237
238 return (index ^ last_used_idx ^ 0x8000) & ~(ring_size - 1);
239 }
240#else
241 return ring.used->idx == last_used_idx;
242#endif
243} 224}
244 225
245void kick_available(void) 226void kick_available(void)
@@ -266,36 +247,21 @@ void disable_kick()
266 247
267bool enable_kick() 248bool enable_kick()
268{ 249{
269 unsigned head = host.used_idx; 250 vring_avail_event(&ring) = host.used_idx;
270
271 vring_avail_event(&ring) = head;
272 /* Barrier C (for pairing) */ 251 /* Barrier C (for pairing) */
273 smp_mb(); 252 smp_mb();
274#ifdef RING_POLL 253 return avail_empty();
275 {
276 unsigned index = ring.avail->ring[head & (ring_size - 1)];
277
278 return (index ^ head ^ 0x8000) & ~(ring_size - 1);
279 }
280#else
281 return head == ring.avail->idx;
282#endif
283} 254}
284 255
285void poll_avail(void) 256bool avail_empty()
286{ 257{
287 unsigned head = host.used_idx; 258 unsigned head = host.used_idx;
288#ifdef RING_POLL 259#ifdef RING_POLL
289 for (;;) { 260 unsigned index = ring.avail->ring[head & (ring_size - 1)];
290 unsigned index = ring.avail->ring[head & (ring_size - 1)]; 261
291 if ((index ^ head ^ 0x8000) & ~(ring_size - 1)) 262 return ((index ^ head ^ 0x8000) & ~(ring_size - 1));
292 busy_wait();
293 else
294 break;
295 }
296#else 263#else
297 while (ring.avail->idx == head) 264 return head == ring.avail->idx;
298 busy_wait();
299#endif 265#endif
300} 266}
301 267