diff options
Diffstat (limited to 'drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c')
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 1a636469eeda..aa3e4c3b063a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -3,9 +3,15 @@ * Copyright (C) 2015 Etnaviv Project */ +#include <drm/drm_file.h> #include <linux/dma-fence-array.h> -#include <linux/reservation.h> +#include <linux/file.h> +#include <linux/pm_runtime.h> +#include <linux/dma-resv.h> #include <linux/sync_file.h> +#include <linux/uaccess.h> +#include <linux/vmalloc.h> + #include "etnaviv_cmdbuf.h" #include "etnaviv_drv.h" #include "etnaviv_gpu.h" @@ -66,6 +72,14 @@ static int submit_lookup_objects(struct etnaviv_gem_submit *submit, } submit->bos[i].flags = bo->flags; + if (submit->flags & ETNA_SUBMIT_SOFTPIN) { + if (bo->presumed < ETNAVIV_SOFTPIN_START_ADDRESS) { + DRM_ERROR("invalid softpin address\n"); + ret = -EINVAL; + goto out_unlock; + } + submit->bos[i].va = bo->presumed; + } /* normally use drm_gem_object_lookup(), but for bulk lookup * all under single table_lock just hit object_idr directly: @@ -165,10 +179,10 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit) for (i = 0; i < submit->nr_bos; i++) { struct etnaviv_gem_submit_bo *bo = &submit->bos[i]; - struct reservation_object *robj = bo->obj->base.resv; + struct dma_resv *robj = bo->obj->base.resv; if (!(bo->flags & ETNA_SUBMIT_BO_WRITE)) { - ret = reservation_object_reserve_shared(robj, 1); + ret = dma_resv_reserve_shared(robj, 1); if (ret) return ret; } @@ -177,13 +191,13 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit) continue; if (bo->flags & ETNA_SUBMIT_BO_WRITE) { - ret = reservation_object_get_fences_rcu(robj, &bo->excl, + ret = dma_resv_get_fences_rcu(robj, &bo->excl, &bo->nr_shared, &bo->shared); if (ret) return ret; } else { - bo->excl = reservation_object_get_excl_rcu(robj); + bo->excl = dma_resv_get_excl_rcu(robj); } } @@ -199,10 +213,10 @@ static void submit_attach_object_fences(struct etnaviv_gem_submit *submit) struct drm_gem_object *obj = &submit->bos[i].obj->base; if (submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE) - reservation_object_add_excl_fence(obj->resv, + dma_resv_add_excl_fence(obj->resv, submit->out_fence); else - reservation_object_add_shared_fence(obj->resv, + dma_resv_add_shared_fence(obj->resv, submit->out_fence); submit_unlock_object(submit, i); @@ -218,11 +232,17 @@ static int submit_pin_objects(struct etnaviv_gem_submit *submit) struct etnaviv_vram_mapping *mapping; mapping = etnaviv_gem_mapping_get(&etnaviv_obj->base, - submit->gpu); + submit->mmu_context, + submit->bos[i].va); if (IS_ERR(mapping)) { ret = PTR_ERR(mapping); break; } + + if ((submit->flags & ETNA_SUBMIT_SOFTPIN) && + submit->bos[i].va != mapping->iova) + return -EINVAL; + atomic_inc(&etnaviv_obj->gpu_active); submit->bos[i].flags |= BO_PINNED; @@ -255,6 +275,10 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, void *stream, u32 *ptr = stream; int ret; + /* Submits using softpin don't blend with relocs */ + if ((submit->flags & ETNA_SUBMIT_SOFTPIN) && nr_relocs != 0) + return -EINVAL; + for (i = 0; i < nr_relocs; i++) { const struct drm_etnaviv_gem_submit_reloc *r = relocs + i; struct etnaviv_gem_submit_bo *bo; @@ -355,6 +379,12 @@ static void submit_cleanup(struct kref *kref) if (submit->cmdbuf.suballoc) etnaviv_cmdbuf_free(&submit->cmdbuf); + if (submit->mmu_context) + etnaviv_iommu_context_put(submit->mmu_context); + + if (submit->prev_mmu_context) + etnaviv_iommu_context_put(submit->prev_mmu_context); + for (i = 0; i < submit->nr_bos; i++) { struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; @@ -433,6 +463,12 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, return -EINVAL; } + if ((args->flags & ETNA_SUBMIT_SOFTPIN) && + priv->mmu_global->version != ETNAVIV_IOMMU_V2) { + DRM_ERROR("softpin requested on incompatible MMU\n"); + return -EINVAL; + } + /* * Copy the command submission and bo array to kernel space in * one go, and do this outside of any locks. @@ -490,12 +526,14 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, goto err_submit_ww_acquire; } - ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &submit->cmdbuf, + ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf, ALIGN(args->stream_size, 8) + 8); if (ret) goto err_submit_objects; submit->ctx = file->driver_priv; + etnaviv_iommu_context_get(submit->ctx->mmu); + submit->mmu_context = submit->ctx->mmu; submit->exec_state = args->exec_state; submit->flags = args->flags; @@ -503,7 +541,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, if (ret) goto err_submit_objects; - if (!etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4, + if ((priv->mmu_global->version != ETNAVIV_IOMMU_V2) && + !etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4, relocs, args->nr_relocs)) { ret = -EINVAL; goto err_submit_objects; |