diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2014-12-09 05:46:59 -0500 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2014-12-09 14:42:06 -0500 |
commit | f01a2a811ae04124fc9382925038fcbbd2f0b7c8 (patch) | |
tree | 7265d633ac1bbe24109ce8b79bad0c1712b61e18 | |
parent | f13d8bc2a16c5d1dd3dbd8b64dbd42cfe78da93e (diff) |
virtio_ccw: finalize_features error handling
We previously tried to use device even if finalize_features failed, but
that's wrong since driver and device are now out of sync.
Fail probe if we detect failures during finalize_features.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index f92b9e66c200..71d7802aa8b4 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
@@ -757,6 +757,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev) | |||
757 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); | 757 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); |
758 | struct virtio_feature_desc *features; | 758 | struct virtio_feature_desc *features; |
759 | struct ccw1 *ccw; | 759 | struct ccw1 *ccw; |
760 | int ret; | ||
760 | 761 | ||
761 | if (vcdev->revision >= 1 && | 762 | if (vcdev->revision >= 1 && |
762 | !__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { | 763 | !__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { |
@@ -767,12 +768,13 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev) | |||
767 | 768 | ||
768 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); | 769 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); |
769 | if (!ccw) | 770 | if (!ccw) |
770 | return 0; | 771 | return -ENOMEM; |
771 | 772 | ||
772 | features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); | 773 | features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); |
773 | if (!features) | 774 | if (!features) { |
775 | ret = -ENOMEM; | ||
774 | goto out_free; | 776 | goto out_free; |
775 | 777 | } | |
776 | /* Give virtio_ring a chance to accept features. */ | 778 | /* Give virtio_ring a chance to accept features. */ |
777 | vring_transport_features(vdev); | 779 | vring_transport_features(vdev); |
778 | 780 | ||
@@ -783,7 +785,9 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev) | |||
783 | ccw->flags = 0; | 785 | ccw->flags = 0; |
784 | ccw->count = sizeof(*features); | 786 | ccw->count = sizeof(*features); |
785 | ccw->cda = (__u32)(unsigned long)features; | 787 | ccw->cda = (__u32)(unsigned long)features; |
786 | ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); | 788 | ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); |
789 | if (ret) | ||
790 | goto out_free; | ||
787 | 791 | ||
788 | if (vcdev->revision == 0) | 792 | if (vcdev->revision == 0) |
789 | goto out_free; | 793 | goto out_free; |
@@ -795,13 +799,13 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev) | |||
795 | ccw->flags = 0; | 799 | ccw->flags = 0; |
796 | ccw->count = sizeof(*features); | 800 | ccw->count = sizeof(*features); |
797 | ccw->cda = (__u32)(unsigned long)features; | 801 | ccw->cda = (__u32)(unsigned long)features; |
798 | ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); | 802 | ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); |
799 | 803 | ||
800 | out_free: | 804 | out_free: |
801 | kfree(features); | 805 | kfree(features); |
802 | kfree(ccw); | 806 | kfree(ccw); |
803 | 807 | ||
804 | return 0; | 808 | return ret; |
805 | } | 809 | } |
806 | 810 | ||
807 | static void virtio_ccw_get_config(struct virtio_device *vdev, | 811 | static void virtio_ccw_get_config(struct virtio_device *vdev, |