set FEATURES_OK as per virtio 1.0 spec

Signed-off-by: Michael S. Tsirkin <m...@redhat.com>
---
 include/uapi/linux/virtio_config.h |  2 ++
 drivers/virtio/virtio.c            | 29 ++++++++++++++++++++++-------
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/include/uapi/linux/virtio_config.h 
b/include/uapi/linux/virtio_config.h
index 80e7381..4d05671 100644
--- a/include/uapi/linux/virtio_config.h
+++ b/include/uapi/linux/virtio_config.h
@@ -38,6 +38,8 @@
 #define VIRTIO_CONFIG_S_DRIVER         2
 /* Driver has used its parts of the config, and is happy */
 #define VIRTIO_CONFIG_S_DRIVER_OK      4
+/* Driver has finished configuring features */
+#define VIRTIO_CONFIG_S_FEATURES_OK    8
 /* We've given up on this device. */
 #define VIRTIO_CONFIG_S_FAILED         0x80
 
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 746d350..9248125 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -160,6 +160,7 @@ static int virtio_dev_probe(struct device *_d)
        struct virtio_device *dev = dev_to_virtio(_d);
        struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
        u64 device_features;
+       unsigned status;
 
        /* We have a driver! */
        add_status(dev, VIRTIO_CONFIG_S_DRIVER);
@@ -183,18 +184,32 @@ static int virtio_dev_probe(struct device *_d)
 
        dev->config->finalize_features(dev);
 
+       if (virtio_has_feature(dev, VIRTIO_F_VERSION_1)) {
+               add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK);
+               status = dev->config->get_status(dev);
+               if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) {
+                       dev_err(_d, "virtio: device refuses features: %x\n",
+                              status);
+                       err = -ENODEV;
+                       goto err;
+               }
+       }
+
        err = drv->probe(dev);
        if (err)
-               add_status(dev, VIRTIO_CONFIG_S_FAILED);
-       else {
-               add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
-               if (drv->scan)
-                       drv->scan(dev);
+               goto err;
 
-               virtio_config_enable(dev);
-       }
+       add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
+       if (drv->scan)
+               drv->scan(dev);
+
+       virtio_config_enable(dev);
 
+       return 0;
+err:
+       add_status(dev, VIRTIO_CONFIG_S_FAILED);
        return err;
+
 }
 
 static int virtio_dev_remove(struct device *_d)
-- 
MST

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

Reply via email to