diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-03-06 12:50:54 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-03-06 12:50:54 +0100 |
commit | b010926dc896366602b8dd2430bd3af8c3ef854a (patch) | |
tree | ee4deb69c813ccf6f036fda51dd41d5615dd870c /drivers | |
parent | 1c2af4968ea533e875d7cf8d095c084f18164f5d (diff) | |
parent | 79629b208fc0484ee448c4acfa3762f0350e97ce (diff) |
Merge tag 'kvm-s390-20140306' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into kvm-next
One fix for virtio-ccw, fixing a problem introduced with
"virtio_ccw: fix vcdev pointer handling issues" and noticed just
after it went into git.
Diffstat (limited to 'drivers')
-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 { unsigned long indicators2; struct vq_config_block *config_block; bool is_thinint; + bool going_away; void *airq_info; }; @@ -995,30 +996,39 @@ static struct virtio_ccw_device *virtio_grab_drvdata(struct ccw_device *cdev) spin_lock_irqsave(get_ccwdev_lock(cdev), flags); vcdev = dev_get_drvdata(&cdev->dev); - if (!vcdev) { + if (!vcdev || vcdev->going_away) { spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); return NULL; } - dev_set_drvdata(&cdev->dev, NULL); + vcdev->going_away = true; spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); return vcdev; } static void virtio_ccw_remove(struct ccw_device *cdev) { + unsigned long flags; struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); if (vcdev && cdev->online) unregister_virtio_device(&vcdev->vdev); + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + dev_set_drvdata(&cdev->dev, NULL); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); cdev->handler = NULL; } static int virtio_ccw_offline(struct ccw_device *cdev) { + unsigned long flags; struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); - if (vcdev) + if (vcdev) { unregister_virtio_device(&vcdev->vdev); + spin_lock_irqsave(get_ccwdev_lock(cdev), flags); + dev_set_drvdata(&cdev->dev, NULL); + spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + } return 0; } |