diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 00:10:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 00:10:33 -0400 |
commit | 5c02c392cd2320e8d612376d6b72b6548a680923 (patch) | |
tree | 56615b31e21b34414821564cd9bf4c13d7e5d14e /drivers/s390 | |
parent | 3c81bdd9e7ec5c7e28bedf7c7bd3b8911ffee94a (diff) | |
parent | c77fba9ab058d1e96ed51d4215e56905c9ef8d2a (diff) |
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull virtio updates from Rusty Russell:
"Main excitement is a virtio_scsi fix for alloc holding spinlock on the
abort path, which I refuse to CC stable since (1) I discovered it
myself, and (2) it's been there forever with no reports"
* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
virtio_scsi: don't call virtqueue_add_sgs(... GFP_NOIO) holding spinlock.
virtio-rng: fixes for device registration/unregistration
virtio-rng: fix boot with virtio-rng device
virtio-rng: support multiple virtio-rng devices
virtio_ccw: introduce device_lost in virtio_ccw_device
virtio: virtio_break_device() to mark all virtqueues broken.
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index 1e1fc671f89a..d2c0b442bce5 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/kvm_para.h> | 29 | #include <linux/kvm_para.h> |
30 | #include <linux/notifier.h> | ||
30 | #include <asm/setup.h> | 31 | #include <asm/setup.h> |
31 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
32 | #include <asm/cio.h> | 33 | #include <asm/cio.h> |
@@ -62,6 +63,7 @@ struct virtio_ccw_device { | |||
62 | struct vq_config_block *config_block; | 63 | struct vq_config_block *config_block; |
63 | bool is_thinint; | 64 | bool is_thinint; |
64 | bool going_away; | 65 | bool going_away; |
66 | bool device_lost; | ||
65 | void *airq_info; | 67 | void *airq_info; |
66 | }; | 68 | }; |
67 | 69 | ||
@@ -1010,11 +1012,14 @@ static void virtio_ccw_remove(struct ccw_device *cdev) | |||
1010 | unsigned long flags; | 1012 | unsigned long flags; |
1011 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); | 1013 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); |
1012 | 1014 | ||
1013 | if (vcdev && cdev->online) | 1015 | if (vcdev && cdev->online) { |
1016 | if (vcdev->device_lost) | ||
1017 | virtio_break_device(&vcdev->vdev); | ||
1014 | unregister_virtio_device(&vcdev->vdev); | 1018 | unregister_virtio_device(&vcdev->vdev); |
1015 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | 1019 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); |
1016 | dev_set_drvdata(&cdev->dev, NULL); | 1020 | dev_set_drvdata(&cdev->dev, NULL); |
1017 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1021 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); |
1022 | } | ||
1018 | cdev->handler = NULL; | 1023 | cdev->handler = NULL; |
1019 | } | 1024 | } |
1020 | 1025 | ||
@@ -1023,12 +1028,14 @@ static int virtio_ccw_offline(struct ccw_device *cdev) | |||
1023 | unsigned long flags; | 1028 | unsigned long flags; |
1024 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); | 1029 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); |
1025 | 1030 | ||
1026 | if (vcdev) { | 1031 | if (!vcdev) |
1027 | unregister_virtio_device(&vcdev->vdev); | 1032 | return 0; |
1028 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | 1033 | if (vcdev->device_lost) |
1029 | dev_set_drvdata(&cdev->dev, NULL); | 1034 | virtio_break_device(&vcdev->vdev); |
1030 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1035 | unregister_virtio_device(&vcdev->vdev); |
1031 | } | 1036 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); |
1037 | dev_set_drvdata(&cdev->dev, NULL); | ||
1038 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | ||
1032 | return 0; | 1039 | return 0; |
1033 | } | 1040 | } |
1034 | 1041 | ||
@@ -1096,8 +1103,26 @@ out_free: | |||
1096 | 1103 | ||
1097 | static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event) | 1104 | static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event) |
1098 | { | 1105 | { |
1099 | /* TODO: Check whether we need special handling here. */ | 1106 | int rc; |
1100 | return 0; | 1107 | struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); |
1108 | |||
1109 | /* | ||
1110 | * Make sure vcdev is set | ||
1111 | * i.e. set_offline/remove callback not already running | ||
1112 | */ | ||
1113 | if (!vcdev) | ||
1114 | return NOTIFY_DONE; | ||
1115 | |||
1116 | switch (event) { | ||
1117 | case CIO_GONE: | ||
1118 | vcdev->device_lost = true; | ||
1119 | rc = NOTIFY_DONE; | ||
1120 | break; | ||
1121 | default: | ||
1122 | rc = NOTIFY_DONE; | ||
1123 | break; | ||
1124 | } | ||
1125 | return rc; | ||
1101 | } | 1126 | } |
1102 | 1127 | ||
1103 | static struct ccw_device_id virtio_ids[] = { | 1128 | static struct ccw_device_id virtio_ids[] = { |