diff options
author | Kishon Vijay Abraham I | 2019-03-01 05:20:00 -0600 |
---|---|---|
committer | Sekhar Nori | 2019-03-04 04:33:48 -0600 |
commit | 3afea8e969f7b50f714fb68ec585d0725607f86c (patch) | |
tree | 606948528a2ebc1bba37cc5f3dcb40bb32d1e9da | |
parent | a58cb2bfaafe7401c9f1fcfa4def54f7c09ea1e5 (diff) | |
download | afd-analog-3afea8e969f7b50f714fb68ec585d0725607f86c.tar.gz afd-analog-3afea8e969f7b50f714fb68ec585d0725607f86c.tar.xz afd-analog-3afea8e969f7b50f714fb68ec585d0725607f86c.zip |
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>
-rw-r--r-- | drivers/pci/endpoint/functions/pci-epf-test.c | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index efd24df35da2..d7b6a1fcf125 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c | |||
@@ -74,6 +74,7 @@ static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 }; | |||
74 | 74 | ||
75 | static int pci_epf_test_copy(struct pci_epf_test *epf_test) | 75 | static int pci_epf_test_copy(struct pci_epf_test *epf_test) |
76 | { | 76 | { |
77 | int tx; | ||
77 | int ret; | 78 | int ret; |
78 | void __iomem *src_addr; | 79 | void __iomem *src_addr; |
79 | void __iomem *dst_addr; | 80 | void __iomem *dst_addr; |
@@ -117,7 +118,11 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test) | |||
117 | goto err_dst_addr; | 118 | goto err_dst_addr; |
118 | } | 119 | } |
119 | 120 | ||
120 | memcpy(dst_addr, src_addr, reg->size); | 121 | tx = pci_epf_tx(epf, dst_phys_addr, src_phys_addr, reg->size); |
122 | if (tx) { | ||
123 | dev_err(dev, "DMA transfer failed, using memcpy..\n"); | ||
124 | memcpy(dst_addr, src_addr, reg->size); | ||
125 | } | ||
121 | 126 | ||
122 | pci_epc_unmap_addr(epc, epf->func_no, dst_phys_addr); | 127 | pci_epc_unmap_addr(epc, epf->func_no, dst_phys_addr); |
123 | 128 | ||
@@ -136,14 +141,17 @@ err: | |||
136 | 141 | ||
137 | static int pci_epf_test_read(struct pci_epf_test *epf_test) | 142 | static int pci_epf_test_read(struct pci_epf_test *epf_test) |
138 | { | 143 | { |
144 | int tx; | ||
139 | int ret; | 145 | int ret; |
140 | void __iomem *src_addr; | 146 | void __iomem *src_addr; |
141 | void *buf; | 147 | void *buf; |
142 | u32 crc32; | 148 | u32 crc32; |
143 | phys_addr_t phys_addr; | 149 | phys_addr_t phys_addr; |
150 | phys_addr_t dst_addr; | ||
144 | struct pci_epf *epf = epf_test->epf; | 151 | struct pci_epf *epf = epf_test->epf; |
145 | struct device *dev = &epf->dev; | 152 | struct device *dev = &epf->dev; |
146 | struct pci_epc *epc = epf->epc; | 153 | struct pci_epc *epc = epf->epc; |
154 | struct device *dma_dev = epf->epc->dev.parent; | ||
147 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; | 155 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
148 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; | 156 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; |
149 | 157 | ||
@@ -169,8 +177,24 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test) | |||
169 | goto err_map_addr; | 177 | goto err_map_addr; |
170 | } | 178 | } |
171 | 179 | ||
172 | memcpy(buf, src_addr, reg->size); | 180 | dst_addr = dma_map_single(dma_dev, buf, reg->size, DMA_FROM_DEVICE); |
181 | if (dma_mapping_error(dma_dev, dst_addr)) { | ||
182 | dev_err(dev, "failed to map destination buffer address\n"); | ||
183 | memcpy(buf, src_addr, reg->size); | ||
184 | goto skip_dma; | ||
185 | } | ||
186 | |||
187 | tx = pci_epf_tx(epf, dst_addr, phys_addr, reg->size); | ||
188 | if (tx) { | ||
189 | dev_err(dev, "DMA transfer failed, using memcpy..\n"); | ||
190 | dma_unmap_single(dma_dev, dst_addr, reg->size, DMA_FROM_DEVICE); | ||
191 | memcpy(buf, src_addr, reg->size); | ||
192 | goto skip_dma; | ||
193 | } | ||
173 | 194 | ||
195 | dma_unmap_single(dma_dev, dst_addr, reg->size, DMA_FROM_DEVICE); | ||
196 | |||
197 | skip_dma: | ||
174 | crc32 = crc32_le(~0, buf, reg->size); | 198 | crc32 = crc32_le(~0, buf, reg->size); |
175 | if (crc32 != reg->checksum) | 199 | if (crc32 != reg->checksum) |
176 | ret = -EIO; | 200 | ret = -EIO; |
@@ -189,13 +213,16 @@ err: | |||
189 | 213 | ||
190 | static int pci_epf_test_write(struct pci_epf_test *epf_test) | 214 | static int pci_epf_test_write(struct pci_epf_test *epf_test) |
191 | { | 215 | { |
216 | int tx; | ||
192 | int ret; | 217 | int ret; |
193 | void __iomem *dst_addr; | 218 | void __iomem *dst_addr; |
194 | void *buf; | 219 | void *buf; |
195 | phys_addr_t phys_addr; | 220 | phys_addr_t phys_addr; |
221 | phys_addr_t src_addr; | ||
196 | struct pci_epf *epf = epf_test->epf; | 222 | struct pci_epf *epf = epf_test->epf; |
197 | struct device *dev = &epf->dev; | 223 | struct device *dev = &epf->dev; |
198 | struct pci_epc *epc = epf->epc; | 224 | struct pci_epc *epc = epf->epc; |
225 | struct device *dma_dev = epf->epc->dev.parent; | ||
199 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; | 226 | enum pci_barno test_reg_bar = epf_test->test_reg_bar; |
200 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; | 227 | struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; |
201 | 228 | ||
@@ -224,8 +251,22 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test) | |||
224 | get_random_bytes(buf, reg->size); | 251 | get_random_bytes(buf, reg->size); |
225 | reg->checksum = crc32_le(~0, buf, reg->size); | 252 | reg->checksum = crc32_le(~0, buf, reg->size); |
226 | 253 | ||
227 | memcpy(dst_addr, buf, reg->size); | 254 | src_addr = dma_map_single(dma_dev, buf, reg->size, DMA_TO_DEVICE); |
255 | if (dma_mapping_error(dma_dev, src_addr)) { | ||
256 | dev_err(dev, "failed to map source buffer address\n"); | ||
257 | memcpy(dst_addr, buf, reg->size); | ||
258 | goto skip_dma; | ||
259 | } | ||
228 | 260 | ||
261 | tx = pci_epf_tx(epf, phys_addr, src_addr, reg->size); | ||
262 | if (tx) { | ||
263 | dev_err(dev, "DMA transfer failed, using memcpy..\n"); | ||
264 | memcpy(dst_addr, buf, reg->size); | ||
265 | } | ||
266 | |||
267 | dma_unmap_single(dma_dev, src_addr, reg->size, DMA_TO_DEVICE); | ||
268 | |||
269 | skip_dma: | ||
229 | /* | 270 | /* |
230 | * wait 1ms inorder for the write to complete. Without this delay L3 | 271 | * wait 1ms inorder for the write to complete. Without this delay L3 |
231 | * error in observed in the host system. | 272 | * error in observed in the host system. |
@@ -389,6 +430,7 @@ static void pci_epf_test_unbind(struct pci_epf *epf) | |||
389 | pci_epc_clear_bar(epc, epf->func_no, epf_bar); | 430 | pci_epc_clear_bar(epc, epf->func_no, epf_bar); |
390 | } | 431 | } |
391 | } | 432 | } |
433 | pci_epc_epf_exit(epc, epf); | ||
392 | } | 434 | } |
393 | 435 | ||
394 | static int pci_epf_test_set_bar(struct pci_epf *epf) | 436 | 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) | |||
515 | epf_test->test_reg_bar = test_reg_bar; | 557 | epf_test->test_reg_bar = test_reg_bar; |
516 | epf_test->epc_features = epc_features; | 558 | epf_test->epc_features = epc_features; |
517 | 559 | ||
560 | ret = pci_epc_epf_init(epc, epf); | ||
561 | if (ret) { | ||
562 | dev_err(dev, "Failed to initialize EPF\n"); | ||
563 | return ret; | ||
564 | } | ||
565 | |||
518 | ret = pci_epc_write_header(epc, epf->func_no, header); | 566 | ret = pci_epc_write_header(epc, epf->func_no, header); |
519 | if (ret) { | 567 | if (ret) { |
520 | dev_err(dev, "Configuration header write failed\n"); | 568 | dev_err(dev, "Configuration header write failed\n"); |