Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dma-fence: Add helper to sort and deduplicate dma_fence arrays

Export a new helper function `dma_fence_dedup_array()` that sorts
an array of dma_fence pointers by context, then deduplicates the array
by retaining only the most recent fence per context.

This utility is useful when merging or optimizing sets of fences where
redundant entries from the same context can be pruned. The operation is
performed in-place and releases references to dropped fences using
dma_fence_put().

v2: - Export this code from dma-fence-unwrap.c(by Christian).
v3: - To split this in a dma_buf patch and amd userq patch(by Sunil).
- No need to add a new function just re-use existing(by Christian).
v4: - Export dma_fence_dedub_array and use it(by Christian).

Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Reviewed-by: Sunil Khatri <sunil.khatri@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Arvind Yadav <Arvind.Yadav@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Arvind Yadav and committed by
Alex Deucher
575ec9b0 71353c1a

+39 -14
+37 -14
drivers/dma-buf/dma-fence-unwrap.c
··· 79 79 return 0; 80 80 } 81 81 82 + /** 83 + * dma_fence_dedup_array - Sort and deduplicate an array of dma_fence pointers 84 + * @fences: Array of dma_fence pointers to be deduplicated 85 + * @num_fences: Number of entries in the @fences array 86 + * 87 + * Sorts the input array by context, then removes duplicate 88 + * fences with the same context, keeping only the most recent one. 89 + * 90 + * The array is modified in-place and unreferenced duplicate fences are released 91 + * via dma_fence_put(). The function returns the new number of fences after 92 + * deduplication. 93 + * 94 + * Return: Number of unique fences remaining in the array. 95 + */ 96 + int dma_fence_dedup_array(struct dma_fence **fences, int num_fences) 97 + { 98 + int i, j; 99 + 100 + sort(fences, num_fences, sizeof(*fences), fence_cmp, NULL); 101 + 102 + /* 103 + * Only keep the most recent fence for each context. 104 + */ 105 + j = 0; 106 + for (i = 1; i < num_fences; i++) { 107 + if (fences[i]->context == fences[j]->context) 108 + dma_fence_put(fences[i]); 109 + else 110 + fences[++j] = fences[i]; 111 + } 112 + 113 + return ++j; 114 + } 115 + EXPORT_SYMBOL_GPL(dma_fence_dedup_array); 116 + 82 117 /* Implementation for the dma_fence_merge() marco, don't use directly */ 83 118 struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, 84 119 struct dma_fence **fences, ··· 122 87 struct dma_fence *tmp, *unsignaled = NULL, **array; 123 88 struct dma_fence_array *result; 124 89 ktime_t timestamp; 125 - int i, j, count; 90 + int i, count; 126 91 127 92 count = 0; 128 93 timestamp = ns_to_ktime(0); ··· 176 141 if (count == 0 || count == 1) 177 142 goto return_fastpath; 178 143 179 - sort(array, count, sizeof(*array), fence_cmp, NULL); 180 - 181 - /* 182 - * Only keep the most recent fence for each context. 183 - */ 184 - j = 0; 185 - for (i = 1; i < count; i++) { 186 - if (array[i]->context == array[j]->context) 187 - dma_fence_put(array[i]); 188 - else 189 - array[++j] = array[i]; 190 - } 191 - count = ++j; 144 + count = dma_fence_dedup_array(array, count); 192 145 193 146 if (count > 1) { 194 147 result = dma_fence_array_create(count, array,
+2
include/linux/dma-fence-unwrap.h
··· 52 52 struct dma_fence **fences, 53 53 struct dma_fence_unwrap *cursors); 54 54 55 + int dma_fence_dedup_array(struct dma_fence **array, int num_fences); 56 + 55 57 /** 56 58 * dma_fence_unwrap_merge - unwrap and merge fences 57 59 *