diff options
Diffstat (limited to 'drivers/s390/kvm/kvm_virtio.c')
-rw-r--r-- | drivers/s390/kvm/kvm_virtio.c | 58 |
1 files changed, 29 insertions, 29 deletions
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 47a7e6200b26..5ab34340919b 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -31,11 +31,6 @@ | |||
31 | */ | 31 | */ |
32 | static void *kvm_devices; | 32 | static void *kvm_devices; |
33 | 33 | ||
34 | /* | ||
35 | * Unique numbering for kvm devices. | ||
36 | */ | ||
37 | static unsigned int dev_index; | ||
38 | |||
39 | struct kvm_device { | 34 | struct kvm_device { |
40 | struct virtio_device vdev; | 35 | struct virtio_device vdev; |
41 | struct kvm_device_desc *desc; | 36 | struct kvm_device_desc *desc; |
@@ -78,27 +73,32 @@ static unsigned desc_size(const struct kvm_device_desc *desc) | |||
78 | + desc->config_len; | 73 | + desc->config_len; |
79 | } | 74 | } |
80 | 75 | ||
81 | /* | 76 | /* This gets the device's feature bits. */ |
82 | * This tests (and acknowleges) a feature bit. | 77 | static u32 kvm_get_features(struct virtio_device *vdev) |
83 | */ | ||
84 | static bool kvm_feature(struct virtio_device *vdev, unsigned fbit) | ||
85 | { | 78 | { |
79 | unsigned int i; | ||
80 | u32 features = 0; | ||
86 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; | 81 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; |
87 | u8 *features; | 82 | u8 *in_features = kvm_vq_features(desc); |
88 | 83 | ||
89 | if (fbit / 8 > desc->feature_len) | 84 | for (i = 0; i < min(desc->feature_len * 8, 32); i++) |
90 | return false; | 85 | if (in_features[i / 8] & (1 << (i % 8))) |
86 | features |= (1 << i); | ||
87 | return features; | ||
88 | } | ||
91 | 89 | ||
92 | features = kvm_vq_features(desc); | 90 | static void kvm_set_features(struct virtio_device *vdev, u32 features) |
93 | if (!(features[fbit / 8] & (1 << (fbit % 8)))) | 91 | { |
94 | return false; | 92 | unsigned int i; |
93 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; | ||
94 | /* Second half of bitmap is features we accept. */ | ||
95 | u8 *out_features = kvm_vq_features(desc) + desc->feature_len; | ||
95 | 96 | ||
96 | /* | 97 | memset(out_features, 0, desc->feature_len); |
97 | * We set the matching bit in the other half of the bitmap to tell the | 98 | for (i = 0; i < min(desc->feature_len * 8, 32); i++) { |
98 | * Host we want to use this feature. | 99 | if (features & (1 << i)) |
99 | */ | 100 | out_features[i / 8] |= (1 << (i % 8)); |
100 | features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8)); | 101 | } |
101 | return true; | ||
102 | } | 102 | } |
103 | 103 | ||
104 | /* | 104 | /* |
@@ -221,7 +221,8 @@ static void kvm_del_vq(struct virtqueue *vq) | |||
221 | * The config ops structure as defined by virtio config | 221 | * The config ops structure as defined by virtio config |
222 | */ | 222 | */ |
223 | static struct virtio_config_ops kvm_vq_configspace_ops = { | 223 | static struct virtio_config_ops kvm_vq_configspace_ops = { |
224 | .feature = kvm_feature, | 224 | .get_features = kvm_get_features, |
225 | .set_features = kvm_set_features, | ||
225 | .get = kvm_get, | 226 | .get = kvm_get, |
226 | .set = kvm_set, | 227 | .set = kvm_set, |
227 | .get_status = kvm_get_status, | 228 | .get_status = kvm_get_status, |
@@ -244,26 +245,25 @@ static struct device kvm_root = { | |||
244 | * adds a new device and register it with virtio | 245 | * adds a new device and register it with virtio |
245 | * appropriate drivers are loaded by the device model | 246 | * appropriate drivers are loaded by the device model |
246 | */ | 247 | */ |
247 | static void add_kvm_device(struct kvm_device_desc *d) | 248 | static void add_kvm_device(struct kvm_device_desc *d, unsigned int offset) |
248 | { | 249 | { |
249 | struct kvm_device *kdev; | 250 | struct kvm_device *kdev; |
250 | 251 | ||
251 | kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); | 252 | kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); |
252 | if (!kdev) { | 253 | if (!kdev) { |
253 | printk(KERN_EMERG "Cannot allocate kvm dev %u\n", | 254 | printk(KERN_EMERG "Cannot allocate kvm dev %u type %u\n", |
254 | dev_index++); | 255 | offset, d->type); |
255 | return; | 256 | return; |
256 | } | 257 | } |
257 | 258 | ||
258 | kdev->vdev.dev.parent = &kvm_root; | 259 | kdev->vdev.dev.parent = &kvm_root; |
259 | kdev->vdev.index = dev_index++; | ||
260 | kdev->vdev.id.device = d->type; | 260 | kdev->vdev.id.device = d->type; |
261 | kdev->vdev.config = &kvm_vq_configspace_ops; | 261 | kdev->vdev.config = &kvm_vq_configspace_ops; |
262 | kdev->desc = d; | 262 | kdev->desc = d; |
263 | 263 | ||
264 | if (register_virtio_device(&kdev->vdev) != 0) { | 264 | if (register_virtio_device(&kdev->vdev) != 0) { |
265 | printk(KERN_ERR "Failed to register kvm device %u\n", | 265 | printk(KERN_ERR "Failed to register kvm device %u type %u\n", |
266 | kdev->vdev.index); | 266 | offset, d->type); |
267 | kfree(kdev); | 267 | kfree(kdev); |
268 | } | 268 | } |
269 | } | 269 | } |
@@ -283,7 +283,7 @@ static void scan_devices(void) | |||
283 | if (d->type == 0) | 283 | if (d->type == 0) |
284 | break; | 284 | break; |
285 | 285 | ||
286 | add_kvm_device(d); | 286 | add_kvm_device(d, i); |
287 | } | 287 | } |
288 | } | 288 | } |
289 | 289 | ||