aboutsummaryrefslogtreecommitdiff
path: root/hw/net/virtio-net.c
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2015-09-11 16:01:56 +0800
committerMichael S. Tsirkin <mst@redhat.com>2015-09-24 13:39:46 +0300
commit1f8828ef573c83365b4a87a776daf8bcef1caa21 (patch)
tree94ac890c7836776dc22b7e22da33ae07a8a2a868 /hw/net/virtio-net.c
parent50764fc8a382dc17ccc06c0ba29184d0fd73016e (diff)
virtio-net: unbreak self announcement and guest offloads after migration
After commit 019a3edbb25f1571e876f8af1ce4c55412939e5d ("virtio: make features 64bit wide"). Device's guest_features was actually set after vdc->load(). This breaks the assumption that device specific load() function can check guest_features. For virtio-net, self announcement and guest offloads won't work after migration. Fixing this by defer them to virtio_net_load() where guest_features were guaranteed to be set. Other virtio devices looks fine. Fixes: 019a3edbb25f1571e876f8af1ce4c55412939e5d ("virtio: make features 64bit wide") Cc: qemu-stable@nongnu.org Cc: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Jason Wang <jasowang@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'hw/net/virtio-net.c')
-rw-r--r--hw/net/virtio-net.c40
1 files changed, 23 insertions, 17 deletions
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index f72eebff2b..2775e6a03e 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1458,11 +1458,33 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIONet *n = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(n);
+ int ret;
if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
return -EINVAL;
- return virtio_load(vdev, f, version_id);
+ ret = virtio_load(vdev, f, version_id);
+ if (ret) {
+ return ret;
+ }
+
+ if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
+ n->curr_guest_offloads = qemu_get_be64(f);
+ } else {
+ n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
+ }
+
+ if (peer_has_vnet_hdr(n)) {
+ virtio_net_apply_guest_offloads(n);
+ }
+
+ if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
+ virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
+ n->announce_counter = SELF_ANNOUNCE_ROUNDS;
+ timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
+ }
+
+ return 0;
}
static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
@@ -1559,16 +1581,6 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
}
}
- if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
- n->curr_guest_offloads = qemu_get_be64(f);
- } else {
- n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
- }
-
- if (peer_has_vnet_hdr(n)) {
- virtio_net_apply_guest_offloads(n);
- }
-
virtio_net_set_queues(n);
/* Find the first multicast entry in the saved MAC filter */
@@ -1586,12 +1598,6 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f,
qemu_get_subqueue(n->nic, i)->link_down = link_down;
}
- if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
- virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
- n->announce_counter = SELF_ANNOUNCE_ROUNDS;
- timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL));
- }
-
return 0;
}