Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 
0003 /*
0004  * Copyright (C) 2022 Advanced Micro Devices, Inc.
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     /* The resulting array has the fences in reverse */
0308     f4 = dma_fence_unwrap_merge(f2, f1);
0309     if (!f4)
0310         goto error_put_f3;
0311 
0312     /* Signaled fences should be filtered, the two arrays merged. */
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 }