Mesa passes shared bo, fence syncobj to userq_ioctl. There can be duplicates here or some fences that are old. This patch is remove duplicates fence and only keep the most recent fence for each context.
v2: Export this code from dma-fence-unwrap.c(by Christian). Cc: Alex Deucher <alexander.deuc...@amd.com> Cc: Christian König <christian.koe...@amd.com> Cc: Sunil Khatri <sunil.kha...@amd.com> Cc: Arunpravin Paneer Selvam <arunpravin.paneersel...@amd.com> Signed-off-by: Arvind Yadav <arvind.ya...@amd.com> --- drivers/dma-buf/dma-fence-unwrap.c | 29 +++++++++++++++++++ .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.c | 2 ++ include/linux/dma-fence-unwrap.h | 3 ++ 3 files changed, 34 insertions(+) diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c index 2a059ac0ed27..18874eedf091 100644 --- a/drivers/dma-buf/dma-fence-unwrap.c +++ b/drivers/dma-buf/dma-fence-unwrap.c @@ -179,3 +179,32 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, return tmp; } EXPORT_SYMBOL_GPL(__dma_fence_unwrap_merge); + +/** + * dma_fence_shrink_array - return the shrink fences from fence containers + * @fences: array of fence + * @num_fences: number of fence in fence array @fences + * + * only keep most recent fence for each context. It will remove duplicate + * and old fence of same context. + */ +unsigned short dma_fence_shrink_array(struct dma_fence **fences, + unsigned short num_fences) +{ + unsigned short count = 0; + + if (num_fences <= 1) + return num_fences; + + sort(fences, num_fences, sizeof(*fences), fence_cmp, NULL); + + for (int i = 1; i < num_fences; i++) { + if (fences[i]->context == fences[count]->context) + dma_fence_put(fences[i]); + else + fences[++count] = fences[i]; + } + + return ++count; +} +EXPORT_SYMBOL_GPL(dma_fence_shrink_array); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c index 3288c2ff692e..cc74bb0ed06f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c @@ -851,6 +851,8 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, fences[num_fences++] = fence; } + num_fences = dma_fence_shrink_array(fences, num_fences); + waitq = idr_find(&userq_mgr->userq_idr, wait_info->waitq_id); if (!waitq) goto free_fences; diff --git a/include/linux/dma-fence-unwrap.h b/include/linux/dma-fence-unwrap.h index 66b1e56fbb81..94801feeee4b 100644 --- a/include/linux/dma-fence-unwrap.h +++ b/include/linux/dma-fence-unwrap.h @@ -72,4 +72,7 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, __dma_fence_unwrap_merge(ARRAY_SIZE(__f), __f, __c); \ }) + +unsigned short dma_fence_shrink_array(struct dma_fence **fences, + unsigned short num_fences); #endif -- 2.34.1