Re: [PATCH 10/26] iommu/vt-d: Replace iommu_bmp with a refcount

From: Alex Williamson
Date: Thu Aug 06 2015 - 15:20:34 EST


On Wed, 2015-08-05 at 17:18 +0200, Joerg Roedel wrote:
> From: Joerg Roedel <jroedel@xxxxxxx>
>
> 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@xxxxxxx>
> ---
> 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];
>
> /*



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/