diff options
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index 6a2b5fdcd552..1e1fc671f89a 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
@@ -61,6 +61,7 @@ struct virtio_ccw_device { | |||
61 | unsigned long indicators2; | 61 | unsigned long indicators2; |
62 | struct vq_config_block *config_block; | 62 | struct vq_config_block *config_block; |
63 | bool is_thinint; | 63 | bool is_thinint; |
64 | bool going_away; | ||
64 | void *airq_info; | 65 | void *airq_info; |
65 | }; | 66 | }; |
66 | 67 | ||
@@ -995,30 +996,39 @@ static struct virtio_ccw_device *virtio_grab_drvdata(struct ccw_device *cdev) | |||
995 | 996 | ||
996 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | 997 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); |
997 | vcdev = dev_get_drvdata(&cdev->dev); | 998 | vcdev = dev_get_drvdata(&cdev->dev); |
998 | if (!vcdev) { | 999 | if (!vcdev || vcdev->going_away) { |
999 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1000 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); |
1000 | return NULL; | 1001 | return NULL; |
1001 | } | 1002 | } |
1002 | dev_set_drvdata(&cdev->dev, NULL); | 1003 | vcdev->going_away = true; |
1003 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1004 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); |
1004 | return vcdev; | 1005 | return vcdev; |
1005 | } | 1006 | } |
1006 | 1007 | ||
1007 | static void virtio_ccw_remove(struct ccw_device *cdev) | 1008 | static void virtio_ccw_remove(struct ccw_device *cdev) |
1008 | { | 1009 | { |
1010 | unsigned long flags; | ||
1009 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); | 1011 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); |
1010 | 1012 | ||
1011 | if (vcdev && cdev->online) | 1013 | if (vcdev && cdev->online) |
1012 | unregister_virtio_device(&vcdev->vdev); | 1014 | unregister_virtio_device(&vcdev->vdev); |
1015 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | ||
1016 | dev_set_drvdata(&cdev->dev, NULL); | ||
1017 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | ||
1013 | cdev->handler = NULL; | 1018 | cdev->handler = NULL; |
1014 | } | 1019 | } |
1015 | 1020 | ||
1016 | static int virtio_ccw_offline(struct ccw_device *cdev) | 1021 | static int virtio_ccw_offline(struct ccw_device *cdev) |
1017 | { | 1022 | { |
1023 | unsigned long flags; | ||
1018 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); | 1024 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); |
1019 | 1025 | ||
1020 | if (vcdev) | 1026 | if (vcdev) { |
1021 | unregister_virtio_device(&vcdev->vdev); | 1027 | unregister_virtio_device(&vcdev->vdev); |
1028 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | ||
1029 | dev_set_drvdata(&cdev->dev, NULL); | ||
1030 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | ||
1031 | } | ||
1022 | return 0; | 1032 | return 0; |
1023 | } | 1033 | } |
1024 | 1034 | ||