firmware: coreboot: Check size of table entry and use flex-array
[platform/kernel/linux-rpi.git] / drivers / virtio / virtio.c
index 236081a..c2b733e 100644 (file)
@@ -166,14 +166,13 @@ void virtio_add_status(struct virtio_device *dev, unsigned int status)
 }
 EXPORT_SYMBOL_GPL(virtio_add_status);
 
-int virtio_finalize_features(struct virtio_device *dev)
+/* Do some validation, then set FEATURES_OK */
+static int virtio_features_ok(struct virtio_device *dev)
 {
-       int ret = dev->config->finalize_features(dev);
        unsigned status;
+       int ret;
 
        might_sleep();
-       if (ret)
-               return ret;
 
        ret = arch_has_restricted_virtio_memory_access();
        if (ret) {
@@ -202,7 +201,6 @@ int virtio_finalize_features(struct virtio_device *dev)
        }
        return 0;
 }
-EXPORT_SYMBOL_GPL(virtio_finalize_features);
 
 static int virtio_dev_probe(struct device *_d)
 {
@@ -239,17 +237,6 @@ static int virtio_dev_probe(struct device *_d)
                driver_features_legacy = driver_features;
        }
 
-       /*
-        * Some devices detect legacy solely via F_VERSION_1. Write
-        * F_VERSION_1 to force LE config space accesses before FEATURES_OK for
-        * these when needed.
-        */
-       if (drv->validate && !virtio_legacy_is_little_endian()
-                         && device_features & BIT_ULL(VIRTIO_F_VERSION_1)) {
-               dev->features = BIT_ULL(VIRTIO_F_VERSION_1);
-               dev->config->finalize_features(dev);
-       }
-
        if (device_features & (1ULL << VIRTIO_F_VERSION_1))
                dev->features = driver_features & device_features;
        else
@@ -260,13 +247,26 @@ static int virtio_dev_probe(struct device *_d)
                if (device_features & (1ULL << i))
                        __virtio_set_bit(dev, i);
 
+       err = dev->config->finalize_features(dev);
+       if (err)
+               goto err;
+
        if (drv->validate) {
+               u64 features = dev->features;
+
                err = drv->validate(dev);
                if (err)
                        goto err;
+
+               /* Did validation change any features? Then write them again. */
+               if (features != dev->features) {
+                       err = dev->config->finalize_features(dev);
+                       if (err)
+                               goto err;
+               }
        }
 
-       err = virtio_finalize_features(dev);
+       err = virtio_features_ok(dev);
        if (err)
                goto err;
 
@@ -490,7 +490,11 @@ int virtio_device_restore(struct virtio_device *dev)
        /* We have a driver! */
        virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
 
-       ret = virtio_finalize_features(dev);
+       ret = dev->config->finalize_features(dev);
+       if (ret)
+               goto err;
+
+       ret = virtio_features_ok(dev);
        if (ret)
                goto err;