s390/virtio_ccw: use DMA handle from DMA API
authorHalil Pasic <pasic@linux.ibm.com>
Thu, 7 Mar 2024 12:28:08 +0000 (13:28 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 13 Mar 2024 08:23:46 +0000 (09:23 +0100)
Change and use ccw_device_dma_zalloc() so it returns a virtual address like
before, which can be used to access data. However also pass a new dma32_t
pointer type handle, which correlates to the returned virtual address.
This pointer is used to directly pass/set the DMA handle as returned by the
DMA API.

Signed-off-by: Halil Pasic <pasic@linux.ibm.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/include/asm/ccwdev.h
arch/s390/include/asm/cio.h
drivers/s390/cio/css.c
drivers/s390/cio/device_ops.c
drivers/s390/virtio/virtio_ccw.c

index 91d2617..436365f 100644 (file)
@@ -217,7 +217,8 @@ extern void ccw_device_destroy_console(struct ccw_device *);
 extern int ccw_device_enable_console(struct ccw_device *);
 extern void ccw_device_wait_idle(struct ccw_device *);
 
-extern void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size);
+extern void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size,
+                                  dma32_t *dma_handle);
 extern void ccw_device_dma_free(struct ccw_device *cdev,
                                void *cpu_addr, size_t size);
 
index 80aeff8..b6b619f 100644 (file)
@@ -365,6 +365,8 @@ extern struct device *cio_get_dma_css_dev(void);
 
 void *cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
                        size_t size);
+void *__cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
+                         size_t size, dma32_t *dma_handle);
 void cio_gp_dma_free(struct gen_pool *gp_dma, void *cpu_addr, size_t size);
 void cio_gp_dma_destroy(struct gen_pool *gp_dma, struct device *dma_dev);
 struct gen_pool *cio_gp_dma_create(struct device *dma_dev, int nr_pages);
index 094431a..1d68db1 100644 (file)
@@ -1114,26 +1114,33 @@ static int cio_dma_pool_init(void)
        return 0;
 }
 
-void *cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
-                       size_t size)
+void *__cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
+                         size_t size, dma32_t *dma_handle)
 {
        dma_addr_t dma_addr;
-       unsigned long addr;
        size_t chunk_size;
+       void *addr;
 
        if (!gp_dma)
                return NULL;
-       addr = gen_pool_alloc(gp_dma, size);
+       addr = gen_pool_dma_alloc(gp_dma, size, &dma_addr);
        while (!addr) {
                chunk_size = round_up(size, PAGE_SIZE);
-               addr = (unsigned long) dma_alloc_coherent(dma_dev,
-                                        chunk_size, &dma_addr, CIO_DMA_GFP);
+               addr = dma_alloc_coherent(dma_dev, chunk_size, &dma_addr, CIO_DMA_GFP);
                if (!addr)
                        return NULL;
-               gen_pool_add_virt(gp_dma, addr, dma_addr, chunk_size, -1);
-               addr = gen_pool_alloc(gp_dma, size);
+               gen_pool_add_virt(gp_dma, (unsigned long)addr, dma_addr, chunk_size, -1);
+               addr = gen_pool_dma_alloc(gp_dma, size, dma_handle ? &dma_addr : NULL);
        }
-       return (void *) addr;
+       if (dma_handle)
+               *dma_handle = (__force dma32_t)dma_addr;
+       return addr;
+}
+
+void *cio_gp_dma_zalloc(struct gen_pool *gp_dma, struct device *dma_dev,
+                       size_t size)
+{
+       return __cio_gp_dma_zalloc(gp_dma, dma_dev, size, NULL);
 }
 
 void cio_gp_dma_free(struct gen_pool *gp_dma, void *cpu_addr, size_t size)
index a5dba38..40c97f8 100644 (file)
@@ -823,13 +823,14 @@ EXPORT_SYMBOL_GPL(ccw_device_get_chid);
  * the subchannels dma pool. Maximal size of allocation supported
  * is PAGE_SIZE.
  */
-void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size)
+void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size,
+                           dma32_t *dma_handle)
 {
        void *addr;
 
        if (!get_device(&cdev->dev))
                return NULL;
-       addr = cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size);
+       addr = __cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size, dma_handle);
        if (IS_ERR_OR_NULL(addr))
                put_device(&cdev->dev);
        return addr;
