Skip to content

Commit 933f31a

Browse files
damien-lemoalbjorn-helgaas
authored andcommitted
PCI: epf-test: Fix DMA transfer completion detection
pci_epf_test_data_transfer() and pci_epf_test_dma_callback() are not handling DMA transfer completion correctly, leading to completion notifications to the RC side that are too early. This problem can be detected when the RC side is running an IOMMU with messages such as: pci-endpoint-test 0000:0b:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x001c address=0xfff00000 flags=0x0000] When running the pcitest.sh tests: the address used for a previous test transfer generates the above error while the next test transfer is running. Fix this by testing the DMA transfer status in pci_epf_test_dma_callback() and notifying the completion only when the transfer status is DMA_COMPLETE or DMA_ERROR. Furthermore, in pci_epf_test_data_transfer(), be paranoid and check again the transfer status and always call dmaengine_terminate_sync() before returning. Link: https://lore.kernel.org/r/[email protected] Fixes: 8353813 ("PCI: endpoint: Enable DMA tests for endpoints with DMA capabilities") Signed-off-by: Damien Le Moal <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Manivannan Sadhasivam <[email protected]> Cc: [email protected]
1 parent 4aca56f commit 933f31a

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

drivers/pci/endpoint/functions/pci-epf-test.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ struct pci_epf_test {
5454
struct delayed_work cmd_handler;
5555
struct dma_chan *dma_chan_tx;
5656
struct dma_chan *dma_chan_rx;
57+
struct dma_chan *transfer_chan;
58+
dma_cookie_t transfer_cookie;
59+
enum dma_status transfer_status;
5760
struct completion transfer_complete;
5861
bool dma_supported;
5962
bool dma_private;
@@ -85,8 +88,14 @@ static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
8588
static void pci_epf_test_dma_callback(void *param)
8689
{
8790
struct pci_epf_test *epf_test = param;
88-
89-
complete(&epf_test->transfer_complete);
91+
struct dma_tx_state state;
92+
93+
epf_test->transfer_status =
94+
dmaengine_tx_status(epf_test->transfer_chan,
95+
epf_test->transfer_cookie, &state);
96+
if (epf_test->transfer_status == DMA_COMPLETE ||
97+
epf_test->transfer_status == DMA_ERROR)
98+
complete(&epf_test->transfer_complete);
9099
}
91100

92101
/**
@@ -120,7 +129,6 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
120129
struct dma_async_tx_descriptor *tx;
121130
struct dma_slave_config sconf = {};
122131
struct device *dev = &epf->dev;
123-
dma_cookie_t cookie;
124132
int ret;
125133

126134
if (IS_ERR_OR_NULL(chan)) {
@@ -152,25 +160,33 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
152160
}
153161

154162
reinit_completion(&epf_test->transfer_complete);
163+
epf_test->transfer_chan = chan;
155164
tx->callback = pci_epf_test_dma_callback;
156165
tx->callback_param = epf_test;
157-
cookie = tx->tx_submit(tx);
166+
epf_test->transfer_cookie = tx->tx_submit(tx);
158167

159-
ret = dma_submit_error(cookie);
168+
ret = dma_submit_error(epf_test->transfer_cookie);
160169
if (ret) {
161-
dev_err(dev, "Failed to do DMA tx_submit %d\n", cookie);
162-
return -EIO;
170+
dev_err(dev, "Failed to do DMA tx_submit %d\n", ret);
171+
goto terminate;
163172
}
164173

165174
dma_async_issue_pending(chan);
166175
ret = wait_for_completion_interruptible(&epf_test->transfer_complete);
167176
if (ret < 0) {
168-
dmaengine_terminate_sync(chan);
169-
dev_err(dev, "DMA wait_for_completion_timeout\n");
170-
return -ETIMEDOUT;
177+
dev_err(dev, "DMA wait_for_completion interrupted\n");
178+
goto terminate;
171179
}
172180

173-
return 0;
181+
if (epf_test->transfer_status == DMA_ERROR) {
182+
dev_err(dev, "DMA transfer failed\n");
183+
ret = -EIO;
184+
}
185+
186+
terminate:
187+
dmaengine_terminate_sync(chan);
188+
189+
return ret;
174190
}
175191

176192
struct epf_dma_filter {

0 commit comments

Comments
 (0)