]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/s390/virtio/virtio_ccw.c
virtio/s390: use vring_create_virtqueue
[linux.git] / drivers / s390 / virtio / virtio_ccw.c
index ae1d56da671dfe9eab824e379d7d482b639dacf2..2c66941ef3d0426ba7d11783302be3160726afab 100644 (file)
@@ -108,7 +108,6 @@ struct virtio_rev_info {
 struct virtio_ccw_vq_info {
        struct virtqueue *vq;
        int num;
-       void *queue;
        union {
                struct vq_info_block s;
                struct vq_info_block_legacy l;
@@ -272,6 +271,8 @@ static void virtio_ccw_drop_indicators(struct virtio_ccw_device *vcdev)
 {
        struct virtio_ccw_vq_info *info;
 
+       if (!vcdev->airq_info)
+               return;
        list_for_each_entry(info, &vcdev->virtqueues, node)
                drop_airq_indicator(info->vq, vcdev->airq_info);
 }
@@ -413,7 +414,7 @@ static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
        ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF);
        if (ret)
                return ret;
-       return vcdev->config_block->num;
+       return vcdev->config_block->num ?: -ENOENT;
 }
 
 static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
@@ -421,7 +422,6 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
        struct virtio_ccw_device *vcdev = to_vc_device(vq->vdev);
        struct virtio_ccw_vq_info *info = vq->priv;
        unsigned long flags;
-       unsigned long size;
        int ret;
        unsigned int index = vq->index;
 
@@ -459,8 +459,6 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
                         ret, index);
 
        vring_del_virtqueue(vq);
-       size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN));
-       free_pages_exact(info->queue, size);
        kfree(info->info_block);
        kfree(info);
 }
@@ -492,8 +490,9 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
        int err;
        struct virtqueue *vq = NULL;
        struct virtio_ccw_vq_info *info;
-       unsigned long size = 0; /* silence the compiler */
+       u64 queue;
        unsigned long flags;
+       bool may_reduce;
 
        /* Allocate queue. */
        info = kzalloc(sizeof(struct virtio_ccw_vq_info), GFP_KERNEL);
@@ -514,33 +513,30 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
                err = info->num;
                goto out_err;
        }
-       size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN));
-       info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
-       if (info->queue == NULL) {
-               dev_warn(&vcdev->cdev->dev, "no queue\n");
-               err = -ENOMEM;
-               goto out_err;
-       }
+       may_reduce = vcdev->revision > 0;
+       vq = vring_create_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN,
+                                   vdev, true, may_reduce, ctx,
+                                   virtio_ccw_kvm_notify, callback, name);
 
-       vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev,
-                                true, ctx, info->queue, virtio_ccw_kvm_notify,
-                                callback, name);
        if (!vq) {
                /* For now, we fail if we can't get the requested size. */
                dev_warn(&vcdev->cdev->dev, "no vq\n");
                err = -ENOMEM;
                goto out_err;
        }
+       /* it may have been reduced */
+       info->num = virtqueue_get_vring_size(vq);
 
        /* Register it with the host. */
+       queue = virtqueue_get_desc_addr(vq);
        if (vcdev->revision == 0) {
-               info->info_block->l.queue = (__u64)info->queue;
+               info->info_block->l.queue = queue;
                info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN;
                info->info_block->l.index = i;
                info->info_block->l.num = info->num;
                ccw->count = sizeof(info->info_block->l);
        } else {
-               info->info_block->s.desc = (__u64)info->queue;
+               info->info_block->s.desc = queue;
                info->info_block->s.index = i;
                info->info_block->s.num = info->num;
                info->info_block->s.avail = (__u64)virtqueue_get_avail(vq);
@@ -570,8 +566,6 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
        if (vq)
                vring_del_virtqueue(vq);
        if (info) {
-               if (info->queue)
-                       free_pages_exact(info->queue, size);
                kfree(info->info_block);
        }
        kfree(info);
@@ -973,6 +967,13 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status)
        kfree(ccw);
 }
 
+static const char *virtio_ccw_bus_name(struct virtio_device *vdev)
+{
+       struct virtio_ccw_device *vcdev = to_vc_device(vdev);
+
+       return dev_name(&vcdev->cdev->dev);
+}
+
 static const struct virtio_config_ops virtio_ccw_config_ops = {
        .get_features = virtio_ccw_get_features,
        .finalize_features = virtio_ccw_finalize_features,
@@ -983,6 +984,7 @@ static const struct virtio_config_ops virtio_ccw_config_ops = {
        .reset = virtio_ccw_reset,
        .find_vqs = virtio_ccw_find_vqs,
        .del_vqs = virtio_ccw_del_vqs,
+       .bus_name = virtio_ccw_bus_name,
 };