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

Configure Feed

Select the types of activity you want to include in your feed.

at f2aeea57504cbbc58da3c59b939fc16150087648 360 lines 6.2 kB view raw
1// SPDX-License-Identifier: MIT 2 3/* 4 * Copyright (C) 2022 Advanced Micro Devices, Inc. 5 */ 6 7#include <linux/dma-fence.h> 8#include <linux/dma-fence-array.h> 9#include <linux/dma-fence-chain.h> 10#include <linux/dma-fence-unwrap.h> 11 12#include "selftest.h" 13 14#define CHAIN_SZ (4 << 10) 15 16struct mock_fence { 17 struct dma_fence base; 18 spinlock_t lock; 19}; 20 21static const char *mock_name(struct dma_fence *f) 22{ 23 return "mock"; 24} 25 26static const struct dma_fence_ops mock_ops = { 27 .get_driver_name = mock_name, 28 .get_timeline_name = mock_name, 29}; 30 31static struct dma_fence *mock_fence(void) 32{ 33 struct mock_fence *f; 34 35 f = kmalloc(sizeof(*f), GFP_KERNEL); 36 if (!f) 37 return NULL; 38 39 spin_lock_init(&f->lock); 40 dma_fence_init(&f->base, &mock_ops, &f->lock, 41 dma_fence_context_alloc(1), 1); 42 43 return &f->base; 44} 45 46static struct dma_fence *mock_array(unsigned int num_fences, ...) 47{ 48 struct dma_fence_array *array; 49 struct dma_fence **fences; 50 va_list valist; 51 int i; 52 53 fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL); 54 if (!fences) 55 goto error_put; 56 57 va_start(valist, num_fences); 58 for (i = 0; i < num_fences; ++i) 59 fences[i] = va_arg(valist, typeof(*fences)); 60 va_end(valist); 61 62 array = dma_fence_array_create(num_fences, fences, 63 dma_fence_context_alloc(1), 64 1, false); 65 if (!array) 66 goto error_free; 67 return &array->base; 68 69error_free: 70 kfree(fences); 71 72error_put: 73 va_start(valist, num_fences); 74 for (i = 0; i < num_fences; ++i) 75 dma_fence_put(va_arg(valist, typeof(*fences))); 76 va_end(valist); 77 return NULL; 78} 79 80static struct dma_fence *mock_chain(struct dma_fence *prev, 81 struct dma_fence *fence) 82{ 83 struct dma_fence_chain *f; 84 85 f = dma_fence_chain_alloc(); 86 if (!f) { 87 dma_fence_put(prev); 88 dma_fence_put(fence); 89 return NULL; 90 } 91 92 dma_fence_chain_init(f, prev, fence, 1); 93 return &f->base; 94} 95 96static int sanitycheck(void *arg) 97{ 98 struct dma_fence *f, *chain, *array; 99 int err = 0; 100 101 f = mock_fence(); 102 if (!f) 103 return -ENOMEM; 104 105 array = mock_array(1, f); 106 if (!array) 107 return -ENOMEM; 108 109 chain = mock_chain(NULL, array); 110 if (!chain) 111 return -ENOMEM; 112 113 dma_fence_put(chain); 114 return err; 115} 116 117static int unwrap_array(void *arg) 118{ 119 struct dma_fence *fence, *f1, *f2, *array; 120 struct dma_fence_unwrap iter; 121 int err = 0; 122 123 f1 = mock_fence(); 124 if (!f1) 125 return -ENOMEM; 126 127 f2 = mock_fence(); 128 if (!f2) { 129 dma_fence_put(f1); 130 return -ENOMEM; 131 } 132 133 array = mock_array(2, f1, f2); 134 if (!array) 135 return -ENOMEM; 136 137 dma_fence_unwrap_for_each(fence, &iter, array) { 138 if (fence == f1) { 139 f1 = NULL; 140 } else if (fence == f2) { 141 f2 = NULL; 142 } else { 143 pr_err("Unexpected fence!\n"); 144 err = -EINVAL; 145 } 146 } 147 148 if (f1 || f2) { 149 pr_err("Not all fences seen!\n"); 150 err = -EINVAL; 151 } 152 153 dma_fence_put(array); 154 return err; 155} 156 157static int unwrap_chain(void *arg) 158{ 159 struct dma_fence *fence, *f1, *f2, *chain; 160 struct dma_fence_unwrap iter; 161 int err = 0; 162 163 f1 = mock_fence(); 164 if (!f1) 165 return -ENOMEM; 166 167 f2 = mock_fence(); 168 if (!f2) { 169 dma_fence_put(f1); 170 return -ENOMEM; 171 } 172 173 chain = mock_chain(f1, f2); 174 if (!chain) 175 return -ENOMEM; 176 177 dma_fence_unwrap_for_each(fence, &iter, chain) { 178 if (fence == f1) { 179 f1 = NULL; 180 } else if (fence == f2) { 181 f2 = NULL; 182 } else { 183 pr_err("Unexpected fence!\n"); 184 err = -EINVAL; 185 } 186 } 187 188 if (f1 || f2) { 189 pr_err("Not all fences seen!\n"); 190 err = -EINVAL; 191 } 192 193 dma_fence_put(chain); 194 return err; 195} 196 197static int unwrap_chain_array(void *arg) 198{ 199 struct dma_fence *fence, *f1, *f2, *array, *chain; 200 struct dma_fence_unwrap iter; 201 int err = 0; 202 203 f1 = mock_fence(); 204 if (!f1) 205 return -ENOMEM; 206 207 f2 = mock_fence(); 208 if (!f2) { 209 dma_fence_put(f1); 210 return -ENOMEM; 211 } 212 213 array = mock_array(2, f1, f2); 214 if (!array) 215 return -ENOMEM; 216 217 chain = mock_chain(NULL, array); 218 if (!chain) 219 return -ENOMEM; 220 221 dma_fence_unwrap_for_each(fence, &iter, chain) { 222 if (fence == f1) { 223 f1 = NULL; 224 } else if (fence == f2) { 225 f2 = NULL; 226 } else { 227 pr_err("Unexpected fence!\n"); 228 err = -EINVAL; 229 } 230 } 231 232 if (f1 || f2) { 233 pr_err("Not all fences seen!\n"); 234 err = -EINVAL; 235 } 236 237 dma_fence_put(chain); 238 return err; 239} 240 241static int unwrap_merge(void *arg) 242{ 243 struct dma_fence *fence, *f1, *f2, *f3; 244 struct dma_fence_unwrap iter; 245 int err = 0; 246 247 f1 = mock_fence(); 248 if (!f1) 249 return -ENOMEM; 250 251 f2 = mock_fence(); 252 if (!f2) { 253 err = -ENOMEM; 254 goto error_put_f1; 255 } 256 257 f3 = dma_fence_unwrap_merge(f1, f2); 258 if (!f3) { 259 err = -ENOMEM; 260 goto error_put_f2; 261 } 262 263 dma_fence_unwrap_for_each(fence, &iter, f3) { 264 if (fence == f1) { 265 dma_fence_put(f1); 266 f1 = NULL; 267 } else if (fence == f2) { 268 dma_fence_put(f2); 269 f2 = NULL; 270 } else { 271 pr_err("Unexpected fence!\n"); 272 err = -EINVAL; 273 } 274 } 275 276 if (f1 || f2) { 277 pr_err("Not all fences seen!\n"); 278 err = -EINVAL; 279 } 280 281 dma_fence_put(f3); 282error_put_f2: 283 dma_fence_put(f2); 284error_put_f1: 285 dma_fence_put(f1); 286 return err; 287} 288 289static int unwrap_merge_complex(void *arg) 290{ 291 struct dma_fence *fence, *f1, *f2, *f3, *f4, *f5; 292 struct dma_fence_unwrap iter; 293 int err = -ENOMEM; 294 295 f1 = mock_fence(); 296 if (!f1) 297 return -ENOMEM; 298 299 f2 = mock_fence(); 300 if (!f2) 301 goto error_put_f1; 302 303 f3 = dma_fence_unwrap_merge(f1, f2); 304 if (!f3) 305 goto error_put_f2; 306 307 /* The resulting array has the fences in reverse */ 308 f4 = dma_fence_unwrap_merge(f2, f1); 309 if (!f4) 310 goto error_put_f3; 311 312 /* Signaled fences should be filtered, the two arrays merged. */ 313 f5 = dma_fence_unwrap_merge(f3, f4, dma_fence_get_stub()); 314 if (!f5) 315 goto error_put_f4; 316 317 err = 0; 318 dma_fence_unwrap_for_each(fence, &iter, f5) { 319 if (fence == f1) { 320 dma_fence_put(f1); 321 f1 = NULL; 322 } else if (fence == f2) { 323 dma_fence_put(f2); 324 f2 = NULL; 325 } else { 326 pr_err("Unexpected fence!\n"); 327 err = -EINVAL; 328 } 329 } 330 331 if (f1 || f2) { 332 pr_err("Not all fences seen!\n"); 333 err = -EINVAL; 334 } 335 336 dma_fence_put(f5); 337error_put_f4: 338 dma_fence_put(f4); 339error_put_f3: 340 dma_fence_put(f3); 341error_put_f2: 342 dma_fence_put(f2); 343error_put_f1: 344 dma_fence_put(f1); 345 return err; 346} 347 348int dma_fence_unwrap(void) 349{ 350 static const struct subtest tests[] = { 351 SUBTEST(sanitycheck), 352 SUBTEST(unwrap_array), 353 SUBTEST(unwrap_chain), 354 SUBTEST(unwrap_chain_array), 355 SUBTEST(unwrap_merge), 356 SUBTEST(unwrap_merge_complex), 357 }; 358 359 return subtests(tests, NULL); 360}