diff options
author | Thomas Huth <thuth@linux.vnet.ibm.com> | 2014-10-07 10:39:50 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2014-12-09 05:05:26 -0500 |
commit | 6bb2c835c78add24d01351e8c7b040e670c31a46 (patch) | |
tree | c27139d5420bed88b49d89698cc371d7844e3bb3 /drivers/s390 | |
parent | 19c1c5a64c3b8eeb65b63abba248b880dd584589 (diff) |
KVM: s390: Set virtio-ccw transport revision
With the new SET-VIRTIO-REVISION command of the virtio 1.0 standard, we
can now negotiate the virtio-ccw revision after setting a channel online.
Note that we don't negotiate version 1 yet.
[Cornelia Huck: reworked revision loop a bit]
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index 65d0c80236ee..f6eb47b4775b 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; |
@@ -86,6 +87,15 @@ struct virtio_thinint_area { | |||
86 | u8 isc; | 87 | u8 isc; |
87 | } __packed; | 88 | } __packed; |
88 | 89 | ||
90 | struct virtio_rev_info { | ||
91 | __u16 revision; | ||
92 | __u16 length; | ||
93 | __u8 data[]; | ||
94 | }; | ||
95 | |||
96 | /* the highest virtio-ccw revision we support */ | ||
97 | #define VIRTIO_CCW_REV_MAX 0 | ||
98 | |||
89 | struct virtio_ccw_vq_info { | 99 | struct virtio_ccw_vq_info { |
90 | struct virtqueue *vq; | 100 | struct virtqueue *vq; |
91 | int num; | 101 | int num; |
@@ -122,6 +132,7 @@ static struct airq_info *airq_areas[MAX_AIRQ_AREAS]; | |||
122 | #define CCW_CMD_WRITE_STATUS 0x31 | 132 | #define CCW_CMD_WRITE_STATUS 0x31 |
123 | #define CCW_CMD_READ_VQ_CONF 0x32 | 133 | #define CCW_CMD_READ_VQ_CONF 0x32 |
124 | #define CCW_CMD_SET_IND_ADAPTER 0x73 | 134 | #define CCW_CMD_SET_IND_ADAPTER 0x73 |
135 | #define CCW_CMD_SET_VIRTIO_REV 0x83 | ||
125 | 136 | ||
126 | #define VIRTIO_CCW_DOING_SET_VQ 0x00010000 | 137 | #define VIRTIO_CCW_DOING_SET_VQ 0x00010000 |
127 | #define VIRTIO_CCW_DOING_RESET 0x00040000 | 138 | #define VIRTIO_CCW_DOING_RESET 0x00040000 |
@@ -134,6 +145,7 @@ static struct airq_info *airq_areas[MAX_AIRQ_AREAS]; | |||
134 | #define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000 | 145 | #define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000 |
135 | #define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000 | 146 | #define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000 |
136 | #define VIRTIO_CCW_DOING_SET_IND_ADAPTER 0x08000000 | 147 | #define VIRTIO_CCW_DOING_SET_IND_ADAPTER 0x08000000 |
148 | #define VIRTIO_CCW_DOING_SET_VIRTIO_REV 0x10000000 | ||
137 | #define VIRTIO_CCW_INTPARM_MASK 0xffff0000 | 149 | #define VIRTIO_CCW_INTPARM_MASK 0xffff0000 |
138 | 150 | ||
139 | static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev) | 151 | static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev) |
@@ -933,6 +945,7 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, | |||
933 | case VIRTIO_CCW_DOING_RESET: | 945 | case VIRTIO_CCW_DOING_RESET: |
934 | case VIRTIO_CCW_DOING_READ_VQ_CONF: | 946 | case VIRTIO_CCW_DOING_READ_VQ_CONF: |
935 | case VIRTIO_CCW_DOING_SET_IND_ADAPTER: | 947 | case VIRTIO_CCW_DOING_SET_IND_ADAPTER: |
948 | case VIRTIO_CCW_DOING_SET_VIRTIO_REV: | ||
936 | vcdev->curr_io &= ~activity; | 949 | vcdev->curr_io &= ~activity; |
937 | wake_up(&vcdev->wait_q); | 950 | wake_up(&vcdev->wait_q); |
938 | break; | 951 | break; |
@@ -1048,6 +1061,51 @@ static int virtio_ccw_offline(struct ccw_device *cdev) | |||
1048 | return 0; | 1061 | return 0; |
1049 | } | 1062 | } |
1050 | 1063 | ||
1064 | static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev) | ||
1065 | { | ||
1066 | struct virtio_rev_info *rev; | ||
1067 | struct ccw1 *ccw; | ||
1068 | int ret; | ||
1069 | |||
1070 | ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); | ||
1071 | if (!ccw) | ||
1072 | return -ENOMEM; | ||
1073 | rev = kzalloc(sizeof(*rev), GFP_DMA | GFP_KERNEL); | ||
1074 | if (!rev) { | ||
1075 | kfree(ccw); | ||
1076 | return -ENOMEM; | ||
1077 | } | ||
1078 | |||
1079 | /* Set transport revision */ | ||
1080 | ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV; | ||
1081 | ccw->flags = 0; | ||
1082 | ccw->count = sizeof(*rev); | ||
1083 | ccw->cda = (__u32)(unsigned long)rev; | ||
1084 | |||
1085 | vcdev->revision = VIRTIO_CCW_REV_MAX; | ||
1086 | do { | ||
1087 | rev->revision = vcdev->revision; | ||
1088 | /* none of our supported revisions carry payload */ | ||
1089 | rev->length = 0; | ||
1090 | ret = ccw_io_helper(vcdev, ccw, | ||
1091 | VIRTIO_CCW_DOING_SET_VIRTIO_REV); | ||
1092 | if (ret == -EOPNOTSUPP) { | ||
1093 | if (vcdev->revision == 0) | ||
1094 | /* | ||
1095 | * The host device does not support setting | ||
1096 | * the revision: let's operate it in legacy | ||
1097 | * mode. | ||
1098 | */ | ||
1099 | ret = 0; | ||
1100 | else | ||
1101 | vcdev->revision--; | ||
1102 | } | ||
1103 | } while (ret == -EOPNOTSUPP); | ||
1104 | |||
1105 | kfree(ccw); | ||
1106 | kfree(rev); | ||
1107 | return ret; | ||
1108 | } | ||
1051 | 1109 | ||
1052 | static int virtio_ccw_online(struct ccw_device *cdev) | 1110 | static int virtio_ccw_online(struct ccw_device *cdev) |
1053 | { | 1111 | { |
@@ -1088,6 +1146,11 @@ static int virtio_ccw_online(struct ccw_device *cdev) | |||
1088 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1146 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); |
1089 | vcdev->vdev.id.vendor = cdev->id.cu_type; | 1147 | vcdev->vdev.id.vendor = cdev->id.cu_type; |
1090 | vcdev->vdev.id.device = cdev->id.cu_model; | 1148 | vcdev->vdev.id.device = cdev->id.cu_model; |
1149 | |||
1150 | ret = virtio_ccw_set_transport_rev(vcdev); | ||
1151 | if (ret) | ||
1152 | goto out_free; | ||
1153 | |||
1091 | ret = register_virtio_device(&vcdev->vdev); | 1154 | ret = register_virtio_device(&vcdev->vdev); |
1092 | if (ret) { | 1155 | if (ret) { |
1093 | dev_warn(&cdev->dev, "Failed to register virtio device: %d\n", | 1156 | dev_warn(&cdev->dev, "Failed to register virtio device: %d\n", |