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 | ||
