diff options
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index 244d611a0df2..65d0c80236ee 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
@@ -664,7 +664,8 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev) | |||
664 | { | 664 | { |
665 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); | 665 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); |
666 | struct virtio_feature_desc *features; | 666 | struct virtio_feature_desc *features; |
667 | int ret, rc; | 667 | int ret; |
668 | u64 rc; | ||
668 | struct ccw1 *ccw; | 669 | struct ccw1 *ccw; |
669 | 670 | ||
670 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); | 671 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); |
@@ -677,7 +678,6 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev) | |||
677 | goto out_free; | 678 | goto out_free; |
678 | } | 679 | } |
679 | /* Read the feature bits from the host. */ | 680 | /* Read the feature bits from the host. */ |
680 | /* TODO: Features > 32 bits */ | ||
681 | features->index = 0; | 681 | features->index = 0; |
682 | ccw->cmd_code = CCW_CMD_READ_FEAT; | 682 | ccw->cmd_code = CCW_CMD_READ_FEAT; |
683 | ccw->flags = 0; | 683 | ccw->flags = 0; |
@@ -691,6 +691,16 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev) | |||
691 | 691 | ||
692 | rc = le32_to_cpu(features->features); | 692 | rc = le32_to_cpu(features->features); |
693 | 693 | ||
694 | /* Read second half of the feature bits from the host. */ | ||
695 | features->index = 1; | ||
696 | ccw->cmd_code = CCW_CMD_READ_FEAT; | ||
697 | ccw->flags = 0; | ||
698 | ccw->count = sizeof(*features); | ||
699 | ccw->cda = (__u32)(unsigned long)features; | ||
700 | ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT); | ||
701 | if (ret == 0) | ||
702 | rc |= (u64)le32_to_cpu(features->features) << 32; | ||
703 | |||
694 | out_free: | 704 | out_free: |
695 | kfree(features); | 705 | kfree(features); |
696 | kfree(ccw); | 706 | kfree(ccw); |
@@ -714,12 +724,18 @@ static void virtio_ccw_finalize_features(struct virtio_device *vdev) | |||
714 | /* Give virtio_ring a chance to accept features. */ | 724 | /* Give virtio_ring a chance to accept features. */ |
715 | vring_transport_features(vdev); | 725 | vring_transport_features(vdev); |
716 | 726 | ||
717 | /* Make sure we don't have any features > 32 bits! */ | ||
718 | BUG_ON((u32)vdev->features != vdev->features); | ||
719 | |||
720 | features->index = 0; | 727 | features->index = 0; |
721 | features->features = cpu_to_le32(vdev->features); | 728 | features->features = cpu_to_le32((u32)vdev->features); |
722 | /* Write the feature bits to the host. */ | 729 | /* Write the first half of the feature bits to the host. */ |
730 | ccw->cmd_code = CCW_CMD_WRITE_FEAT; | ||
731 | ccw->flags = 0; | ||
732 | ccw->count = sizeof(*features); | ||
733 | ccw->cda = (__u32)(unsigned long)features; | ||
734 | ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); | ||
735 | |||
736 | features->index = 1; | ||
737 | features->features = cpu_to_le32(vdev->features >> 32); | ||
738 | /* Write the second half of the feature bits to the host. */ | ||
723 | ccw->cmd_code = CCW_CMD_WRITE_FEAT; | 739 | ccw->cmd_code = CCW_CMD_WRITE_FEAT; |
724 | ccw->flags = 0; | 740 | ccw->flags = 0; |
725 | ccw->count = sizeof(*features); | 741 | ccw->count = sizeof(*features); |