0001
0002
0003
0004
0005
0006
0007 #include <linux/dma-fence.h>
0008 #include <linux/dma-fence-array.h>
0009 #include <linux/dma-fence-chain.h>
0010 #include <linux/dma-fence-unwrap.h>
0011
0012 #include "selftest.h"
0013
0014 #define CHAIN_SZ (4 << 10)
0015
0016 struct mock_fence {
0017 struct dma_fence base;
0018 spinlock_t lock;
0019 };
0020
0021 static const char *mock_name(struct dma_fence *f)
0022 {
0023 return "mock";
0024 }
0025
0026 static const struct dma_fence_ops mock_ops = {
0027 .get_driver_name = mock_name,
0028 .get_timeline_name = mock_name,
0029 };
0030
0031 static struct dma_fence *mock_fence(void)
0032 {
0033 struct mock_fence *f;
0034
0035 f = kmalloc(sizeof(*f), GFP_KERNEL);
0036 if (!f)
0037 return NULL;
0038
0039 spin_lock_init(&f->lock);
0040 dma_fence_init(&f->base, &mock_ops, &f->lock,
0041 dma_fence_context_alloc(1), 1);
0042
0043 return &f->base;
0044 }
0045
0046 static struct dma_fence *mock_array(unsigned int num_fences, ...)
0047 {
0048 struct dma_fence_array *array;
0049 struct dma_fence **fences;
0050 va_list valist;
0051 int i;
0052
0053 fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
0054 if (!fences)
0055 goto error_put;
0056
0057 va_start(valist, num_fences);
0058 for (i = 0; i < num_fences; ++i)
0059 fences[i] = va_arg(valist, typeof(*fences));
0060 va_end(valist);
0061
0062 array = dma_fence_array_create(num_fences, fences,
0063 dma_fence_context_alloc(1),
0064 1, false);
0065 if (!array)
0066 goto error_free;
0067 return &array->base;
0068
0069 error_free:
0070 kfree(fences);
0071
0072 error_put:
0073 va_start(valist, num_fences);
0074 for (i = 0; i < num_fences; ++i)
0075 dma_fence_put(va_arg(valist, typeof(*fences)));
0076 va_end(valist);
0077 return NULL;
0078 }
0079
0080 static struct dma_fence *mock_chain(struct dma_fence *prev,
0081 struct dma_fence *fence)
0082 {
0083 struct dma_fence_chain *f;
0084
0085 f = dma_fence_chain_alloc();
0086 if (!f) {
0087 dma_fence_put(prev);
0088 dma_fence_put(fence);
0089 return NULL;
0090 }
0091
0092 dma_fence_chain_init(f, prev, fence, 1);
0093 return &f->base;
0094 }
0095
0096 static int sanitycheck(void *arg)
0097 {
0098 struct dma_fence *f, *chain, *array;
0099 int err = 0;
0100
0101 f = mock_fence();
0102 if (!f)
0103 return -ENOMEM;
0104
0105 array = mock_array(1, f);
0106 if (!array)
0107 return -ENOMEM;
0108
0109 chain = mock_chain(NULL, array);
0110 if (!chain)
0111 return -ENOMEM;
0112
0113 dma_fence_put(chain);
0114 return err;
0115 }
0116
0117 static int unwrap_array(void *arg)
0118 {
0119 struct dma_fence *fence, *f1, *f2, *array;
0120 struct dma_fence_unwrap iter;
0121 int err = 0;
0122
0123 f1 = mock_fence();
0124 if (!f1)
0125 return -ENOMEM;
0126
0127 f2 = mock_fence();
0128 if (!f2) {
0129 dma_fence_put(f1);
0130 return -ENOMEM;
0131 }
0132
0133 array = mock_array(2, f1, f2);
0134 if (!array)
0135 return -ENOMEM;
0136
0137 dma_fence_unwrap_for_each(fence, &iter, array) {
0138 if (fence == f1) {
0139 f1 = NULL;
0140 } else if (fence == f2) {
0141 f2 = NULL;
0142 } else {
0143 pr_err("Unexpected fence!\n");
0144 err = -EINVAL;
0145 }
0146 }
0147
0148 if (f1 || f2) {
0149 pr_err("Not all fences seen!\n");
0150 err = -EINVAL;
0151 }
0152
0153 dma_fence_put(array);
0154 return err;
0155 }
0156
0157 static int unwrap_chain(void *arg)
0158 {
0159 struct dma_fence *fence, *f1, *f2, *chain;
0160 struct dma_fence_unwrap iter;
0161 int err = 0;
0162
0163 f1 = mock_fence();
0164 if (!f1)
0165 return -ENOMEM;
0166
0167 f2 = mock_fence();
0168 if (!f2) {
0169 dma_fence_put(f1);
0170 return -ENOMEM;
0171 }
0172
0173 chain = mock_chain(f1, f2);
0174 if (!chain)
0175 return -ENOMEM;
0176
0177 dma_fence_unwrap_for_each(fence, &iter, chain) {
0178 if (fence == f1) {
0179 f1 = NULL;
0180 } else if (fence == f2) {
0181 f2 = NULL;
0182 } else {
0183 pr_err("Unexpected fence!\n");
0184 err = -EINVAL;
0185 }
0186 }
0187
0188 if (f1 || f2) {
0189 pr_err("Not all fences seen!\n");
0190 err = -EINVAL;
0191 }
0192
0193 dma_fence_put(chain);
0194 return err;
0195 }
0196
0197 static int unwrap_chain_array(void *arg)
0198 {
0199 struct dma_fence *fence, *f1, *f2, *array, *chain;
0200 struct dma_fence_unwrap iter;
0201 int err = 0;
0202
0203 f1 = mock_fence();
0204 if (!f1)
0205 return -ENOMEM;
0206
0207 f2 = mock_fence();
0208 if (!f2) {
0209 dma_fence_put(f1);
0210 return -ENOMEM;
0211 }
0212
0213 array = mock_array(2, f1, f2);
0214 if (!array)
0215 return -ENOMEM;
0216
0217 chain = mock_chain(NULL, array);
0218 if (!chain)
0219 return -ENOMEM;
0220
0221 dma_fence_unwrap_for_each(fence, &iter, chain) {
0222 if (fence == f1) {
0223 f1 = NULL;
0224 } else if (fence == f2) {
0225 f2 = NULL;
0226 } else {
0227 pr_err("Unexpected fence!\n");
0228 err = -EINVAL;
0229 }
0230 }
0231
0232 if (f1 || f2) {
0233 pr_err("Not all fences seen!\n");
0234 err = -EINVAL;
0235 }
0236
0237 dma_fence_put(chain);
0238 return err;
0239 }
0240
0241 static int unwrap_merge(void *arg)
0242 {
0243 struct dma_fence *fence, *f1, *f2, *f3;
0244 struct dma_fence_unwrap iter;
0245 int err = 0;
0246
0247 f1 = mock_fence();
0248 if (!f1)
0249 return -ENOMEM;
0250
0251 f2 = mock_fence();
0252 if (!f2) {
0253 err = -ENOMEM;
0254 goto error_put_f1;
0255 }
0256
0257 f3 = dma_fence_unwrap_merge(f1, f2);
0258 if (!f3) {
0259 err = -ENOMEM;
0260 goto error_put_f2;
0261 }
0262
0263 dma_fence_unwrap_for_each(fence, &iter, f3) {
0264 if (fence == f1) {
0265 dma_fence_put(f1);
0266 f1 = NULL;
0267 } else if (fence == f2) {
0268 dma_fence_put(f2);
0269 f2 = NULL;
0270 } else {
0271 pr_err("Unexpected fence!\n");
0272 err = -EINVAL;
0273 }
0274 }
0275
0276 if (f1 || f2) {
0277 pr_err("Not all fences seen!\n");
0278 err = -EINVAL;
0279 }
0280
0281 dma_fence_put(f3);
0282 error_put_f2:
0283 dma_fence_put(f2);
0284 error_put_f1:
0285 dma_fence_put(f1);
0286 return err;
0287 }
0288
0289 static int unwrap_merge_complex(void *arg)
0290 {
0291 struct dma_fence *fence, *f1, *f2, *f3, *f4, *f5;
0292 struct dma_fence_unwrap iter;
0293 int err = -ENOMEM;
0294
0295 f1 = mock_fence();
0296 if (!f1)
0297 return -ENOMEM;
0298
0299 f2 = mock_fence();
0300 if (!f2)
0301 goto error_put_f1;
0302
0303 f3 = dma_fence_unwrap_merge(f1, f2);
0304 if (!f3)
0305 goto error_put_f2;
0306
0307
0308 f4 = dma_fence_unwrap_merge(f2, f1);
0309 if (!f4)
0310 goto error_put_f3;
0311
0312
0313 f5 = dma_fence_unwrap_merge(f3, f4, dma_fence_get_stub());
0314 if (!f5)
0315 goto error_put_f4;
0316
0317 err = 0;
0318 dma_fence_unwrap_for_each(fence, &iter, f5) {
0319 if (fence == f1) {
0320 dma_fence_put(f1);
0321 f1 = NULL;
0322 } else if (fence == f2) {
0323 dma_fence_put(f2);
0324 f2 = NULL;
0325 } else {
0326 pr_err("Unexpected fence!\n");
0327 err = -EINVAL;
0328 }
0329 }
0330
0331 if (f1 || f2) {
0332 pr_err("Not all fences seen!\n");
0333 err = -EINVAL;
0334 }
0335
0336 dma_fence_put(f5);
0337 error_put_f4:
0338 dma_fence_put(f4);
0339 error_put_f3:
0340 dma_fence_put(f3);
0341 error_put_f2:
0342 dma_fence_put(f2);
0343 error_put_f1:
0344 dma_fence_put(f1);
0345 return err;
0346 }
0347
0348 int dma_fence_unwrap(void)
0349 {
0350 static const struct subtest tests[] = {
0351 SUBTEST(sanitycheck),
0352 SUBTEST(unwrap_array),
0353 SUBTEST(unwrap_chain),
0354 SUBTEST(unwrap_chain_array),
0355 SUBTEST(unwrap_merge),
0356 SUBTEST(unwrap_merge_complex),
0357 };
0358
0359 return subtests(tests, NULL);
0360 }