Commit e3e9bda3 authored by Halil Pasic's avatar Halil Pasic Committed by Heiko Carstens
Browse files

s390/virtio_ccw: use DMA handle from DMA API



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: default avatarHalil Pasic <pasic@linux.ibm.com>
Reviewed-by: default avatarEric Farman <farman@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent d5cc4168
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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);

+2 −0
Original line number Diff line number Diff line
@@ -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);
+16 −9
Original line number Diff line number Diff line
@@ -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)
+3 −2
Original line number Diff line number Diff line
@@ -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;
+34 −35
Original line number Diff line number Diff line
@@ -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;