aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2015-07-22 05:52:53 -0400
committerJoerg Roedel <jroedel@suse.de>2015-08-12 10:23:36 -0400
commitd160aca5276d093fc68d6ff48888586c90309d03 (patch)
tree027e1adb88553ebcfe1b308cf687564c17d90055 /drivers/iommu
parentc6c2cebd665933216785246a1d15b4112fa74bbf (diff)
iommu/vt-d: Unify domain->iommu attach/detachment
Move the code to attach/detach domains to iommus and vice verce into a single function to make sure there are no dangling references. Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/intel-iommu.c125
1 files changed, 49 insertions, 76 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 46359bd9da63..1cb7a3eb29d3 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1678,90 +1678,64 @@ static struct dmar_domain *alloc_domain(int flags)
1678 return domain; 1678 return domain;
1679} 1679}
1680 1680
1681static int __iommu_attach_domain(struct dmar_domain *domain, 1681/* Must be called with iommu->lock */
1682 struct intel_iommu *iommu) 1682static int domain_attach_iommu(struct dmar_domain *domain,
1683{
1684 int num;
1685 unsigned long ndomains;
1686
1687 num = domain->iommu_did[iommu->seq_id];
1688 if (num)
1689 return num;
1690
1691 ndomains = cap_ndoms(iommu->cap);
1692 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1693
1694 if (num < ndomains) {
1695 set_bit(num, iommu->domain_ids);
1696 set_iommu_domain(iommu, num, domain);
1697 domain->iommu_did[iommu->seq_id] = num;
1698 } else {
1699 num = -ENOSPC;
1700 }
1701
1702 if (num < 0)
1703 pr_err("%s: No free domain ids\n", iommu->name);
1704
1705 return num;
1706}
1707
1708static int iommu_attach_domain(struct dmar_domain *domain,
1709 struct intel_iommu *iommu) 1683 struct intel_iommu *iommu)
1710{ 1684{
1711 int num; 1685 unsigned long ndomains;
1712 unsigned long flags;
1713
1714 spin_lock_irqsave(&iommu->lock, flags);
1715 num = __iommu_attach_domain(domain, iommu);
1716 spin_unlock_irqrestore(&iommu->lock, flags);
1717
1718 return num;
1719}
1720
1721static void iommu_detach_domain(struct dmar_domain *domain,
1722 struct intel_iommu *iommu)
1723{
1724 unsigned long flags; 1686 unsigned long flags;
1725 int num; 1687 int ret, num;
1726
1727 spin_lock_irqsave(&iommu->lock, flags);
1728 1688
1729 num = domain->iommu_did[iommu->seq_id]; 1689 assert_spin_locked(&iommu->lock);
1730
1731 if (num == 0)
1732 return;
1733
1734 clear_bit(num, iommu->domain_ids);
1735 set_iommu_domain(iommu, num, NULL);
1736
1737 spin_unlock_irqrestore(&iommu->lock, flags);
1738}
1739
1740static void domain_attach_iommu(struct dmar_domain *domain,
1741 struct intel_iommu *iommu)
1742{
1743 unsigned long flags;
1744 1690
1745 spin_lock_irqsave(&domain->iommu_lock, flags); 1691 spin_lock_irqsave(&domain->iommu_lock, flags);
1692
1746 domain->iommu_refcnt[iommu->seq_id] += 1; 1693 domain->iommu_refcnt[iommu->seq_id] += 1;
1747 domain->iommu_count += 1; 1694 domain->iommu_count += 1;
1748 if (domain->iommu_refcnt[iommu->seq_id] == 1) { 1695 if (domain->iommu_refcnt[iommu->seq_id] == 1) {
1749 domain->nid = iommu->node; 1696 ndomains = cap_ndoms(iommu->cap);
1697 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1698
1699 if (num >= ndomains) {
1700 pr_err("%s: No free domain ids\n", iommu->name);
1701 domain->iommu_refcnt[iommu->seq_id] -= 1;
1702 domain->iommu_count -= 1;
1703 ret = -ENOSPC;
1704 goto out_unlock;
1705 }
1706
1707 set_bit(num, iommu->domain_ids);
1708 set_iommu_domain(iommu, num, domain);
1709
1710 domain->iommu_did[iommu->seq_id] = num;
1711 domain->nid = iommu->node;
1712
1750 domain_update_iommu_cap(domain); 1713 domain_update_iommu_cap(domain);
1751 } 1714 }
1715
1716 ret = 0;
1717out_unlock:
1752 spin_unlock_irqrestore(&domain->iommu_lock, flags); 1718 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1719
1720 return ret;
1753} 1721}
1754 1722
1755static int domain_detach_iommu(struct dmar_domain *domain, 1723static int domain_detach_iommu(struct dmar_domain *domain,
1756 struct intel_iommu *iommu) 1724 struct intel_iommu *iommu)
1757{ 1725{
1726 int num, count = INT_MAX;
1758 unsigned long flags; 1727 unsigned long flags;
1759 int count = INT_MAX; 1728
1729 assert_spin_locked(&iommu->lock);
1760 1730
1761 spin_lock_irqsave(&domain->iommu_lock, flags); 1731 spin_lock_irqsave(&domain->iommu_lock, flags);
1762 domain->iommu_refcnt[iommu->seq_id] -= 1; 1732 domain->iommu_refcnt[iommu->seq_id] -= 1;
1763 count = --domain->iommu_count; 1733 count = --domain->iommu_count;
1764 if (domain->iommu_refcnt[iommu->seq_id] == 0) { 1734 if (domain->iommu_refcnt[iommu->seq_id] == 0) {
1735 num = domain->iommu_did[iommu->seq_id];
1736 clear_bit(num, iommu->domain_ids);
1737 set_iommu_domain(iommu, num, NULL);
1738
1765 domain_update_iommu_cap(domain); 1739 domain_update_iommu_cap(domain);
1766 domain->iommu_did[iommu->seq_id] = 0; 1740 domain->iommu_did[iommu->seq_id] = 0;
1767 } 1741 }
@@ -1886,7 +1860,6 @@ static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
1886static void domain_exit(struct dmar_domain *domain) 1860static void domain_exit(struct dmar_domain *domain)
1887{ 1861{
1888 struct page *freelist = NULL; 1862 struct page *freelist = NULL;
1889 int i;
1890 1863
1891 /* Domain 0 is reserved, so dont process it */ 1864 /* Domain 0 is reserved, so dont process it */
1892 if (!domain) 1865 if (!domain)
@@ -1896,20 +1869,16 @@ static void domain_exit(struct dmar_domain *domain)
1896 if (!intel_iommu_strict) 1869 if (!intel_iommu_strict)
1897 flush_unmaps_timeout(0); 1870 flush_unmaps_timeout(0);
1898 1871
1899 /* remove associated devices */ 1872 /* Remove associated devices and clear attached or cached domains */
1873 rcu_read_lock();
1900 domain_remove_dev_info(domain); 1874 domain_remove_dev_info(domain);
1875 rcu_read_unlock();
1901 1876
1902 /* destroy iovas */ 1877 /* destroy iovas */
1903 put_iova_domain(&domain->iovad); 1878 put_iova_domain(&domain->iovad);
1904 1879
1905 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); 1880 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
1906 1881
1907 /* clear attached or cached domains */
1908 rcu_read_lock();
1909 for_each_domain_iommu(i, domain)
1910 iommu_detach_domain(domain, g_iommus[i]);
1911 rcu_read_unlock();
1912
1913 dma_free_pagelist(freelist); 1882 dma_free_pagelist(freelist);
1914 1883
1915 free_domain_mem(domain); 1884 free_domain_mem(domain);
@@ -2286,6 +2255,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2286 struct dmar_domain *found = NULL; 2255 struct dmar_domain *found = NULL;
2287 struct device_domain_info *info; 2256 struct device_domain_info *info;
2288 unsigned long flags; 2257 unsigned long flags;
2258 int ret;
2289 2259
2290 info = alloc_devinfo_mem(); 2260 info = alloc_devinfo_mem();
2291 if (!info) 2261 if (!info)
@@ -2313,11 +2283,14 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2313 return found; 2283 return found;
2314 } 2284 }
2315 2285
2316 if (iommu_attach_domain(domain, iommu) < 0) { 2286 spin_lock(&iommu->lock);
2287 ret = domain_attach_iommu(domain, iommu);
2288 spin_unlock(&iommu->lock);
2289
2290 if (ret) {
2317 spin_unlock_irqrestore(&device_domain_lock, flags); 2291 spin_unlock_irqrestore(&device_domain_lock, flags);
2318 return NULL; 2292 return NULL;
2319 } 2293 }
2320 domain_attach_iommu(domain, iommu);
2321 2294
2322 list_add(&info->link, &domain->devices); 2295 list_add(&info->link, &domain->devices);
2323 list_add(&info->global, &device_domain_list); 2296 list_add(&info->global, &device_domain_list);
@@ -4590,12 +4563,10 @@ static void dmar_remove_one_dev_info(struct dmar_domain *domain,
4590 iommu_disable_dev_iotlb(info); 4563 iommu_disable_dev_iotlb(info);
4591 domain_context_clear(iommu, dev); 4564 domain_context_clear(iommu, dev);
4592 free_devinfo_mem(info); 4565 free_devinfo_mem(info);
4593 domain_detach_iommu(domain, iommu);
4594 4566
4595 spin_lock_irqsave(&domain->iommu_lock, flags); 4567 spin_lock_irqsave(&iommu->lock, flags);
4596 if (!domain->iommu_refcnt[iommu->seq_id]) 4568 domain_detach_iommu(domain, iommu);
4597 iommu_detach_domain(domain, iommu); 4569 spin_unlock_irqrestore(&iommu->lock, flags);
4598 spin_unlock_irqrestore(&domain->iommu_lock, flags);
4599} 4570}
4600 4571
4601static int md_domain_init(struct dmar_domain *domain, int guest_width) 4572static int md_domain_init(struct dmar_domain *domain, int guest_width)
@@ -4676,10 +4647,12 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
4676 4647
4677 old_domain = find_domain(dev); 4648 old_domain = find_domain(dev);
4678 if (old_domain) { 4649 if (old_domain) {
4650 rcu_read_lock();
4679 if (domain_type_is_vm_or_si(dmar_domain)) 4651 if (domain_type_is_vm_or_si(dmar_domain))
4680 dmar_remove_one_dev_info(old_domain, dev); 4652 dmar_remove_one_dev_info(old_domain, dev);
4681 else 4653 else
4682 domain_remove_dev_info(old_domain); 4654 domain_remove_dev_info(old_domain);
4655 rcu_read_unlock();
4683 4656
4684 if (!domain_type_is_vm_or_si(old_domain) && 4657 if (!domain_type_is_vm_or_si(old_domain) &&
4685 list_empty(&old_domain->devices)) 4658 list_empty(&old_domain->devices))