Skip to content

Commit 13107c6

Browse files
kishonbjorn-helgaas
authored andcommitted
misc: pci_endpoint_test: Add support to provide aligned buffer addresses
Some platforms like TI's K2G have a restriction that the host side buffer address should be aligned to either 1MB/2MB/4MB or 8MB (Ref: 11.14.4.9.1 Outbound Address Translation in K2G TRM SPRUHY8F January 2016 – Revised May 2017) addresses depending on how it is configured in the endpoint. Add support to provide such aligned address here so that pci_endpoint_test driver can be used to test K2G EP. Signed-off-by: Kishon Vijay Abraham I <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]>
1 parent 834b905 commit 13107c6

File tree

1 file changed

+76
-15
lines changed

1 file changed

+76
-15
lines changed

drivers/misc/pci_endpoint_test.c

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,12 @@ struct pci_endpoint_test {
9191
struct mutex mutex;
9292
struct miscdevice miscdev;
9393
enum pci_barno test_reg_bar;
94+
size_t alignment;
9495
};
9596

9697
struct pci_endpoint_test_data {
9798
enum pci_barno test_reg_bar;
99+
size_t alignment;
98100
};
99101

100102
static int bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
@@ -210,16 +212,32 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
210212
dma_addr_t dst_phys_addr;
211213
struct pci_dev *pdev = test->pdev;
212214
struct device *dev = &pdev->dev;
215+
void *orig_src_addr;
216+
dma_addr_t orig_src_phys_addr;
217+
void *orig_dst_addr;
218+
dma_addr_t orig_dst_phys_addr;
219+
size_t offset;
220+
size_t alignment = test->alignment;
213221
u32 src_crc32;
214222
u32 dst_crc32;
215223

216-
src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL);
217-
if (!src_addr) {
224+
orig_src_addr = dma_alloc_coherent(dev, size + alignment,
225+
&orig_src_phys_addr, GFP_KERNEL);
226+
if (!orig_src_addr) {
218227
dev_err(dev, "failed to allocate source buffer\n");
219228
ret = false;
220229
goto err;
221230
}
222231

232+
if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) {
233+
src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment);
234+
offset = src_phys_addr - orig_src_phys_addr;
235+
src_addr = orig_src_addr + offset;
236+
} else {
237+
src_phys_addr = orig_src_phys_addr;
238+
src_addr = orig_src_addr;
239+
}
240+
223241
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
224242
lower_32_bits(src_phys_addr));
225243

@@ -229,11 +247,21 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
229247
get_random_bytes(src_addr, size);
230248
src_crc32 = crc32_le(~0, src_addr, size);
231249

232-
dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL);
233-
if (!dst_addr) {
250+
orig_dst_addr = dma_alloc_coherent(dev, size + alignment,
251+
&orig_dst_phys_addr, GFP_KERNEL);
252+
if (!orig_dst_addr) {
234253
dev_err(dev, "failed to allocate destination address\n");
235254
ret = false;
236-
goto err_src_addr;
255+
goto err_orig_src_addr;
256+
}
257+
258+
if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) {
259+
dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment);
260+
offset = dst_phys_addr - orig_dst_phys_addr;
261+
dst_addr = orig_dst_addr + offset;
262+
} else {
263+
dst_phys_addr = orig_dst_phys_addr;
264+
dst_addr = orig_dst_addr;
237265
}
238266

239267
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
@@ -253,10 +281,12 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
253281
if (dst_crc32 == src_crc32)
254282
ret = true;
255283

256-
dma_free_coherent(dev, size, dst_addr, dst_phys_addr);
284+
dma_free_coherent(dev, size + alignment, orig_dst_addr,
285+
orig_dst_phys_addr);
257286

258-
err_src_addr:
259-
dma_free_coherent(dev, size, src_addr, src_phys_addr);
287+
err_orig_src_addr:
288+
dma_free_coherent(dev, size + alignment, orig_src_addr,
289+
orig_src_phys_addr);
260290

261291
err:
262292
return ret;
@@ -270,15 +300,29 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
270300
dma_addr_t phys_addr;
271301
struct pci_dev *pdev = test->pdev;
272302
struct device *dev = &pdev->dev;
303+
void *orig_addr;
304+
dma_addr_t orig_phys_addr;
305+
size_t offset;
306+
size_t alignment = test->alignment;
273307
u32 crc32;
274308

275-
addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
276-
if (!addr) {
309+
orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
310+
GFP_KERNEL);
311+
if (!orig_addr) {
277312
dev_err(dev, "failed to allocate address\n");
278313
ret = false;
279314
goto err;
280315
}
281316

317+
if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
318+
phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
319+
offset = phys_addr - orig_phys_addr;
320+
addr = orig_addr + offset;
321+
} else {
322+
phys_addr = orig_phys_addr;
323+
addr = orig_addr;
324+
}
325+
282326
get_random_bytes(addr, size);
283327

284328
crc32 = crc32_le(~0, addr, size);
@@ -301,7 +345,7 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
301345
if (reg & STATUS_READ_SUCCESS)
302346
ret = true;
303347

304-
dma_free_coherent(dev, size, addr, phys_addr);
348+
dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
305349

306350
err:
307351
return ret;
@@ -314,15 +358,29 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
314358
dma_addr_t phys_addr;
315359
struct pci_dev *pdev = test->pdev;
316360
struct device *dev = &pdev->dev;
361+
void *orig_addr;
362+
dma_addr_t orig_phys_addr;
363+
size_t offset;
364+
size_t alignment = test->alignment;
317365
u32 crc32;
318366

319-
addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
320-
if (!addr) {
367+
orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
368+
GFP_KERNEL);
369+
if (!orig_addr) {
321370
dev_err(dev, "failed to allocate destination address\n");
322371
ret = false;
323372
goto err;
324373
}
325374

375+
if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
376+
phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
377+
offset = phys_addr - orig_phys_addr;
378+
addr = orig_addr + offset;
379+
} else {
380+
phys_addr = orig_phys_addr;
381+
addr = orig_addr;
382+
}
383+
326384
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
327385
lower_32_bits(phys_addr));
328386
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
@@ -339,7 +397,7 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
339397
if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
340398
ret = true;
341399

342-
dma_free_coherent(dev, size, addr, phys_addr);
400+
dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
343401
err:
344402
return ret;
345403
}
@@ -410,11 +468,14 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
410468
return -ENOMEM;
411469

412470
test->test_reg_bar = 0;
471+
test->alignment = 0;
413472
test->pdev = pdev;
414473

415474
data = (struct pci_endpoint_test_data *)ent->driver_data;
416-
if (data)
475+
if (data) {
417476
test_reg_bar = data->test_reg_bar;
477+
test->alignment = data->alignment;
478+
}
418479

419480
init_completion(&test->irq_raised);
420481
mutex_init(&test->mutex);

0 commit comments

Comments
 (0)