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:
Родитель
58c610bd1a
Коммит
dbb9fd8630
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче