diff options
| -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[] = { |
