diff options
-rw-r--r-- | drivers/lguest/lguest_device.c | 11 | ||||
-rw-r--r-- | drivers/s390/kvm/kvm_virtio.c | 11 | ||||
-rw-r--r-- | drivers/virtio/virtio.c | 5 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 10 | ||||
-rw-r--r-- | include/linux/virtio_config.h | 7 |
5 files changed, 24 insertions, 20 deletions
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 1a8de57289eb..54fdc2aa4806 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
@@ -98,16 +98,17 @@ static u32 lg_get_features(struct virtio_device *vdev) | |||
98 | return features; | 98 | return features; |
99 | } | 99 | } |
100 | 100 | ||
101 | static void lg_set_features(struct virtio_device *vdev, u32 features) | 101 | static void lg_finalize_features(struct virtio_device *vdev) |
102 | { | 102 | { |
103 | unsigned int i; | 103 | unsigned int i, bits; |
104 | struct lguest_device_desc *desc = to_lgdev(vdev)->desc; | 104 | struct lguest_device_desc *desc = to_lgdev(vdev)->desc; |
105 | /* Second half of bitmap is features we accept. */ | 105 | /* Second half of bitmap is features we accept. */ |
106 | u8 *out_features = lg_features(desc) + desc->feature_len; | 106 | u8 *out_features = lg_features(desc) + desc->feature_len; |
107 | 107 | ||
108 | memset(out_features, 0, desc->feature_len); | 108 | memset(out_features, 0, desc->feature_len); |
109 | for (i = 0; i < min(desc->feature_len * 8, 32); i++) { | 109 | bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; |
110 | if (features & (1 << i)) | 110 | for (i = 0; i < bits; i++) { |
111 | if (test_bit(i, vdev->features)) | ||
111 | out_features[i / 8] |= (1 << (i % 8)); | 112 | out_features[i / 8] |= (1 << (i % 8)); |
112 | } | 113 | } |
113 | } | 114 | } |
@@ -297,7 +298,7 @@ static void lg_del_vq(struct virtqueue *vq) | |||
297 | /* The ops structure which hooks everything together. */ | 298 | /* The ops structure which hooks everything together. */ |
298 | static struct virtio_config_ops lguest_config_ops = { | 299 | static struct virtio_config_ops lguest_config_ops = { |
299 | .get_features = lg_get_features, | 300 | .get_features = lg_get_features, |
300 | .set_features = lg_set_features, | 301 | .finalize_features = lg_finalize_features, |
301 | .get = lg_get, | 302 | .get = lg_get, |
302 | .set = lg_set, | 303 | .set = lg_set, |
303 | .get_status = lg_get_status, | 304 | .get_status = lg_get_status, |
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index d41f234bb2c2..5953510e7d5f 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -88,16 +88,17 @@ static u32 kvm_get_features(struct virtio_device *vdev) | |||
88 | return features; | 88 | return features; |
89 | } | 89 | } |
90 | 90 | ||
91 | static void kvm_set_features(struct virtio_device *vdev, u32 features) | 91 | static void kvm_finalize_features(struct virtio_device *vdev) |
92 | { | 92 | { |
93 | unsigned int i; | 93 | unsigned int i, bits; |
94 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; | 94 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; |
95 | /* Second half of bitmap is features we accept. */ | 95 | /* Second half of bitmap is features we accept. */ |
96 | u8 *out_features = kvm_vq_features(desc) + desc->feature_len; | 96 | u8 *out_features = kvm_vq_features(desc) + desc->feature_len; |
97 | 97 | ||
98 | memset(out_features, 0, desc->feature_len); | 98 | memset(out_features, 0, desc->feature_len); |
99 | for (i = 0; i < min(desc->feature_len * 8, 32); i++) { | 99 | bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; |
100 | if (features & (1 << i)) | 100 | for (i = 0; i < bits; i++) { |
101 | if (test_bit(i, vdev->features)) | ||
101 | out_features[i / 8] |= (1 << (i % 8)); | 102 | out_features[i / 8] |= (1 << (i % 8)); |
102 | } | 103 | } |
103 | } | 104 | } |
@@ -223,7 +224,7 @@ static void kvm_del_vq(struct virtqueue *vq) | |||
223 | */ | 224 | */ |
224 | static struct virtio_config_ops kvm_vq_configspace_ops = { | 225 | static struct virtio_config_ops kvm_vq_configspace_ops = { |
225 | .get_features = kvm_get_features, | 226 | .get_features = kvm_get_features, |
226 | .set_features = kvm_set_features, | 227 | .finalize_features = kvm_finalize_features, |
227 | .get = kvm_get, | 228 | .get = kvm_get, |
228 | .set = kvm_set, | 229 | .set = kvm_set, |
229 | .get_status = kvm_get_status, | 230 | .get_status = kvm_get_status, |
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index baf103361e3a..5b78fd0aff0a 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
@@ -113,7 +113,7 @@ static int virtio_dev_probe(struct device *_d) | |||
113 | set_bit(f, dev->features); | 113 | set_bit(f, dev->features); |
114 | } | 114 | } |
115 | 115 | ||
116 | /* Transport features are always preserved to pass to set_features. */ | 116 | /* Transport features always preserved to pass to finalize_features. */ |
117 | for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) | 117 | for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) |
118 | if (device_features & (1 << i)) | 118 | if (device_features & (1 << i)) |
119 | set_bit(i, dev->features); | 119 | set_bit(i, dev->features); |
@@ -122,8 +122,7 @@ static int virtio_dev_probe(struct device *_d) | |||
122 | if (err) | 122 | if (err) |
123 | add_status(dev, VIRTIO_CONFIG_S_FAILED); | 123 | add_status(dev, VIRTIO_CONFIG_S_FAILED); |
124 | else { | 124 | else { |
125 | /* They should never have set feature bits beyond 32 */ | 125 | dev->config->finalize_features(dev); |
126 | dev->config->set_features(dev, dev->features[0]); | ||
127 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); | 126 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); |
128 | } | 127 | } |
129 | return err; | 128 | return err; |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index eae7236310e4..9855975a72a3 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
@@ -94,12 +94,14 @@ static u32 vp_get_features(struct virtio_device *vdev) | |||
94 | return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); | 94 | return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); |
95 | } | 95 | } |
96 | 96 | ||
97 | /* virtio config->set_features() implementation */ | 97 | /* virtio config->finalize_features() implementation */ |
98 | static void vp_set_features(struct virtio_device *vdev, u32 features) | 98 | static void vp_finalize_features(struct virtio_device *vdev) |
99 | { | 99 | { |
100 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 100 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
101 | 101 | ||
102 | iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); | 102 | /* We only support 32 feature bits. */ |
103 | BUILD_BUG_ON(ARRAY_SIZE(vdev->features) != 1); | ||
104 | iowrite32(vdev->features[0], vp_dev->ioaddr+VIRTIO_PCI_GUEST_FEATURES); | ||
103 | } | 105 | } |
104 | 106 | ||
105 | /* virtio config->get() implementation */ | 107 | /* virtio config->get() implementation */ |
@@ -297,7 +299,7 @@ static struct virtio_config_ops virtio_pci_config_ops = { | |||
297 | .find_vq = vp_find_vq, | 299 | .find_vq = vp_find_vq, |
298 | .del_vq = vp_del_vq, | 300 | .del_vq = vp_del_vq, |
299 | .get_features = vp_get_features, | 301 | .get_features = vp_get_features, |
300 | .set_features = vp_set_features, | 302 | .finalize_features = vp_finalize_features, |
301 | }; | 303 | }; |
302 | 304 | ||
303 | /* the PCI probing function */ | 305 | /* the PCI probing function */ |
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 5a30cfb7934b..bf8ec283b232 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h | |||
@@ -61,9 +61,10 @@ | |||
61 | * @get_features: get the array of feature bits for this device. | 61 | * @get_features: get the array of feature bits for this device. |
62 | * vdev: the virtio_device | 62 | * vdev: the virtio_device |
63 | * Returns the first 32 feature bits (all we currently need). | 63 | * Returns the first 32 feature bits (all we currently need). |
64 | * @set_features: confirm what device features we'll be using. | 64 | * @finalize_features: confirm what device features we'll be using. |
65 | * vdev: the virtio_device | 65 | * vdev: the virtio_device |
66 | * feature: the first 32 feature bits | 66 | * This gives the final feature bits for the device: it can change |
67 | * the dev->feature bits if it wants. | ||
67 | */ | 68 | */ |
68 | struct virtio_config_ops | 69 | struct virtio_config_ops |
69 | { | 70 | { |
@@ -79,7 +80,7 @@ struct virtio_config_ops | |||
79 | void (*callback)(struct virtqueue *)); | 80 | void (*callback)(struct virtqueue *)); |
80 | void (*del_vq)(struct virtqueue *vq); | 81 | void (*del_vq)(struct virtqueue *vq); |
81 | u32 (*get_features)(struct virtio_device *vdev); | 82 | u32 (*get_features)(struct virtio_device *vdev); |
82 | void (*set_features)(struct virtio_device *vdev, u32 features); | 83 | void (*finalize_features)(struct virtio_device *vdev); |
83 | }; | 84 | }; |
84 | 85 | ||
85 | /* If driver didn't advertise the feature, it will never appear. */ | 86 | /* If driver didn't advertise the feature, it will never appear. */ |