mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
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: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Niklas Cassel <cassel@kernel.org> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Link: https://lore.kernel.org/r/20241012113246.95634-6-dlemoal@kernel.org Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
This commit is contained in:
parent
6067ccf36f
commit
08cac1006b
|
|
@ -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;
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr,
|
||||
reg->src_addr, reg->size);
|
||||
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;
|
||||
}
|
||||
|
||||
ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr,
|
||||
reg->dst_addr, reg->size);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to map destination address\n");
|
||||
reg->status = STATUS_DST_ADDR_INVALID;
|
||||
goto err_dst_addr;
|
||||
}
|
||||
|
||||
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;
|
||||
goto set_status;
|
||||
}
|
||||
|
||||
ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
|
||||
src_phys_addr, reg->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) {
|
||||
copy_buf = kzalloc(copy_size, GFP_KERNEL);
|
||||
if (!copy_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto err_map_addr;
|
||||
goto set_status;
|
||||
}
|
||||
buf = copy_buf;
|
||||
}
|
||||
|
||||
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 free_buf;
|
||||
}
|
||||
|
||||
memcpy_fromio(buf, src_addr, reg->size);
|
||||
memcpy_toio(dst_addr, buf, reg->size);
|
||||
kfree(buf);
|
||||
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;
|
||||
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) {
|
||||
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");
|
||||
goto unmap;
|
||||
}
|
||||
} 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);
|
||||
|
||||
copy_size -= map_size;
|
||||
src_addr += map_size;
|
||||
dst_addr += 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);
|
||||
map_size = 0;
|
||||
}
|
||||
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);
|
||||
pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start,
|
||||
&end, reg->flags & FLAG_USE_DMA);
|
||||
|
||||
err_dst_addr:
|
||||
pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size);
|
||||
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_map_addr:
|
||||
pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr);
|
||||
free_buf:
|
||||
kfree(copy_buf);
|
||||
|
||||
err_src_addr:
|
||||
pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size);
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
if (reg->flags & FLAG_USE_DMA) {
|
||||
dst_phys_addr = dma_map_single(dma_dev, buf, reg->size,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(dma_dev, dst_phys_addr)) {
|
||||
dev_err(dev, "Failed to map destination buffer addr\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_dma_map;
|
||||
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 free_buf;
|
||||
}
|
||||
|
||||
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);
|
||||
if (ret)
|
||||
dev_err(dev, "Data transfer failed\n");
|
||||
ktime_get_ts64(&end);
|
||||
map_size = map.pci_size;
|
||||
if (reg->flags & FLAG_USE_DMA) {
|
||||
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");
|
||||
ret = -ENOMEM;
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
dma_unmap_single(dma_dev, dst_phys_addr, reg->size,
|
||||
DMA_FROM_DEVICE);
|
||||
} else {
|
||||
ktime_get_ts64(&start);
|
||||
memcpy_fromio(buf, src_addr, reg->size);
|
||||
ktime_get_ts64(&end);
|
||||
ktime_get_ts64(&start);
|
||||
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, map_size,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
if (ret)
|
||||
goto unmap;
|
||||
} else {
|
||||
ktime_get_ts64(&start);
|
||||
memcpy_fromio(buf, map.virt_addr, map_size);
|
||||
ktime_get_ts64(&end);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
get_random_bytes(buf, reg->size);
|
||||
reg->checksum = crc32_le(~0, buf, reg->size);
|
||||
|
||||
if (reg->flags & FLAG_USE_DMA) {
|
||||
src_phys_addr = dma_map_single(dma_dev, buf, reg->size,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dma_dev, src_phys_addr)) {
|
||||
dev_err(dev, "Failed to map source buffer addr\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_dma_map;
|
||||
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 free_buf;
|
||||
}
|
||||
|
||||
ktime_get_ts64(&start);
|
||||
map_size = map.pci_size;
|
||||
if (reg->flags & FLAG_USE_DMA) {
|
||||
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");
|
||||
ret = -ENOMEM;
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
ret = pci_epf_test_data_transfer(epf_test, phys_addr,
|
||||
src_phys_addr, reg->size,
|
||||
reg->dst_addr,
|
||||
DMA_MEM_TO_DEV);
|
||||
if (ret)
|
||||
dev_err(dev, "Data transfer failed\n");
|
||||
ktime_get_ts64(&end);
|
||||
ktime_get_ts64(&start);
|
||||
|
||||
dma_unmap_single(dma_dev, src_phys_addr, reg->size,
|
||||
DMA_TO_DEVICE);
|
||||
} else {
|
||||
ktime_get_ts64(&start);
|
||||
memcpy_toio(dst_addr, buf, reg->size);
|
||||
ktime_get_ts64(&end);
|
||||
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, map_size,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (ret)
|
||||
goto unmap;
|
||||
} else {
|
||||
ktime_get_ts64(&start);
|
||||
memcpy_toio(map.virt_addr, buf, map_size);
|
||||
ktime_get_ts64(&end);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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(dst_buf);
|
||||
|
||||
err_addr:
|
||||
pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size);
|
||||
|
||||
err:
|
||||
set_status:
|
||||
if (!ret)
|
||||
reg->status |= STATUS_WRITE_SUCCESS;
|
||||
else
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user