brintos

brintos / linux-shallow public Read only

0
0
Text · 6.5 KiB · f0cee98 Raw
383 lines · c
1// SPDX-License-Identifier: MIT2 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	dma_fence_enable_sw_signaling(f);106 107	array = mock_array(1, f);108	if (!array)109		return -ENOMEM;110 111	chain = mock_chain(NULL, array);112	if (!chain)113		return -ENOMEM;114 115	dma_fence_put(chain);116	return err;117}118 119static int unwrap_array(void *arg)120{121	struct dma_fence *fence, *f1, *f2, *array;122	struct dma_fence_unwrap iter;123	int err = 0;124 125	f1 = mock_fence();126	if (!f1)127		return -ENOMEM;128 129	dma_fence_enable_sw_signaling(f1);130 131	f2 = mock_fence();132	if (!f2) {133		dma_fence_put(f1);134		return -ENOMEM;135	}136 137	dma_fence_enable_sw_signaling(f2);138 139	array = mock_array(2, f1, f2);140	if (!array)141		return -ENOMEM;142 143	dma_fence_unwrap_for_each(fence, &iter, array) {144		if (fence == f1) {145			f1 = NULL;146		} else if (fence == f2) {147			f2 = NULL;148		} else {149			pr_err("Unexpected fence!\n");150			err = -EINVAL;151		}152	}153 154	if (f1 || f2) {155		pr_err("Not all fences seen!\n");156		err = -EINVAL;157	}158 159	dma_fence_put(array);160	return err;161}162 163static int unwrap_chain(void *arg)164{165	struct dma_fence *fence, *f1, *f2, *chain;166	struct dma_fence_unwrap iter;167	int err = 0;168 169	f1 = mock_fence();170	if (!f1)171		return -ENOMEM;172 173	dma_fence_enable_sw_signaling(f1);174 175	f2 = mock_fence();176	if (!f2) {177		dma_fence_put(f1);178		return -ENOMEM;179	}180 181	dma_fence_enable_sw_signaling(f2);182 183	chain = mock_chain(f1, f2);184	if (!chain)185		return -ENOMEM;186 187	dma_fence_unwrap_for_each(fence, &iter, chain) {188		if (fence == f1) {189			f1 = NULL;190		} else if (fence == f2) {191			f2 = NULL;192		} else {193			pr_err("Unexpected fence!\n");194			err = -EINVAL;195		}196	}197 198	if (f1 || f2) {199		pr_err("Not all fences seen!\n");200		err = -EINVAL;201	}202 203	dma_fence_put(chain);204	return err;205}206 207static int unwrap_chain_array(void *arg)208{209	struct dma_fence *fence, *f1, *f2, *array, *chain;210	struct dma_fence_unwrap iter;211	int err = 0;212 213	f1 = mock_fence();214	if (!f1)215		return -ENOMEM;216 217	dma_fence_enable_sw_signaling(f1);218 219	f2 = mock_fence();220	if (!f2) {221		dma_fence_put(f1);222		return -ENOMEM;223	}224 225	dma_fence_enable_sw_signaling(f2);226 227	array = mock_array(2, f1, f2);228	if (!array)229		return -ENOMEM;230 231	chain = mock_chain(NULL, array);232	if (!chain)233		return -ENOMEM;234 235	dma_fence_unwrap_for_each(fence, &iter, chain) {236		if (fence == f1) {237			f1 = NULL;238		} else if (fence == f2) {239			f2 = NULL;240		} else {241			pr_err("Unexpected fence!\n");242			err = -EINVAL;243		}244	}245 246	if (f1 || f2) {247		pr_err("Not all fences seen!\n");248		err = -EINVAL;249	}250 251	dma_fence_put(chain);252	return err;253}254 255static int unwrap_merge(void *arg)256{257	struct dma_fence *fence, *f1, *f2, *f3;258	struct dma_fence_unwrap iter;259	int err = 0;260 261	f1 = mock_fence();262	if (!f1)263		return -ENOMEM;264 265	dma_fence_enable_sw_signaling(f1);266 267	f2 = mock_fence();268	if (!f2) {269		err = -ENOMEM;270		goto error_put_f1;271	}272 273	dma_fence_enable_sw_signaling(f2);274 275	f3 = dma_fence_unwrap_merge(f1, f2);276	if (!f3) {277		err = -ENOMEM;278		goto error_put_f2;279	}280 281	dma_fence_unwrap_for_each(fence, &iter, f3) {282		if (fence == f1) {283			dma_fence_put(f1);284			f1 = NULL;285		} else if (fence == f2) {286			dma_fence_put(f2);287			f2 = NULL;288		} else {289			pr_err("Unexpected fence!\n");290			err = -EINVAL;291		}292	}293 294	if (f1 || f2) {295		pr_err("Not all fences seen!\n");296		err = -EINVAL;297	}298 299	dma_fence_put(f3);300error_put_f2:301	dma_fence_put(f2);302error_put_f1:303	dma_fence_put(f1);304	return err;305}306 307static int unwrap_merge_complex(void *arg)308{309	struct dma_fence *fence, *f1, *f2, *f3, *f4, *f5;310	struct dma_fence_unwrap iter;311	int err = -ENOMEM;312 313	f1 = mock_fence();314	if (!f1)315		return -ENOMEM;316 317	dma_fence_enable_sw_signaling(f1);318 319	f2 = mock_fence();320	if (!f2)321		goto error_put_f1;322 323	dma_fence_enable_sw_signaling(f2);324 325	f3 = dma_fence_unwrap_merge(f1, f2);326	if (!f3)327		goto error_put_f2;328 329	/* The resulting array has the fences in reverse */330	f4 = dma_fence_unwrap_merge(f2, f1);331	if (!f4)332		goto error_put_f3;333 334	/* Signaled fences should be filtered, the two arrays merged. */335	f5 = dma_fence_unwrap_merge(f3, f4, dma_fence_get_stub());336	if (!f5)337		goto error_put_f4;338 339	err = 0;340	dma_fence_unwrap_for_each(fence, &iter, f5) {341		if (fence == f1) {342			dma_fence_put(f1);343			f1 = NULL;344		} else if (fence == f2) {345			dma_fence_put(f2);346			f2 = NULL;347		} else {348			pr_err("Unexpected fence!\n");349			err = -EINVAL;350		}351	}352 353	if (f1 || f2) {354		pr_err("Not all fences seen!\n");355		err = -EINVAL;356	}357 358	dma_fence_put(f5);359error_put_f4:360	dma_fence_put(f4);361error_put_f3:362	dma_fence_put(f3);363error_put_f2:364	dma_fence_put(f2);365error_put_f1:366	dma_fence_put(f1);367	return err;368}369 370int dma_fence_unwrap(void)371{372	static const struct subtest tests[] = {373		SUBTEST(sanitycheck),374		SUBTEST(unwrap_array),375		SUBTEST(unwrap_chain),376		SUBTEST(unwrap_chain_array),377		SUBTEST(unwrap_merge),378		SUBTEST(unwrap_merge_complex),379	};380 381	return subtests(tests, NULL);382}383