Browse Source

PCI: endpoint: functions/pci-epf-test: Use data_transfer API for tranferring data

Use pci_epc_data_transfer() for tranferring data to the remote PCIe
RC and only on failure use memcpy. Using pci_epc_data_transfer()
will help to use DMA in the platform (either system or within PCIe
controller) to transfer data.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Kishon Vijay Abraham I 6 years ago
parent
commit
3afea8e969
1 changed files with 51 additions and 3 deletions
  1. 51 3
      drivers/pci/endpoint/functions/pci-epf-test.c

+ 51 - 3
drivers/pci/endpoint/functions/pci-epf-test.c

@@ -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");