| 591 | } |
| 592 | |
| 593 | static rt_ssize_t msi_capability_init(struct rt_pci_device *pdev, |
| 594 | int nvec, RT_IRQ_AFFINITY_DECLARE((*affinities))) |
| 595 | { |
| 596 | rt_err_t err; |
| 597 | struct rt_pci_msi_desc *desc; |
| 598 | |
| 599 | msi_write_enable(pdev, RT_FALSE); |
| 600 | |
| 601 | spin_lock(&pdev->msi_lock); |
| 602 | |
| 603 | if (!(err = msi_setup_msi_desc(pdev, nvec))) |
| 604 | { |
| 605 | /* All MSIs are unmasked by default; mask them all */ |
| 606 | desc = rt_pci_msi_first_desc(pdev); |
| 607 | msi_mask(&desc->msi, msi_multi_mask(&desc->msi), pdev); |
| 608 | |
| 609 | if (!(err = rt_pci_msi_setup_irqs(pdev, nvec, PCIY_MSI))) |
| 610 | { |
| 611 | err = msi_verify_entries(pdev); |
| 612 | } |
| 613 | |
| 614 | if (err) |
| 615 | { |
| 616 | msi_unmask(&desc->msi, msi_multi_mask(&desc->msi), pdev); |
| 617 | } |
| 618 | } |
| 619 | |
| 620 | spin_unlock(&pdev->msi_lock); |
| 621 | |
| 622 | if (err) |
| 623 | { |
| 624 | rt_pci_msi_free_irqs(pdev); |
| 625 | |
| 626 | LOG_E("%s: Setup %s interrupts(%d) error = %s", |
| 627 | rt_dm_dev_get_name(&pdev->parent), "MSI", nvec, rt_strerror(err)); |
| 628 | |
| 629 | return err; |
| 630 | } |
| 631 | |
| 632 | if (affinities) |
| 633 | { |
| 634 | for (int idx = 0; idx < nvec; ++idx) |
| 635 | { |
| 636 | msi_affinity_init(desc, idx, affinities[idx]); |
| 637 | } |
| 638 | } |
| 639 | |
| 640 | /* Disable INTX */ |
| 641 | rt_pci_intx(pdev, RT_FALSE); |
| 642 | |
| 643 | /* Set MSI enabled bits */ |
| 644 | msi_write_enable(pdev, RT_TRUE); |
| 645 | |
| 646 | pdev->irq = desc->irq; |
| 647 | |
| 648 | pdev->msi_enabled = RT_TRUE; |
| 649 | |
| 650 | return nvec; |
no test coverage detected