aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-12 00:10:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-12 00:10:33 -0400
commit5c02c392cd2320e8d612376d6b72b6548a680923 (patch)
tree56615b31e21b34414821564cd9bf4c13d7e5d14e /drivers/s390
parent3c81bdd9e7ec5c7e28bedf7c7bd3b8911ffee94a (diff)
parentc77fba9ab058d1e96ed51d4215e56905c9ef8d2a (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.c49
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
1097static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event) 1104static 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
1103static struct ccw_device_id virtio_ids[] = { 1128static struct ccw_device_id virtio_ids[] = {