0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/slab.h>
0009 #include <linux/spinlock.h>
0010 #include <linux/dma-resv.h>
0011
0012 #include "selftest.h"
0013
0014 static struct spinlock fence_lock;
0015
0016 static const char *fence_name(struct dma_fence *f)
0017 {
0018 return "selftest";
0019 }
0020
0021 static const struct dma_fence_ops fence_ops = {
0022 .get_driver_name = fence_name,
0023 .get_timeline_name = fence_name,
0024 };
0025
0026 static struct dma_fence *alloc_fence(void)
0027 {
0028 struct dma_fence *f;
0029
0030 f = kmalloc(sizeof(*f), GFP_KERNEL);
0031 if (!f)
0032 return NULL;
0033
0034 dma_fence_init(f, &fence_ops, &fence_lock, 0, 0);
0035 return f;
0036 }
0037
0038 static int sanitycheck(void *arg)
0039 {
0040 struct dma_resv resv;
0041 struct dma_fence *f;
0042 int r;
0043
0044 f = alloc_fence();
0045 if (!f)
0046 return -ENOMEM;
0047
0048 dma_fence_signal(f);
0049 dma_fence_put(f);
0050
0051 dma_resv_init(&resv);
0052 r = dma_resv_lock(&resv, NULL);
0053 if (r)
0054 pr_err("Resv locking failed\n");
0055 else
0056 dma_resv_unlock(&resv);
0057 dma_resv_fini(&resv);
0058 return r;
0059 }
0060
0061 static int test_signaling(void *arg)
0062 {
0063 enum dma_resv_usage usage = (unsigned long)arg;
0064 struct dma_resv resv;
0065 struct dma_fence *f;
0066 int r;
0067
0068 f = alloc_fence();
0069 if (!f)
0070 return -ENOMEM;
0071
0072 dma_resv_init(&resv);
0073 r = dma_resv_lock(&resv, NULL);
0074 if (r) {
0075 pr_err("Resv locking failed\n");
0076 goto err_free;
0077 }
0078
0079 r = dma_resv_reserve_fences(&resv, 1);
0080 if (r) {
0081 pr_err("Resv shared slot allocation failed\n");
0082 goto err_unlock;
0083 }
0084
0085 dma_resv_add_fence(&resv, f, usage);
0086 if (dma_resv_test_signaled(&resv, usage)) {
0087 pr_err("Resv unexpectedly signaled\n");
0088 r = -EINVAL;
0089 goto err_unlock;
0090 }
0091 dma_fence_signal(f);
0092 if (!dma_resv_test_signaled(&resv, usage)) {
0093 pr_err("Resv not reporting signaled\n");
0094 r = -EINVAL;
0095 goto err_unlock;
0096 }
0097 err_unlock:
0098 dma_resv_unlock(&resv);
0099 err_free:
0100 dma_resv_fini(&resv);
0101 dma_fence_put(f);
0102 return r;
0103 }
0104
0105 static int test_for_each(void *arg)
0106 {
0107 enum dma_resv_usage usage = (unsigned long)arg;
0108 struct dma_resv_iter cursor;
0109 struct dma_fence *f, *fence;
0110 struct dma_resv resv;
0111 int r;
0112
0113 f = alloc_fence();
0114 if (!f)
0115 return -ENOMEM;
0116
0117 dma_resv_init(&resv);
0118 r = dma_resv_lock(&resv, NULL);
0119 if (r) {
0120 pr_err("Resv locking failed\n");
0121 goto err_free;
0122 }
0123
0124 r = dma_resv_reserve_fences(&resv, 1);
0125 if (r) {
0126 pr_err("Resv shared slot allocation failed\n");
0127 goto err_unlock;
0128 }
0129
0130 dma_resv_add_fence(&resv, f, usage);
0131
0132 r = -ENOENT;
0133 dma_resv_for_each_fence(&cursor, &resv, usage, fence) {
0134 if (!r) {
0135 pr_err("More than one fence found\n");
0136 r = -EINVAL;
0137 goto err_unlock;
0138 }
0139 if (f != fence) {
0140 pr_err("Unexpected fence\n");
0141 r = -EINVAL;
0142 goto err_unlock;
0143 }
0144 if (dma_resv_iter_usage(&cursor) != usage) {
0145 pr_err("Unexpected fence usage\n");
0146 r = -EINVAL;
0147 goto err_unlock;
0148 }
0149 r = 0;
0150 }
0151 if (r) {
0152 pr_err("No fence found\n");
0153 goto err_unlock;
0154 }
0155 dma_fence_signal(f);
0156 err_unlock:
0157 dma_resv_unlock(&resv);
0158 err_free:
0159 dma_resv_fini(&resv);
0160 dma_fence_put(f);
0161 return r;
0162 }
0163
0164 static int test_for_each_unlocked(void *arg)
0165 {
0166 enum dma_resv_usage usage = (unsigned long)arg;
0167 struct dma_resv_iter cursor;
0168 struct dma_fence *f, *fence;
0169 struct dma_resv resv;
0170 int r;
0171
0172 f = alloc_fence();
0173 if (!f)
0174 return -ENOMEM;
0175
0176 dma_resv_init(&resv);
0177 r = dma_resv_lock(&resv, NULL);
0178 if (r) {
0179 pr_err("Resv locking failed\n");
0180 goto err_free;
0181 }
0182
0183 r = dma_resv_reserve_fences(&resv, 1);
0184 if (r) {
0185 pr_err("Resv shared slot allocation failed\n");
0186 dma_resv_unlock(&resv);
0187 goto err_free;
0188 }
0189
0190 dma_resv_add_fence(&resv, f, usage);
0191 dma_resv_unlock(&resv);
0192
0193 r = -ENOENT;
0194 dma_resv_iter_begin(&cursor, &resv, usage);
0195 dma_resv_for_each_fence_unlocked(&cursor, fence) {
0196 if (!r) {
0197 pr_err("More than one fence found\n");
0198 r = -EINVAL;
0199 goto err_iter_end;
0200 }
0201 if (!dma_resv_iter_is_restarted(&cursor)) {
0202 pr_err("No restart flag\n");
0203 goto err_iter_end;
0204 }
0205 if (f != fence) {
0206 pr_err("Unexpected fence\n");
0207 r = -EINVAL;
0208 goto err_iter_end;
0209 }
0210 if (dma_resv_iter_usage(&cursor) != usage) {
0211 pr_err("Unexpected fence usage\n");
0212 r = -EINVAL;
0213 goto err_iter_end;
0214 }
0215
0216
0217 if (r == -ENOENT) {
0218 r = -EINVAL;
0219
0220 cursor.fences = (void*)~0;
0221 } else if (r == -EINVAL) {
0222 r = 0;
0223 }
0224 }
0225 if (r)
0226 pr_err("No fence found\n");
0227 err_iter_end:
0228 dma_resv_iter_end(&cursor);
0229 dma_fence_signal(f);
0230 err_free:
0231 dma_resv_fini(&resv);
0232 dma_fence_put(f);
0233 return r;
0234 }
0235
0236 static int test_get_fences(void *arg)
0237 {
0238 enum dma_resv_usage usage = (unsigned long)arg;
0239 struct dma_fence *f, **fences = NULL;
0240 struct dma_resv resv;
0241 int r, i;
0242
0243 f = alloc_fence();
0244 if (!f)
0245 return -ENOMEM;
0246
0247 dma_resv_init(&resv);
0248 r = dma_resv_lock(&resv, NULL);
0249 if (r) {
0250 pr_err("Resv locking failed\n");
0251 goto err_resv;
0252 }
0253
0254 r = dma_resv_reserve_fences(&resv, 1);
0255 if (r) {
0256 pr_err("Resv shared slot allocation failed\n");
0257 dma_resv_unlock(&resv);
0258 goto err_resv;
0259 }
0260
0261 dma_resv_add_fence(&resv, f, usage);
0262 dma_resv_unlock(&resv);
0263
0264 r = dma_resv_get_fences(&resv, usage, &i, &fences);
0265 if (r) {
0266 pr_err("get_fences failed\n");
0267 goto err_free;
0268 }
0269
0270 if (i != 1 || fences[0] != f) {
0271 pr_err("get_fences returned unexpected fence\n");
0272 goto err_free;
0273 }
0274
0275 dma_fence_signal(f);
0276 err_free:
0277 while (i--)
0278 dma_fence_put(fences[i]);
0279 kfree(fences);
0280 err_resv:
0281 dma_resv_fini(&resv);
0282 dma_fence_put(f);
0283 return r;
0284 }
0285
0286 int dma_resv(void)
0287 {
0288 static const struct subtest tests[] = {
0289 SUBTEST(sanitycheck),
0290 SUBTEST(test_signaling),
0291 SUBTEST(test_for_each),
0292 SUBTEST(test_for_each_unlocked),
0293 SUBTEST(test_get_fences),
0294 };
0295 enum dma_resv_usage usage;
0296 int r;
0297
0298 spin_lock_init(&fence_lock);
0299 for (usage = DMA_RESV_USAGE_KERNEL; usage <= DMA_RESV_USAGE_BOOKKEEP;
0300 ++usage) {
0301 r = subtests(tests, (void *)(unsigned long)usage);
0302 if (r)
0303 return r;
0304 }
0305 return 0;
0306 }