diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-11 15:20:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-11 15:20:31 -0500 |
commit | 6b9e2cea428cf7af93a84bcb865e478d8bf1c165 (patch) | |
tree | 11be387e37129fce0c4c111803df1a2e56637b60 /drivers/s390 | |
parent | 14ba9a2e4bacc6f5a0dbe0de5390daedd544508f (diff) | |
parent | f01a2a811ae04124fc9382925038fcbbd2f0b7c8 (diff) |
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull virtio updates from Michael Tsirkin:
"virtio: virtio 1.0 support, misc patches
This adds a lot of infrastructure for virtio 1.0 support. Notable
missing pieces: virtio pci, virtio balloon (needs spec extension),
vhost scsi.
Plus, there are some minor fixes in a couple of places.
Note: some net drivers are affected by these patches. David said he's
fine with merging these patches through my tree.
Rusty's on vacation, he acked using my tree for these, too"
* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (70 commits)
virtio_ccw: finalize_features error handling
virtio_ccw: future-proof finalize_features
virtio_pci: rename virtio_pci -> virtio_pci_common
virtio_pci: update file descriptions and copyright
virtio_pci: split out legacy device support
virtio_pci: setup config vector indirectly
virtio_pci: setup vqs indirectly
virtio_pci: delete vqs indirectly
virtio_pci: use priv for vq notification
virtio_pci: free up vq->priv
virtio_pci: fix coding style for structs
virtio_pci: add isr field
virtio: drop legacy_only driver flag
virtio_balloon: drop legacy_only driver flag
virtio_ccw: rev 1 devices set VIRTIO_F_VERSION_1
virtio: allow finalize_features to fail
virtio_ccw: legacy: don't negotiate rev 1/features
virtio: add API to detect legacy devices
virtio_console: fix sparse warnings
vhost: remove unnecessary forward declarations in vhost.h
...
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/kvm/kvm_virtio.c | 11 | ||||
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 203 |
2 files changed, 177 insertions, 37 deletions
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 643129070c51..dd65c8b4c7fe 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -80,7 +80,7 @@ static unsigned desc_size(const struct kvm_device_desc *desc) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | /* This gets the device's feature bits. */ | 82 | /* This gets the device's feature bits. */ |
83 | static u32 kvm_get_features(struct virtio_device *vdev) | 83 | static u64 kvm_get_features(struct virtio_device *vdev) |
84 | { | 84 | { |
85 | unsigned int i; | 85 | unsigned int i; |
86 | u32 features = 0; | 86 | u32 features = 0; |
@@ -93,7 +93,7 @@ static u32 kvm_get_features(struct virtio_device *vdev) | |||
93 | return features; | 93 | return features; |
94 | } | 94 | } |
95 | 95 | ||
96 | static void kvm_finalize_features(struct virtio_device *vdev) | 96 | static int kvm_finalize_features(struct virtio_device *vdev) |
97 | { | 97 | { |
98 | unsigned int i, bits; | 98 | unsigned int i, bits; |
99 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; | 99 | struct kvm_device_desc *desc = to_kvmdev(vdev)->desc; |
@@ -103,12 +103,17 @@ static void kvm_finalize_features(struct virtio_device *vdev) | |||
103 | /* Give virtio_ring a chance to accept features. */ | 103 | /* Give virtio_ring a chance to accept features. */ |
104 | vring_transport_features(vdev); | 104 | vring_transport_features(vdev); |
105 | 105 | ||
106 | /* Make sure we don't have any features > 32 bits! */ | ||
107 | BUG_ON((u32)vdev->features != vdev->features); | ||
108 | |||
106 | memset(out_features, 0, desc->feature_len); | 109 | memset(out_features, 0, desc->feature_len); |
107 | bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; | 110 | bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; |
108 | for (i = 0; i < bits; i++) { | 111 | for (i = 0; i < bits; i++) { |
109 | if (test_bit(i, vdev->features)) | 112 | if (__virtio_test_bit(vdev, i)) |
110 | out_features[i / 8] |= (1 << (i % 8)); | 113 | out_features[i / 8] |= (1 << (i % 8)); |
111 | } | 114 | } |
115 | |||
116 | return 0; | ||
112 | } | 117 | } |
113 | 118 | ||
114 | /* | 119 | /* |
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index bda52f18e967..71d7802aa8b4 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
@@ -55,6 +55,7 @@ struct virtio_ccw_device { | |||
55 | struct ccw_device *cdev; | 55 | struct ccw_device *cdev; |
56 | __u32 curr_io; | 56 | __u32 curr_io; |
57 | int err; | 57 | int err; |
58 | unsigned int revision; /* Transport revision */ | ||
58 | wait_queue_head_t wait_q; | 59 | wait_queue_head_t wait_q; |
59 | spinlock_t lock; | 60 | spinlock_t lock; |
60 | struct list_head virtqueues; | 61 | struct list_head virtqueues; |
@@ -67,13 +68,22 @@ struct virtio_ccw_device { | |||
67 | void *airq_info; | 68 | void *airq_info; |
68 | }; | 69 | }; |
69 | 70 | ||
70 | struct vq_info_block { | 71 | struct vq_info_block_legacy { |
71 | __u64 queue; | 72 | __u64 queue; |
72 | __u32 align; | 73 | __u32 align; |
73 | __u16 index; | 74 | __u16 index; |
74 | __u16 num; | 75 | __u16 num; |
75 | } __packed; | 76 | } __packed; |
76 | 77 | ||
78 | struct vq_info_block { | ||
79 | __u64 desc; | ||
80 | __u32 res0; | ||
81 | __u16 index; | ||
82 | __u16 num; | ||
83 | __u64 avail; | ||
84 | __u64 used; | ||
85 | } __packed; | ||
86 | |||
77 | struct virtio_feature_desc { | 87 | struct virtio_feature_desc { |
78 | __u32 features; | 88 | __u32 features; |
79 | __u8 index; | 89 | __u8 index; |
@@ -86,11 +96,23 @@ struct virtio_thinint_area { | |||
86 | u8 isc; | 96 | u8 isc; |
87 | } __packed; | 97 | } __packed; |
88 | 98 | ||
99 | struct virtio_rev_info { | ||
100 | __u16 revision; | ||
101 | __u16 length; | ||
102 | __u8 data[]; | ||
103 | }; | ||
104 | |||
105 | /* the highest virtio-ccw revision we support */ | ||
106 | #define VIRTIO_CCW_REV_MAX 1 | ||
107 | |||
89 | struct virtio_ccw_vq_info { | 108 | struct virtio_ccw_vq_info { |
90 | struct virtqueue *vq; | 109 | struct virtqueue *vq; |
91 | int num; | 110 | int num; |
92 | void *queue; | 111 | void *queue; |
93 | struct vq_info_block *info_block; | 112 | union { |
113 | struct vq_info_block s; | ||
114 | struct vq_info_block_legacy l; | ||
115 | } *info_block; | ||
94 | int bit_nr; | 116 | int bit_nr; |
95 | struct list_head node; | 117 | struct list_head node; |
96 | long cookie; | 118 | long cookie; |
@@ -122,6 +144,7 @@ static struct airq_info *airq_areas[MAX_AIRQ_AREAS]; | |||
122 | #define CCW_CMD_WRITE_STATUS 0x31 | 144 | #define CCW_CMD_WRITE_STATUS 0x31 |
123 | #define CCW_CMD_READ_VQ_CONF 0x32 | 145 | #define CCW_CMD_READ_VQ_CONF 0x32 |
124 | #define CCW_CMD_SET_IND_ADAPTER 0x73 | 146 | #define CCW_CMD_SET_IND_ADAPTER 0x73 |
147 | #define CCW_CMD_SET_VIRTIO_REV 0x83 | ||
125 | 148 | ||
126 | #define VIRTIO_CCW_DOING_SET_VQ 0x00010000 | 149 | #define VIRTIO_CCW_DOING_SET_VQ 0x00010000 |
127 | #define VIRTIO_CCW_DOING_RESET 0x00040000 | 150 | #define VIRTIO_CCW_DOING_RESET 0x00040000 |
@@ -134,6 +157,7 @@ static struct airq_info *airq_areas[MAX_AIRQ_AREAS]; | |||
134 | #define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000 | 157 | #define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000 |
135 | #define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000 | 158 | #define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000 |
136 | #define VIRTIO_CCW_DOING_SET_IND_ADAPTER 0x08000000 | 159 | #define VIRTIO_CCW_DOING_SET_IND_ADAPTER 0x08000000 |
160 | #define VIRTIO_CCW_DOING_SET_VIRTIO_REV 0x10000000 | ||
137 | #define VIRTIO_CCW_INTPARM_MASK 0xffff0000 | 161 | #define VIRTIO_CCW_INTPARM_MASK 0xffff0000 |
138 | 162 | ||
139 | static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev) | 163 | static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev) |
@@ -399,13 +423,22 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) | |||
399 | spin_unlock_irqrestore(&vcdev->lock, flags); | 423 | spin_unlock_irqrestore(&vcdev->lock, flags); |
400 | 424 | ||
401 | /* Release from host. */ | 425 | /* Release from host. */ |
402 | info->info_block->queue = 0; | 426 | if (vcdev->revision == 0) { |
403 | info->info_block->align = 0; | 427 | info->info_block->l.queue = 0; |
404 | info->info_block->index = index; | 428 | info->info_block->l.align = 0; |
405 | info->info_block->num = 0; | 429 | info->info_block->l.index = index; |
430 | info->info_block->l.num = 0; | ||
431 | ccw->count = sizeof(info->info_block->l); | ||
432 | } else { | ||
433 | info->info_block->s.desc = 0; | ||
434 | info->info_block->s.index = index; | ||
435 | info->info_block->s.num = 0; | ||
436 | info->info_block->s.avail = 0; | ||
437 | info->info_block->s.used = 0; | ||
438 | ccw->count = sizeof(info->info_block->s); | ||
439 | } | ||
406 | ccw->cmd_code = CCW_CMD_SET_VQ; | 440 | ccw->cmd_code = CCW_CMD_SET_VQ; |
407 | ccw->flags = 0; | 441 | ccw->flags = 0; |
408 | ccw->count = sizeof(*info->info_block); | ||
409 | ccw->cda = (__u32)(unsigned long)(info->info_block); | 442 | ccw->cda = (__u32)(unsigned long)(info->info_block); |
410 | ret = ccw_io_helper(vcdev, ccw, | 443 | ret = ccw_io_helper(vcdev, ccw, |
411 | VIRTIO_CCW_DOING_SET_VQ | index); | 444 | VIRTIO_CCW_DOING_SET_VQ | index); |
@@ -488,13 +521,22 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, | |||
488 | } | 521 | } |
489 | 522 | ||
490 | /* Register it with the host. */ | 523 | /* Register it with the host. */ |
491 | info->info_block->queue = (__u64)info->queue; | 524 | if (vcdev->revision == 0) { |
492 | info->info_block->align = KVM_VIRTIO_CCW_RING_ALIGN; | 525 | info->info_block->l.queue = (__u64)info->queue; |
493 | info->info_block->index = i; | 526 | info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN; |
494 | info->info_block->num = info->num; | 527 | info->info_block->l.index = i; |
528 | info->info_block->l.num = info->num; | ||
529 | ccw->count = sizeof(info->info_block->l); | ||
530 | } else { | ||
531 | info->info_block->s.desc = (__u64)info->queue; | ||
532 | info->info_block->s.index = i; | ||
533 | info->info_block->s.num = info->num; | ||
534 | info->info_block->s.avail = (__u64)virtqueue_get_avail(vq); | ||
535 | info->info_block->s.used = (__u64)virtqueue_get_used(vq); | ||
536 | ccw->count = sizeof(info->info_block->s); | ||
537 | } | ||
495 | ccw->cmd_code = CCW_CMD_SET_VQ; | 538 | ccw->cmd_code = CCW_CMD_SET_VQ; |
496 | ccw->flags = 0; | 539 | ccw->flags = 0; |
497 | ccw->count = sizeof(*info->info_block); | ||
498 | ccw->cda = (__u32)(unsigned long)(info->info_block); | 540 | ccw->cda = (__u32)(unsigned long)(info->info_block); |
499 | err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i); | 541 | err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i); |
500 | if (err) { | 542 | if (err) { |
@@ -660,11 +702,12 @@ static void virtio_ccw_reset(struct virtio_device *vdev) | |||
660 | kfree(ccw); | 702 | kfree(ccw); |
661 | } | 703 | } |
662 | 704 | ||
663 | static u32 virtio_ccw_get_features(struct virtio_device *vdev) | 705 | static u64 virtio_ccw_get_features(struct virtio_device *vdev) |
664 | { | 706 | { |
665 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); | 707 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); |
666 | struct virtio_feature_desc *features; | 708 | struct virtio_feature_desc *features; |
667 | int ret, rc; | 709 | int ret; |
710 | u64 rc; | ||
668 | struct ccw1 *ccw; | 711 | struct ccw1 *ccw; |
669 | 712 | ||
670 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); | 713 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); |
@@ -677,7 +720,6 @@ static u32 virtio_ccw_get_features(struct virtio_device *vdev) | |||
677 | goto out_free; | 720 | goto out_free; |
678 | } | 721 | } |
679 | /* Read the feature bits from the host. */ | 722 | /* Read the feature bits from the host. */ |
680 | /* TODO: Features > 32 bits */ | ||
681 | features->index = 0; | 723 | features->index = 0; |
682 | ccw->cmd_code = CCW_CMD_READ_FEAT; | 724 | ccw->cmd_code = CCW_CMD_READ_FEAT; |
683 | ccw->flags = 0; | 725 | ccw->flags = 0; |
@@ -691,46 +733,79 @@ static u32 virtio_ccw_get_features(struct virtio_device *vdev) | |||
691 | 733 | ||
692 | rc = le32_to_cpu(features->features); | 734 | rc = le32_to_cpu(features->features); |
693 | 735 | ||
736 | if (vcdev->revision == 0) | ||
737 | goto out_free; | ||
738 | |||
739 | /* Read second half of the feature bits from the host. */ | ||
740 | features->index = 1; | ||
741 | ccw->cmd_code = CCW_CMD_READ_FEAT; | ||
742 | ccw->flags = 0; | ||
743 | ccw->count = sizeof(*features); | ||
744 | ccw->cda = (__u32)(unsigned long)features; | ||
745 | ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT); | ||
746 | if (ret == 0) | ||
747 | rc |= (u64)le32_to_cpu(features->features) << 32; | ||
748 | |||
694 | out_free: | 749 | out_free: |
695 | kfree(features); | 750 | kfree(features); |
696 | kfree(ccw); | 751 | kfree(ccw); |
697 | return rc; | 752 | return rc; |
698 | } | 753 | } |
699 | 754 | ||
700 | static void virtio_ccw_finalize_features(struct virtio_device *vdev) | 755 | static int virtio_ccw_finalize_features(struct virtio_device *vdev) |
701 | { | 756 | { |
702 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); | 757 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); |
703 | struct virtio_feature_desc *features; | 758 | struct virtio_feature_desc *features; |
704 | int i; | ||
705 | struct ccw1 *ccw; | 759 | struct ccw1 *ccw; |
760 | int ret; | ||
761 | |||
762 | if (vcdev->revision >= 1 && | ||
763 | !__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { | ||
764 | dev_err(&vdev->dev, "virtio: device uses revision 1 " | ||
765 | "but does not have VIRTIO_F_VERSION_1\n"); | ||
766 | return -EINVAL; | ||
767 | } | ||
706 | 768 | ||
707 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); | 769 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); |
708 | if (!ccw) | 770 | if (!ccw) |
709 | return; | 771 | return -ENOMEM; |
710 | 772 | ||
711 | features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); | 773 | features = kzalloc(sizeof(*features), GFP_DMA | GFP_KERNEL); |
712 | if (!features) | 774 | if (!features) { |
775 | ret = -ENOMEM; | ||
713 | goto out_free; | 776 | goto out_free; |
714 | 777 | } | |
715 | /* Give virtio_ring a chance to accept features. */ | 778 | /* Give virtio_ring a chance to accept features. */ |
716 | vring_transport_features(vdev); | 779 | vring_transport_features(vdev); |
717 | 780 | ||
718 | for (i = 0; i < sizeof(*vdev->features) / sizeof(features->features); | 781 | features->index = 0; |
719 | i++) { | 782 | features->features = cpu_to_le32((u32)vdev->features); |
720 | int highbits = i % 2 ? 32 : 0; | 783 | /* Write the first half of the feature bits to the host. */ |
721 | features->index = i; | 784 | ccw->cmd_code = CCW_CMD_WRITE_FEAT; |
722 | features->features = cpu_to_le32(vdev->features[i / 2] | 785 | ccw->flags = 0; |
723 | >> highbits); | 786 | ccw->count = sizeof(*features); |
724 | /* Write the feature bits to the host. */ | 787 | ccw->cda = (__u32)(unsigned long)features; |
725 | ccw->cmd_code = CCW_CMD_WRITE_FEAT; | 788 | ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); |
726 | ccw->flags = 0; | 789 | if (ret) |
727 | ccw->count = sizeof(*features); | 790 | goto out_free; |
728 | ccw->cda = (__u32)(unsigned long)features; | 791 | |
729 | ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); | 792 | if (vcdev->revision == 0) |
730 | } | 793 | goto out_free; |
794 | |||
795 | features->index = 1; | ||
796 | features->features = cpu_to_le32(vdev->features >> 32); | ||
797 | /* Write the second half of the feature bits to the host. */ | ||
798 | ccw->cmd_code = CCW_CMD_WRITE_FEAT; | ||
799 | ccw->flags = 0; | ||
800 | ccw->count = sizeof(*features); | ||
801 | ccw->cda = (__u32)(unsigned long)features; | ||
802 | ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT); | ||
803 | |||
731 | out_free: | 804 | out_free: |
732 | kfree(features); | 805 | kfree(features); |
733 | kfree(ccw); | 806 | kfree(ccw); |
807 | |||
808 | return ret; | ||
734 | } | 809 | } |
735 | 810 | ||
736 | static void virtio_ccw_get_config(struct virtio_device *vdev, | 811 | static void virtio_ccw_get_config(struct virtio_device *vdev, |
@@ -806,7 +881,9 @@ static u8 virtio_ccw_get_status(struct virtio_device *vdev) | |||
806 | static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status) | 881 | static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status) |
807 | { | 882 | { |
808 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); | 883 | struct virtio_ccw_device *vcdev = to_vc_device(vdev); |
884 | u8 old_status = *vcdev->status; | ||
809 | struct ccw1 *ccw; | 885 | struct ccw1 *ccw; |
886 | int ret; | ||
810 | 887 | ||
811 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); | 888 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); |
812 | if (!ccw) | 889 | if (!ccw) |
@@ -818,7 +895,10 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status) | |||
818 | ccw->flags = 0; | 895 | ccw->flags = 0; |
819 | ccw->count = sizeof(status); | 896 | ccw->count = sizeof(status); |
820 | ccw->cda = (__u32)(unsigned long)vcdev->status; | 897 | ccw->cda = (__u32)(unsigned long)vcdev->status; |
821 | ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS); | 898 | ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS); |
899 | /* Write failed? We assume status is unchanged. */ | ||
900 | if (ret) | ||
901 | *vcdev->status = old_status; | ||
822 | kfree(ccw); | 902 | kfree(ccw); |
823 | } | 903 | } |
824 | 904 | ||
@@ -919,6 +999,7 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, | |||
919 | case VIRTIO_CCW_DOING_RESET: | 999 | case VIRTIO_CCW_DOING_RESET: |
920 | case VIRTIO_CCW_DOING_READ_VQ_CONF: | 1000 | case VIRTIO_CCW_DOING_READ_VQ_CONF: |
921 | case VIRTIO_CCW_DOING_SET_IND_ADAPTER: | 1001 | case VIRTIO_CCW_DOING_SET_IND_ADAPTER: |
1002 | case VIRTIO_CCW_DOING_SET_VIRTIO_REV: | ||
922 | vcdev->curr_io &= ~activity; | 1003 | vcdev->curr_io &= ~activity; |
923 | wake_up(&vcdev->wait_q); | 1004 | wake_up(&vcdev->wait_q); |
924 | break; | 1005 | break; |
@@ -1034,6 +1115,51 @@ static int virtio_ccw_offline(struct ccw_device *cdev) | |||
1034 | return 0; | 1115 | return 0; |
1035 | } | 1116 | } |
1036 | 1117 | ||
1118 | static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev) | ||
1119 | { | ||
1120 | struct virtio_rev_info *rev; | ||
1121 | struct ccw1 *ccw; | ||
1122 | int ret; | ||
1123 | |||
1124 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); | ||
1125 | if (!ccw) | ||
1126 | return -ENOMEM; | ||
1127 | rev = kzalloc(sizeof(*rev), GFP_DMA | GFP_KERNEL); | ||
1128 | if (!rev) { | ||
1129 | kfree(ccw); | ||
1130 | return -ENOMEM; | ||
1131 | } | ||
1132 | |||
1133 | /* Set transport revision */ | ||
1134 | ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV; | ||
1135 | ccw->flags = 0; | ||
1136 | ccw->count = sizeof(*rev); | ||
1137 | ccw->cda = (__u32)(unsigned long)rev; | ||
1138 | |||
1139 | vcdev->revision = VIRTIO_CCW_REV_MAX; | ||
1140 | do { | ||
1141 | rev->revision = vcdev->revision; | ||
1142 | /* none of our supported revisions carry payload */ | ||
1143 | rev->length = 0; | ||
1144 | ret = ccw_io_helper(vcdev, ccw, | ||
1145 | VIRTIO_CCW_DOING_SET_VIRTIO_REV); | ||
1146 | if (ret == -EOPNOTSUPP) { | ||
1147 | if (vcdev->revision == 0) | ||
1148 | /* | ||
1149 | * The host device does not support setting | ||
1150 | * the revision: let's operate it in legacy | ||
1151 | * mode. | ||
1152 | */ | ||
1153 | ret = 0; | ||
1154 | else | ||
1155 | vcdev->revision--; | ||
1156 | } | ||
1157 | } while (ret == -EOPNOTSUPP); | ||
1158 | |||
1159 | kfree(ccw); | ||
1160 | kfree(rev); | ||
1161 | return ret; | ||
1162 | } | ||
1037 | 1163 | ||
1038 | static int virtio_ccw_online(struct ccw_device *cdev) | 1164 | static int virtio_ccw_online(struct ccw_device *cdev) |
1039 | { | 1165 | { |
@@ -1074,6 +1200,15 @@ static int virtio_ccw_online(struct ccw_device *cdev) | |||
1074 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1200 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); |
1075 | vcdev->vdev.id.vendor = cdev->id.cu_type; | 1201 | vcdev->vdev.id.vendor = cdev->id.cu_type; |
1076 | vcdev->vdev.id.device = cdev->id.cu_model; | 1202 | vcdev->vdev.id.device = cdev->id.cu_model; |
1203 | |||
1204 | if (virtio_device_is_legacy_only(vcdev->vdev.id)) { | ||
1205 | vcdev->revision = 0; | ||
1206 | } else { | ||
1207 | ret = virtio_ccw_set_transport_rev(vcdev); | ||
1208 | if (ret) | ||
1209 | goto out_free; | ||
1210 | } | ||
1211 | |||
1077 | ret = register_virtio_device(&vcdev->vdev); | 1212 | ret = register_virtio_device(&vcdev->vdev); |
1078 | if (ret) { | 1213 | if (ret) { |
1079 | dev_warn(&cdev->dev, "Failed to register virtio device: %d\n", | 1214 | dev_warn(&cdev->dev, "Failed to register virtio device: %d\n", |