vhost: add vhost_get_features and vhost_ack_features
authorNikolay Nikolaev <n.nikolaev@virtualopensystems.com>
Tue, 27 May 2014 12:04:42 +0000 (15:04 +0300)
committerMichael S. Tsirkin <mst@redhat.com>
Thu, 19 Jun 2014 13:41:55 +0000 (16:41 +0300)
Generalize the features get/ack to be used for both vhost-net and vhost-scsi.
In vhost-net add vhost_net_get_feature_bits to select the feature bit set
depending on the NetClient kind.

Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
hw/net/vhost_net.c
hw/scsi/vhost-scsi.c
hw/virtio/vhost.c
include/hw/virtio/vhost.h

index a1de2f43a0f911ced788b3e8b42c2c9606a6565d..6a9a32f56b5ae12755c8aa19378171b4ec9e867a 100644 (file)
@@ -46,39 +46,41 @@ struct vhost_net {
     NetClientState *nc;
 };
 
-unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
+/* Features supported by host kernel. */
+static const int kernel_feature_bits[] = {
+    VIRTIO_F_NOTIFY_ON_EMPTY,
+    VIRTIO_RING_F_INDIRECT_DESC,
+    VIRTIO_RING_F_EVENT_IDX,
+    VIRTIO_NET_F_MRG_RXBUF,
+    VHOST_INVALID_FEATURE_BIT
+};
+
+static const int *vhost_net_get_feature_bits(struct vhost_net *net)
 {
-    /* Clear features not supported by host kernel. */
-    if (!(net->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))) {
-        features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
-    }
-    if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
-        features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
-    }
-    if (!(net->dev.features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
-        features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
-    }
-    if (!(net->dev.features & (1 << VIRTIO_NET_F_MRG_RXBUF))) {
-        features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+    const int *feature_bits = 0;
+
+    switch (net->nc->info->type) {
+    case NET_CLIENT_OPTIONS_KIND_TAP:
+        feature_bits = kernel_feature_bits;
+        break;
+    default:
+        error_report("Feature bits not defined for this type: %d",
+                net->nc->info->type);
+        break;
     }
-    return features;
+
+    return feature_bits;
+}
+
+unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
+{
+    return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net),
+            features);
 }
 
 void vhost_net_ack_features(struct vhost_net *net, unsigned features)
 {
-    net->dev.acked_features = net->dev.backend_features;
-    if (features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) {
-        net->dev.acked_features |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
-    }
-    if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC)) {
-        net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
-    }
-    if (features & (1 << VIRTIO_RING_F_EVENT_IDX)) {
-        net->dev.acked_features |= (1 << VIRTIO_RING_F_EVENT_IDX);
-    }
-    if (features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
-        net->dev.acked_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
-    }
+    vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
 }
 
 static int vhost_net_get_fd(NetClientState *backend)
index 668bafa72a612e40ae7a0c767882d834583f0214..a12d88846f4cc9806b60fee38fb6f305aa4321b3 100644 (file)
 #include "hw/virtio/virtio-scsi.h"
 #include "hw/virtio/virtio-bus.h"
 
+/* Features supported by host kernel. */
+static const int kernel_feature_bits[] = {
+    VIRTIO_F_NOTIFY_ON_EMPTY,
+    VIRTIO_RING_F_INDIRECT_DESC,
+    VIRTIO_RING_F_EVENT_IDX,
+    VIRTIO_SCSI_F_HOTPLUG,
+    VHOST_INVALID_FEATURE_BIT
+};
+
 static int vhost_scsi_set_endpoint(VHostSCSI *s)
 {
     VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
@@ -141,21 +150,7 @@ static uint32_t vhost_scsi_get_features(VirtIODevice *vdev,
 {
     VHostSCSI *s = VHOST_SCSI(vdev);
 
-    /* Clear features not supported by host kernel. */
-    if (!(s->dev.features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY))) {
-        features &= ~(1 << VIRTIO_F_NOTIFY_ON_EMPTY);
-    }
-    if (!(s->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
-        features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
-    }
-    if (!(s->dev.features & (1 << VIRTIO_RING_F_EVENT_IDX))) {
-        features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
-    }
-    if (!(s->dev.features & (1 << VIRTIO_SCSI_F_HOTPLUG))) {
-        features &= ~(1 << VIRTIO_SCSI_F_HOTPLUG);
-    }
-
-    return features;
+    return vhost_get_features(&s->dev, kernel_feature_bits, features);
 }
 
 static void vhost_scsi_set_config(VirtIODevice *vdev,
index 9e6023af360754e85486b4510f30f16de0ac2d1f..a3e872d2f1b57ce2823d60a1229b23425e22f1dd 100644 (file)
@@ -990,6 +990,33 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
     assert(r >= 0);
 }
 
+unsigned vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
+        unsigned features)
+{
+    const int *bit = feature_bits;
+    while (*bit != VHOST_INVALID_FEATURE_BIT) {
+        unsigned bit_mask = (1 << *bit);
+        if (!(hdev->features & bit_mask)) {
+            features &= ~bit_mask;
+        }
+        bit++;
+    }
+    return features;
+}
+
+void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
+        unsigned features)
+{
+    const int *bit = feature_bits;
+    while (*bit != VHOST_INVALID_FEATURE_BIT) {
+        unsigned bit_mask = (1 << *bit);
+        if (features & bit_mask) {
+            hdev->acked_features |= bit_mask;
+        }
+        bit++;
+    }
+}
+
 /* Host notifiers must be enabled at this point. */
 int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
 {
index de24746c7e2e66595ba5d0f1368f060be6315cff..df1f2149cca7c2cc2d3b3318542a1e0facf30226 100644 (file)
@@ -25,6 +25,7 @@ typedef unsigned long vhost_log_chunk_t;
 #define VHOST_LOG_PAGE 0x1000
 #define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t))
 #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS)
+#define VHOST_INVALID_FEATURE_BIT   (0xff)
 
 struct vhost_memory;
 struct vhost_dev {
@@ -68,4 +69,8 @@ bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n);
  */
 void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
                           bool mask);
+unsigned vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
+        unsigned features);
+void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
+        unsigned features);
 #endif