|
|
@@ -74,6 +74,7 @@ static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
|
|
|
|
|
|
static int pci_epf_test_copy(struct pci_epf_test *epf_test)
|
|
|
{
|
|
|
+ int tx;
|
|
|
int ret;
|
|
|
void __iomem *src_addr;
|
|
|
void __iomem *dst_addr;
|
|
|
@@ -117,7 +118,11 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
|
|
|
goto err_dst_addr;
|
|
|
}
|
|
|
|
|
|
- memcpy(dst_addr, src_addr, reg->size);
|
|
|
+ tx = pci_epf_tx(epf, dst_phys_addr, src_phys_addr, reg->size);
|
|
|
+ if (tx) {
|
|
|
+ dev_err(dev, "DMA transfer failed, using memcpy..\n");
|
|
|
+ memcpy(dst_addr, src_addr, reg->size);
|
|
|
+ }
|
|
|
|
|
|
pci_epc_unmap_addr(epc, epf->func_no, dst_phys_addr);
|
|
|
|
|
|
@@ -136,14 +141,17 @@ err:
|
|
|
|
|
|
static int pci_epf_test_read(struct pci_epf_test *epf_test)
|
|
|
{
|
|
|
+ int tx;
|
|
|
int ret;
|
|
|
void __iomem *src_addr;
|
|
|
void *buf;
|
|
|
u32 crc32;
|
|
|
phys_addr_t phys_addr;
|
|
|
+ phys_addr_t dst_addr;
|
|
|
struct pci_epf *epf = epf_test->epf;
|
|
|
struct device *dev = &epf->dev;
|
|
|
struct pci_epc *epc = epf->epc;
|
|
|
+ struct device *dma_dev = epf->epc->dev.parent;
|
|
|
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
|
|
|
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
|
|
|
|
|
|
@@ -169,8 +177,24 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
|
|
|
goto err_map_addr;
|
|
|
}
|
|
|
|
|
|
- memcpy(buf, src_addr, reg->size);
|
|
|
+ dst_addr = dma_map_single(dma_dev, buf, reg->size, DMA_FROM_DEVICE);
|
|
|
+ if (dma_mapping_error(dma_dev, dst_addr)) {
|
|
|
+ dev_err(dev, "failed to map destination buffer address\n");
|
|
|
+ memcpy(buf, src_addr, reg->size);
|
|
|
+ goto skip_dma;
|
|
|
+ }
|
|
|
+
|
|
|
+ tx = pci_epf_tx(epf, dst_addr, phys_addr, reg->size);
|
|
|
+ if (tx) {
|
|
|
+ dev_err(dev, "DMA transfer failed, using memcpy..\n");
|
|
|
+ dma_unmap_single(dma_dev, dst_addr, reg->size, DMA_FROM_DEVICE);
|
|
|
+ memcpy(buf, src_addr, reg->size);
|
|
|
+ goto skip_dma;
|
|
|
+ }
|
|
|
|
|
|
+ dma_unmap_single(dma_dev, dst_addr, reg->size, DMA_FROM_DEVICE);
|
|
|
+
|
|
|
+skip_dma:
|
|
|
crc32 = crc32_le(~0, buf, reg->size);
|
|
|
if (crc32 != reg->checksum)
|
|
|
ret = -EIO;
|
|
|
@@ -189,13 +213,16 @@ err:
|
|
|
|
|
|
static int pci_epf_test_write(struct pci_epf_test *epf_test)
|
|
|
{
|
|
|
+ int tx;
|
|
|
int ret;
|
|
|
void __iomem *dst_addr;
|
|
|
void *buf;
|
|
|
phys_addr_t phys_addr;
|
|
|
+ phys_addr_t src_addr;
|
|
|
struct pci_epf *epf = epf_test->epf;
|
|
|
struct device *dev = &epf->dev;
|
|
|
struct pci_epc *epc = epf->epc;
|
|
|
+ struct device *dma_dev = epf->epc->dev.parent;
|
|
|
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
|
|
|
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
|
|
|
|
|
|
@@ -224,8 +251,22 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
|
|
|
get_random_bytes(buf, reg->size);
|
|
|
reg->checksum = crc32_le(~0, buf, reg->size);
|
|
|
|
|
|
- memcpy(dst_addr, buf, reg->size);
|
|
|
+ src_addr = dma_map_single(dma_dev, buf, reg->size, DMA_TO_DEVICE);
|
|
|
+ if (dma_mapping_error(dma_dev, src_addr)) {
|
|
|
+ dev_err(dev, "failed to map source buffer address\n");
|
|
|
+ memcpy(dst_addr, buf, reg->size);
|
|
|
+ goto skip_dma;
|
|
|
+ }
|
|
|
|
|
|
+ tx = pci_epf_tx(epf, phys_addr, src_addr, reg->size);
|
|
|
+ if (tx) {
|
|
|
+ dev_err(dev, "DMA transfer failed, using memcpy..\n");
|
|
|
+ memcpy(dst_addr, buf, reg->size);
|
|
|
+ }
|
|
|
+
|
|
|
+ dma_unmap_single(dma_dev, src_addr, reg->size, DMA_TO_DEVICE);
|
|
|
+
|
|
|
+skip_dma:
|
|
|
/*
|
|
|
* wait 1ms inorder for the write to complete. Without this delay L3
|
|
|
* error in observed in the host system.
|
|
|
@@ -389,6 +430,7 @@ static void pci_epf_test_unbind(struct pci_epf *epf)
|
|
|
pci_epc_clear_bar(epc, epf->func_no, epf_bar);
|
|
|
}
|
|
|
}
|
|
|
+ pci_epc_epf_exit(epc, epf);
|
|
|
}
|
|
|
|
|
|
static int pci_epf_test_set_bar(struct pci_epf *epf)
|
|
|
@@ -515,6 +557,12 @@ static int pci_epf_test_bind(struct pci_epf *epf)
|
|
|
epf_test->test_reg_bar = test_reg_bar;
|
|
|
epf_test->epc_features = epc_features;
|
|
|
|
|
|
+ ret = pci_epc_epf_init(epc, epf);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(dev, "Failed to initialize EPF\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
ret = pci_epc_write_header(epc, epf->func_no, header);
|
|
|
if (ret) {
|
|
|
dev_err(dev, "Configuration header write failed\n");
|