diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-07 13:50:07 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-07 13:50:07 -0500 |
commit | 62ea1ec5e17fe36e2c728bc534f9f78b216dfe83 (patch) | |
tree | 7d398881db98f2c2b28f45ba595688db6bbe602b | |
parent | f41683a204ea61568f0fd0804d47c19561f2ee39 (diff) | |
parent | f277ec42f38f406ed073569b24b04f1c291fec0f (diff) |
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull virtio fixes from Michael Tsirkin:
"This includes some fixes and cleanups in virtio and vhost code.
Most notably, shadowing the index fixes the excessive cacheline
bouncing observed on AMD platforms"
* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
virtio_ring: shadow available ring flags & index
virtio: Do not drop __GFP_HIGH in alloc_indirect
vhost: replace % with & on data path
tools/virtio: fix byteswap logic
tools/virtio: move list macro stubs
virtio: fix memory leak of virtio ida cache layers
vhost: relax log address alignment
virtio-net: Stop doing DMA from the stack
-rw-r--r-- | drivers/net/virtio_net.c | 34 | ||||
-rw-r--r-- | drivers/vhost/vhost.c | 8 | ||||
-rw-r--r-- | drivers/virtio/virtio.c | 1 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 48 | ||||
-rw-r--r-- | tools/virtio/linux/kernel.h | 6 | ||||
-rw-r--r-- | tools/virtio/linux/virtio.h | 6 | ||||
-rw-r--r-- | tools/virtio/linux/virtio_config.h | 20 |
7 files changed, 78 insertions, 45 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d8838dedb7a4..f94ab786088f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -140,6 +140,12 @@ struct virtnet_info { | |||
140 | 140 | ||
141 | /* CPU hot plug notifier */ | 141 | /* CPU hot plug notifier */ |
142 | struct notifier_block nb; | 142 | struct notifier_block nb; |
143 | |||
144 | /* Control VQ buffers: protected by the rtnl lock */ | ||
145 | struct virtio_net_ctrl_hdr ctrl_hdr; | ||
146 | virtio_net_ctrl_ack ctrl_status; | ||
147 | u8 ctrl_promisc; | ||
148 | u8 ctrl_allmulti; | ||
143 | }; | 149 | }; |
144 | 150 | ||
145 | struct padded_vnet_hdr { | 151 | struct padded_vnet_hdr { |
@@ -976,31 +982,30 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | |||
976 | struct scatterlist *out) | 982 | struct scatterlist *out) |
977 | { | 983 | { |
978 | struct scatterlist *sgs[4], hdr, stat; | 984 | struct scatterlist *sgs[4], hdr, stat; |
979 | struct virtio_net_ctrl_hdr ctrl; | ||
980 | virtio_net_ctrl_ack status = ~0; | ||
981 | unsigned out_num = 0, tmp; | 985 | unsigned out_num = 0, tmp; |
982 | 986 | ||
983 | /* Caller should know better */ | 987 | /* Caller should know better */ |
984 | BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)); | 988 | BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)); |
985 | 989 | ||
986 | ctrl.class = class; | 990 | vi->ctrl_status = ~0; |
987 | ctrl.cmd = cmd; | 991 | vi->ctrl_hdr.class = class; |
992 | vi->ctrl_hdr.cmd = cmd; | ||
988 | /* Add header */ | 993 | /* Add header */ |
989 | sg_init_one(&hdr, &ctrl, sizeof(ctrl)); | 994 | sg_init_one(&hdr, &vi->ctrl_hdr, sizeof(vi->ctrl_hdr)); |
990 | sgs[out_num++] = &hdr; | 995 | sgs[out_num++] = &hdr; |
991 | 996 | ||
992 | if (out) | 997 | if (out) |
993 | sgs[out_num++] = out; | 998 | sgs[out_num++] = out; |
994 | 999 | ||
995 | /* Add return status. */ | 1000 | /* Add return status. */ |
996 | sg_init_one(&stat, &status, sizeof(status)); | 1001 | sg_init_one(&stat, &vi->ctrl_status, sizeof(vi->ctrl_status)); |
997 | sgs[out_num] = &stat; | 1002 | sgs[out_num] = &stat; |
998 | 1003 | ||
999 | BUG_ON(out_num + 1 > ARRAY_SIZE(sgs)); | 1004 | BUG_ON(out_num + 1 > ARRAY_SIZE(sgs)); |
1000 | virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC); | 1005 | virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC); |
1001 | 1006 | ||
1002 | if (unlikely(!virtqueue_kick(vi->cvq))) | 1007 | if (unlikely(!virtqueue_kick(vi->cvq))) |
1003 | return status == VIRTIO_NET_OK; | 1008 | return vi->ctrl_status == VIRTIO_NET_OK; |
1004 | 1009 | ||
1005 | /* Spin for a response, the kick causes an ioport write, trapping | 1010 | /* Spin for a response, the kick causes an ioport write, trapping |
1006 | * into the hypervisor, so the request should be handled immediately. | 1011 | * into the hypervisor, so the request should be handled immediately. |
@@ -1009,7 +1014,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | |||
1009 | !virtqueue_is_broken(vi->cvq)) | 1014 | !virtqueue_is_broken(vi->cvq)) |
1010 | cpu_relax(); | 1015 | cpu_relax(); |
1011 | 1016 | ||
1012 | return status == VIRTIO_NET_OK; | 1017 | return vi->ctrl_status == VIRTIO_NET_OK; |
1013 | } | 1018 | } |
1014 | 1019 | ||
1015 | static int virtnet_set_mac_address(struct net_device *dev, void *p) | 1020 | static int virtnet_set_mac_address(struct net_device *dev, void *p) |
@@ -1151,7 +1156,6 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
1151 | { | 1156 | { |
1152 | struct virtnet_info *vi = netdev_priv(dev); | 1157 | struct virtnet_info *vi = netdev_priv(dev); |
1153 | struct scatterlist sg[2]; | 1158 | struct scatterlist sg[2]; |
1154 | u8 promisc, allmulti; | ||
1155 | struct virtio_net_ctrl_mac *mac_data; | 1159 | struct virtio_net_ctrl_mac *mac_data; |
1156 | struct netdev_hw_addr *ha; | 1160 | struct netdev_hw_addr *ha; |
1157 | int uc_count; | 1161 | int uc_count; |
@@ -1163,22 +1167,22 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
1163 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) | 1167 | if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) |
1164 | return; | 1168 | return; |
1165 | 1169 | ||
1166 | promisc = ((dev->flags & IFF_PROMISC) != 0); | 1170 | vi->ctrl_promisc = ((dev->flags & IFF_PROMISC) != 0); |
1167 | allmulti = ((dev->flags & IFF_ALLMULTI) != 0); | 1171 | vi->ctrl_allmulti = ((dev->flags & IFF_ALLMULTI) != 0); |
1168 | 1172 | ||
1169 | sg_init_one(sg, &promisc, sizeof(promisc)); | 1173 | sg_init_one(sg, &vi->ctrl_promisc, sizeof(vi->ctrl_promisc)); |
1170 | 1174 | ||
1171 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, | 1175 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, |
1172 | VIRTIO_NET_CTRL_RX_PROMISC, sg)) | 1176 | VIRTIO_NET_CTRL_RX_PROMISC, sg)) |
1173 | dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", | 1177 | dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", |
1174 | promisc ? "en" : "dis"); | 1178 | vi->ctrl_promisc ? "en" : "dis"); |
1175 | 1179 | ||
1176 | sg_init_one(sg, &allmulti, sizeof(allmulti)); | 1180 | sg_init_one(sg, &vi->ctrl_allmulti, sizeof(vi->ctrl_allmulti)); |
1177 | 1181 | ||
1178 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, | 1182 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, |
1179 | VIRTIO_NET_CTRL_RX_ALLMULTI, sg)) | 1183 | VIRTIO_NET_CTRL_RX_ALLMULTI, sg)) |
1180 | dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", | 1184 | dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", |
1181 | allmulti ? "en" : "dis"); | 1185 | vi->ctrl_allmulti ? "en" : "dis"); |
1182 | 1186 | ||
1183 | uc_count = netdev_uc_count(dev); | 1187 | uc_count = netdev_uc_count(dev); |
1184 | mc_count = netdev_mc_count(dev); | 1188 | mc_count = netdev_mc_count(dev); |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index eec2f11809ff..ad2146a9ab2d 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -819,7 +819,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) | |||
819 | BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE); | 819 | BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE); |
820 | if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) || | 820 | if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) || |
821 | (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) || | 821 | (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) || |
822 | (a.log_guest_addr & (sizeof(u64) - 1))) { | 822 | (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1))) { |
823 | r = -EINVAL; | 823 | r = -EINVAL; |
824 | break; | 824 | break; |
825 | } | 825 | } |
@@ -1369,7 +1369,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq, | |||
1369 | /* Grab the next descriptor number they're advertising, and increment | 1369 | /* Grab the next descriptor number they're advertising, and increment |
1370 | * the index we've seen. */ | 1370 | * the index we've seen. */ |
1371 | if (unlikely(__get_user(ring_head, | 1371 | if (unlikely(__get_user(ring_head, |
1372 | &vq->avail->ring[last_avail_idx % vq->num]))) { | 1372 | &vq->avail->ring[last_avail_idx & (vq->num - 1)]))) { |
1373 | vq_err(vq, "Failed to read head: idx %d address %p\n", | 1373 | vq_err(vq, "Failed to read head: idx %d address %p\n", |
1374 | last_avail_idx, | 1374 | last_avail_idx, |
1375 | &vq->avail->ring[last_avail_idx % vq->num]); | 1375 | &vq->avail->ring[last_avail_idx % vq->num]); |
@@ -1489,7 +1489,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, | |||
1489 | u16 old, new; | 1489 | u16 old, new; |
1490 | int start; | 1490 | int start; |
1491 | 1491 | ||
1492 | start = vq->last_used_idx % vq->num; | 1492 | start = vq->last_used_idx & (vq->num - 1); |
1493 | used = vq->used->ring + start; | 1493 | used = vq->used->ring + start; |
1494 | if (count == 1) { | 1494 | if (count == 1) { |
1495 | if (__put_user(heads[0].id, &used->id)) { | 1495 | if (__put_user(heads[0].id, &used->id)) { |
@@ -1531,7 +1531,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads, | |||
1531 | { | 1531 | { |
1532 | int start, n, r; | 1532 | int start, n, r; |
1533 | 1533 | ||
1534 | start = vq->last_used_idx % vq->num; | 1534 | start = vq->last_used_idx & (vq->num - 1); |
1535 | n = vq->num - start; | 1535 | n = vq->num - start; |
1536 | if (n < count) { | 1536 | if (n < count) { |
1537 | r = __vhost_add_used_n(vq, heads, n); | 1537 | r = __vhost_add_used_n(vq, heads, n); |
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index b1877d73fa56..7062bb0975a5 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
@@ -412,6 +412,7 @@ static int virtio_init(void) | |||
412 | static void __exit virtio_exit(void) | 412 | static void __exit virtio_exit(void) |
413 | { | 413 | { |
414 | bus_unregister(&virtio_bus); | 414 | bus_unregister(&virtio_bus); |
415 | ida_destroy(&virtio_index_ida); | ||
415 | } | 416 | } |
416 | core_initcall(virtio_init); | 417 | core_initcall(virtio_init); |
417 | module_exit(virtio_exit); | 418 | module_exit(virtio_exit); |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 096b857e7b75..ee663c458b20 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -80,6 +80,12 @@ struct vring_virtqueue { | |||
80 | /* Last used index we've seen. */ | 80 | /* Last used index we've seen. */ |
81 | u16 last_used_idx; | 81 | u16 last_used_idx; |
82 | 82 | ||
83 | /* Last written value to avail->flags */ | ||
84 | u16 avail_flags_shadow; | ||
85 | |||
86 | /* Last written value to avail->idx in guest byte order */ | ||
87 | u16 avail_idx_shadow; | ||
88 | |||
83 | /* How to notify other side. FIXME: commonalize hcalls! */ | 89 | /* How to notify other side. FIXME: commonalize hcalls! */ |
84 | bool (*notify)(struct virtqueue *vq); | 90 | bool (*notify)(struct virtqueue *vq); |
85 | 91 | ||
@@ -109,7 +115,7 @@ static struct vring_desc *alloc_indirect(struct virtqueue *_vq, | |||
109 | * otherwise virt_to_phys will give us bogus addresses in the | 115 | * otherwise virt_to_phys will give us bogus addresses in the |
110 | * virtqueue. | 116 | * virtqueue. |
111 | */ | 117 | */ |
112 | gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH); | 118 | gfp &= ~__GFP_HIGHMEM; |
113 | 119 | ||
114 | desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp); | 120 | desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp); |
115 | if (!desc) | 121 | if (!desc) |
@@ -235,13 +241,14 @@ static inline int virtqueue_add(struct virtqueue *_vq, | |||
235 | 241 | ||
236 | /* Put entry in available array (but don't update avail->idx until they | 242 | /* Put entry in available array (but don't update avail->idx until they |
237 | * do sync). */ | 243 | * do sync). */ |
238 | avail = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) & (vq->vring.num - 1); | 244 | avail = vq->avail_idx_shadow & (vq->vring.num - 1); |
239 | vq->vring.avail->ring[avail] = cpu_to_virtio16(_vq->vdev, head); | 245 | vq->vring.avail->ring[avail] = cpu_to_virtio16(_vq->vdev, head); |
240 | 246 | ||
241 | /* Descriptors and available array need to be set before we expose the | 247 | /* Descriptors and available array need to be set before we expose the |
242 | * new available array entries. */ | 248 | * new available array entries. */ |
243 | virtio_wmb(vq->weak_barriers); | 249 | virtio_wmb(vq->weak_barriers); |
244 | vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) + 1); | 250 | vq->avail_idx_shadow++; |
251 | vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow); | ||
245 | vq->num_added++; | 252 | vq->num_added++; |
246 | 253 | ||
247 | pr_debug("Added buffer head %i to %p\n", head, vq); | 254 | pr_debug("Added buffer head %i to %p\n", head, vq); |
@@ -354,8 +361,8 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq) | |||
354 | * event. */ | 361 | * event. */ |
355 | virtio_mb(vq->weak_barriers); | 362 | virtio_mb(vq->weak_barriers); |
356 | 363 | ||
357 | old = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - vq->num_added; | 364 | old = vq->avail_idx_shadow - vq->num_added; |
358 | new = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx); | 365 | new = vq->avail_idx_shadow; |
359 | vq->num_added = 0; | 366 | vq->num_added = 0; |
360 | 367 | ||
361 | #ifdef DEBUG | 368 | #ifdef DEBUG |
@@ -510,7 +517,7 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) | |||
510 | /* If we expect an interrupt for the next entry, tell host | 517 | /* If we expect an interrupt for the next entry, tell host |
511 | * by writing event index and flush out the write before | 518 | * by writing event index and flush out the write before |
512 | * the read in the next get_buf call. */ | 519 | * the read in the next get_buf call. */ |
513 | if (!(vq->vring.avail->flags & cpu_to_virtio16(_vq->vdev, VRING_AVAIL_F_NO_INTERRUPT))) { | 520 | if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { |
514 | vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx); | 521 | vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx); |
515 | virtio_mb(vq->weak_barriers); | 522 | virtio_mb(vq->weak_barriers); |
516 | } | 523 | } |
@@ -537,7 +544,11 @@ void virtqueue_disable_cb(struct virtqueue *_vq) | |||
537 | { | 544 | { |
538 | struct vring_virtqueue *vq = to_vvq(_vq); | 545 | struct vring_virtqueue *vq = to_vvq(_vq); |
539 | 546 | ||
540 | vq->vring.avail->flags |= cpu_to_virtio16(_vq->vdev, VRING_AVAIL_F_NO_INTERRUPT); | 547 | if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { |
548 | vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; | ||
549 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | ||
550 | } | ||
551 | |||
541 | } | 552 | } |
542 | EXPORT_SYMBOL_GPL(virtqueue_disable_cb); | 553 | EXPORT_SYMBOL_GPL(virtqueue_disable_cb); |
543 | 554 | ||
@@ -565,7 +576,10 @@ unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq) | |||
565 | /* Depending on the VIRTIO_RING_F_EVENT_IDX feature, we need to | 576 | /* Depending on the VIRTIO_RING_F_EVENT_IDX feature, we need to |
566 | * either clear the flags bit or point the event index at the next | 577 | * either clear the flags bit or point the event index at the next |
567 | * entry. Always do both to keep code simple. */ | 578 | * entry. Always do both to keep code simple. */ |
568 | vq->vring.avail->flags &= cpu_to_virtio16(_vq->vdev, ~VRING_AVAIL_F_NO_INTERRUPT); | 579 | if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { |
580 | vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; | ||
581 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | ||
582 | } | ||
569 | vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx); | 583 | vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx); |
570 | END_USE(vq); | 584 | END_USE(vq); |
571 | return last_used_idx; | 585 | return last_used_idx; |
@@ -633,9 +647,12 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq) | |||
633 | /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to | 647 | /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to |
634 | * either clear the flags bit or point the event index at the next | 648 | * either clear the flags bit or point the event index at the next |
635 | * entry. Always do both to keep code simple. */ | 649 | * entry. Always do both to keep code simple. */ |
636 | vq->vring.avail->flags &= cpu_to_virtio16(_vq->vdev, ~VRING_AVAIL_F_NO_INTERRUPT); | 650 | if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { |
651 | vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; | ||
652 | vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); | ||
653 | } | ||
637 | /* TODO: tune this threshold */ | 654 | /* TODO: tune this threshold */ |
638 | bufs = (u16)(virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - vq->last_used_idx) * 3 / 4; | 655 | bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4; |
639 | vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx + bufs); | 656 | vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx + bufs); |
640 | virtio_mb(vq->weak_barriers); | 657 | virtio_mb(vq->weak_barriers); |
641 | if (unlikely((u16)(virtio16_to_cpu(_vq->vdev, vq->vring.used->idx) - vq->last_used_idx) > bufs)) { | 658 | if (unlikely((u16)(virtio16_to_cpu(_vq->vdev, vq->vring.used->idx) - vq->last_used_idx) > bufs)) { |
@@ -670,7 +687,8 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq) | |||
670 | /* detach_buf clears data, so grab it now. */ | 687 | /* detach_buf clears data, so grab it now. */ |
671 | buf = vq->data[i]; | 688 | buf = vq->data[i]; |
672 | detach_buf(vq, i); | 689 | detach_buf(vq, i); |
673 | vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - 1); | 690 | vq->avail_idx_shadow--; |
691 | vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow); | ||
674 | END_USE(vq); | 692 | END_USE(vq); |
675 | return buf; | 693 | return buf; |
676 | } | 694 | } |
@@ -735,6 +753,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
735 | vq->weak_barriers = weak_barriers; | 753 | vq->weak_barriers = weak_barriers; |
736 | vq->broken = false; | 754 | vq->broken = false; |
737 | vq->last_used_idx = 0; | 755 | vq->last_used_idx = 0; |
756 | vq->avail_flags_shadow = 0; | ||
757 | vq->avail_idx_shadow = 0; | ||
738 | vq->num_added = 0; | 758 | vq->num_added = 0; |
739 | list_add_tail(&vq->vq.list, &vdev->vqs); | 759 | list_add_tail(&vq->vq.list, &vdev->vqs); |
740 | #ifdef DEBUG | 760 | #ifdef DEBUG |
@@ -746,8 +766,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
746 | vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); | 766 | vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); |
747 | 767 | ||
748 | /* No callback? Tell other side not to bother us. */ | 768 | /* No callback? Tell other side not to bother us. */ |
749 | if (!callback) | 769 | if (!callback) { |
750 | vq->vring.avail->flags |= cpu_to_virtio16(vdev, VRING_AVAIL_F_NO_INTERRUPT); | 770 | vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; |
771 | vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow); | ||
772 | } | ||
751 | 773 | ||
752 | /* Put everything in free lists. */ | 774 | /* Put everything in free lists. */ |
753 | vq->free_head = 0; | 775 | vq->free_head = 0; |
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h index 0a3da64638ce..4db7d5691ba7 100644 --- a/tools/virtio/linux/kernel.h +++ b/tools/virtio/linux/kernel.h | |||
@@ -110,4 +110,10 @@ static inline void free_page(unsigned long addr) | |||
110 | (void) (&_min1 == &_min2); \ | 110 | (void) (&_min1 == &_min2); \ |
111 | _min1 < _min2 ? _min1 : _min2; }) | 111 | _min1 < _min2 ? _min1 : _min2; }) |
112 | 112 | ||
113 | /* TODO: empty stubs for now. Broken but enough for virtio_ring.c */ | ||
114 | #define list_add_tail(a, b) do {} while (0) | ||
115 | #define list_del(a) do {} while (0) | ||
116 | #define list_for_each_entry(a, b, c) while (0) | ||
117 | /* end of stubs */ | ||
118 | |||
113 | #endif /* KERNEL_H */ | 119 | #endif /* KERNEL_H */ |
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index a3e07016a440..ee125e714053 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h | |||
@@ -3,12 +3,6 @@ | |||
3 | #include <linux/scatterlist.h> | 3 | #include <linux/scatterlist.h> |
4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
5 | 5 | ||
6 | /* TODO: empty stubs for now. Broken but enough for virtio_ring.c */ | ||
7 | #define list_add_tail(a, b) do {} while (0) | ||
8 | #define list_del(a) do {} while (0) | ||
9 | #define list_for_each_entry(a, b, c) while (0) | ||
10 | /* end of stubs */ | ||
11 | |||
12 | struct virtio_device { | 6 | struct virtio_device { |
13 | void *dev; | 7 | void *dev; |
14 | u64 features; | 8 | u64 features; |
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h index 806d683ab107..57a6964a1e35 100644 --- a/tools/virtio/linux/virtio_config.h +++ b/tools/virtio/linux/virtio_config.h | |||
@@ -40,33 +40,39 @@ static inline void __virtio_clear_bit(struct virtio_device *vdev, | |||
40 | #define virtio_has_feature(dev, feature) \ | 40 | #define virtio_has_feature(dev, feature) \ |
41 | (__virtio_test_bit((dev), feature)) | 41 | (__virtio_test_bit((dev), feature)) |
42 | 42 | ||
43 | static inline bool virtio_is_little_endian(struct virtio_device *vdev) | ||
44 | { | ||
45 | return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) || | ||
46 | virtio_legacy_is_little_endian(); | ||
47 | } | ||
48 | |||
49 | /* Memory accessors */ | ||
43 | static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val) | 50 | static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val) |
44 | { | 51 | { |
45 | return __virtio16_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | 52 | return __virtio16_to_cpu(virtio_is_little_endian(vdev), val); |
46 | } | 53 | } |
47 | 54 | ||
48 | static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val) | 55 | static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val) |
49 | { | 56 | { |
50 | return __cpu_to_virtio16(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | 57 | return __cpu_to_virtio16(virtio_is_little_endian(vdev), val); |
51 | } | 58 | } |
52 | 59 | ||
53 | static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val) | 60 | static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val) |
54 | { | 61 | { |
55 | return __virtio32_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | 62 | return __virtio32_to_cpu(virtio_is_little_endian(vdev), val); |
56 | } | 63 | } |
57 | 64 | ||
58 | static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val) | 65 | static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val) |
59 | { | 66 | { |
60 | return __cpu_to_virtio32(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | 67 | return __cpu_to_virtio32(virtio_is_little_endian(vdev), val); |
61 | } | 68 | } |
62 | 69 | ||
63 | static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val) | 70 | static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val) |
64 | { | 71 | { |
65 | return __virtio64_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | 72 | return __virtio64_to_cpu(virtio_is_little_endian(vdev), val); |
66 | } | 73 | } |
67 | 74 | ||
68 | static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val) | 75 | static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val) |
69 | { | 76 | { |
70 | return __cpu_to_virtio64(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val); | 77 | return __cpu_to_virtio64(virtio_is_little_endian(vdev), val); |
71 | } | 78 | } |
72 | |||