diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2014-10-07 10:39:51 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2014-12-09 05:05:26 -0500 |
commit | d4674240f31f8c4289abba07d64291c6ddce51bc (patch) | |
tree | f4ddf856acbd9d29156998bc4cc59ee55bf10fe7 /drivers/s390 | |
parent | 6bb2c835c78add24d01351e8c7b040e670c31a46 (diff) |
KVM: s390: virtio-ccw revision 1 SET_VQ
The CCW_CMD_SET_VQ command has a different format for revision 1+
devices, allowing to specify a more complex virtqueue layout. For
now, we stay however with the old layout and simply use the new
command format for virtio-1 devices.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index f6eb47b4775b..1c21c08f33be 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
@@ -68,13 +68,22 @@ struct virtio_ccw_device { | |||
68 | void *airq_info; | 68 | void *airq_info; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | struct vq_info_block { | 71 | struct vq_info_block_legacy { |
72 | __u64 queue; | 72 | __u64 queue; |
73 | __u32 align; | 73 | __u32 align; |
74 | __u16 index; | 74 | __u16 index; |
75 | __u16 num; | 75 | __u16 num; |
76 | } __packed; | 76 | } __packed; |
77 | 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 | |||
78 | struct virtio_feature_desc { | 87 | struct virtio_feature_desc { |
79 | __u32 features; | 88 | __u32 features; |
80 | __u8 index; | 89 | __u8 index; |
@@ -100,7 +109,10 @@ struct virtio_ccw_vq_info { | |||
100 | struct virtqueue *vq; | 109 | struct virtqueue *vq; |
101 | int num; | 110 | int num; |
102 | void *queue; | 111 | void *queue; |
103 | struct vq_info_block *info_block; | 112 | union { |
113 | struct vq_info_block s; | ||
114 | struct vq_info_block_legacy l; | ||
115 | } *info_block; | ||
104 | int bit_nr; | 116 | int bit_nr; |
105 | struct list_head node; | 117 | struct list_head node; |
106 | long cookie; | 118 | long cookie; |
@@ -411,13 +423,22 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw) | |||
411 | spin_unlock_irqrestore(&vcdev->lock, flags); | 423 | spin_unlock_irqrestore(&vcdev->lock, flags); |
412 | 424 | ||
413 | /* Release from host. */ | 425 | /* Release from host. */ |
414 | info->info_block->queue = 0; | 426 | if (vcdev->revision == 0) { |
415 | info->info_block->align = 0; | 427 | info->info_block->l.queue = 0; |
416 | info->info_block->index = index; | 428 | info->info_block->l.align = 0; |
417 | 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 | } | ||
418 | ccw->cmd_code = CCW_CMD_SET_VQ; | 440 | ccw->cmd_code = CCW_CMD_SET_VQ; |
419 | ccw->flags = 0; | 441 | ccw->flags = 0; |
420 | ccw->count = sizeof(*info->info_block); | ||
421 | ccw->cda = (__u32)(unsigned long)(info->info_block); | 442 | ccw->cda = (__u32)(unsigned long)(info->info_block); |
422 | ret = ccw_io_helper(vcdev, ccw, | 443 | ret = ccw_io_helper(vcdev, ccw, |
423 | VIRTIO_CCW_DOING_SET_VQ | index); | 444 | VIRTIO_CCW_DOING_SET_VQ | index); |
@@ -500,13 +521,22 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, | |||
500 | } | 521 | } |
501 | 522 | ||
502 | /* Register it with the host. */ | 523 | /* Register it with the host. */ |
503 | info->info_block->queue = (__u64)info->queue; | 524 | if (vcdev->revision == 0) { |
504 | info->info_block->align = KVM_VIRTIO_CCW_RING_ALIGN; | 525 | info->info_block->l.queue = (__u64)info->queue; |
505 | info->info_block->index = i; | 526 | info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN; |
506 | 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 | } | ||
507 | ccw->cmd_code = CCW_CMD_SET_VQ; | 538 | ccw->cmd_code = CCW_CMD_SET_VQ; |
508 | ccw->flags = 0; | 539 | ccw->flags = 0; |
509 | ccw->count = sizeof(*info->info_block); | ||
510 | ccw->cda = (__u32)(unsigned long)(info->info_block); | 540 | ccw->cda = (__u32)(unsigned long)(info->info_block); |
511 | 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); |
512 | if (err) { | 542 | if (err) { |