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