iommu: Add domain_has_cap iommu_ops

This iommu_op can tell if domain have a specific capability, like snooping
control for Intel IOMMU, which can be used by other components of kernel to
adjust the behaviour.

Signed-off-by: Sheng Yang <sheng@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
Sheng Yang 2009-03-18 15:33:06 +08:00 committed by David Woodhouse
parent 58c610bd1a
commit dbb9fd8630
4 changed files with 38 additions and 0 deletions

View File

@ -1924,6 +1924,12 @@ static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
return paddr; return paddr;
} }
static int amd_iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap)
{
return 0;
}
static struct iommu_ops amd_iommu_ops = { static struct iommu_ops amd_iommu_ops = {
.domain_init = amd_iommu_domain_init, .domain_init = amd_iommu_domain_init,
.domain_destroy = amd_iommu_domain_destroy, .domain_destroy = amd_iommu_domain_destroy,
@ -1932,5 +1938,6 @@ static struct iommu_ops amd_iommu_ops = {
.map = amd_iommu_map_range, .map = amd_iommu_map_range,
.unmap = amd_iommu_unmap_range, .unmap = amd_iommu_unmap_range,
.iova_to_phys = amd_iommu_iova_to_phys, .iova_to_phys = amd_iommu_iova_to_phys,
.domain_has_cap = amd_iommu_domain_has_cap,
}; };

View File

@ -98,3 +98,10 @@ phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
return iommu_ops->iova_to_phys(domain, iova); return iommu_ops->iova_to_phys(domain, iova);
} }
EXPORT_SYMBOL_GPL(iommu_iova_to_phys); EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
int iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap)
{
return iommu_ops->domain_has_cap(domain, cap);
}
EXPORT_SYMBOL_GPL(iommu_domain_has_cap);

View File

@ -3158,6 +3158,17 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
return phys; return phys;
} }
static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap)
{
struct dmar_domain *dmar_domain = domain->priv;
if (cap == IOMMU_CAP_CACHE_COHERENCY)
return dmar_domain->iommu_snooping;
return 0;
}
static struct iommu_ops intel_iommu_ops = { static struct iommu_ops intel_iommu_ops = {
.domain_init = intel_iommu_domain_init, .domain_init = intel_iommu_domain_init,
.domain_destroy = intel_iommu_domain_destroy, .domain_destroy = intel_iommu_domain_destroy,
@ -3166,6 +3177,7 @@ static struct iommu_ops intel_iommu_ops = {
.map = intel_iommu_map_range, .map = intel_iommu_map_range,
.unmap = intel_iommu_unmap_range, .unmap = intel_iommu_unmap_range,
.iova_to_phys = intel_iommu_iova_to_phys, .iova_to_phys = intel_iommu_iova_to_phys,
.domain_has_cap = intel_iommu_domain_has_cap,
}; };
static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)

View File

@ -28,6 +28,8 @@ struct iommu_domain {
void *priv; void *priv;
}; };
#define IOMMU_CAP_CACHE_COHERENCY 0x1
struct iommu_ops { struct iommu_ops {
int (*domain_init)(struct iommu_domain *domain); int (*domain_init)(struct iommu_domain *domain);
void (*domain_destroy)(struct iommu_domain *domain); void (*domain_destroy)(struct iommu_domain *domain);
@ -39,6 +41,8 @@ struct iommu_ops {
size_t size); size_t size);
phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, phys_addr_t (*iova_to_phys)(struct iommu_domain *domain,
unsigned long iova); unsigned long iova);
int (*domain_has_cap)(struct iommu_domain *domain,
unsigned long cap);
}; };
#ifdef CONFIG_IOMMU_API #ifdef CONFIG_IOMMU_API
@ -57,6 +61,8 @@ extern void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
size_t size); size_t size);
extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long iova); unsigned long iova);
extern int iommu_domain_has_cap(struct iommu_domain *domain,
unsigned long cap);
#else /* CONFIG_IOMMU_API */ #else /* CONFIG_IOMMU_API */
@ -107,6 +113,12 @@ static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
return 0; return 0;
} }
static inline int domain_has_cap(struct iommu_domain *domain,
unsigned long cap)
{
return 0;
}
#endif /* CONFIG_IOMMU_API */ #endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */ #endif /* __LINUX_IOMMU_H */