diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index ef9b309e8e09..2f7c0b3a448b 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -1683,4 +1683,39 @@ static void amd_iommu_detach_device(struct iommu_domain *dom, | |||
1683 | iommu_completion_wait(iommu); | 1683 | iommu_completion_wait(iommu); |
1684 | } | 1684 | } |
1685 | 1685 | ||
1686 | static int amd_iommu_attach_device(struct iommu_domain *dom, | ||
1687 | struct device *dev) | ||
1688 | { | ||
1689 | struct protection_domain *domain = dom->priv; | ||
1690 | struct protection_domain *old_domain; | ||
1691 | struct amd_iommu *iommu; | ||
1692 | struct pci_dev *pdev; | ||
1693 | u16 devid; | ||
1694 | |||
1695 | if (dev->bus != &pci_bus_type) | ||
1696 | return -EINVAL; | ||
1697 | |||
1698 | pdev = to_pci_dev(dev); | ||
1699 | |||
1700 | devid = calc_devid(pdev->bus->number, pdev->devfn); | ||
1701 | |||
1702 | if (devid >= amd_iommu_last_bdf || | ||
1703 | devid != amd_iommu_alias_table[devid]) | ||
1704 | return -EINVAL; | ||
1705 | |||
1706 | iommu = amd_iommu_rlookup_table[devid]; | ||
1707 | if (!iommu) | ||
1708 | return -EINVAL; | ||
1709 | |||
1710 | old_domain = domain_for_device(devid); | ||
1711 | if (old_domain) | ||
1712 | return -EBUSY; | ||
1713 | |||
1714 | attach_device(iommu, domain, devid); | ||
1715 | |||
1716 | iommu_completion_wait(iommu); | ||
1717 | |||
1718 | return 0; | ||
1719 | } | ||
1720 | |||
1686 | #endif | 1721 | #endif |