aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/kvm/kvm_virtio.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 68cef4da15e8..5a46b8c5d68a 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -32,6 +32,7 @@
32 * The pointer to our (page) of device descriptions. 32 * The pointer to our (page) of device descriptions.
33 */ 33 */
34static void *kvm_devices; 34static void *kvm_devices;
35struct work_struct hotplug_work;
35 36
36struct kvm_device { 37struct kvm_device {
37 struct virtio_device vdev; 38 struct virtio_device vdev;
@@ -328,6 +329,47 @@ static void scan_devices(void)
328} 329}
329 330
330/* 331/*
332 * match for a kvm device with a specific desc pointer
333 */
334static int match_desc(struct device *dev, void *data)
335{
336 if ((ulong)to_kvmdev(dev_to_virtio(dev))->desc == (ulong)data)
337 return 1;
338
339 return 0;
340}
341
342/*
343 * hotplug_device tries to find changes in the device page.
344 */
345static void hotplug_devices(struct work_struct *dummy)
346{
347 unsigned int i;
348 struct kvm_device_desc *d;
349 struct device *dev;
350
351 for (i = 0; i < PAGE_SIZE; i += desc_size(d)) {
352 d = kvm_devices + i;
353
354 /* end of list */
355 if (d->type == 0)
356 break;
357
358 /* device already exists */
359 dev = device_find_child(kvm_root, d, match_desc);
360 if (dev) {
361 /* XXX check for hotplug remove */
362 put_device(dev);
363 continue;
364 }
365
366 /* new device */
367 printk(KERN_INFO "Adding new virtio device %p\n", d);
368 add_kvm_device(d, i);
369 }
370}
371
372/*
331 * we emulate the request_irq behaviour on top of s390 extints 373 * we emulate the request_irq behaviour on top of s390 extints
332 */ 374 */
333static void kvm_extint_handler(u16 code) 375static void kvm_extint_handler(u16 code)
@@ -357,6 +399,9 @@ static void kvm_extint_handler(u16 code)
357 399
358 break; 400 break;
359 } 401 }
402 case VIRTIO_PARAM_DEV_ADD:
403 schedule_work(&hotplug_work);
404 break;
360 case VIRTIO_PARAM_VRING_INTERRUPT: 405 case VIRTIO_PARAM_VRING_INTERRUPT:
361 default: 406 default:
362 vring_interrupt(0, vq); 407 vring_interrupt(0, vq);
@@ -390,6 +435,8 @@ static int __init kvm_devices_init(void)
390 435
391 kvm_devices = (void *) real_memory_size; 436 kvm_devices = (void *) real_memory_size;
392 437
438 INIT_WORK(&hotplug_work, hotplug_devices);
439
393 ctl_set_bit(0, 9); 440 ctl_set_bit(0, 9);
394 register_external_interrupt(0x2603, kvm_extint_handler); 441 register_external_interrupt(0x2603, kvm_extint_handler);
395 442