diff mbox

virtio: legacy features callback

Message ID 1426008164-8002-1-git-send-email-cornelia.huck@de.ibm.com
State New
Headers show

Commit Message

Cornelia Huck March 10, 2015, 5:22 p.m. UTC
Use a "legacy features" instead of a "revision specific" callback.

Updates "virtio: support revision-specific features" and
"virtio-blk: revision specific feature bits" as currently in
git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git virtio-1.0

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 hw/9pfs/virtio-9p-device.c     |  5 +++--
 hw/block/virtio-blk.c          | 14 ++++----------
 hw/char/virtio-serial-bus.c    | 22 +++++++++++++++++-----
 hw/net/virtio-net.c            | 31 +++++++++++++++++++++++++++----
 hw/s390x/s390-virtio-bus.c     |  4 ++--
 hw/s390x/virtio-ccw.c          | 12 ++++++------
 hw/s390x/virtio-ccw.h          |  4 ++--
 hw/scsi/virtio-scsi.c          |  8 ++++++++
 hw/virtio/virtio-balloon.c     |  5 +++--
 hw/virtio/virtio-bus.c         | 28 ++++++++++++++++++----------
 hw/virtio/virtio-mmio.c        |  4 ++--
 hw/virtio/virtio-pci.c         |  4 ++--
 hw/virtio/virtio-rng.c         |  7 +++++++
 hw/virtio/virtio.c             | 12 ++++++++++++
 include/hw/virtio/virtio-bus.h |  5 ++---
 include/hw/virtio/virtio.h     |  6 +++---
 16 files changed, 118 insertions(+), 53 deletions(-)
diff mbox

Patch

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 60f9ff9..5f0aa99 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -21,7 +21,8 @@ 
 #include "virtio-9p-coth.h"
 #include "hw/virtio/virtio-access.h"
 
-static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features)
+static uint64_t virtio_9p_get_features_legacy(VirtIODevice *vdev,
+                                              uint64_t features)
 {
     virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG);
     return features;
@@ -152,7 +153,7 @@  static void virtio_9p_class_init(ObjectClass *klass, void *data)
     dc->props = virtio_9p_properties;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
     vdc->realize = virtio_9p_device_realize;
-    vdc->get_features = virtio_9p_get_features;
+    vdc->get_features_legacy = virtio_9p_get_features_legacy;
     vdc->get_config = virtio_9p_get_config;
 }
 
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index fdc236a..f8abf40 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -564,7 +564,8 @@  static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
     aio_context_release(blk_get_aio_context(s->blk));
 }
 
-static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
+static uint64_t virtio_blk_get_features_legacy(VirtIODevice *vdev,
+                                               uint64_t features)
 {
     VirtIOBlock *s = VIRTIO_BLK(vdev);
 
@@ -587,15 +588,8 @@  static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
     return features;
 }
 