index ac77951..ee9c827 100644 (file)
@@ -123,6 +123,7 @@ struct virtio_rev_info {
 
 struct virtio_ccw_vq_info {
        struct virtqueue *vq;
+       dma32_t info_block_addr;
        int num;
        union {
                struct vq_info_block s;
@@ -354,7 +355,8 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
 
        if (vcdev->is_thinint) {
                thinint_area = ccw_device_dma_zalloc(vcdev->cdev,
-                                                    sizeof(*thinint_area));
+                                                    sizeof(*thinint_area),
+                                                    &ccw->cda);
                if (!thinint_area)
                        return;
                thinint_area->summary_indicator =
@@ -362,17 +364,16 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
                thinint_area->isc = VIRTIO_AIRQ_ISC;
                ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
                ccw->count = sizeof(*thinint_area);
-               ccw->cda = virt_to_dma32(thinint_area);
        } else {
                /* payload is the address of the indicators */
                indicatorp = ccw_device_dma_zalloc(vcdev->cdev,
-                                                  sizeof(indicators(vcdev)));
+                                                  sizeof(indicators(vcdev)),
+                                                  &ccw->cda);
                if (!indicatorp)
                        return;
                *indicatorp = 0;
                ccw->cmd_code = CCW_CMD_SET_IND;
                ccw->count = sizeof(indicators(vcdev));
-               ccw->cda = virt_to_dma32(indicatorp);
        }
        /* Deregister indicators from host. */
        *indicators(vcdev) = 0;
@@ -463,7 +464,7 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
        }
        ccw->cmd_code = CCW_CMD_SET_VQ;
        ccw->flags = 0;
-       ccw->cda = virt_to_dma32(info->info_block);
+       ccw->cda = info->info_block_addr;
        ret = ccw_io_helper(vcdev, ccw,
                            VIRTIO_CCW_DOING_SET_VQ | index);
        /*
@@ -486,7 +487,7 @@ static void virtio_ccw_del_vqs(struct virtio_device *vdev)
        struct ccw1 *ccw;
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return;
 
@@ -525,7 +526,8 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
                goto out_err;
        }
        info->info_block = ccw_device_dma_zalloc(vcdev->cdev,
-                                                sizeof(*info->info_block));
+                                                sizeof(*info->info_block),
+                                                &info->info_block_addr);
        if (!info->info_block) {
                dev_warn(&vcdev->cdev->dev, "no info block\n");
                err = -ENOMEM;
@@ -571,7 +573,7 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
        }
        ccw->cmd_code = CCW_CMD_SET_VQ;
        ccw->flags = 0;
-       ccw->cda = virt_to_dma32(info->info_block);
+       ccw->cda = info->info_block_addr;
        err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i);
        if (err) {
                dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n");
@@ -609,7 +611,8 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
        struct airq_info *info;
 
        thinint_area = ccw_device_dma_zalloc(vcdev->cdev,
-                                            sizeof(*thinint_area));
+                                            sizeof(*thinint_area),
+                                            &ccw->cda);
        if (!thinint_area) {
                ret = -ENOMEM;
                goto out;
@@ -630,7 +633,6 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
        ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
        ccw->flags = CCW_FLAG_SLI;
        ccw->count = sizeof(*thinint_area);
-       ccw->cda = virt_to_dma32(thinint_area);
        ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER);
        if (ret) {
                if (ret == -EOPNOTSUPP) {
@@ -662,7 +664,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
        int ret, i, queue_idx = 0;
        struct ccw1 *ccw;
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return -ENOMEM;
 
@@ -687,7 +689,8 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
         * the address of the indicators.
        */
        indicatorp = ccw_device_dma_zalloc(vcdev->cdev,
-                                          sizeof(indicators(vcdev)));
+                                          sizeof(indicators(vcdev)),
+                                          &ccw->cda);
        if (!indicatorp)
                goto out;
        *indicatorp = virt_to_dma64(indicators(vcdev));
@@ -703,7 +706,6 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                ccw->cmd_code = CCW_CMD_SET_IND;
                ccw->flags = 0;
                ccw->count = sizeof(indicators(vcdev));
-               ccw->cda = virt_to_dma32(indicatorp);
                ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND);
                if (ret)
                        goto out;
@@ -714,7 +716,6 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
        ccw->cmd_code = CCW_CMD_SET_CONF_IND;
        ccw->flags = 0;
        ccw->count = sizeof(indicators2(vcdev));
-       ccw->cda = virt_to_dma32(indicatorp);
        ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND);
        if (ret)
                goto out;
@@ -738,7 +739,7 @@ static void virtio_ccw_reset(struct virtio_device *vdev)
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
        struct ccw1 *ccw;
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return;
 
@@ -762,11 +763,12 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
        u64 rc;
        struct ccw1 *ccw;
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return 0;
 
