From 53530e16447303d6e4ff4372be5bfe9922261596 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 12 Jun 2017 09:16:48 -0600 Subject: [PATCH 1/4] drm/msm: Simplify ringbuffer cleanup Cleanup and consolidate sanity checking on the ringbuffer cleanup code. Change-Id: Ic0dedbad551d36ca8ed3db56a4366a5008768791 Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/msm_gpu.c | 15 +++------------ drivers/gpu/drm/msm/msm_ringbuffer.c | 5 ++++- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 6bbd4c338433..4e43b96341f8 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -935,10 +935,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, return 0; fail: - for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { - if (gpu->rb[i]) - msm_ringbuffer_destroy(gpu->rb[i]); - } + for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) + msm_ringbuffer_destroy(gpu->rb[i]); pm_runtime_disable(&pdev->dev); return ret; @@ -957,15 +955,8 @@ void msm_gpu_cleanup(struct msm_gpu *gpu) bs_fini(gpu); - for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { - if (!gpu->rb[i]) - continue; - - if (gpu->rb[i]->iova) - msm_gem_put_iova(gpu->rb[i]->bo, gpu->aspace); - + for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) msm_ringbuffer_destroy(gpu->rb[i]); - } msm_snapshot_destroy(gpu, gpu->snapshot); pm_runtime_disable(&pdev->dev); diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index 458f80426b39..9b8e76da449f 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -60,7 +60,10 @@ fail: void msm_ringbuffer_destroy(struct msm_ringbuffer *ring) { - if (ring->bo) + if (ring && ring->bo) { + msm_gem_put_iova(ring->bo, ring->gpu->aspace); drm_gem_object_unreference_unlocked(ring->bo); + } + kfree(ring); } From 1db3fbd43a0bbc38494d11c65828e4d8b8eaa315 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 12 Jun 2017 09:16:48 -0600 Subject: [PATCH 2/4] drm/msm: Add a helper function for in-kernel buffer allocations Nearly all of the buffer allocations for kernel allocate an buffer object, virtual address and GPU iova at the same time. Make a helper function to handle the details. Change-Id: Ic0dedbad0ecd85d360895cc0d1e418277ba44c62 Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 24 ++--------- drivers/gpu/drm/msm/adreno/a5xx_power.c | 16 ++------ drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 43 ++----------------- drivers/gpu/drm/msm/adreno/a5xx_snapshot.c | 28 ++++--------- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 29 ++++--------- drivers/gpu/drm/msm/msm_drv.h | 7 +++- drivers/gpu/drm/msm/msm_gem.c | 48 ++++++++++++++++++++++ 7 files changed, 81 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 8a136fef86f1..3fc3065147b2 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -477,30 +477,14 @@ static int a5xx_preempt_start(struct msm_gpu *gpu) static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu, const struct firmware *fw, u64 *iova) { - struct drm_device *drm = gpu->dev; struct drm_gem_object *bo; void *ptr; - bo = msm_gem_new(drm, fw->size - 4, - MSM_BO_UNCACHED | MSM_BO_GPU_READONLY); + ptr = msm_gem_kernel_new(gpu->dev, fw->size - 4, + MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, &bo, iova); - if (IS_ERR(bo)) - return bo; - - ptr = msm_gem_vaddr(bo); - if (!ptr) { - drm_gem_object_unreference_unlocked(bo); - return ERR_PTR(-ENOMEM); - } - - if (iova) { - int ret = msm_gem_get_iova(bo, gpu->aspace, iova); - - if (ret) { - drm_gem_object_unreference_unlocked(bo); - return ERR_PTR(ret); - } - } + if (IS_ERR(ptr)) + return ERR_CAST(ptr); memcpy(ptr, &fw->data[4], fw->size - 4); return bo; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c index 0025922540df..647b61313fc2 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c @@ -458,18 +458,10 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu) */ bosize = (cmds_size + (cmds_size / TYPE4_MAX_PAYLOAD) + 1) << 2; - a5xx_gpu->gpmu_bo = msm_gem_new(drm, bosize, - MSM_BO_UNCACHED | MSM_BO_GPU_READONLY); - - if (IS_ERR(a5xx_gpu->gpmu_bo)) - goto err; - - if (msm_gem_get_iova(a5xx_gpu->gpmu_bo, gpu->aspace, - &a5xx_gpu->gpmu_iova)) - goto err; - - ptr = msm_gem_vaddr(a5xx_gpu->gpmu_bo); - if (!ptr) + ptr = msm_gem_kernel_new(drm, bosize, + MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, + &a5xx_gpu->gpmu_bo, &a5xx_gpu->gpmu_iova); + if (IS_ERR(ptr)) goto err; while (cmds_size > 0) { diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index 57046089434c..dacdb4752393 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -15,41 +15,6 @@ #include "msm_iommu.h" #include "a5xx_gpu.h" -static void *alloc_kernel_bo(struct drm_device *drm, struct msm_gpu *gpu, - size_t size, uint32_t flags, struct drm_gem_object **bo, - u64 *iova) -{ - struct drm_gem_object *_bo; - u64 _iova; - void *ptr; - int ret; - - _bo = msm_gem_new(drm, size, flags); - - if (IS_ERR(_bo)) - return _bo; - - ret = msm_gem_get_iova(_bo, gpu->aspace, &_iova); - if (ret) - goto out; - - ptr = msm_gem_vaddr(_bo); - if (!ptr) { - ret = -ENOMEM; - goto out; - } - - if (bo) - *bo = _bo; - if (iova) - *iova = _iova; - - return ptr; -out: - drm_gem_object_unreference_unlocked(_bo); - return ERR_PTR(ret); -} - /* * Try to transition the preemption state from old to new. Return * true on success or false if the original state wasn't 'old' @@ -278,10 +243,10 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, struct drm_gem_object *bo; u64 iova; - ptr = alloc_kernel_bo(gpu->dev, gpu, + ptr = msm_gem_kernel_new(gpu->dev, A5XX_PREEMPT_RECORD_SIZE + A5XX_PREEMPT_COUNTER_SIZE, MSM_BO_UNCACHED | MSM_BO_PRIVILEGED, - &bo, &iova); + gpu->aspace, &bo, &iova); if (IS_ERR(ptr)) return PTR_ERR(ptr); @@ -352,10 +317,10 @@ void a5xx_preempt_init(struct msm_gpu *gpu) } if (msm_iommu_allow_dynamic(gpu->aspace->mmu)) { - ptr = alloc_kernel_bo(gpu->dev, gpu, + ptr = msm_gem_kernel_new(gpu->dev, sizeof(struct a5xx_smmu_info), MSM_BO_UNCACHED | MSM_BO_PRIVILEGED, - &bo, &iova); + gpu->aspace, &bo, &iova); if (IS_ERR(ptr)) goto fail; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_snapshot.c b/drivers/gpu/drm/msm/adreno/a5xx_snapshot.c index c2773cb325d5..d1c1ab460c95 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_snapshot.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_snapshot.c @@ -214,28 +214,14 @@ struct crashdump { static int crashdump_init(struct msm_gpu *gpu, struct crashdump *crashdump) { - struct drm_device *drm = gpu->dev; - int ret = -ENOMEM; + int ret = 0; - crashdump->bo = msm_gem_new_locked(drm, CRASHDUMP_BO_SIZE, - MSM_BO_UNCACHED); - if (IS_ERR(crashdump->bo)) { - ret = PTR_ERR(crashdump->bo); - crashdump->bo = NULL; - return ret; - } - - crashdump->ptr = msm_gem_vaddr(crashdump->bo); - if (!crashdump->ptr) - goto out; - - ret = msm_gem_get_iova(crashdump->bo, gpu->aspace, - &crashdump->iova); - -out: - if (ret) { - drm_gem_object_unreference(crashdump->bo); - crashdump->bo = NULL; + crashdump->ptr = msm_gem_kernel_new_locked(gpu->dev, + CRASHDUMP_BO_SIZE, MSM_BO_UNCACHED, + gpu->aspace, &crashdump->bo, &crashdump->iova); + if (IS_ERR(crashdump->ptr)) { + ret = PTR_ERR(crashdump->ptr); + crashdump->ptr = NULL; } return ret; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 81fa37ee9671..0c8f24e25ac7 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -563,29 +563,16 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, } } - adreno_gpu->memptrs_bo = msm_gem_new(drm, sizeof(*adreno_gpu->memptrs), - MSM_BO_UNCACHED); - if (IS_ERR(adreno_gpu->memptrs_bo)) { - ret = PTR_ERR(adreno_gpu->memptrs_bo); - adreno_gpu->memptrs_bo = NULL; - dev_err(drm->dev, "could not allocate memptrs: %d\n", ret); - return ret; + adreno_gpu->memptrs = msm_gem_kernel_new(drm, + sizeof(*adreno_gpu->memptrs), MSM_BO_UNCACHED, gpu->aspace, + &adreno_gpu->memptrs_bo, &adreno_gpu->memptrs_iova); + + if (IS_ERR(adreno_gpu->memptrs)) { + ret = PTR_ERR(adreno_gpu->memptrs); + adreno_gpu->memptrs = NULL; } - adreno_gpu->memptrs = msm_gem_vaddr(adreno_gpu->memptrs_bo); - if (!adreno_gpu->memptrs) { - dev_err(drm->dev, "could not vmap memptrs\n"); - return -ENOMEM; - } - - ret = msm_gem_get_iova(adreno_gpu->memptrs_bo, gpu->aspace, - &adreno_gpu->memptrs_iova); - if (ret) { - dev_err(drm->dev, "could not map memptrs: %d\n", ret); - return ret; - } - - return 0; + return ret; } void adreno_gpu_cleanup(struct adreno_gpu *gpu) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index adc1e021b6f7..c2ccc5d462a7 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -494,7 +494,12 @@ int msm_gem_svm_new_handle(struct drm_device *dev, struct drm_file *file, struct drm_gem_object *msm_gem_svm_new(struct drm_device *dev, struct drm_file *file, uint64_t hostptr, uint64_t size, uint32_t flags); - +void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova); +void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova); int msm_framebuffer_prepare(struct drm_framebuffer *fb, struct msm_gem_address_space *aspace); void msm_framebuffer_cleanup(struct drm_framebuffer *fb, diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index b7dd84cb23b9..70af0d41f970 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -1285,3 +1285,51 @@ void msm_mn_invalidate_range_start(struct mmu_notifier *mn, msm_gem_mn_put(msm_mn); } + +/* + * Helper function to consolidate in-kernel buffer allocations that usually need + * to allocate a buffer object, iova and a virtual address all in one shot + */ +static void *_msm_gem_kernel_new(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova, bool locked) +{ + void *vaddr; + struct drm_gem_object *obj = _msm_gem_new(dev, size, flags, locked); + int ret; + + if (IS_ERR(obj)) + return ERR_CAST(obj); + + ret = msm_gem_get_iova(obj, aspace, iova); + if (ret) { + drm_gem_object_unreference(obj); + return ERR_PTR(ret); + } + + vaddr = msm_gem_vaddr(obj); + if (!vaddr) { + msm_gem_put_iova(obj, aspace); + drm_gem_object_unreference(obj); + return ERR_PTR(-ENOMEM); + } + + *bo = obj; + return vaddr; +} + +void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova) +{ + return _msm_gem_kernel_new(dev, size, flags, aspace, bo, iova, + false); +} + +void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova) +{ + return _msm_gem_kernel_new(dev, size, flags, aspace, bo, iova, + true); +} From ae2cb03114bd664101ff72709a534ed4ddafd012 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 12 Jun 2017 09:16:49 -0600 Subject: [PATCH 3/4] drm/msm: Attach the MMUs as soon as they are allocated Currently the normal and secure MMUs are allocated when the address space is created in msm_gpu_init() but not attached until the end of adreno_gpu_init(). Since we can't map buffer objects in the IOMMU without attaching it first this restricts when we can allocate buffer objects in the sequence. For arm-smmu based targets there isn't any reason why we can't immediately attach the MMU after creating the address space - this makes the whole system immediately available to map memory and will facilitate moving around global allocations. Change-Id: Ic0dedbad161396e9d095f3f3d1e4fca2d240a084 Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 33 +------------------------ drivers/gpu/drm/msm/msm_gpu.c | 28 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 0c8f24e25ac7..0de73f61bfcb 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -516,7 +516,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, { struct adreno_platform_config *config = pdev->dev.platform_data; struct msm_gpu *gpu = &adreno_gpu->base; - struct msm_mmu *mmu; int ret; adreno_gpu->funcs = funcs; @@ -547,22 +546,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, return ret; } - mmu = gpu->aspace->mmu; - if (mmu) { - ret = mmu->funcs->attach(mmu, NULL, 0); - if (ret) - return ret; - } - - if (gpu->secure_aspace) { - mmu = gpu->secure_aspace->mmu; - if (mmu) { - ret = mmu->funcs->attach(mmu, NULL, 0); - if (ret) - return ret; - } - } - adreno_gpu->memptrs = msm_gem_kernel_new(drm, sizeof(*adreno_gpu->memptrs), MSM_BO_UNCACHED, gpu->aspace, &adreno_gpu->memptrs_bo, &adreno_gpu->memptrs_iova); @@ -577,28 +560,14 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, void adreno_gpu_cleanup(struct adreno_gpu *gpu) { - struct msm_gem_address_space *aspace = gpu->base.aspace; - if (gpu->memptrs_bo) { - if (gpu->memptrs_iova) - msm_gem_put_iova(gpu->memptrs_bo, aspace); + msm_gem_put_iova(gpu->memptrs_bo, gpu->base.aspace); drm_gem_object_unreference_unlocked(gpu->memptrs_bo); } release_firmware(gpu->pm4); release_firmware(gpu->pfp); msm_gpu_cleanup(&gpu->base); - - if (aspace) { - aspace->mmu->funcs->detach(aspace->mmu); - msm_gem_address_space_put(aspace); - } - - if (gpu->base.secure_aspace) { - aspace = gpu->base.secure_aspace; - aspace->mmu->funcs->detach(aspace->mmu); - msm_gem_address_space_put(aspace); - } } static void adreno_snapshot_os(struct msm_gpu *gpu, diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 4e43b96341f8..159dc6d75cbb 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -810,12 +810,32 @@ msm_gpu_create_address_space(struct msm_gpu *gpu, struct device *dev, gpu->name, name, PTR_ERR(aspace)); iommu_domain_free(iommu); - aspace = NULL; + return NULL; + } + + if (aspace->mmu) { + int ret = aspace->mmu->funcs->attach(aspace->mmu, NULL, 0); + + if (ret) { + dev_err(gpu->dev->dev, + "%s: failed to atach IOMMU '%s': %d\n", + gpu->name, name, ret); + msm_gem_address_space_put(aspace); + aspace = ERR_PTR(ret); + } } return aspace; } +static void msm_gpu_destroy_address_space(struct msm_gem_address_space *aspace) +{ + if (!IS_ERR_OR_NULL(aspace) && aspace->mmu) + aspace->mmu->funcs->detach(aspace->mmu); + + msm_gem_address_space_put(aspace); +} + int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs, const char *name, struct msm_gpu_config *config) @@ -938,6 +958,9 @@ fail: for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) msm_ringbuffer_destroy(gpu->rb[i]); + msm_gpu_destroy_address_space(gpu->aspace); + msm_gpu_destroy_address_space(gpu->secure_aspace); + pm_runtime_disable(&pdev->dev); return ret; } @@ -960,4 +983,7 @@ void msm_gpu_cleanup(struct msm_gpu *gpu) msm_snapshot_destroy(gpu, gpu->snapshot); pm_runtime_disable(&pdev->dev); + + msm_gpu_destroy_address_space(gpu->aspace); + msm_gpu_destroy_address_space(gpu->secure_aspace); } From 180cb9a578d1333651912f9539ba8c2db91b3d04 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 12 Jun 2017 09:16:49 -0600 Subject: [PATCH 4/4] drm/msm: Move memptrs to msm_gpu and reorganize Since most of the heavy lifting for managing submits lives in the msm_gpu domain it makes sense to move the memptrs so that they are globally visible and we can use them without relying on function pointers. Additionally, instead of having a single struct full of per-ring arrays, reorganize the structure and assign a sub-allocation to each ring. This simplifies all of the various macros and other bits and allows us to make the size of the allocation dependent on the acutal number of rings for the implementation. Change-Id: Ic0dedbadc18ba1dc786c82b082c5030e13ff8012 Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 15 ++++---- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 11 +++--- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 43 ++++++----------------- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 23 ------------ drivers/gpu/drm/msm/msm_gpu.c | 27 ++++++++++++-- drivers/gpu/drm/msm/msm_gpu.h | 2 ++ drivers/gpu/drm/msm/msm_ringbuffer.c | 7 +++- drivers/gpu/drm/msm/msm_ringbuffer.h | 16 ++++++++- 8 files changed, 69 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 3fc3065147b2..f8dbc843f852 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -46,7 +46,6 @@ static void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) static void a5xx_set_pagetable(struct msm_gpu *gpu, struct msm_ringbuffer *ring, struct msm_gem_address_space *aspace) { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct msm_mmu *mmu = aspace->mmu; struct msm_iommu *iommu = to_msm_iommu(mmu); @@ -75,17 +74,15 @@ static void a5xx_set_pagetable(struct msm_gpu *gpu, struct msm_ringbuffer *ring, * reload the pagetable if the current ring gets preempted out. */ OUT_PKT7(ring, CP_MEM_WRITE, 4); - OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, ring->id, ttbr0))); - OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, ring->id, ttbr0))); + OUT_RING(ring, lower_32_bits(rbmemptr(ring, ttbr0))); + OUT_RING(ring, upper_32_bits(rbmemptr(ring, ttbr0))); OUT_RING(ring, lower_32_bits(iommu->ttbr0)); OUT_RING(ring, upper_32_bits(iommu->ttbr0)); /* Also write the current contextidr (ASID) */ OUT_PKT7(ring, CP_MEM_WRITE, 3); - OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, ring->id, - contextidr))); - OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, ring->id, - contextidr))); + OUT_RING(ring, lower_32_bits(rbmemptr(ring, contextidr))); + OUT_RING(ring, upper_32_bits(rbmemptr(ring, contextidr))); OUT_RING(ring, iommu->contextidr); /* Invalidate the draw state so we start off fresh */ @@ -217,8 +214,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) OUT_PKT7(ring, CP_EVENT_WRITE, 4); OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31)); - OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, ring->id, fence))); - OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, ring->id, fence))); + OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence))); + OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence))); OUT_RING(ring, submit->fence); if (submit->secure) { diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index dacdb4752393..57ef366cf82c 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -65,7 +65,6 @@ static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) /* Return the highest priority ringbuffer with something in it */ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); unsigned long flags; int i; @@ -74,7 +73,7 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) struct msm_ringbuffer *ring = gpu->rb[i]; spin_lock_irqsave(&ring->lock, flags); - empty = (get_wptr(ring) == adreno_gpu->memptrs->rptr[ring->id]); + empty = (get_wptr(ring) == ring->memptrs->rptr); spin_unlock_irqrestore(&ring->lock, flags); if (!empty) @@ -141,10 +140,8 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu) /* Set the SMMU info for the preemption */ if (a5xx_gpu->smmu_info) { - a5xx_gpu->smmu_info->ttbr0 = - adreno_gpu->memptrs->ttbr0[ring->id]; - a5xx_gpu->smmu_info->contextidr = - adreno_gpu->memptrs->contextidr[ring->id]; + a5xx_gpu->smmu_info->ttbr0 = ring->memptrs->ttbr0; + a5xx_gpu->smmu_info->contextidr = ring->memptrs->contextidr; } /* Set the address of the incoming preemption record */ @@ -261,7 +258,7 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, ptr->info = 0; ptr->data = 0; ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT; - ptr->rptr_addr = rbmemptr(adreno_gpu, ring->id, rptr); + ptr->rptr_addr = rbmemptr(ring, rptr); ptr->counter = iova + A5XX_PREEMPT_RECORD_SIZE; return 0; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 0de73f61bfcb..9f3d957499d3 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -90,7 +90,7 @@ int adreno_hw_init(struct msm_gpu *gpu) REG_ADRENO_CP_RB_BASE_HI, gpu->rb[0]->iova); adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR, - REG_ADRENO_CP_RB_RPTR_ADDR_HI, rbmemptr(adreno_gpu, 0, rptr)); + REG_ADRENO_CP_RB_RPTR_ADDR_HI, rbmemptr(gpu->rb[0], rptr)); return 0; } @@ -106,10 +106,11 @@ static uint32_t get_rptr(struct adreno_gpu *adreno_gpu, * ensure that it won't be. If not then this is why your * a430 stopped working. */ - return adreno_gpu->memptrs->rptr[ring->id] = adreno_gpu_read( - adreno_gpu, REG_ADRENO_CP_RB_RPTR); - } else - return adreno_gpu->memptrs->rptr[ring->id]; + return ring->memptrs->rptr = + adreno_gpu_read(adreno_gpu, REG_ADRENO_CP_RB_RPTR); + } + + return ring->memptrs->rptr; } struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu) @@ -128,17 +129,11 @@ uint32_t adreno_submitted_fence(struct msm_gpu *gpu, uint32_t adreno_last_fence(struct msm_gpu *gpu, struct msm_ringbuffer *ring) { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - - if (!ring) - return 0; - - return adreno_gpu->memptrs->fence[ring->id]; + return ring ? ring->memptrs->fence : 0; } void adreno_recover(struct msm_gpu *gpu) { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct drm_device *dev = gpu->dev; struct msm_ringbuffer *ring; int ret, i; @@ -156,9 +151,8 @@ void adreno_recover(struct msm_gpu *gpu) ring->next = ring->start; /* reset completed fence seqno, discard anything pending: */ - adreno_gpu->memptrs->fence[ring->id] = - adreno_submitted_fence(gpu, ring); - adreno_gpu->memptrs->rptr[ring->id] = 0; + ring->memptrs->fence = adreno_submitted_fence(gpu, ring); + ring->memptrs->rptr = 0; } gpu->funcs->pm_resume(gpu); @@ -213,7 +207,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) OUT_PKT3(ring, CP_EVENT_WRITE, 3); OUT_RING(ring, CACHE_FLUSH_TS); - OUT_RING(ring, rbmemptr(adreno_gpu, ring->id, fence)); + OUT_RING(ring, rbmemptr(ring, fence)); OUT_RING(ring, submit->fence); /* we could maybe be clever and only CP_COND_EXEC the interrupt: */ @@ -540,30 +534,15 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, } ret = request_firmware(&adreno_gpu->pfp, adreno_gpu->info->pfpfw, drm->dev); - if (ret) { + if (ret) dev_err(drm->dev, "failed to load %s PFP firmware: %d\n", adreno_gpu->info->pfpfw, ret); - return ret; - } - - adreno_gpu->memptrs = msm_gem_kernel_new(drm, - sizeof(*adreno_gpu->memptrs), MSM_BO_UNCACHED, gpu->aspace, - &adreno_gpu->memptrs_bo, &adreno_gpu->memptrs_iova); - - if (IS_ERR(adreno_gpu->memptrs)) { - ret = PTR_ERR(adreno_gpu->memptrs); - adreno_gpu->memptrs = NULL; - } return ret; } void adreno_gpu_cleanup(struct adreno_gpu *gpu) { - if (gpu->memptrs_bo) { - msm_gem_put_iova(gpu->memptrs_bo, gpu->base.aspace); - drm_gem_object_unreference_unlocked(gpu->memptrs_bo); - } release_firmware(gpu->pm4); release_firmware(gpu->pfp); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 9e622fa06ce4..c894956fb5e8 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -83,22 +83,6 @@ struct adreno_info { const struct adreno_info *adreno_info(struct adreno_rev rev); -#define _sizeof(member) \ - sizeof(((struct adreno_rbmemptrs *) 0)->member[0]) - -#define _base(adreno_gpu, member) \ - ((adreno_gpu)->memptrs_iova + offsetof(struct adreno_rbmemptrs, member)) - -#define rbmemptr(adreno_gpu, index, member) \ - (_base((adreno_gpu), member) + ((index) * _sizeof(member))) - -struct adreno_rbmemptrs { - volatile uint32_t rptr[MSM_GPU_MAX_RINGS]; - volatile uint32_t fence[MSM_GPU_MAX_RINGS]; - volatile uint64_t ttbr0[MSM_GPU_MAX_RINGS]; - volatile unsigned int contextidr[MSM_GPU_MAX_RINGS]; -}; - struct adreno_counter { u32 lo; u32 hi; @@ -137,13 +121,6 @@ struct adreno_gpu { /* firmware: */ const struct firmware *pm4, *pfp; - /* ringbuffer rptr/wptr: */ - // TODO should this be in msm_ringbuffer? I think it would be - // different for z180.. - struct adreno_rbmemptrs *memptrs; - struct drm_gem_object *memptrs_bo; - uint64_t memptrs_iova; - /* * Register offsets are different between some GPUs. * GPU specific offsets will be exported by GPU specific diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 159dc6d75cbb..16049e830b7a 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -841,6 +841,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, const char *name, struct msm_gpu_config *config) { int i, ret, nr_rings; + void *memptrs; + uint64_t memptrs_iova; if (WARN_ON(gpu->num_perfcntrs > ARRAY_SIZE(gpu->last_cntrs))) gpu->num_perfcntrs = ARRAY_SIZE(gpu->last_cntrs); @@ -923,10 +925,18 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, nr_rings = ARRAY_SIZE(gpu->rb); } + /* Allocate one buffer to hold all the memptr records for the rings */ + memptrs = msm_gem_kernel_new(drm, sizeof(struct msm_memptrs) * nr_rings, + MSM_BO_UNCACHED, gpu->aspace, &gpu->memptrs_bo, &memptrs_iova); + + if (IS_ERR(memptrs)) { + ret = PTR_ERR(memptrs); + goto fail; + } + /* Create ringbuffer(s): */ for (i = 0; i < nr_rings; i++) { - - gpu->rb[i] = msm_ringbuffer_new(gpu, i); + gpu->rb[i] = msm_ringbuffer_new(gpu, i, memptrs, memptrs_iova); if (IS_ERR(gpu->rb[i])) { ret = PTR_ERR(gpu->rb[i]); gpu->rb[i] = NULL; @@ -934,6 +944,9 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, "could not create ringbuffer %d: %d\n", i, ret); goto fail; } + + memptrs += sizeof(struct msm_memptrs); + memptrs_iova += sizeof(struct msm_memptrs); } gpu->nr_rings = nr_rings; @@ -958,6 +971,11 @@ fail: for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) msm_ringbuffer_destroy(gpu->rb[i]); + if (gpu->memptrs_bo) { + msm_gem_put_iova(gpu->memptrs_bo, gpu->aspace); + drm_gem_object_unreference_unlocked(gpu->memptrs_bo); + } + msm_gpu_destroy_address_space(gpu->aspace); msm_gpu_destroy_address_space(gpu->secure_aspace); @@ -981,6 +999,11 @@ void msm_gpu_cleanup(struct msm_gpu *gpu) for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) msm_ringbuffer_destroy(gpu->rb[i]); + if (gpu->memptrs_bo) { + msm_gem_put_iova(gpu->memptrs_bo, gpu->aspace); + drm_gem_object_unreference_unlocked(gpu->memptrs_bo); + } + msm_snapshot_destroy(gpu, gpu->snapshot); pm_runtime_disable(&pdev->dev); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index cddbcbbb8557..306139bcd103 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -131,6 +131,8 @@ struct msm_gpu { struct pm_qos_request pm_qos_req_dma; + struct drm_gem_object *memptrs_bo; + #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING struct msm_bus_scale_pdata *bus_scale_table; uint32_t bsc; diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index 9b8e76da449f..2a5843e6f81b 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -18,7 +18,8 @@ #include "msm_ringbuffer.h" #include "msm_gpu.h" -struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id) +struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, + struct msm_memptrs *memptrs, uint64_t memptrs_iova) { struct msm_ringbuffer *ring; int ret; @@ -42,6 +43,10 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id) goto fail; } + ring->memptrs = memptrs; + ring->memptrs_iova = memptrs_iova; + + ring->start = msm_gem_vaddr(ring->bo); ring->end = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2); ring->next = ring->start; diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h index 70643a7b4cc4..3eb9a86b2a2e 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.h +++ b/drivers/gpu/drm/msm/msm_ringbuffer.h @@ -20,6 +20,16 @@ #include "msm_drv.h" +#define rbmemptr(ring, member) \ + ((ring)->memptrs_iova + offsetof(struct msm_memptrs, member)) + +struct msm_memptrs { + volatile uint32_t rptr; + volatile uint32_t fence; + volatile uint64_t ttbr0; + volatile unsigned int contextidr; +}; + struct msm_ringbuffer { struct msm_gpu *gpu; int id; @@ -29,9 +39,13 @@ struct msm_ringbuffer { uint32_t submitted_fence; spinlock_t lock; struct list_head submits; + + struct msm_memptrs *memptrs; + uint64_t memptrs_iova; }; -struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id); +struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, + struct msm_memptrs *memptrs, uint64_t memptrs_iova); void msm_ringbuffer_destroy(struct msm_ringbuffer *ring); /* ringbuffer helpers (the parts that are same for a3xx/a2xx/z180..) */