-static uint64_t virtio_blk_get_features_rev(VirtIODevice *vdev,
-                                            uint64_t features,
-                                            unsigned int revision)
+static uint64_t virtio_blk_get_features(VirtIODevice *vdev, uint64_t features)
 {
-    if (revision == 0) {
-        /* legacy */
-        virtio_clear_feature(&features, VIRTIO_F_VERSION_1);
-        return virtio_blk_get_features(vdev, features);
-    }
     /* virtio 1.0 or later */
     virtio_clear_feature(&features, VIRTIO_BLK_F_SCSI);
     virtio_clear_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
@@ -839,7 +833,7 @@  static void virtio_blk_class_init(ObjectClass *klass, void *data)
     vdc->get_config = virtio_blk_update_config;
     vdc->set_config = virtio_blk_set_config;
     vdc->get_features = virtio_blk_get_features;
-    vdc->get_features_rev = virtio_blk_get_features_rev;
+    vdc->get_features_legacy = virtio_blk_get_features_legacy;
     vdc->set_status = virtio_blk_set_status;
     vdc->reset = virtio_blk_reset;
     vdc->save = virtio_blk_save_device;
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 2d2ed9c..7119f97 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -467,18 +467,29 @@  static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 {
 }
 
-static uint64_t get_features(VirtIODevice *vdev, uint64_t features)
+static uint64_t get_features_common(VirtIOSerial *vser, uint64_t features)
 {
-    VirtIOSerial *vser;
-
-    vser = VIRTIO_SERIAL(vdev);
-
     if (vser->bus.max_nr_ports > 1) {
         virtio_add_feature(&features, VIRTIO_CONSOLE_F_MULTIPORT);
     }
     return features;
 }
 
+static uint64_t get_features(VirtIODevice *vdev, uint64_t features)
+{
+    VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
+
+    /* virtio_add_feature(&features, VIRTIO_F_VERSION_1); */
+    return get_features_common(vser, features);
+}
+
+static uint64_t get_features_legacy(VirtIODevice *vdev, uint64_t features)
+{
+    VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
+
+    return get_features_common(vser, features);
+}
+
 /* Guest requested config info */
 static void get_config(VirtIODevice *vdev, uint8_t *config_data)
 {
@@ -1076,6 +1087,7 @@  static void virtio_serial_class_init(ObjectClass *klass, void *data)
     vdc->realize = virtio_serial_device_realize;
     vdc->unrealize = virtio_serial_device_unrealize;
     vdc->get_features = get_features;
+    vdc->get_features_legacy = get_features_legacy;
     vdc->get_config = get_config;
     vdc->set_status = set_status;
     vdc->reset = vser_reset;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 5fff769..0f6d283 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -448,11 +448,9 @@  static void virtio_net_set_queues(VirtIONet *n)
 
 static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
 
-static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
+static uint64_t virtio_net_get_features_common(VirtIONet *n,
+                                               uint64_t features)
 {
-    VirtIONet *n = VIRTIO_NET(vdev);
-    NetClientState *nc = qemu_get_queue(n->nic);
-
     virtio_add_feature(&features, VIRTIO_NET_F_MAC);
 
     if (!peer_has_vnet_hdr(n)) {
@@ -472,6 +470,16 @@  static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
         virtio_clear_feature(&features, VIRTIO_NET_F_HOST_UFO);
     }
 
+    return features;
+}
+
+static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
+{
+    VirtIONet *n = VIRTIO_NET(vdev);
+    NetClientState *nc = qemu_get_queue(n->nic);
+
+    features = virtio_net_get_features_common(n, features);
+
     if (!get_vhost_net(nc->peer)) {
         virtio_add_feature(&features, VIRTIO_F_VERSION_1);
         return features;
@@ -479,6 +487,20 @@  static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features)
     return vhost_net_get_features(get_vhost_net(nc->peer), features);
 }
 
+static uint64_t virtio_net_get_features_legacy(VirtIODevice *vdev,
+                                               uint64_t features)
+{
+    VirtIONet *n = VIRTIO_NET(vdev);
+    NetClientState *nc = qemu_get_queue(n->nic);
+
+    features = virtio_net_get_features_common(n, features);
+
+    if (!get_vhost_net(nc->peer)) {
+        return features;
+    }
+    return vhost_net_get_features(get_vhost_net(nc->peer), features);
+}
+
 static uint64_t virtio_net_bad_features(VirtIODevice *vdev)
 {
     uint64_t features = 0;
@@ -1753,6 +1775,7 @@  static void virtio_net_class_init(ObjectClass *klass, void *data)
     vdc->get_config = virtio_net_get_config;
     vdc->set_config = virtio_net_set_config;
     vdc->get_features = virtio_net_get_features;
+    vdc->get_features_legacy = virtio_net_get_features_legacy;
     vdc->set_features = virtio_net_set_features;
     vdc->bad_features = virtio_net_bad_features;
     vdc->reset = virtio_net_reset;
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 3635909..74cc2ad 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -128,8 +128,8 @@  static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
 
     bus->dev_offs += dev_len;
 
-    dev->host_features = virtio_bus_get_vdev_features(&dev->bus,
-                                                      dev->host_features);
+    dev->host_features =
+        virtio_bus_get_vdev_features_legacy(&dev->bus, dev->host_features);
     s390_virtio_device_sync(dev);
     s390_virtio_reset_idx(dev);
     if (dev->qdev.hotplugged) {
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 8b6b2ab..7359e01 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -693,16 +693,16 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         }
         cpu_physical_memory_read(ccw.cda, &revinfo, len);
         if (dev->revision >= 0 ||
-            revinfo.revision > virtio_ccw_rev_max(dev)) {
+            revinfo.revision > virtio_ccw_rev_max(dev, vdev)) {
             ret = -ENOSYS;
             break;
         }
         ret = 0;
         dev->revision = revinfo.revision;
         /* Re-evaluate which features the device wants to offer. */
-        dev->host_features =
-            virtio_bus_get_vdev_features_rev(&dev->bus, dev->host_features,
-                                             dev->revision >= 1 ? 1 : 0);
+        dev->host_features = dev->revision >= 1 ?
+            virtio_bus_get_vdev_features(&dev->bus, dev->host_features) :
+            virtio_bus_get_vdev_features_legacy(&dev->bus, dev->host_features);
         break;
     default:
         ret = -ENOSYS;
@@ -718,7 +718,7 @@  static void virtio_sch_disable_cb(SubchDev *sch)
     dev->revision = -1;
     /* Reset the device's features to legacy. */
     dev->host_features =
-        virtio_bus_get_vdev_features_rev(&dev->bus, dev->host_features, 0);
+        virtio_bus_get_vdev_features_legacy(&dev->bus, dev->host_features);
 }
 
 static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
@@ -862,7 +862,7 @@  static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
 
     /* All devices start in legacy mode. */
     dev->host_features =
-        virtio_bus_get_vdev_features_rev(&dev->bus, dev->host_features, 0);
+        virtio_bus_get_vdev_features_legacy(&dev->bus, dev->host_features);
 
     css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
                           parent->hotplugged, 1);
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 37a9840..89f7685 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -102,9 +102,9 @@  struct VirtioCcwDevice {
 };
 
 /* The maximum virtio revision we support. */
-static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev)
+static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev, VirtIODevice *vdev)
 {
-    return dev->host_features & (1ULL << VIRTIO_F_VERSION_1) ? 1 : 0;
+    return virtio_version_1_capable(vdev, dev->host_features) ? 1 : 0;
 }
 
 /* virtual css bus type */
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 1e7427e..77c451b 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -630,6 +630,13 @@  static void virtio_scsi_set_config(VirtIODevice *vdev,
 static uint64_t virtio_scsi_get_features(VirtIODevice *vdev,
                                          uint64_t requested_features)
 {
+    /* virtio_add_feature(&requested_features, VIRTIO_F_VERSION_1); */
+    return requested_features;
+}
+
+static uint64_t virtio_scsi_get_features_legacy(VirtIODevice *vdev,
+                                                uint64_t requested_features)
+{
     return requested_features;
 }
 
@@ -961,6 +968,7 @@  static void virtio_scsi_class_init(ObjectClass *klass, void *data)
     vdc->unrealize = virtio_scsi_device_unrealize;
     vdc->set_config = virtio_scsi_set_config;
     vdc->get_features = virtio_scsi_get_features;
+    vdc->get_features_legacy = virtio_scsi_get_features_legacy;
     vdc->reset = virtio_scsi_reset;
     hc->plug = virtio_scsi_hotplug;
     hc->unplug = virtio_scsi_hotunplug;
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index d2d7c3e..e33b93f 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -303,7 +303,8 @@  static void virtio_balloon_set_config(VirtIODevice *vdev,
     }
 }
 
