aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/intel-iommu.c
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-07-11 02:19:28 -0400
committerJoerg Roedel <jroedel@suse.de>2014-07-23 10:04:46 -0400
commitfb170fb4c548c6d9fe9f71db946e216abb5c6641 (patch)
treece30c43160df179131588774d14a5ea9724b758d /drivers/iommu/intel-iommu.c
parentab8dfe251571e4a04d367e47e5be93976a77c610 (diff)
iommu/vt-d: Introduce helper functions to make code symmetric for readability
Introduce domain_attach_iommu()/domain_detach_iommu() and refine iommu_attach_domain()/iommu_detach_domain() to make code symmetric and improve readability. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r--drivers/iommu/intel-iommu.c147
1 files changed, 80 insertions, 67 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 52250b3e58d1..eae9b0d8bc60 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1523,32 +1523,39 @@ static struct dmar_domain *alloc_domain(int flags)
1523 return domain; 1523 return domain;
1524} 1524}
1525 1525
1526static int iommu_attach_domain(struct dmar_domain *domain, 1526static int __iommu_attach_domain(struct dmar_domain *domain,
1527 struct intel_iommu *iommu) 1527 struct intel_iommu *iommu)
1528{ 1528{
1529 int num; 1529 int num;
1530 unsigned long ndomains; 1530 unsigned long ndomains;
1531 unsigned long flags;
1532 1531
1533 ndomains = cap_ndoms(iommu->cap); 1532 ndomains = cap_ndoms(iommu->cap);
1534
1535 spin_lock_irqsave(&iommu->lock, flags);
1536
1537 num = find_first_zero_bit(iommu->domain_ids, ndomains); 1533 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1538 if (num >= ndomains) { 1534 if (num < ndomains) {
1539 spin_unlock_irqrestore(&iommu->lock, flags); 1535 set_bit(num, iommu->domain_ids);
1540 printk(KERN_ERR "IOMMU: no free domain ids\n"); 1536 iommu->domains[num] = domain;
1541 return -ENOMEM; 1537 } else {
1538 num = -ENOSPC;
1542 } 1539 }
1543 1540
1544 domain->id = num; 1541 return num;
1545 domain->iommu_count++; 1542}
1546 set_bit(num, iommu->domain_ids); 1543
1547 set_bit(iommu->seq_id, domain->iommu_bmp); 1544static int iommu_attach_domain(struct dmar_domain *domain,
1548 iommu->domains[num] = domain; 1545 struct intel_iommu *iommu)
1546{
1547 int num;
1548 unsigned long flags;
1549
1550 spin_lock_irqsave(&iommu->lock, flags);
1551 num = __iommu_attach_domain(domain, iommu);
1552 if (num < 0)
1553 pr_err("IOMMU: no free domain ids\n");
1554 else
1555 domain->id = num;
1549 spin_unlock_irqrestore(&iommu->lock, flags); 1556 spin_unlock_irqrestore(&iommu->lock, flags);
1550 1557
1551 return 0; 1558 return num;
1552} 1559}
1553 1560
1554static void iommu_detach_domain(struct dmar_domain *domain, 1561static void iommu_detach_domain(struct dmar_domain *domain,
@@ -1558,17 +1565,53 @@ static void iommu_detach_domain(struct dmar_domain *domain,
1558 int num, ndomains; 1565 int num, ndomains;
1559 1566
1560 spin_lock_irqsave(&iommu->lock, flags); 1567 spin_lock_irqsave(&iommu->lock, flags);
1561 ndomains = cap_ndoms(iommu->cap); 1568 if (domain_type_is_vm_or_si(domain)) {
1562 for_each_set_bit(num, iommu->domain_ids, ndomains) { 1569 ndomains = cap_ndoms(iommu->cap);
1563 if (iommu->domains[num] == domain) { 1570 for_each_set_bit(num, iommu->domain_ids, ndomains) {
1564 clear_bit(num, iommu->domain_ids); 1571 if (iommu->domains[num] == domain) {
1565 iommu->domains[num] = NULL; 1572 clear_bit(num, iommu->domain_ids);
1566 break; 1573 iommu->domains[num] = NULL;
1574 break;
1575 }
1567 } 1576 }
1577 } else {
1578 clear_bit(domain->id, iommu->domain_ids);
1579 iommu->domains[domain->id] = NULL;
1568 } 1580 }
1569 spin_unlock_irqrestore(&iommu->lock, flags); 1581 spin_unlock_irqrestore(&iommu->lock, flags);
1570} 1582}
1571 1583
1584static void domain_attach_iommu(struct dmar_domain *domain,
1585 struct intel_iommu *iommu)
1586{
1587 unsigned long flags;
1588
1589 spin_lock_irqsave(&domain->iommu_lock, flags);
1590 if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
1591 domain->iommu_count++;
1592 if (domain->iommu_count == 1)
1593 domain->nid = iommu->node;
1594 domain_update_iommu_cap(domain);
1595 }
1596 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1597}
1598
1599static int domain_detach_iommu(struct dmar_domain *domain,
1600 struct intel_iommu *iommu)
1601{
1602 unsigned long flags;
1603 int count = INT_MAX;
1604
1605 spin_lock_irqsave(&domain->iommu_lock, flags);
1606 if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
1607 count = --domain->iommu_count;
1608 domain_update_iommu_cap(domain);
1609 }
1610 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1611
1612 return count;
1613}
1614
1572static struct iova_domain reserved_iova_list; 1615static struct iova_domain reserved_iova_list;
1573static struct lock_class_key reserved_rbtree_key; 1616static struct lock_class_key reserved_rbtree_key;
1574 1617
@@ -1706,9 +1749,7 @@ static void domain_exit(struct dmar_domain *domain)
1706 /* clear attached or cached domains */ 1749 /* clear attached or cached domains */
1707 rcu_read_lock(); 1750 rcu_read_lock();
1708 for_each_active_iommu(iommu, drhd) 1751 for_each_active_iommu(iommu, drhd)
1709 if (domain_type_is_vm(domain) || 1752 iommu_detach_domain(domain, iommu);
1710 test_bit(iommu->seq_id, domain->iommu_bmp))
1711 iommu_detach_domain(domain, iommu);
1712 rcu_read_unlock(); 1753 rcu_read_unlock();
1713 1754
1714 dma_free_pagelist(freelist); 1755 dma_free_pagelist(freelist);
@@ -1762,16 +1803,12 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
1762 } 1803 }
1763 1804
1764 if (found == 0) { 1805 if (found == 0) {
1765 num = find_first_zero_bit(iommu->domain_ids, ndomains); 1806 id = __iommu_attach_domain(domain, iommu);
1766 if (num >= ndomains) { 1807 if (id < 0) {
1767 spin_unlock_irqrestore(&iommu->lock, flags); 1808 spin_unlock_irqrestore(&iommu->lock, flags);
1768 printk(KERN_ERR "IOMMU: no free domain ids\n"); 1809 pr_err("IOMMU: no free domain ids\n");
1769 return -EFAULT; 1810 return -EFAULT;
1770 } 1811 }
1771
1772 set_bit(num, iommu->domain_ids);
1773 iommu->domains[num] = domain;
1774 id = num;
1775 } 1812 }
1776 1813
1777 /* Skip top levels of page tables for 1814 /* Skip top levels of page tables for
@@ -1830,14 +1867,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
1830 iommu_enable_dev_iotlb(info); 1867 iommu_enable_dev_iotlb(info);
1831 spin_unlock_irqrestore(&iommu->lock, flags); 1868 spin_unlock_irqrestore(&iommu->lock, flags);
1832 1869
1833 spin_lock_irqsave(&domain->iommu_lock, flags); 1870 domain_attach_iommu(domain, iommu);
1834 if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) { 1871
1835 domain->iommu_count++;
1836 if (domain->iommu_count == 1)
1837 domain->nid = iommu->node;
1838 domain_update_iommu_cap(domain);
1839 }
1840 spin_unlock_irqrestore(&domain->iommu_lock, flags);
1841 return 0; 1872 return 0;
1842} 1873}
1843 1874
@@ -2085,7 +2116,7 @@ static inline void unlink_domain_info(struct device_domain_info *info)
2085static void domain_remove_dev_info(struct dmar_domain *domain) 2116static void domain_remove_dev_info(struct dmar_domain *domain)
2086{ 2117{
2087 struct device_domain_info *info, *tmp; 2118 struct device_domain_info *info, *tmp;
2088 unsigned long flags, flags2; 2119 unsigned long flags;
2089 2120
2090 spin_lock_irqsave(&device_domain_lock, flags); 2121 spin_lock_irqsave(&device_domain_lock, flags);
2091 list_for_each_entry_safe(info, tmp, &domain->devices, link) { 2122 list_for_each_entry_safe(info, tmp, &domain->devices, link) {
@@ -2097,16 +2128,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
2097 2128
2098 if (domain_type_is_vm(domain)) { 2129 if (domain_type_is_vm(domain)) {
2099 iommu_detach_dependent_devices(info->iommu, info->dev); 2130 iommu_detach_dependent_devices(info->iommu, info->dev);
2100 /* clear this iommu in iommu_bmp, update iommu count 2131 domain_detach_iommu(domain, info->iommu);
2101 * and capabilities
2102 */
2103 spin_lock_irqsave(&domain->iommu_lock, flags2);
2104 if (test_and_clear_bit(info->iommu->seq_id,
2105 domain->iommu_bmp)) {
2106 domain->iommu_count--;
2107 domain_update_iommu_cap(domain);
2108 }
2109 spin_unlock_irqrestore(&domain->iommu_lock, flags2);
2110 } 2132 }
2111 2133
2112 free_devinfo_mem(info); 2134 free_devinfo_mem(info);
@@ -2236,11 +2258,11 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
2236 if (!domain) 2258 if (!domain)
2237 return NULL; 2259 return NULL;
2238 2260
2239 if (iommu_attach_domain(domain, iommu)) { 2261 if (iommu_attach_domain(domain, iommu) < 0) {
2240 free_domain_mem(domain); 2262 free_domain_mem(domain);
2241 return NULL; 2263 return NULL;
2242 } 2264 }
2243 2265 domain_attach_iommu(domain, iommu);
2244 if (domain_init(domain, gaw)) { 2266 if (domain_init(domain, gaw)) {
2245 domain_exit(domain); 2267 domain_exit(domain);
2246 return NULL; 2268 return NULL;
@@ -2413,10 +2435,11 @@ static int __init si_domain_init(int hw)
2413 2435
2414 for_each_active_iommu(iommu, drhd) { 2436 for_each_active_iommu(iommu, drhd) {
2415 ret = iommu_attach_domain(si_domain, iommu); 2437 ret = iommu_attach_domain(si_domain, iommu);
2416 if (ret) { 2438 if (ret < 0) {
2417 domain_exit(si_domain); 2439 domain_exit(si_domain);
2418 return -EFAULT; 2440 return -EFAULT;
2419 } 2441 }
2442 domain_attach_iommu(si_domain, iommu);
2420 } 2443 }
2421 2444
2422 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { 2445 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
@@ -4155,19 +4178,9 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
4155 spin_unlock_irqrestore(&device_domain_lock, flags); 4178 spin_unlock_irqrestore(&device_domain_lock, flags);
4156 4179
4157 if (found == 0) { 4180 if (found == 0) {
4158 unsigned long tmp_flags; 4181 domain_detach_iommu(domain, iommu);
4159 spin_lock_irqsave(&domain->iommu_lock, tmp_flags); 4182 if (!domain_type_is_vm_or_si(domain))
4160 clear_bit(iommu->seq_id, domain->iommu_bmp); 4183 iommu_detach_domain(domain, iommu);
4161 domain->iommu_count--;
4162 domain_update_iommu_cap(domain);
4163 spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
4164
4165 if (!domain_type_is_vm_or_si(domain)) {
4166 spin_lock_irqsave(&iommu->lock, tmp_flags);
4167 clear_bit(domain->id, iommu->domain_ids);
4168 iommu->domains[domain->id] = NULL;
4169 spin_unlock_irqrestore(&iommu->lock, tmp_flags);
4170 }
4171 } 4184 }
4172} 4185}
4173 4186