diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2014-07-11 02:19:28 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2014-07-23 10:04:46 -0400 |
commit | fb170fb4c548c6d9fe9f71db946e216abb5c6641 (patch) | |
tree | ce30c43160df179131588774d14a5ea9724b758d /drivers/iommu/intel-iommu.c | |
parent | ab8dfe251571e4a04d367e47e5be93976a77c610 (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.c | 147 |
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 | ||
1526 | static int iommu_attach_domain(struct dmar_domain *domain, | 1526 | static 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); | 1544 | static 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 | ||
1554 | static void iommu_detach_domain(struct dmar_domain *domain, | 1561 | static 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 | ||
1584 | static 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 | |||
1599 | static 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 | |||
1572 | static struct iova_domain reserved_iova_list; | 1615 | static struct iova_domain reserved_iova_list; |
1573 | static struct lock_class_key reserved_rbtree_key; | 1616 | static 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) | |||
2085 | static void domain_remove_dev_info(struct dmar_domain *domain) | 2116 | static 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 | ||