-static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f)
+static uint64_t virtio_balloon_get_features_legacy(VirtIODevice *vdev,
+                                                   uint64_t f)
 {
     f |= (1 << VIRTIO_BALLOON_F_STATS_VQ);
     return f;
@@ -423,7 +424,7 @@  static void virtio_balloon_class_init(ObjectClass *klass, void *data)
     vdc->unrealize = virtio_balloon_device_unrealize;
     vdc->get_config = virtio_balloon_get_config;
     vdc->set_config = virtio_balloon_set_config;
-    vdc->get_features = virtio_balloon_get_features;
+    vdc->get_features_legacy = virtio_balloon_get_features_legacy;
     vdc->save = virtio_balloon_save_device;
     vdc->load = virtio_balloon_load_device;
 }
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 927fa11..e4ab736 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -97,26 +97,34 @@  size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
 }
 
 /* Get the features of the plugged device. */
-uint64_t virtio_bus_get_vdev_features_rev(VirtioBusState *bus,
-                                          uint64_t requested_features,
-                                          unsigned int revision)
+uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus,
+                                      uint64_t requested_features)
 {
     VirtIODevice *vdev = virtio_bus_get_device(bus);
     VirtioDeviceClass *k;
 
     assert(vdev != NULL);
     k = VIRTIO_DEVICE_GET_CLASS(vdev);
-    if (revision > 0 && k->get_features_rev) {
-        return k->get_features_rev(vdev, requested_features, revision);
+    assert((k->get_features != NULL) || (k->get_features_legacy != NULL));
+    if (k->get_features) {
+        return k->get_features(vdev, requested_features);
     }
-    assert(k->get_features != NULL);
-    return k->get_features(vdev, requested_features);
+    /* ensure version_1 is cleared on unsupported devices */
+    virtio_clear_feature(&requested_features, VIRTIO_F_VERSION_1);
+    return k->get_features_legacy(vdev, requested_features);
 }
 
-uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus,
-                                      uint64_t requested_features)
+uint64_t virtio_bus_get_vdev_features_legacy(VirtioBusState *bus,
+                                             uint64_t requested_features)
 {
-    return virtio_bus_get_vdev_features_rev(bus, requested_features, 0);
+    VirtIODevice *vdev = virtio_bus_get_device(bus);
+    VirtioDeviceClass *k;
+
+    assert(vdev != NULL);
+    k = VIRTIO_DEVICE_GET_CLASS(vdev);
+    assert(k->get_features_legacy != NULL);
+    virtio_clear_feature(&requested_features, VIRTIO_F_VERSION_1);
+    return k->get_features_legacy(vdev, requested_features);
 }
 
 /* Get bad features of the plugged device. */
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 0c9b63b..3389b18 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -353,8 +353,8 @@  static void virtio_mmio_device_plugged(DeviceState *opaque)
     VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
 
     virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
