Messages in this thread | | | Subject | Re: [PATCH 10/26] iommu/vt-d: Replace iommu_bmp with a refcount | From | Alex Williamson <> | Date | Thu, 06 Aug 2015 13:19:57 -0600 |
| |
On Wed, 2015-08-05 at 17:18 +0200, Joerg Roedel wrote: > From: Joerg Roedel <jroedel@suse.de> > > This replaces the dmar_domain->iommu_bmp with a similar > reference count array. This allows us to keep track of how > many devices behind each iommu are attached to the domain. > > This is necessary for further simplifications and > optimizations to the iommu<->domain attachment code. > > Signed-off-by: Joerg Roedel <jroedel@suse.de> > --- > drivers/iommu/intel-iommu.c | 82 +++++++++++++++++++++++++-------------------- > 1 file changed, 45 insertions(+), 37 deletions(-) > > diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c > index 25b2ba7..c46afb6 100644 > --- a/drivers/iommu/intel-iommu.c > +++ b/drivers/iommu/intel-iommu.c > @@ -373,10 +373,16 @@ static int hw_pass_through = 1; > /* si_domain contains mulitple devices */ > #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1) > > +#define for_each_domain_iommu(idx, domain) \ > + for (idx = 0; idx < g_num_of_iommus; idx++) \ > + if (domain->iommu_refcnt[idx]) > + > struct dmar_domain { > int nid; /* node id */ > - DECLARE_BITMAP(iommu_bmp, DMAR_UNITS_SUPPORTED); > - /* bitmap of iommus this domain uses*/ > + > + int iommu_refcnt[DMAR_UNITS_SUPPORTED]; > + /* Refcount of devices per iommu */
unsigned?
> + > > u16 iommu_did[DMAR_UNITS_SUPPORTED]; > /* Domain ids per IOMMU */ > @@ -697,7 +703,9 @@ static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) > > /* si_domain and vm domain should not get here. */ > BUG_ON(domain_type_is_vm_or_si(domain)); > - iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus); > + for_each_domain_iommu(iommu_id, domain) > + break; > + > if (iommu_id < 0 || iommu_id >= g_num_of_iommus) > return NULL; > > @@ -713,7 +721,7 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) > > domain->iommu_coherency = 1; > > - for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { > + for_each_domain_iommu(i, domain) { > found = true; > if (!ecap_coherent(g_iommus[i]->ecap)) { > domain->iommu_coherency = 0; > @@ -1605,25 +1613,26 @@ static int iommu_init_domains(struct intel_iommu *iommu) > > static void disable_dmar_iommu(struct intel_iommu *iommu) > { > - struct dmar_domain *domain; > - int i; > + struct device_domain_info *info, *tmp; > > - if ((iommu->domains) && (iommu->domain_ids)) { > - for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) { > - /* > - * Domain id 0 is reserved for invalid translation > - * if hardware supports caching mode and used as > - * a non-allocated marker. > - */ > - if (i == 0) > - continue; > + if (!iommu->domains || !iommu->domain_ids) > + return; > > - domain = get_iommu_domain(iommu, i); > - clear_bit(i, iommu->domain_ids); > - if (domain_detach_iommu(domain, iommu) == 0 && > - !domain_type_is_vm(domain)) > - domain_exit(domain); > - } > + list_for_each_entry_safe(info, tmp, &device_domain_list, global) { > + struct dmar_domain *domain; > + > + if (info->iommu != iommu) > + continue; > + > + if (!info->dev || !info->domain) > + continue; > + > + domain = info->domain; > + > + domain_remove_one_dev_info(domain, info->dev); > + > + if (!domain_type_is_vm_or_si(domain)) > + domain_exit(domain); > } > > if (iommu->gcmd & DMA_GCMD_TE) > @@ -1731,10 +1740,10 @@ static void domain_attach_iommu(struct dmar_domain *domain, > 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->iommu_refcnt[iommu->seq_id] += 1; > + domain->iommu_count += 1; > + if (domain->iommu_refcnt[iommu->seq_id] == 1) { > + domain->nid = iommu->node; > domain_update_iommu_cap(domain); > } > spin_unlock_irqrestore(&domain->iommu_lock, flags); > @@ -1747,8 +1756,9 @@ static int domain_detach_iommu(struct dmar_domain *domain, > 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->iommu_refcnt[iommu->seq_id] -= 1; > + count = --domain->iommu_count; > + if (domain->iommu_refcnt[iommu->seq_id] == 0) { > domain_update_iommu_cap(domain); > domain->iommu_did[iommu->seq_id] = 0; > } > @@ -1873,9 +1883,8 @@ static int domain_init(struct dmar_domain *domain, int guest_width) > > static void domain_exit(struct dmar_domain *domain) > { > - struct dmar_drhd_unit *drhd; > - struct intel_iommu *iommu; > struct page *freelist = NULL; > + int i; > > /* Domain 0 is reserved, so dont process it */ > if (!domain) > @@ -1895,10 +1904,8 @@ static void domain_exit(struct dmar_domain *domain) > > /* clear attached or cached domains */ > rcu_read_lock(); > - 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); > + for_each_domain_iommu(i, domain) > + iommu_detach_domain(domain, g_iommus[i]);
Yay!
> rcu_read_unlock(); > > dma_free_pagelist(freelist); > @@ -4610,9 +4617,10 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain, > continue; > } > > - /* if there is no other devices under the same iommu > - * owned by this domain, clear this iommu in iommu_bmp > - * update iommu count and coherency > + /* > + * If there is no other devices under the same iommu owned by > + * this domain, clear this iommu in iommu_refcnt update iommu > + * count and coherency. > */ > if (info->iommu == iommu) > found = true; > @@ -4820,7 +4828,7 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain, > > npages = last_pfn - start_pfn + 1; > > - for_each_set_bit(iommu_id, dmar_domain->iommu_bmp, g_num_of_iommus) { > + for_each_domain_iommu(iommu_id, dmar_domain) { > iommu = g_iommus[iommu_id]; > > /*
| |