diff options
Diffstat (limited to 'gxp-domain-pool.c')
-rw-r--r-- | gxp-domain-pool.c | 109 |
1 files changed, 42 insertions, 67 deletions
diff --git a/gxp-domain-pool.c b/gxp-domain-pool.c index 53a5b38..a0f9ead 100644 --- a/gxp-domain-pool.c +++ b/gxp-domain-pool.c @@ -5,100 +5,75 @@ * Copyright (C) 2022 Google LLC */ -#include <linux/idr.h> #include <linux/iommu.h> #include <linux/slab.h> +#include <gcip/gcip-domain-pool.h> + +#include "gxp-dma.h" #include "gxp-domain-pool.h" -#include "gxp-internal.h" -int gxp_domain_pool_init(struct gxp_dev *gxp, struct gxp_domain_pool *pool, +int gxp_domain_pool_init(struct gxp_dev *gxp, struct gcip_domain_pool *pool, unsigned int size) { - unsigned int i; - struct iommu_domain *domain; - - pool->size = size; - pool->gxp = gxp; - - if (!size) - return 0; + int ret = gcip_domain_pool_init(gxp->dev, pool, size); + __maybe_unused int i; - dev_dbg(pool->gxp->dev, "Initializing domain pool with %u domains\n", size); + if (ret) + return ret; - ida_init(&pool->idp); - pool->array = vzalloc(sizeof(*pool->array) * size); - if (!pool->array) { - dev_err(gxp->dev, "Failed to allocate memory for domain pool array\n"); - return -ENOMEM; - } +#if IS_ENABLED(CONFIG_GXP_GEM5) for (i = 0; i < size; i++) { - domain = iommu_domain_alloc(pool->gxp->dev->bus); - if (!domain) { - dev_err(pool->gxp->dev, - "Failed to allocate iommu domain %d of %u\n", - i + 1, size); + struct iommu_domain *domain = pool->array[i]; + + /* + * Gem5 uses arm-smmu-v3 which requires domain finalization to do iommu map. Calling + * iommu_aux_attach_device to finalize the allocated domain and detach the device + * right after that. + */ + ret = iommu_aux_attach_device(domain, gxp->dev); + if (ret) { + dev_err(gxp->dev, + "Failed to attach device to iommu domain %d of %u, ret=%d\n", + i + 1, size, ret); gxp_domain_pool_destroy(pool); - return -ENOMEM; + return ret; } - pool->array[i] = domain; + + iommu_aux_detach_device(domain, gxp->dev); } +#endif /* CONFIG_GXP_GEM5 */ + return 0; } -struct iommu_domain *gxp_domain_pool_alloc(struct gxp_domain_pool *pool) +struct gxp_iommu_domain *gxp_domain_pool_alloc(struct gcip_domain_pool *pool) { - int id; - - if (!pool->size) - return iommu_domain_alloc(pool->gxp->dev->bus); + struct iommu_domain *domain = gcip_domain_pool_alloc(pool); + struct gxp_iommu_domain *gdomain; - id = ida_alloc_max(&pool->idp, pool->size - 1, GFP_KERNEL); + if (!domain) + return NULL; - if (id < 0) { - dev_err(pool->gxp->dev, - "No more domains available from pool of size %u\n", - pool->size); + gdomain = kmalloc(sizeof(*gdomain), GFP_KERNEL); + if (!gdomain) { + gcip_domain_pool_free(pool, domain); return NULL; } - dev_dbg(pool->gxp->dev, "Allocated domain from pool with id = %d\n", id); + gdomain->domain = domain; - return pool->array[id]; + return gdomain; } -void gxp_domain_pool_free(struct gxp_domain_pool *pool, struct iommu_domain *domain) +void gxp_domain_pool_free(struct gcip_domain_pool *pool, + struct gxp_iommu_domain *gdomain) { - int id; - - if (!pool->size) { - iommu_domain_free(domain); - return; - } - for (id = 0; id < pool->size; id++) { - if (pool->array[id] == domain) { - dev_dbg(pool->gxp->dev, "Released domain from pool with id = %d\n", id); - ida_free(&pool->idp, id); - return; - } - } - dev_err(pool->gxp->dev, "%s: domain not found in pool", __func__); + gcip_domain_pool_free(pool, gdomain->domain); + kfree(gdomain); } -void gxp_domain_pool_destroy(struct gxp_domain_pool *pool) +void gxp_domain_pool_destroy(struct gcip_domain_pool *pool) { - int i; - - if (!pool->size) - return; - - dev_dbg(pool->gxp->dev, "Destroying domain pool with %u domains\n", pool->size); - - for (i = 0; i < pool->size; i++) { - if (pool->array[i]) - iommu_domain_free(pool->array[i]); - } - - ida_destroy(&pool->idp); - vfree(pool->array); + gcip_domain_pool_destroy(pool); } |