Commit 08cac100 authored by Damien Le Moal's avatar Damien Le Moal Committed by Manivannan Sadhasivam
Browse files

PCI: endpoint: test: Use pci_epc_mem_map/unmap()



Modify the endpoint test driver to use the functions pci_epc_mem_map()
and pci_epc_mem_unmap() for the read, write and copy tests. For each
test case, the transfer (dma or mmio) are executed in a loop to ensure
that potentially partial mappings returned by pci_epc_mem_map() are
correctly handled.

Signed-off-by: default avatarDamien Le Moal <dlemoal@kernel.org>
Reviewed-by: default avatarNiklas Cassel <cassel@kernel.org>
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20241012113246.95634-6-dlemoal@kernel.org


Signed-off-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
parent 6067ccf3
Loading
Loading
Loading
Loading
+193 −179
Original line number Diff line number Diff line
@@ -317,91 +317,92 @@ static void pci_epf_test_print_rate(struct pci_epf_test *epf_test,
static void pci_epf_test_copy(struct pci_epf_test *epf_test,
			      struct pci_epf_test_reg *reg)
{
	int ret;
	void __iomem *src_addr;
	void __iomem *dst_addr;
	phys_addr_t src_phys_addr;
	phys_addr_t dst_phys_addr;
	int ret = 0;
	struct timespec64 start, end;
	struct pci_epf *epf = epf_test->epf;
	struct device *dev = &epf->dev;
	struct pci_epc *epc = epf->epc;
	struct device *dev = &epf->dev;
	struct pci_epc_map src_map, dst_map;
	u64 src_addr = reg->src_addr;
	u64 dst_addr = reg->dst_addr;
	size_t copy_size = reg->size;
	ssize_t map_size = 0;
	void *copy_buf = NULL, *buf;

	src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size);
	if (!src_addr) {
		dev_err(dev, "Failed to allocate source address\n");
		reg->status = STATUS_SRC_ADDR_INVALID;
	if (reg->flags & FLAG_USE_DMA) {
		if (epf_test->dma_private) {
			dev_err(dev, "Cannot transfer data using DMA\n");
			ret = -EINVAL;
			goto set_status;
		}
	} else {
		copy_buf = kzalloc(copy_size, GFP_KERNEL);
		if (!copy_buf) {
			ret = -ENOMEM;
		goto err;
			goto set_status;
		}
		buf = copy_buf;
	}

	ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr,
			       reg->src_addr, reg->size);
	while (copy_size) {
		ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
				      src_addr, copy_size, &src_map);
		if (ret) {
			dev_err(dev, "Failed to map source address\n");
			reg->status = STATUS_SRC_ADDR_INVALID;
		goto err_src_addr;
	}

	dst_addr = pci_epc_mem_alloc_addr(epc, &dst_phys_addr, reg->size);
	if (!dst_addr) {
		dev_err(dev, "Failed to allocate destination address\n");
		reg->status = STATUS_DST_ADDR_INVALID;
		ret = -ENOMEM;
		goto err_src_map_addr;
			goto free_buf;
		}

	ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr,
			       reg->dst_addr, reg->size);
		ret = pci_epc_mem_map(epf->epc, epf->func_no, epf->vfunc_no,
					   dst_addr, copy_size, &dst_map);
		if (ret) {
			dev_err(dev, "Failed to map destination address\n");
			reg->status = STATUS_DST_ADDR_INVALID;
		goto err_dst_addr;
			pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no,
					  &src_map);
			goto free_buf;
		}

		map_size = min_t(size_t, dst_map.pci_size, src_map.pci_size);

		ktime_get_ts64(&start);
		if (reg->flags & FLAG_USE_DMA) {
		if (epf_test->dma_private) {
			dev_err(dev, "Cannot transfer data using DMA\n");
			ret = -EINVAL;
			goto err_map_addr;
		}

		ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
						 src_phys_addr, reg->size, 0,
						 DMA_MEM_TO_MEM);
		if (ret)
			ret = pci_epf_test_data_transfer(epf_test,
					dst_map.phys_addr, src_map.phys_addr,
					map_size, 0, DMA_MEM_TO_MEM);
			if (ret) {
				dev_err(dev, "Data transfer failed\n");
	} else {
		void *buf;

		buf = kzalloc(reg->size, GFP_KERNEL);
		if (!buf) {
			ret = -ENOMEM;
			goto err_map_addr;
				goto unmap;
			}

		memcpy_fromio(buf, src_addr, reg->size);
		memcpy_toio(dst_addr, buf, reg->size);
		kfree(buf);
		} else {
			memcpy_fromio(buf, src_map.virt_addr, map_size);
			memcpy_toio(dst_map.virt_addr, buf, map_size);
			buf += map_size;
		}
		ktime_get_ts64(&end);
	pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, &end,
				reg->flags & FLAG_USE_DMA);

err_map_addr:
	pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr);
		copy_size -= map_size;
		src_addr += map_size;
		dst_addr += map_size;

err_dst_addr:
	pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size);
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &dst_map);
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &src_map);
		map_size = 0;
	}

	pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start,
				&end, reg->flags & FLAG_USE_DMA);

err_src_map_addr:
	pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr);
unmap:
	if (map_size) {
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &dst_map);
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &src_map);
	}

err_src_addr:
	pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size);
free_buf:
	kfree(copy_buf);

err:
set_status:
	if (!ret)
		reg->status |= STATUS_COPY_SUCCESS;
	else
@@ -411,82 +412,89 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test,
static void pci_epf_test_read(struct pci_epf_test *epf_test,
			      struct pci_epf_test_reg *reg)
{
	int ret;
	void __iomem *src_addr;
	void *buf;
	int ret = 0;
	void *src_buf, *buf;
	u32 crc32;
	phys_addr_t phys_addr;
	struct pci_epc_map map;
	phys_addr_t dst_phys_addr;
	struct timespec64 start, end;
	struct pci_epf *epf = epf_test->epf;
	struct device *dev = &epf->dev;
	struct pci_epc *epc = epf->epc;
	struct device *dev = &epf->dev;
	struct device *dma_dev = epf->epc->dev.parent;
	u64 src_addr = reg->src_addr;
	size_t src_size = reg->size;
	ssize_t map_size = 0;

	src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
	if (!src_addr) {
		dev_err(dev, "Failed to allocate address\n");
		reg->status = STATUS_SRC_ADDR_INVALID;
	src_buf = kzalloc(src_size, GFP_KERNEL);
	if (!src_buf) {
		ret = -ENOMEM;
		goto err;
		goto set_status;
	}
	buf = src_buf;

	ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr,
			       reg->src_addr, reg->size);
	while (src_size) {
		ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
					   src_addr, src_size, &map);
		if (ret) {
			dev_err(dev, "Failed to map address\n");
			reg->status = STATUS_SRC_ADDR_INVALID;
		goto err_addr;
	}

	buf = kzalloc(reg->size, GFP_KERNEL);
	if (!buf) {
		ret = -ENOMEM;
		goto err_map_addr;
			goto free_buf;
		}

		map_size = map.pci_size;
		if (reg->flags & FLAG_USE_DMA) {
		dst_phys_addr = dma_map_single(dma_dev, buf, reg->size,
			dst_phys_addr = dma_map_single(dma_dev, buf, map_size,
						       DMA_FROM_DEVICE);
			if (dma_mapping_error(dma_dev, dst_phys_addr)) {
			dev_err(dev, "Failed to map destination buffer addr\n");
				dev_err(dev,
					"Failed to map destination buffer addr\n");
				ret = -ENOMEM;
			goto err_dma_map;
				goto unmap;
			}

			ktime_get_ts64(&start);
		ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
						 phys_addr, reg->size,
						 reg->src_addr, DMA_DEV_TO_MEM);
			ret = pci_epf_test_data_transfer(epf_test,
					dst_phys_addr, map.phys_addr,
					map_size, src_addr, DMA_DEV_TO_MEM);
			if (ret)
				dev_err(dev, "Data transfer failed\n");
			ktime_get_ts64(&end);

		dma_unmap_single(dma_dev, dst_phys_addr, reg->size,
			dma_unmap_single(dma_dev, dst_phys_addr, map_size,
					 DMA_FROM_DEVICE);

			if (ret)
				goto unmap;
		} else {
			ktime_get_ts64(&start);
		memcpy_fromio(buf, src_addr, reg->size);
			memcpy_fromio(buf, map.virt_addr, map_size);
			ktime_get_ts64(&end);
		}

	pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, &end,
				reg->flags & FLAG_USE_DMA);
		src_size -= map_size;
		src_addr += map_size;
		buf += map_size;

		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);
		map_size = 0;
	}

	pci_epf_test_print_rate(epf_test, "READ", reg->size, &start,
				&end, reg->flags & FLAG_USE_DMA);

	crc32 = crc32_le(~0, buf, reg->size);
	crc32 = crc32_le(~0, src_buf, reg->size);
	if (crc32 != reg->checksum)
		ret = -EIO;

err_dma_map:
	kfree(buf);
unmap:
	if (map_size)
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);

err_map_addr:
	pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr);
free_buf:
	kfree(src_buf);

err_addr:
	pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size);

err:
set_status:
	if (!ret)
		reg->status |= STATUS_READ_SUCCESS;
	else
@@ -496,71 +504,79 @@ static void pci_epf_test_read(struct pci_epf_test *epf_test,
static void pci_epf_test_write(struct pci_epf_test *epf_test,
			       struct pci_epf_test_reg *reg)
{
	int ret;
	void __iomem *dst_addr;
	void *buf;
	phys_addr_t phys_addr;
	int ret = 0;
	void *dst_buf, *buf;
	struct pci_epc_map map;
	phys_addr_t src_phys_addr;
	struct timespec64 start, end;
	struct pci_epf *epf = epf_test->epf;
	struct device *dev = &epf->dev;
	struct pci_epc *epc = epf->epc;
	struct device *dev = &epf->dev;
	struct device *dma_dev = epf->epc->dev.parent;
	u64 dst_addr = reg->dst_addr;
	size_t dst_size = reg->size;
	ssize_t map_size = 0;

	dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
	if (!dst_addr) {
		dev_err(dev, "Failed to allocate address\n");
		reg->status = STATUS_DST_ADDR_INVALID;
	dst_buf = kzalloc(dst_size, GFP_KERNEL);
	if (!dst_buf) {
		ret = -ENOMEM;
		goto err;
		goto set_status;
	}
	get_random_bytes(dst_buf, dst_size);
	reg->checksum = crc32_le(~0, dst_buf, dst_size);
	buf = dst_buf;

	ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr,
			       reg->dst_addr, reg->size);
	while (dst_size) {
		ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
					   dst_addr, dst_size, &map);
		if (ret) {
			dev_err(dev, "Failed to map address\n");
			reg->status = STATUS_DST_ADDR_INVALID;
		goto err_addr;
	}

	buf = kzalloc(reg->size, GFP_KERNEL);
	if (!buf) {
		ret = -ENOMEM;
		goto err_map_addr;
			goto free_buf;
		}

	get_random_bytes(buf, reg->size);
	reg->checksum = crc32_le(~0, buf, reg->size);

		map_size = map.pci_size;
		if (reg->flags & FLAG_USE_DMA) {
		src_phys_addr = dma_map_single(dma_dev, buf, reg->size,
			src_phys_addr = dma_map_single(dma_dev, buf, map_size,
						       DMA_TO_DEVICE);
			if (dma_mapping_error(dma_dev, src_phys_addr)) {
			dev_err(dev, "Failed to map source buffer addr\n");
				dev_err(dev,
					"Failed to map source buffer addr\n");
				ret = -ENOMEM;
			goto err_dma_map;
				goto unmap;
			}

			ktime_get_ts64(&start);

		ret = pci_epf_test_data_transfer(epf_test, phys_addr,
						 src_phys_addr, reg->size,
						 reg->dst_addr,
			ret = pci_epf_test_data_transfer(epf_test,
						map.phys_addr, src_phys_addr,
						map_size, dst_addr,
						DMA_MEM_TO_DEV);
			if (ret)
				dev_err(dev, "Data transfer failed\n");
			ktime_get_ts64(&end);

		dma_unmap_single(dma_dev, src_phys_addr, reg->size,
			dma_unmap_single(dma_dev, src_phys_addr, map_size,
					 DMA_TO_DEVICE);

			if (ret)
				goto unmap;
		} else {
			ktime_get_ts64(&start);
		memcpy_toio(dst_addr, buf, reg->size);
			memcpy_toio(map.virt_addr, buf, map_size);
			ktime_get_ts64(&end);
		}

	pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, &end,
				reg->flags & FLAG_USE_DMA);
		dst_size -= map_size;
		dst_addr += map_size;
		buf += map_size;

		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);
		map_size = 0;
	}

	pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start,
				&end, reg->flags & FLAG_USE_DMA);

	/*
	 * wait 1ms inorder for the write to complete. Without this delay L3
@@ -568,16 +584,14 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test,
	 */
	usleep_range(1000, 2000);

err_dma_map:
	kfree(buf);

err_map_addr:
	pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr);
unmap:
	if (map_size)
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);

err_addr:
	pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size);
free_buf:
	kfree(dst_buf);

err:
set_status:
	if (!ret)
		reg->status |= STATUS_WRITE_SUCCESS;
	else