diff options
Diffstat (limited to 'drivers/iommu/intel/debugfs.c')
| -rw-r--r-- | drivers/iommu/intel/debugfs.c | 51 | 
1 files changed, 34 insertions, 17 deletions
diff --git a/drivers/iommu/intel/debugfs.c b/drivers/iommu/intel/debugfs.c index ed796eea4581..1f925285104e 100644 --- a/drivers/iommu/intel/debugfs.c +++ b/drivers/iommu/intel/debugfs.c @@ -10,11 +10,11 @@  #include <linux/debugfs.h>  #include <linux/dmar.h> -#include <linux/intel-iommu.h>  #include <linux/pci.h>  #include <asm/irq_remapping.h> +#include "iommu.h"  #include "pasid.h"  #include "perf.h" @@ -263,10 +263,9 @@ static void ctx_tbl_walk(struct seq_file *m, struct intel_iommu *iommu, u16 bus)  static void root_tbl_walk(struct seq_file *m, struct intel_iommu *iommu)  { -	unsigned long flags;  	u16 bus; -	spin_lock_irqsave(&iommu->lock, flags); +	spin_lock(&iommu->lock);  	seq_printf(m, "IOMMU %s: Root Table Address: 0x%llx\n", iommu->name,  		   (u64)virt_to_phys(iommu->root_entry));  	seq_puts(m, "B.D.F\tRoot_entry\t\t\t\tContext_entry\t\t\t\tPASID\tPASID_table_entry\n"); @@ -278,8 +277,7 @@ static void root_tbl_walk(struct seq_file *m, struct intel_iommu *iommu)  	 */  	for (bus = 0; bus < 256; bus++)  		ctx_tbl_walk(m, iommu, bus); - -	spin_unlock_irqrestore(&iommu->lock, flags); +	spin_unlock(&iommu->lock);  }  static int dmar_translation_struct_show(struct seq_file *m, void *unused) @@ -342,13 +340,13 @@ static void pgtable_walk_level(struct seq_file *m, struct dma_pte *pde,  	}  } -static int show_device_domain_translation(struct device *dev, void *data) +static int __show_device_domain_translation(struct device *dev, void *data)  { -	struct device_domain_info *info = dev_iommu_priv_get(dev); -	struct dmar_domain *domain = info->domain; +	struct dmar_domain *domain;  	struct seq_file *m = data;  	u64 path[6] = { 0 }; +	domain = to_dmar_domain(iommu_get_domain_for_dev(dev));  	if (!domain)  		return 0; @@ -359,20 +357,39 @@ static int show_device_domain_translation(struct device *dev, void *data)  	pgtable_walk_level(m, domain->pgd, domain->agaw + 2, 0, path);  	seq_putc(m, '\n'); -	return 0; +	/* Don't iterate */ +	return 1;  } -static int domain_translation_struct_show(struct seq_file *m, void *unused) +static int show_device_domain_translation(struct device *dev, void *data)  { -	unsigned long flags; -	int ret; +	struct iommu_group *group; -	spin_lock_irqsave(&device_domain_lock, flags); -	ret = bus_for_each_dev(&pci_bus_type, NULL, m, -			       show_device_domain_translation); -	spin_unlock_irqrestore(&device_domain_lock, flags); +	group = iommu_group_get(dev); +	if (group) { +		/* +		 * The group->mutex is held across the callback, which will +		 * block calls to iommu_attach/detach_group/device. Hence, +		 * the domain of the device will not change during traversal. +		 * +		 * All devices in an iommu group share a single domain, hence +		 * we only dump the domain of the first device. Even though, +		 * this code still possibly races with the iommu_unmap() +		 * interface. This could be solved by RCU-freeing the page +		 * table pages in the iommu_unmap() path. +		 */ +		iommu_group_for_each_dev(group, data, +					 __show_device_domain_translation); +		iommu_group_put(group); +	} -	return ret; +	return 0; +} + +static int domain_translation_struct_show(struct seq_file *m, void *unused) +{ +	return bus_for_each_dev(&pci_bus_type, NULL, m, +				show_device_domain_translation);  }  DEFINE_SHOW_ATTRIBUTE(domain_translation_struct);  |