aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/pci_endpoint_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/pci_endpoint_test.c')
-rw-r--r--drivers/misc/pci_endpoint_test.c132
1 files changed, 109 insertions, 23 deletions
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 09c10f426b64..deb203026496 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -72,6 +72,11 @@ static DEFINE_IDA(pci_endpoint_test_ida);
72 72
73#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \ 73#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
74 miscdev) 74 miscdev)
75
76static bool no_msi;
77module_param(no_msi, bool, 0444);
78MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");
79
75enum pci_barno { 80enum pci_barno {
76 BAR_0, 81 BAR_0,
77 BAR_1, 82 BAR_1,
@@ -90,9 +95,15 @@ struct pci_endpoint_test {
90 /* mutex to protect the ioctls */ 95 /* mutex to protect the ioctls */
91 struct mutex mutex; 96 struct mutex mutex;
92 struct miscdevice miscdev; 97 struct miscdevice miscdev;
98 enum pci_barno test_reg_bar;
99 size_t alignment;
93}; 100};
94 101
95static int bar_size[] = { 4, 512, 1024, 16384, 131072, 1048576 }; 102struct pci_endpoint_test_data {
103 enum pci_barno test_reg_bar;
104 size_t alignment;
105 bool no_msi;
106};
96 107
97static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, 108static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
98 u32 offset) 109 u32 offset)
@@ -141,11 +152,15 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
141 int j; 152 int j;
142 u32 val; 153 u32 val;
143 int size; 154 int size;
155 struct pci_dev *pdev = test->pdev;
144 156
145 if (!test->bar[barno]) 157 if (!test->bar[barno])
146 return false; 158 return false;
147 159
148 size = bar_size[barno]; 160 size = pci_resource_len(pdev, barno);
161
162 if (barno == test->test_reg_bar)
163 size = 0x4;
149 164
150 for (j = 0; j < size; j += 4) 165 for (j = 0; j < size; j += 4)
151 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0); 166 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
@@ -202,16 +217,32 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
202 dma_addr_t dst_phys_addr; 217 dma_addr_t dst_phys_addr;
203 struct pci_dev *pdev = test->pdev; 218 struct pci_dev *pdev = test->pdev;
204 struct device *dev = &pdev->dev; 219 struct device *dev = &pdev->dev;
220 void *orig_src_addr;
221 dma_addr_t orig_src_phys_addr;
222 void *orig_dst_addr;
223 dma_addr_t orig_dst_phys_addr;
224 size_t offset;
225 size_t alignment = test->alignment;
205 u32 src_crc32; 226 u32 src_crc32;
206 u32 dst_crc32; 227 u32 dst_crc32;
207 228
208 src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL); 229 orig_src_addr = dma_alloc_coherent(dev, size + alignment,
209 if (!src_addr) { 230 &orig_src_phys_addr, GFP_KERNEL);
231 if (!orig_src_addr) {
210 dev_err(dev, "failed to allocate source buffer\n"); 232 dev_err(dev, "failed to allocate source buffer\n");
211 ret = false; 233 ret = false;
212 goto err; 234 goto err;
213 } 235 }
214 236
237 if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) {
238 src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment);
239 offset = src_phys_addr - orig_src_phys_addr;
240 src_addr = orig_src_addr + offset;
241 } else {
242 src_phys_addr = orig_src_phys_addr;
243 src_addr = orig_src_addr;
244 }
245
215 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR, 246 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
216 lower_32_bits(src_phys_addr)); 247 lower_32_bits(src_phys_addr));
217 248
@@ -221,11 +252,21 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
221 get_random_bytes(src_addr, size); 252 get_random_bytes(src_addr, size);
222 src_crc32 = crc32_le(~0, src_addr, size); 253 src_crc32 = crc32_le(~0, src_addr, size);
223 254
224 dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL); 255 orig_dst_addr = dma_alloc_coherent(dev, size + alignment,
225 if (!dst_addr) { 256 &orig_dst_phys_addr, GFP_KERNEL);
257 if (!orig_dst_addr) {
226 dev_err(dev, "failed to allocate destination address\n"); 258 dev_err(dev, "failed to allocate destination address\n");
227 ret = false; 259 ret = false;
228 goto err_src_addr; 260 goto err_orig_src_addr;
261 }
262
263 if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) {
264 dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment);
265 offset = dst_phys_addr - orig_dst_phys_addr;
266 dst_addr = orig_dst_addr + offset;
267 } else {
268 dst_phys_addr = orig_dst_phys_addr;
269 dst_addr = orig_dst_addr;
229 } 270 }
230 271
231 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, 272 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
@@ -245,10 +286,12 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
245 if (dst_crc32 == src_crc32) 286 if (dst_crc32 == src_crc32)
246 ret = true; 287 ret = true;
247 288
248 dma_free_coherent(dev, size, dst_addr, dst_phys_addr); 289 dma_free_coherent(dev, size + alignment, orig_dst_addr,
290 orig_dst_phys_addr);
249 291
250err_src_addr: 292err_orig_src_addr:
251 dma_free_coherent(dev, size, src_addr, src_phys_addr); 293 dma_free_coherent(dev, size + alignment, orig_src_addr,
294 orig_src_phys_addr);
252 295
253err: 296err:
254 return ret; 297 return ret;
@@ -262,15 +305,29 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
262 dma_addr_t phys_addr; 305 dma_addr_t phys_addr;
263 struct pci_dev *pdev = test->pdev; 306 struct pci_dev *pdev = test->pdev;
264 struct device *dev = &pdev->dev; 307 struct device *dev = &pdev->dev;
308 void *orig_addr;
309 dma_addr_t orig_phys_addr;
310 size_t offset;
311 size_t alignment = test->alignment;
265 u32 crc32; 312 u32 crc32;
266 313
267 addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL); 314 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
268 if (!addr) { 315 GFP_KERNEL);
316 if (!orig_addr) {
269 dev_err(dev, "failed to allocate address\n"); 317 dev_err(dev, "failed to allocate address\n");
270 ret = false; 318 ret = false;
271 goto err; 319 goto err;
272 } 320 }
273 321
322 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
323 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
324 offset = phys_addr - orig_phys_addr;
325 addr = orig_addr + offset;
326 } else {
327 phys_addr = orig_phys_addr;
328 addr = orig_addr;
329 }
330
274 get_random_bytes(addr, size); 331 get_random_bytes(addr, size);
275 332
276 crc32 = crc32_le(~0, addr, size); 333 crc32 = crc32_le(~0, addr, size);
@@ -293,7 +350,7 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
293 if (reg & STATUS_READ_SUCCESS) 350 if (reg & STATUS_READ_SUCCESS)
294 ret = true; 351 ret = true;
295 352
296 dma_free_coherent(dev, size, addr, phys_addr); 353 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
297 354
298err: 355err:
299 return ret; 356 return ret;
@@ -306,15 +363,29 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
306 dma_addr_t phys_addr; 363 dma_addr_t phys_addr;
307 struct pci_dev *pdev = test->pdev; 364 struct pci_dev *pdev = test->pdev;
308 struct device *dev = &pdev->dev; 365 struct device *dev = &pdev->dev;
366 void *orig_addr;
367 dma_addr_t orig_phys_addr;
368 size_t offset;
369 size_t alignment = test->alignment;
309 u32 crc32; 370 u32 crc32;
310 371
311 addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL); 372 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
312 if (!addr) { 373 GFP_KERNEL);
374 if (!orig_addr) {
313 dev_err(dev, "failed to allocate destination address\n"); 375 dev_err(dev, "failed to allocate destination address\n");
314 ret = false; 376 ret = false;
315 goto err; 377 goto err;
316 } 378 }
317 379
380 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
381 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
382 offset = phys_addr - orig_phys_addr;
383 addr = orig_addr + offset;
384 } else {
385 phys_addr = orig_phys_addr;
386 addr = orig_addr;
387 }
388
318 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, 389 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
319 lower_32_bits(phys_addr)); 390 lower_32_bits(phys_addr));
320 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR, 391 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
@@ -331,7 +402,7 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
331 if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM)) 402 if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
332 ret = true; 403 ret = true;
333 404
334 dma_free_coherent(dev, size, addr, phys_addr); 405 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
335err: 406err:
336 return ret; 407 return ret;
337} 408}
@@ -383,13 +454,15 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
383{ 454{
384 int i; 455 int i;
385 int err; 456 int err;
386 int irq; 457 int irq = 0;
387 int id; 458 int id;
388 char name[20]; 459 char name[20];
389 enum pci_barno bar; 460 enum pci_barno bar;
390 void __iomem *base; 461 void __iomem *base;
391 struct device *dev = &pdev->dev; 462 struct device *dev = &pdev->dev;
392 struct pci_endpoint_test *test; 463 struct pci_endpoint_test *test;
464 struct pci_endpoint_test_data *data;
465 enum pci_barno test_reg_bar = BAR_0;
393 struct miscdevice *misc_device; 466 struct miscdevice *misc_device;
394 467
395 if (pci_is_bridge(pdev)) 468 if (pci_is_bridge(pdev))
@@ -399,7 +472,17 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
399 if (!test) 472 if (!test)
400 return -ENOMEM; 473 return -ENOMEM;
401 474
475 test->test_reg_bar = 0;
476 test->alignment = 0;
402 test->pdev = pdev; 477 test->pdev = pdev;
478
479 data = (struct pci_endpoint_test_data *)ent->driver_data;
480 if (data) {
481 test_reg_bar = data->test_reg_bar;
482 test->alignment = data->alignment;
483 no_msi = data->no_msi;
484 }
485
403 init_completion(&test->irq_raised); 486 init_completion(&test->irq_raised);
404 mutex_init(&test->mutex); 487 mutex_init(&test->mutex);
405 488
@@ -417,9 +500,11 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
417 500
418 pci_set_master(pdev); 501 pci_set_master(pdev);
419 502
420 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); 503 if (!no_msi) {
421 if (irq < 0) 504 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
422 dev_err(dev, "failed to get MSI interrupts\n"); 505 if (irq < 0)
506 dev_err(dev, "failed to get MSI interrupts\n");
507 }
423 508
424 err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, 509 err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
425 IRQF_SHARED, DRV_MODULE_NAME, test); 510 IRQF_SHARED, DRV_MODULE_NAME, test);
@@ -441,14 +526,15 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
441 base = pci_ioremap_bar(pdev, bar); 526 base = pci_ioremap_bar(pdev, bar);
442 if (!base) { 527 if (!base) {
443 dev_err(dev, "failed to read BAR%d\n", bar); 528 dev_err(dev, "failed to read BAR%d\n", bar);
444 WARN_ON(bar == BAR_0); 529 WARN_ON(bar == test_reg_bar);
445 } 530 }
446 test->bar[bar] = base; 531 test->bar[bar] = base;
447 } 532 }
448 533
449 test->base = test->bar[0]; 534 test->base = test->bar[test_reg_bar];
450 if (!test->base) { 535 if (!test->base) {
451 dev_err(dev, "Cannot perform PCI test without BAR0\n"); 536 dev_err(dev, "Cannot perform PCI test without BAR%d\n",
537 test_reg_bar);
452 goto err_iounmap; 538 goto err_iounmap;
453 } 539 }
454 540