summaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-03-06 15:50:54 +0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-03-06 15:50:54 +0400
commitb010926dc896366602b8dd2430bd3af8c3ef854a (patch)
treeee4deb69c813ccf6f036fda51dd41d5615dd870c /drivers/s390
parent1c2af4968ea533e875d7cf8d095c084f18164f5d (diff)
parent79629b208fc0484ee448c4acfa3762f0350e97ce (diff)
downloadlinux-b010926dc896366602b8dd2430bd3af8c3ef854a.tar.xz
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/s390')
-rw-r--r--drivers/s390/kvm/virtio_ccw.c16
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;
}