.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /** |
---|
2 | 3 | * Host side test driver to test endpoint functionality |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2017 Texas Instruments |
---|
5 | 6 | * Author: Kishon Vijay Abraham I <kishon@ti.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software: you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 of |
---|
9 | | - * the License as published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | | - * |
---|
16 | | - * You should have received a copy of the GNU General Public License |
---|
17 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
18 | 7 | */ |
---|
19 | 8 | |
---|
20 | 9 | #include <linux/crc32.h> |
---|
.. | .. |
---|
28 | 17 | #include <linux/mutex.h> |
---|
29 | 18 | #include <linux/random.h> |
---|
30 | 19 | #include <linux/slab.h> |
---|
| 20 | +#include <linux/uaccess.h> |
---|
31 | 21 | #include <linux/pci.h> |
---|
32 | 22 | #include <linux/pci_ids.h> |
---|
33 | 23 | |
---|
.. | .. |
---|
75 | 65 | #define PCI_ENDPOINT_TEST_IRQ_TYPE 0x24 |
---|
76 | 66 | #define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28 |
---|
77 | 67 | |
---|
| 68 | +#define PCI_ENDPOINT_TEST_FLAGS 0x2c |
---|
| 69 | +#define FLAG_USE_DMA BIT(0) |
---|
| 70 | + |
---|
| 71 | +#define PCI_DEVICE_ID_TI_J721E 0xb00d |
---|
78 | 72 | #define PCI_DEVICE_ID_TI_AM654 0xb00c |
---|
| 73 | +#define PCI_DEVICE_ID_LS1088A 0x80c0 |
---|
79 | 74 | |
---|
80 | 75 | #define is_am654_pci_dev(pdev) \ |
---|
81 | 76 | ((pdev)->device == PCI_DEVICE_ID_TI_AM654) |
---|
| 77 | + |
---|
| 78 | +#define PCI_DEVICE_ID_RENESAS_R8A774A1 0x0028 |
---|
| 79 | +#define PCI_DEVICE_ID_RENESAS_R8A774B1 0x002b |
---|
| 80 | +#define PCI_DEVICE_ID_RENESAS_R8A774C0 0x002d |
---|
| 81 | +#define PCI_DEVICE_ID_RENESAS_R8A774E1 0x0025 |
---|
82 | 82 | |
---|
83 | 83 | static DEFINE_IDA(pci_endpoint_test_ida); |
---|
84 | 84 | |
---|
.. | .. |
---|
105 | 105 | struct pci_endpoint_test { |
---|
106 | 106 | struct pci_dev *pdev; |
---|
107 | 107 | void __iomem *base; |
---|
108 | | - void __iomem *bar[6]; |
---|
| 108 | + void __iomem *bar[PCI_STD_NUM_BARS]; |
---|
109 | 109 | struct completion irq_raised; |
---|
110 | 110 | int last_irq; |
---|
111 | 111 | int num_irqs; |
---|
.. | .. |
---|
115 | 115 | struct miscdevice miscdev; |
---|
116 | 116 | enum pci_barno test_reg_bar; |
---|
117 | 117 | size_t alignment; |
---|
| 118 | + const char *name; |
---|
118 | 119 | }; |
---|
119 | 120 | |
---|
120 | 121 | struct pci_endpoint_test_data { |
---|
.. | .. |
---|
233 | 234 | for (i = 0; i < test->num_irqs; i++) { |
---|
234 | 235 | err = devm_request_irq(dev, pci_irq_vector(pdev, i), |
---|
235 | 236 | pci_endpoint_test_irqhandler, |
---|
236 | | - IRQF_SHARED, DRV_MODULE_NAME, test); |
---|
| 237 | + IRQF_SHARED, test->name, test); |
---|
237 | 238 | if (err) |
---|
238 | 239 | goto fail; |
---|
239 | 240 | } |
---|
.. | .. |
---|
330 | 331 | return false; |
---|
331 | 332 | } |
---|
332 | 333 | |
---|
333 | | -static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) |
---|
| 334 | +static int pci_endpoint_test_validate_xfer_params(struct device *dev, |
---|
| 335 | + struct pci_endpoint_test_xfer_param *param, size_t alignment) |
---|
334 | 336 | { |
---|
| 337 | + if (!param->size) { |
---|
| 338 | + dev_dbg(dev, "Data size is zero\n"); |
---|
| 339 | + return -EINVAL; |
---|
| 340 | + } |
---|
| 341 | + |
---|
| 342 | + if (param->size > SIZE_MAX - alignment) { |
---|
| 343 | + dev_dbg(dev, "Maximum transfer data size exceeded\n"); |
---|
| 344 | + return -EINVAL; |
---|
| 345 | + } |
---|
| 346 | + |
---|
| 347 | + return 0; |
---|
| 348 | +} |
---|
| 349 | + |
---|
| 350 | +static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, |
---|
| 351 | + unsigned long arg) |
---|
| 352 | +{ |
---|
| 353 | + struct pci_endpoint_test_xfer_param param; |
---|
335 | 354 | bool ret = false; |
---|
336 | 355 | void *src_addr; |
---|
337 | 356 | void *dst_addr; |
---|
| 357 | + u32 flags = 0; |
---|
| 358 | + bool use_dma; |
---|
| 359 | + size_t size; |
---|
338 | 360 | dma_addr_t src_phys_addr; |
---|
339 | 361 | dma_addr_t dst_phys_addr; |
---|
340 | 362 | struct pci_dev *pdev = test->pdev; |
---|
.. | .. |
---|
348 | 370 | int irq_type = test->irq_type; |
---|
349 | 371 | u32 src_crc32; |
---|
350 | 372 | u32 dst_crc32; |
---|
| 373 | + int err; |
---|
351 | 374 | |
---|
352 | | - if (size > SIZE_MAX - alignment) |
---|
353 | | - goto err; |
---|
| 375 | + err = copy_from_user(¶m, (void __user *)arg, sizeof(param)); |
---|
| 376 | + if (err) { |
---|
| 377 | + dev_err(dev, "Failed to get transfer param\n"); |
---|
| 378 | + return false; |
---|
| 379 | + } |
---|
| 380 | + |
---|
| 381 | + err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); |
---|
| 382 | + if (err) |
---|
| 383 | + return false; |
---|
| 384 | + |
---|
| 385 | + size = param.size; |
---|
| 386 | + |
---|
| 387 | + use_dma = !!(param.flags & PCITEST_FLAGS_USE_DMA); |
---|
| 388 | + if (use_dma) |
---|
| 389 | + flags |= FLAG_USE_DMA; |
---|
354 | 390 | |
---|
355 | 391 | if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { |
---|
356 | 392 | dev_err(dev, "Invalid IRQ type option\n"); |
---|
357 | 393 | goto err; |
---|
358 | 394 | } |
---|
359 | 395 | |
---|
360 | | - orig_src_addr = dma_alloc_coherent(dev, size + alignment, |
---|
361 | | - &orig_src_phys_addr, GFP_KERNEL); |
---|
| 396 | + orig_src_addr = kzalloc(size + alignment, GFP_KERNEL); |
---|
362 | 397 | if (!orig_src_addr) { |
---|
363 | 398 | dev_err(dev, "Failed to allocate source buffer\n"); |
---|
364 | 399 | ret = false; |
---|
365 | 400 | goto err; |
---|
| 401 | + } |
---|
| 402 | + |
---|
| 403 | + get_random_bytes(orig_src_addr, size + alignment); |
---|
| 404 | + orig_src_phys_addr = dma_map_single(dev, orig_src_addr, |
---|
| 405 | + size + alignment, DMA_TO_DEVICE); |
---|
| 406 | + if (dma_mapping_error(dev, orig_src_phys_addr)) { |
---|
| 407 | + dev_err(dev, "failed to map source buffer address\n"); |
---|
| 408 | + ret = false; |
---|
| 409 | + goto err_src_phys_addr; |
---|
366 | 410 | } |
---|
367 | 411 | |
---|
368 | 412 | if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) { |
---|
.. | .. |
---|
380 | 424 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR, |
---|
381 | 425 | upper_32_bits(src_phys_addr)); |
---|
382 | 426 | |
---|
383 | | - get_random_bytes(src_addr, size); |
---|
384 | 427 | src_crc32 = crc32_le(~0, src_addr, size); |
---|
385 | 428 | |
---|
386 | | - orig_dst_addr = dma_alloc_coherent(dev, size + alignment, |
---|
387 | | - &orig_dst_phys_addr, GFP_KERNEL); |
---|
| 429 | + orig_dst_addr = kzalloc(size + alignment, GFP_KERNEL); |
---|
388 | 430 | if (!orig_dst_addr) { |
---|
389 | 431 | dev_err(dev, "Failed to allocate destination address\n"); |
---|
390 | 432 | ret = false; |
---|
391 | | - goto err_orig_src_addr; |
---|
| 433 | + goto err_dst_addr; |
---|
| 434 | + } |
---|
| 435 | + |
---|
| 436 | + orig_dst_phys_addr = dma_map_single(dev, orig_dst_addr, |
---|
| 437 | + size + alignment, DMA_FROM_DEVICE); |
---|
| 438 | + if (dma_mapping_error(dev, orig_dst_phys_addr)) { |
---|
| 439 | + dev_err(dev, "failed to map destination buffer address\n"); |
---|
| 440 | + ret = false; |
---|
| 441 | + goto err_dst_phys_addr; |
---|
392 | 442 | } |
---|
393 | 443 | |
---|
394 | 444 | if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) { |
---|
.. | .. |
---|
408 | 458 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, |
---|
409 | 459 | size); |
---|
410 | 460 | |
---|
| 461 | + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_FLAGS, flags); |
---|
411 | 462 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); |
---|
412 | 463 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); |
---|
413 | 464 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, |
---|
.. | .. |
---|
415 | 466 | |
---|
416 | 467 | wait_for_completion(&test->irq_raised); |
---|
417 | 468 | |
---|
| 469 | + dma_unmap_single(dev, orig_dst_phys_addr, size + alignment, |
---|
| 470 | + DMA_FROM_DEVICE); |
---|
| 471 | + |
---|
418 | 472 | dst_crc32 = crc32_le(~0, dst_addr, size); |
---|
419 | 473 | if (dst_crc32 == src_crc32) |
---|
420 | 474 | ret = true; |
---|
421 | 475 | |
---|
422 | | - dma_free_coherent(dev, size + alignment, orig_dst_addr, |
---|
423 | | - orig_dst_phys_addr); |
---|
| 476 | +err_dst_phys_addr: |
---|
| 477 | + kfree(orig_dst_addr); |
---|
424 | 478 | |
---|
425 | | -err_orig_src_addr: |
---|
426 | | - dma_free_coherent(dev, size + alignment, orig_src_addr, |
---|
427 | | - orig_src_phys_addr); |
---|
| 479 | +err_dst_addr: |
---|
| 480 | + dma_unmap_single(dev, orig_src_phys_addr, size + alignment, |
---|
| 481 | + DMA_TO_DEVICE); |
---|
| 482 | + |
---|
| 483 | +err_src_phys_addr: |
---|
| 484 | + kfree(orig_src_addr); |
---|
428 | 485 | |
---|
429 | 486 | err: |
---|
430 | 487 | return ret; |
---|
431 | 488 | } |
---|
432 | 489 | |
---|
433 | | -static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) |
---|
| 490 | +static bool pci_endpoint_test_write(struct pci_endpoint_test *test, |
---|
| 491 | + unsigned long arg) |
---|
434 | 492 | { |
---|
| 493 | + struct pci_endpoint_test_xfer_param param; |
---|
435 | 494 | bool ret = false; |
---|
| 495 | + u32 flags = 0; |
---|
| 496 | + bool use_dma; |
---|
436 | 497 | u32 reg; |
---|
437 | 498 | void *addr; |
---|
438 | 499 | dma_addr_t phys_addr; |
---|
.. | .. |
---|
443 | 504 | size_t offset; |
---|
444 | 505 | size_t alignment = test->alignment; |
---|
445 | 506 | int irq_type = test->irq_type; |
---|
| 507 | + size_t size; |
---|
446 | 508 | u32 crc32; |
---|
| 509 | + int err; |
---|
447 | 510 | |
---|
448 | | - if (size > SIZE_MAX - alignment) |
---|
449 | | - goto err; |
---|
| 511 | + err = copy_from_user(¶m, (void __user *)arg, sizeof(param)); |
---|
| 512 | + if (err != 0) { |
---|
| 513 | + dev_err(dev, "Failed to get transfer param\n"); |
---|
| 514 | + return false; |
---|
| 515 | + } |
---|
| 516 | + |
---|
| 517 | + err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); |
---|
| 518 | + if (err) |
---|
| 519 | + return false; |
---|
| 520 | + |
---|
| 521 | + size = param.size; |
---|
| 522 | + |
---|
| 523 | + use_dma = !!(param.flags & PCITEST_FLAGS_USE_DMA); |
---|
| 524 | + if (use_dma) |
---|
| 525 | + flags |= FLAG_USE_DMA; |
---|
450 | 526 | |
---|
451 | 527 | if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { |
---|
452 | 528 | dev_err(dev, "Invalid IRQ type option\n"); |
---|
453 | 529 | goto err; |
---|
454 | 530 | } |
---|
455 | 531 | |
---|
456 | | - orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, |
---|
457 | | - GFP_KERNEL); |
---|
| 532 | + orig_addr = kzalloc(size + alignment, GFP_KERNEL); |
---|
458 | 533 | if (!orig_addr) { |
---|
459 | 534 | dev_err(dev, "Failed to allocate address\n"); |
---|
460 | 535 | ret = false; |
---|
461 | 536 | goto err; |
---|
| 537 | + } |
---|
| 538 | + |
---|
| 539 | + get_random_bytes(orig_addr, size + alignment); |
---|
| 540 | + |
---|
| 541 | + orig_phys_addr = dma_map_single(dev, orig_addr, size + alignment, |
---|
| 542 | + DMA_TO_DEVICE); |
---|
| 543 | + if (dma_mapping_error(dev, orig_phys_addr)) { |
---|
| 544 | + dev_err(dev, "failed to map source buffer address\n"); |
---|
| 545 | + ret = false; |
---|
| 546 | + goto err_phys_addr; |
---|
462 | 547 | } |
---|
463 | 548 | |
---|
464 | 549 | if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) { |
---|
.. | .. |
---|
469 | 554 | phys_addr = orig_phys_addr; |
---|
470 | 555 | addr = orig_addr; |
---|
471 | 556 | } |
---|
472 | | - |
---|
473 | | - get_random_bytes(addr, size); |
---|
474 | 557 | |
---|
475 | 558 | crc32 = crc32_le(~0, addr, size); |
---|
476 | 559 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM, |
---|
.. | .. |
---|
483 | 566 | |
---|
484 | 567 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); |
---|
485 | 568 | |
---|
| 569 | + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_FLAGS, flags); |
---|
486 | 570 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); |
---|
487 | 571 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); |
---|
488 | 572 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, |
---|
.. | .. |
---|
494 | 578 | if (reg & STATUS_READ_SUCCESS) |
---|
495 | 579 | ret = true; |
---|
496 | 580 | |
---|
497 | | - dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); |
---|
| 581 | + dma_unmap_single(dev, orig_phys_addr, size + alignment, |
---|
| 582 | + DMA_TO_DEVICE); |
---|
| 583 | + |
---|
| 584 | +err_phys_addr: |
---|
| 585 | + kfree(orig_addr); |
---|
498 | 586 | |
---|
499 | 587 | err: |
---|
500 | 588 | return ret; |
---|
501 | 589 | } |
---|
502 | 590 | |
---|
503 | | -static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) |
---|
| 591 | +static bool pci_endpoint_test_read(struct pci_endpoint_test *test, |
---|
| 592 | + unsigned long arg) |
---|
504 | 593 | { |
---|
| 594 | + struct pci_endpoint_test_xfer_param param; |
---|
505 | 595 | bool ret = false; |
---|
| 596 | + u32 flags = 0; |
---|
| 597 | + bool use_dma; |
---|
| 598 | + size_t size; |
---|
506 | 599 | void *addr; |
---|
507 | 600 | dma_addr_t phys_addr; |
---|
508 | 601 | struct pci_dev *pdev = test->pdev; |
---|
.. | .. |
---|
513 | 606 | size_t alignment = test->alignment; |
---|
514 | 607 | int irq_type = test->irq_type; |
---|
515 | 608 | u32 crc32; |
---|
| 609 | + int err; |
---|
516 | 610 | |
---|
517 | | - if (size > SIZE_MAX - alignment) |
---|
518 | | - goto err; |
---|
| 611 | + err = copy_from_user(¶m, (void __user *)arg, sizeof(param)); |
---|
| 612 | + if (err) { |
---|
| 613 | + dev_err(dev, "Failed to get transfer param\n"); |
---|
| 614 | + return false; |
---|
| 615 | + } |
---|
| 616 | + |
---|
| 617 | + err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); |
---|
| 618 | + if (err) |
---|
| 619 | + return false; |
---|
| 620 | + |
---|
| 621 | + size = param.size; |
---|
| 622 | + |
---|
| 623 | + use_dma = !!(param.flags & PCITEST_FLAGS_USE_DMA); |
---|
| 624 | + if (use_dma) |
---|
| 625 | + flags |= FLAG_USE_DMA; |
---|
519 | 626 | |
---|
520 | 627 | if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { |
---|
521 | 628 | dev_err(dev, "Invalid IRQ type option\n"); |
---|
522 | 629 | goto err; |
---|
523 | 630 | } |
---|
524 | 631 | |
---|
525 | | - orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, |
---|
526 | | - GFP_KERNEL); |
---|
| 632 | + orig_addr = kzalloc(size + alignment, GFP_KERNEL); |
---|
527 | 633 | if (!orig_addr) { |
---|
528 | 634 | dev_err(dev, "Failed to allocate destination address\n"); |
---|
529 | 635 | ret = false; |
---|
530 | 636 | goto err; |
---|
| 637 | + } |
---|
| 638 | + |
---|
| 639 | + orig_phys_addr = dma_map_single(dev, orig_addr, size + alignment, |
---|
| 640 | + DMA_FROM_DEVICE); |
---|
| 641 | + if (dma_mapping_error(dev, orig_phys_addr)) { |
---|
| 642 | + dev_err(dev, "failed to map source buffer address\n"); |
---|
| 643 | + ret = false; |
---|
| 644 | + goto err_phys_addr; |
---|
531 | 645 | } |
---|
532 | 646 | |
---|
533 | 647 | if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) { |
---|
.. | .. |
---|
546 | 660 | |
---|
547 | 661 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); |
---|
548 | 662 | |
---|
| 663 | + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_FLAGS, flags); |
---|
549 | 664 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); |
---|
550 | 665 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); |
---|
551 | 666 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, |
---|
.. | .. |
---|
553 | 668 | |
---|
554 | 669 | wait_for_completion(&test->irq_raised); |
---|
555 | 670 | |
---|
| 671 | + dma_unmap_single(dev, orig_phys_addr, size + alignment, |
---|
| 672 | + DMA_FROM_DEVICE); |
---|
| 673 | + |
---|
556 | 674 | crc32 = crc32_le(~0, addr, size); |
---|
557 | 675 | if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM)) |
---|
558 | 676 | ret = true; |
---|
559 | 677 | |
---|
560 | | - dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); |
---|
| 678 | +err_phys_addr: |
---|
| 679 | + kfree(orig_addr); |
---|
561 | 680 | err: |
---|
562 | 681 | return ret; |
---|
| 682 | +} |
---|
| 683 | + |
---|
| 684 | +static bool pci_endpoint_test_clear_irq(struct pci_endpoint_test *test) |
---|
| 685 | +{ |
---|
| 686 | + pci_endpoint_test_release_irq(test); |
---|
| 687 | + pci_endpoint_test_free_irq_vectors(test); |
---|
| 688 | + return true; |
---|
563 | 689 | } |
---|
564 | 690 | |
---|
565 | 691 | static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test, |
---|
.. | .. |
---|
601 | 727 | struct pci_dev *pdev = test->pdev; |
---|
602 | 728 | |
---|
603 | 729 | mutex_lock(&test->mutex); |
---|
| 730 | + |
---|
| 731 | + reinit_completion(&test->irq_raised); |
---|
| 732 | + test->last_irq = -ENODATA; |
---|
| 733 | + |
---|
604 | 734 | switch (cmd) { |
---|
605 | 735 | case PCITEST_BAR: |
---|
606 | 736 | bar = arg; |
---|
.. | .. |
---|
631 | 761 | break; |
---|
632 | 762 | case PCITEST_GET_IRQTYPE: |
---|
633 | 763 | ret = irq_type; |
---|
| 764 | + break; |
---|
| 765 | + case PCITEST_CLEAR_IRQ: |
---|
| 766 | + ret = pci_endpoint_test_clear_irq(test); |
---|
634 | 767 | break; |
---|
635 | 768 | } |
---|
636 | 769 | |
---|
.. | .. |
---|
684 | 817 | init_completion(&test->irq_raised); |
---|
685 | 818 | mutex_init(&test->mutex); |
---|
686 | 819 | |
---|
| 820 | + if ((dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48)) != 0) && |
---|
| 821 | + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) { |
---|
| 822 | + dev_err(dev, "Cannot set DMA mask\n"); |
---|
| 823 | + return -EINVAL; |
---|
| 824 | + } |
---|
| 825 | + |
---|
687 | 826 | err = pci_enable_device(pdev); |
---|
688 | 827 | if (err) { |
---|
689 | 828 | dev_err(dev, "Cannot enable PCI device\n"); |
---|
.. | .. |
---|
698 | 837 | |
---|
699 | 838 | pci_set_master(pdev); |
---|
700 | 839 | |
---|
701 | | - if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) |
---|
| 840 | + if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) { |
---|
| 841 | + err = -EINVAL; |
---|
702 | 842 | goto err_disable_irq; |
---|
| 843 | + } |
---|
703 | 844 | |
---|
704 | | - if (!pci_endpoint_test_request_irq(test)) |
---|
705 | | - goto err_disable_irq; |
---|
706 | | - |
---|
707 | | - for (bar = BAR_0; bar <= BAR_5; bar++) { |
---|
| 845 | + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { |
---|
708 | 846 | if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { |
---|
709 | 847 | base = pci_ioremap_bar(pdev, bar); |
---|
710 | 848 | if (!base) { |
---|
.. | .. |
---|
733 | 871 | } |
---|
734 | 872 | |
---|
735 | 873 | snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); |
---|
| 874 | + test->name = kstrdup(name, GFP_KERNEL); |
---|
| 875 | + if (!test->name) { |
---|
| 876 | + err = -ENOMEM; |
---|
| 877 | + goto err_ida_remove; |
---|
| 878 | + } |
---|
| 879 | + |
---|
| 880 | + if (!pci_endpoint_test_request_irq(test)) { |
---|
| 881 | + err = -EINVAL; |
---|
| 882 | + goto err_kfree_test_name; |
---|
| 883 | + } |
---|
| 884 | + |
---|
736 | 885 | misc_device = &test->miscdev; |
---|
737 | 886 | misc_device->minor = MISC_DYNAMIC_MINOR; |
---|
738 | 887 | misc_device->name = kstrdup(name, GFP_KERNEL); |
---|
739 | 888 | if (!misc_device->name) { |
---|
740 | 889 | err = -ENOMEM; |
---|
741 | | - goto err_ida_remove; |
---|
| 890 | + goto err_release_irq; |
---|
742 | 891 | } |
---|
743 | 892 | misc_device->fops = &pci_endpoint_test_fops, |
---|
744 | 893 | |
---|
.. | .. |
---|
753 | 902 | err_kfree_name: |
---|
754 | 903 | kfree(misc_device->name); |
---|
755 | 904 | |
---|
| 905 | +err_release_irq: |
---|
| 906 | + pci_endpoint_test_release_irq(test); |
---|
| 907 | + |
---|
| 908 | +err_kfree_test_name: |
---|
| 909 | + kfree(test->name); |
---|
| 910 | + |
---|
756 | 911 | err_ida_remove: |
---|
757 | 912 | ida_simple_remove(&pci_endpoint_test_ida, id); |
---|
758 | 913 | |
---|
759 | 914 | err_iounmap: |
---|
760 | | - for (bar = BAR_0; bar <= BAR_5; bar++) { |
---|
| 915 | + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { |
---|
761 | 916 | if (test->bar[bar]) |
---|
762 | 917 | pci_iounmap(pdev, test->bar[bar]); |
---|
763 | 918 | } |
---|
764 | | - pci_endpoint_test_release_irq(test); |
---|
765 | 919 | |
---|
766 | 920 | err_disable_irq: |
---|
767 | 921 | pci_endpoint_test_free_irq_vectors(test); |
---|
.. | .. |
---|
785 | 939 | if (id < 0) |
---|
786 | 940 | return; |
---|
787 | 941 | |
---|
| 942 | + pci_endpoint_test_release_irq(test); |
---|
| 943 | + pci_endpoint_test_free_irq_vectors(test); |
---|
| 944 | + |
---|
788 | 945 | misc_deregister(&test->miscdev); |
---|
789 | 946 | kfree(misc_device->name); |
---|
| 947 | + kfree(test->name); |
---|
790 | 948 | ida_simple_remove(&pci_endpoint_test_ida, id); |
---|
791 | | - for (bar = BAR_0; bar <= BAR_5; bar++) { |
---|
| 949 | + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { |
---|
792 | 950 | if (test->bar[bar]) |
---|
793 | 951 | pci_iounmap(pdev, test->bar[bar]); |
---|
794 | 952 | } |
---|
795 | 953 | |
---|
796 | | - pci_endpoint_test_release_irq(test); |
---|
797 | | - pci_endpoint_test_free_irq_vectors(test); |
---|
798 | | - |
---|
799 | 954 | pci_release_regions(pdev); |
---|
800 | 955 | pci_disable_device(pdev); |
---|
801 | 956 | } |
---|
| 957 | + |
---|
| 958 | +static const struct pci_endpoint_test_data default_data = { |
---|
| 959 | + .test_reg_bar = BAR_0, |
---|
| 960 | + .alignment = SZ_4K, |
---|
| 961 | + .irq_type = IRQ_TYPE_MSI, |
---|
| 962 | +}; |
---|
802 | 963 | |
---|
803 | 964 | static const struct pci_endpoint_test_data am654_data = { |
---|
804 | 965 | .test_reg_bar = BAR_2, |
---|
.. | .. |
---|
806 | 967 | .irq_type = IRQ_TYPE_MSI, |
---|
807 | 968 | }; |
---|
808 | 969 | |
---|
| 970 | +static const struct pci_endpoint_test_data j721e_data = { |
---|
| 971 | + .alignment = 256, |
---|
| 972 | + .irq_type = IRQ_TYPE_MSI, |
---|
| 973 | +}; |
---|
| 974 | + |
---|
809 | 975 | static const struct pci_device_id pci_endpoint_test_tbl[] = { |
---|
810 | | - { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) }, |
---|
811 | | - { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) }, |
---|
812 | | - { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0) }, |
---|
| 976 | + { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x), |
---|
| 977 | + .driver_data = (kernel_ulong_t)&default_data, |
---|
| 978 | + }, |
---|
| 979 | + { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x), |
---|
| 980 | + .driver_data = (kernel_ulong_t)&default_data, |
---|
| 981 | + }, |
---|
| 982 | + { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0), |
---|
| 983 | + .driver_data = (kernel_ulong_t)&default_data, |
---|
| 984 | + }, |
---|
| 985 | + { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A), |
---|
| 986 | + .driver_data = (kernel_ulong_t)&default_data, |
---|
| 987 | + }, |
---|
813 | 988 | { PCI_DEVICE_DATA(SYNOPSYS, EDDA, NULL) }, |
---|
814 | 989 | { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654), |
---|
815 | 990 | .driver_data = (kernel_ulong_t)&am654_data |
---|
816 | 991 | }, |
---|
| 992 | + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774A1),}, |
---|
| 993 | + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774B1),}, |
---|
| 994 | + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774C0),}, |
---|
| 995 | + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774E1),}, |
---|
| 996 | + { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721E), |
---|
| 997 | + .driver_data = (kernel_ulong_t)&j721e_data, |
---|
| 998 | + }, |
---|
817 | 999 | { } |
---|
818 | 1000 | }; |
---|
819 | 1001 | MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl); |
---|