-    proxy->host_features = virtio_bus_get_vdev_features(&proxy->bus,
-                                                        proxy->host_features);
+    proxy->host_features =
+        virtio_bus_get_vdev_features_legacy(&proxy->bus, proxy->host_features);
 }
 
 static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index e6b0df4..07a8890 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1414,8 +1414,8 @@  static void virtio_pci_device_plugged(DeviceState *d)
 
     virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY);
     virtio_add_feature(&proxy->host_features, VIRTIO_F_BAD_FEATURE);
-    proxy->host_features = virtio_bus_get_vdev_features(bus,
-                                                      proxy->host_features);
+    proxy->host_features =
+        virtio_bus_get_vdev_features_legacy(bus, proxy->host_features);
 }
 
 static void virtio_pci_device_unplugged(DeviceState *d)
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index edd39cc..4634286 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -101,6 +101,12 @@  static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 
 static uint64_t get_features(VirtIODevice *vdev, uint64_t f)
 {
+    /* virtio_add_feature(&f, VIRTIO_F_VERSION_1); */
+    return f;
+}
+
+static uint64_t get_features_legacy(VirtIODevice *vdev, uint64_t f)
+{
     return f;
 }
 
@@ -233,6 +239,7 @@  static void virtio_rng_class_init(ObjectClass *klass, void *data)
     vdc->realize = virtio_rng_device_realize;
     vdc->unrealize = virtio_rng_device_unrealize;
     vdc->get_features = get_features;
+    vdc->get_features_legacy = get_features_legacy;
 }
 
 static void virtio_rng_initfn(Object *obj)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index b098f44..5f13598 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1122,6 +1122,18 @@  int virtio_set_features(VirtIODevice *vdev, uint64_t val)
     return __virtio_set_features(vdev, val);
 }
 
+bool virtio_version_1_capable(VirtIODevice *vdev, uint64_t host_features)
+{
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+    uint64_t features;
+
+    if (!k->get_features) {
+        return 0;
+    }
+    features = k->get_features(vdev, host_features);
+    return __virtio_has_feature(features, VIRTIO_F_VERSION_1) ? 1 : 0;
+}
+
 int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
 {
     int i, ret;
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index f0916ef..46721f6 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -84,9 +84,8 @@  size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus);
 /* Get the features of the plugged device. */
 uint64_t virtio_bus_get_vdev_features(VirtioBusState *bus,
                                       uint64_t requested_features);
-uint64_t virtio_bus_get_vdev_features_rev(VirtioBusState *bus,
-                                          uint64_t requested_features,
-                                          unsigned int revision);
+uint64_t virtio_bus_get_vdev_features_legacy(VirtioBusState *bus,
+                                             uint64_t requested_features);
 /* Get bad features of the plugged device. */
 uint64_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus);
 /* Get config of the plugged device. */
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 7a6a9d1..2dc9ad7 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -148,9 +148,8 @@  typedef struct VirtioDeviceClass {
     DeviceRealize realize;
     DeviceUnrealize unrealize;
     uint64_t (*get_features)(VirtIODevice *vdev, uint64_t requested_features);
-    uint64_t (*get_features_rev)(VirtIODevice *vdev,
-                                 uint64_t requested_features,
-                                 unsigned int revision);
+    uint64_t (*get_features_legacy)(VirtIODevice *vdev,
+                                    uint64_t requested_features);
     uint64_t (*bad_features)(VirtIODevice *vdev);
     void (*set_features)(VirtIODevice *vdev, uint64_t val);
     int (*validate_features)(VirtIODevice *vdev);
@@ -248,6 +247,7 @@  int virtio_set_status(VirtIODevice *vdev, uint8_t val);
 void virtio_reset(void *opaque);
 void virtio_update_irq(VirtIODevice *vdev);
 int virtio_set_features(VirtIODevice *vdev, uint64_t val);
+bool virtio_version_1_capable(VirtIODevice *vdev, uint64_t host_features);
 
 /* Base devices.  */
 typedef struct VirtIOBlkConf VirtIOBlkConf;