Commit 8359cf39 authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Joerg Roedel

iommu: Add __iommu_group_domain_alloc()

Allocate a domain from a group. Automatically obtains the iommu_ops to use
from the device list of the group. Convert the internal callers to use it.
Tested-by: default avatarSteven Price <steven.price@arm.com>
Tested-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Tested-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Reviewed-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: default avatarJerry Snitselaar <jsnitsel@redhat.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/21-v8-81230027b2fa+9d-iommu_all_defdom_jgg@nvidia.comSigned-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 98ac73f9
...@@ -96,8 +96,8 @@ static const char * const iommu_group_resv_type_string[] = { ...@@ -96,8 +96,8 @@ static const char * const iommu_group_resv_type_string[] = {
static int iommu_bus_notifier(struct notifier_block *nb, static int iommu_bus_notifier(struct notifier_block *nb,
unsigned long action, void *data); unsigned long action, void *data);
static void iommu_release_device(struct device *dev); static void iommu_release_device(struct device *dev);
static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus, static struct iommu_domain *
unsigned type); __iommu_group_domain_alloc(struct iommu_group *group, unsigned int type);
static int __iommu_attach_device(struct iommu_domain *domain, static int __iommu_attach_device(struct iommu_domain *domain,
struct device *dev); struct device *dev);
static int __iommu_attach_group(struct iommu_domain *domain, static int __iommu_attach_group(struct iommu_domain *domain,
...@@ -1719,12 +1719,11 @@ struct iommu_group *fsl_mc_device_group(struct device *dev) ...@@ -1719,12 +1719,11 @@ struct iommu_group *fsl_mc_device_group(struct device *dev)
EXPORT_SYMBOL_GPL(fsl_mc_device_group); EXPORT_SYMBOL_GPL(fsl_mc_device_group);
static struct iommu_domain * static struct iommu_domain *
__iommu_group_alloc_default_domain(const struct bus_type *bus, __iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
struct iommu_group *group, int req_type)
{ {
if (group->default_domain && group->default_domain->type == req_type) if (group->default_domain && group->default_domain->type == req_type)
return group->default_domain; return group->default_domain;
return __iommu_domain_alloc(bus, req_type); return __iommu_group_domain_alloc(group, req_type);
} }
/* /*
...@@ -1751,9 +1750,7 @@ static const struct iommu_ops *group_iommu_ops(struct iommu_group *group) ...@@ -1751,9 +1750,7 @@ static const struct iommu_ops *group_iommu_ops(struct iommu_group *group)
static struct iommu_domain * static struct iommu_domain *
iommu_group_alloc_default_domain(struct iommu_group *group, int req_type) iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
{ {
const struct bus_type *bus = const struct iommu_ops *ops = group_iommu_ops(group);
list_first_entry(&group->devices, struct group_device, list)
->dev->bus;
struct iommu_domain *dom; struct iommu_domain *dom;
lockdep_assert_held(&group->mutex); lockdep_assert_held(&group->mutex);
...@@ -1763,24 +1760,24 @@ iommu_group_alloc_default_domain(struct iommu_group *group, int req_type) ...@@ -1763,24 +1760,24 @@ iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
* domain. This should always be either an IDENTITY/BLOCKED/PLATFORM * domain. This should always be either an IDENTITY/BLOCKED/PLATFORM
* domain. Do not use in new drivers. * domain. Do not use in new drivers.
*/ */
if (bus->iommu_ops->default_domain) { if (ops->default_domain) {
if (req_type) if (req_type)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
return bus->iommu_ops->default_domain; return ops->default_domain;
} }
if (req_type) if (req_type)
return __iommu_group_alloc_default_domain(bus, group, req_type); return __iommu_group_alloc_default_domain(group, req_type);
/* The driver gave no guidance on what type to use, try the default */ /* The driver gave no guidance on what type to use, try the default */
dom = __iommu_group_alloc_default_domain(bus, group, iommu_def_domain_type); dom = __iommu_group_alloc_default_domain(group, iommu_def_domain_type);
if (dom) if (dom)
return dom; return dom;
/* Otherwise IDENTITY and DMA_FQ defaults will try DMA */ /* Otherwise IDENTITY and DMA_FQ defaults will try DMA */
if (iommu_def_domain_type == IOMMU_DOMAIN_DMA) if (iommu_def_domain_type == IOMMU_DOMAIN_DMA)
return NULL; return NULL;
dom = __iommu_group_alloc_default_domain(bus, group, IOMMU_DOMAIN_DMA); dom = __iommu_group_alloc_default_domain(group, IOMMU_DOMAIN_DMA);
if (!dom) if (!dom)
return NULL; return NULL;
...@@ -2043,19 +2040,16 @@ void iommu_set_fault_handler(struct iommu_domain *domain, ...@@ -2043,19 +2040,16 @@ void iommu_set_fault_handler(struct iommu_domain *domain,
} }
EXPORT_SYMBOL_GPL(iommu_set_fault_handler); EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus, static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,
unsigned type) unsigned int type)
{ {
struct iommu_domain *domain; struct iommu_domain *domain;
unsigned int alloc_type = type & IOMMU_DOMAIN_ALLOC_FLAGS; unsigned int alloc_type = type & IOMMU_DOMAIN_ALLOC_FLAGS;
if (bus == NULL || bus->iommu_ops == NULL) if (alloc_type == IOMMU_DOMAIN_IDENTITY && ops->identity_domain)
return NULL; return ops->identity_domain;
if (alloc_type == IOMMU_DOMAIN_IDENTITY && bus->iommu_ops->identity_domain) domain = ops->domain_alloc(alloc_type);
return bus->iommu_ops->identity_domain;
domain = bus->iommu_ops->domain_alloc(alloc_type);
if (!domain) if (!domain)
return NULL; return NULL;
...@@ -2065,10 +2059,10 @@ static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus, ...@@ -2065,10 +2059,10 @@ static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus,
* may override this later * may override this later
*/ */
if (!domain->pgsize_bitmap) if (!domain->pgsize_bitmap)
domain->pgsize_bitmap = bus->iommu_ops->pgsize_bitmap; domain->pgsize_bitmap = ops->pgsize_bitmap;
if (!domain->ops) if (!domain->ops)
domain->ops = bus->iommu_ops->default_domain_ops; domain->ops = ops->default_domain_ops;
if (iommu_is_dma_domain(domain) && iommu_get_dma_cookie(domain)) { if (iommu_is_dma_domain(domain) && iommu_get_dma_cookie(domain)) {
iommu_domain_free(domain); iommu_domain_free(domain);
...@@ -2077,9 +2071,17 @@ static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus, ...@@ -2077,9 +2071,17 @@ static struct iommu_domain *__iommu_domain_alloc(const struct bus_type *bus,
return domain; return domain;
} }
static struct iommu_domain *
__iommu_group_domain_alloc(struct iommu_group *group, unsigned int type)
{
return __iommu_domain_alloc(group_iommu_ops(group), type);
}
struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus) struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus)
{ {
return __iommu_domain_alloc(bus, IOMMU_DOMAIN_UNMANAGED); if (bus == NULL || bus->iommu_ops == NULL)
return NULL;
return __iommu_domain_alloc(bus->iommu_ops, IOMMU_DOMAIN_UNMANAGED);
} }
EXPORT_SYMBOL_GPL(iommu_domain_alloc); EXPORT_SYMBOL_GPL(iommu_domain_alloc);
...@@ -3239,21 +3241,18 @@ void iommu_device_unuse_default_domain(struct device *dev) ...@@ -3239,21 +3241,18 @@ void iommu_device_unuse_default_domain(struct device *dev)
static int __iommu_group_alloc_blocking_domain(struct iommu_group *group) static int __iommu_group_alloc_blocking_domain(struct iommu_group *group)
{ {
struct group_device *dev =
list_first_entry(&group->devices, struct group_device, list);
if (group->blocking_domain) if (group->blocking_domain)
return 0; return 0;
group->blocking_domain = group->blocking_domain =
__iommu_domain_alloc(dev->dev->bus, IOMMU_DOMAIN_BLOCKED); __iommu_group_domain_alloc(group, IOMMU_DOMAIN_BLOCKED);
if (!group->blocking_domain) { if (!group->blocking_domain) {
/* /*
* For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED * For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED
* create an empty domain instead. * create an empty domain instead.
*/ */
group->blocking_domain = __iommu_domain_alloc( group->blocking_domain = __iommu_group_domain_alloc(
dev->dev->bus, IOMMU_DOMAIN_UNMANAGED); group, IOMMU_DOMAIN_UNMANAGED);
if (!group->blocking_domain) if (!group->blocking_domain)
return -EINVAL; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment