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>
This commit is contained in:
parent
ab8dfe2515
commit
fb170fb4c5
@ -1523,32 +1523,39 @@ static struct dmar_domain *alloc_domain(int flags)
|
|||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iommu_attach_domain(struct dmar_domain *domain,
|
static int __iommu_attach_domain(struct dmar_domain *domain,
|
||||||
struct intel_iommu *iommu)
|
struct intel_iommu *iommu)
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
unsigned long ndomains;
|
unsigned long ndomains;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
ndomains = cap_ndoms(iommu->cap);
|
ndomains = cap_ndoms(iommu->cap);
|
||||||
|
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
|
||||||
|
|
||||||
num = find_first_zero_bit(iommu->domain_ids, ndomains);
|
num = find_first_zero_bit(iommu->domain_ids, ndomains);
|
||||||
if (num >= ndomains) {
|
if (num < ndomains) {
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
set_bit(num, iommu->domain_ids);
|
||||||
printk(KERN_ERR "IOMMU: no free domain ids\n");
|
iommu->domains[num] = domain;
|
||||||
return -ENOMEM;
|
} else {
|
||||||
|
num = -ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iommu_attach_domain(struct dmar_domain *domain,
|
||||||
|
struct intel_iommu *iommu)
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&iommu->lock, flags);
|
||||||
|
num = __iommu_attach_domain(domain, iommu);
|
||||||
|
if (num < 0)
|
||||||
|
pr_err("IOMMU: no free domain ids\n");
|
||||||
|
else
|
||||||
domain->id = num;
|
domain->id = num;
|
||||||
domain->iommu_count++;
|
|
||||||
set_bit(num, iommu->domain_ids);
|
|
||||||
set_bit(iommu->seq_id, domain->iommu_bmp);
|
|
||||||
iommu->domains[num] = domain;
|
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
|
|
||||||
return 0;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iommu_detach_domain(struct dmar_domain *domain,
|
static void iommu_detach_domain(struct dmar_domain *domain,
|
||||||
@ -1558,6 +1565,7 @@ static void iommu_detach_domain(struct dmar_domain *domain,
|
|||||||
int num, ndomains;
|
int num, ndomains;
|
||||||
|
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
spin_lock_irqsave(&iommu->lock, flags);
|
||||||
|
if (domain_type_is_vm_or_si(domain)) {
|
||||||
ndomains = cap_ndoms(iommu->cap);
|
ndomains = cap_ndoms(iommu->cap);
|
||||||
for_each_set_bit(num, iommu->domain_ids, ndomains) {
|
for_each_set_bit(num, iommu->domain_ids, ndomains) {
|
||||||
if (iommu->domains[num] == domain) {
|
if (iommu->domains[num] == domain) {
|
||||||
@ -1566,9 +1574,44 @@ static void iommu_detach_domain(struct dmar_domain *domain,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
clear_bit(domain->id, iommu->domain_ids);
|
||||||
|
iommu->domains[domain->id] = NULL;
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void domain_attach_iommu(struct dmar_domain *domain,
|
||||||
|
struct intel_iommu *iommu)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&domain->iommu_lock, flags);
|
||||||
|
if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
|
||||||
|
domain->iommu_count++;
|
||||||
|
if (domain->iommu_count == 1)
|
||||||
|
domain->nid = iommu->node;
|
||||||
|
domain_update_iommu_cap(domain);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&domain->iommu_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int domain_detach_iommu(struct dmar_domain *domain,
|
||||||
|
struct intel_iommu *iommu)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int count = INT_MAX;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&domain->iommu_lock, flags);
|
||||||
|
if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
|
||||||
|
count = --domain->iommu_count;
|
||||||
|
domain_update_iommu_cap(domain);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&domain->iommu_lock, flags);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static struct iova_domain reserved_iova_list;
|
static struct iova_domain reserved_iova_list;
|
||||||
static struct lock_class_key reserved_rbtree_key;
|
static struct lock_class_key reserved_rbtree_key;
|
||||||
|
|
||||||
@ -1706,8 +1749,6 @@ static void domain_exit(struct dmar_domain *domain)
|
|||||||
/* clear attached or cached domains */
|
/* clear attached or cached domains */
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for_each_active_iommu(iommu, drhd)
|
for_each_active_iommu(iommu, drhd)
|
||||||
if (domain_type_is_vm(domain) ||
|
|
||||||
test_bit(iommu->seq_id, domain->iommu_bmp))
|
|
||||||
iommu_detach_domain(domain, iommu);
|
iommu_detach_domain(domain, iommu);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
@ -1762,16 +1803,12 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found == 0) {
|
if (found == 0) {
|
||||||
num = find_first_zero_bit(iommu->domain_ids, ndomains);
|
id = __iommu_attach_domain(domain, iommu);
|
||||||
if (num >= ndomains) {
|
if (id < 0) {
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
printk(KERN_ERR "IOMMU: no free domain ids\n");
|
pr_err("IOMMU: no free domain ids\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_bit(num, iommu->domain_ids);
|
|
||||||
iommu->domains[num] = domain;
|
|
||||||
id = num;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip top levels of page tables for
|
/* Skip top levels of page tables for
|
||||||
@ -1830,14 +1867,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
|
|||||||
iommu_enable_dev_iotlb(info);
|
iommu_enable_dev_iotlb(info);
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
|
|
||||||
spin_lock_irqsave(&domain->iommu_lock, flags);
|
domain_attach_iommu(domain, iommu);
|
||||||
if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
|
|
||||||
domain->iommu_count++;
|
|
||||||
if (domain->iommu_count == 1)
|
|
||||||
domain->nid = iommu->node;
|
|
||||||
domain_update_iommu_cap(domain);
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&domain->iommu_lock, flags);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2085,7 +2116,7 @@ static inline void unlink_domain_info(struct device_domain_info *info)
|
|||||||
static void domain_remove_dev_info(struct dmar_domain *domain)
|
static void domain_remove_dev_info(struct dmar_domain *domain)
|
||||||
{
|
{
|
||||||
struct device_domain_info *info, *tmp;
|
struct device_domain_info *info, *tmp;
|
||||||
unsigned long flags, flags2;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&device_domain_lock, flags);
|
spin_lock_irqsave(&device_domain_lock, flags);
|
||||||
list_for_each_entry_safe(info, tmp, &domain->devices, link) {
|
list_for_each_entry_safe(info, tmp, &domain->devices, link) {
|
||||||
@ -2097,16 +2128,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
|
|||||||
|
|
||||||
if (domain_type_is_vm(domain)) {
|
if (domain_type_is_vm(domain)) {
|
||||||
iommu_detach_dependent_devices(info->iommu, info->dev);
|
iommu_detach_dependent_devices(info->iommu, info->dev);
|
||||||
/* clear this iommu in iommu_bmp, update iommu count
|
domain_detach_iommu(domain, info->iommu);
|
||||||
* and capabilities
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&domain->iommu_lock, flags2);
|
|
||||||
if (test_and_clear_bit(info->iommu->seq_id,
|
|
||||||
domain->iommu_bmp)) {
|
|
||||||
domain->iommu_count--;
|
|
||||||
domain_update_iommu_cap(domain);
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&domain->iommu_lock, flags2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free_devinfo_mem(info);
|
free_devinfo_mem(info);
|
||||||
@ -2236,11 +2258,11 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
|
|||||||
if (!domain)
|
if (!domain)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (iommu_attach_domain(domain, iommu)) {
|
if (iommu_attach_domain(domain, iommu) < 0) {
|
||||||
free_domain_mem(domain);
|
free_domain_mem(domain);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
domain_attach_iommu(domain, iommu);
|
||||||
if (domain_init(domain, gaw)) {
|
if (domain_init(domain, gaw)) {
|
||||||
domain_exit(domain);
|
domain_exit(domain);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2413,10 +2435,11 @@ static int __init si_domain_init(int hw)
|
|||||||
|
|
||||||
for_each_active_iommu(iommu, drhd) {
|
for_each_active_iommu(iommu, drhd) {
|
||||||
ret = iommu_attach_domain(si_domain, iommu);
|
ret = iommu_attach_domain(si_domain, iommu);
|
||||||
if (ret) {
|
if (ret < 0) {
|
||||||
domain_exit(si_domain);
|
domain_exit(si_domain);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
domain_attach_iommu(si_domain, iommu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
|
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,
|
|||||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
spin_unlock_irqrestore(&device_domain_lock, flags);
|
||||||
|
|
||||||
if (found == 0) {
|
if (found == 0) {
|
||||||
unsigned long tmp_flags;
|
domain_detach_iommu(domain, iommu);
|
||||||
spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
|
if (!domain_type_is_vm_or_si(domain))
|
||||||
clear_bit(iommu->seq_id, domain->iommu_bmp);
|
iommu_detach_domain(domain, iommu);
|
||||||
domain->iommu_count--;
|
|
||||||
domain_update_iommu_cap(domain);
|
|
||||||
spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
|
|
||||||
|
|
||||||
if (!domain_type_is_vm_or_si(domain)) {
|
|
||||||
spin_lock_irqsave(&iommu->lock, tmp_flags);
|
|
||||||
clear_bit(domain->id, iommu->domain_ids);
|
|
||||||
iommu->domains[domain->id] = NULL;
|
|
||||||
spin_unlock_irqrestore(&iommu->lock, tmp_flags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user