-       features = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*features));
+       features = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*features),
+                                        &ccw->cda);
        if (!features) {
                rc = 0;
                goto out_free;
@@ -776,7 +778,6 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
        ccw->cmd_code = CCW_CMD_READ_FEAT;
        ccw->flags = 0;
        ccw->count = sizeof(*features);
-       ccw->cda = virt_to_dma32(features);
        ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
        if (ret) {
                rc = 0;
@@ -793,7 +794,6 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
        ccw->cmd_code = CCW_CMD_READ_FEAT;
        ccw->flags = 0;
        ccw->count = sizeof(*features);
-       ccw->cda = virt_to_dma32(features);
        ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
        if (ret == 0)
                rc |= (u64)le32_to_cpu(features->features) << 32;
@@ -825,11 +825,12 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
                return -EINVAL;
        }
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return -ENOMEM;
 
-       features = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*features));
+       features = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*features),
+                                        &ccw->cda);
        if (!features) {
                ret = -ENOMEM;
                goto out_free;
@@ -846,7 +847,6 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
        ccw->cmd_code = CCW_CMD_WRITE_FEAT;
        ccw->flags = 0;
        ccw->count = sizeof(*features);
-       ccw->cda = virt_to_dma32(features);
        ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
        if (ret)
                goto out_free;
@@ -860,7 +860,6 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
        ccw->cmd_code = CCW_CMD_WRITE_FEAT;
        ccw->flags = 0;
        ccw->count = sizeof(*features);
-       ccw->cda = virt_to_dma32(features);
        ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
 
 out_free:
@@ -879,12 +878,13 @@ static void virtio_ccw_get_config(struct virtio_device *vdev,
        void *config_area;
        unsigned long flags;
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return;
 
        config_area = ccw_device_dma_zalloc(vcdev->cdev,
-                                           VIRTIO_CCW_CONFIG_SIZE);
+                                           VIRTIO_CCW_CONFIG_SIZE,
+                                           &ccw->cda);
        if (!config_area)
                goto out_free;
 
@@ -892,7 +892,6 @@ static void virtio_ccw_get_config(struct virtio_device *vdev,
        ccw->cmd_code = CCW_CMD_READ_CONF;
        ccw->flags = 0;
        ccw->count = offset + len;
-       ccw->cda = virt_to_dma32(config_area);
        ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG);
        if (ret)
                goto out_free;
@@ -919,12 +918,13 @@ static void virtio_ccw_set_config(struct virtio_device *vdev,
        void *config_area;
        unsigned long flags;
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return;
 
        config_area = ccw_device_dma_zalloc(vcdev->cdev,
-                                           VIRTIO_CCW_CONFIG_SIZE);
+                                           VIRTIO_CCW_CONFIG_SIZE,
+                                           &ccw->cda);
        if (!config_area)
                goto out_free;
 
@@ -939,7 +939,6 @@ static void virtio_ccw_set_config(struct virtio_device *vdev,
        ccw->cmd_code = CCW_CMD_WRITE_CONF;
        ccw->flags = 0;
        ccw->count = offset + len;
-       ccw->cda = virt_to_dma32(config_area);
        ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG);
 
 out_free:
@@ -956,7 +955,7 @@ static u8 virtio_ccw_get_status(struct virtio_device *vdev)
        if (vcdev->revision < 2)
                return vcdev->dma_area->status;
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return old_status;
 
@@ -983,7 +982,7 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status)
        struct ccw1 *ccw;
        int ret;
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return;
 
@@ -1278,10 +1277,10 @@ static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev)
        struct ccw1 *ccw;
        int ret;
 
-       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
+       ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw), NULL);
        if (!ccw)
                return -ENOMEM;
-       rev = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*rev));
+       rev = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*rev), &ccw->cda);
        if (!rev) {
                ccw_device_dma_free(vcdev->cdev, ccw, sizeof(*ccw));
                return -ENOMEM;
@@ -1291,7 +1290,6 @@ static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev)
        ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV;
        ccw->flags = 0;
        ccw->count = sizeof(*rev);
-       ccw->cda = virt_to_dma32(rev);
 
        vcdev->revision = VIRTIO_CCW_REV_MAX;
        do {
@@ -1333,7 +1331,8 @@ static int virtio_ccw_online(struct ccw_device *cdev)
        vcdev->vdev.dev.parent = &cdev->dev;
        vcdev->cdev = cdev;
        vcdev->dma_area = ccw_device_dma_zalloc(vcdev->cdev,
-                                               sizeof(*vcdev->dma_area));
+                                               sizeof(*vcdev->dma_area),
+                                               NULL);
        if (!vcdev->dma_area) {
                ret = -ENOMEM;
                goto out_free;