0001
0002
0003
0004
0005
0006 #include <linux/dma-fence.h>
0007 #include <linux/slab.h>
0008
0009 #include <drm/ttm/ttm_bo_api.h>
0010
0011 #include "i915_deps.h"
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #define I915_DEPS_MIN_ALLOC_CHUNK 8U
0035
0036 static void i915_deps_reset_fences(struct i915_deps *deps)
0037 {
0038 if (deps->fences != &deps->single)
0039 kfree(deps->fences);
0040 deps->num_deps = 0;
0041 deps->fences_size = 1;
0042 deps->fences = &deps->single;
0043 }
0044
0045
0046
0047
0048
0049
0050 void i915_deps_init(struct i915_deps *deps, gfp_t gfp)
0051 {
0052 deps->fences = NULL;
0053 deps->gfp = gfp;
0054 i915_deps_reset_fences(deps);
0055 }
0056
0057
0058
0059
0060
0061
0062
0063
0064 void i915_deps_fini(struct i915_deps *deps)
0065 {
0066 unsigned int i;
0067
0068 for (i = 0; i < deps->num_deps; ++i)
0069 dma_fence_put(deps->fences[i]);
0070
0071 if (deps->fences != &deps->single)
0072 kfree(deps->fences);
0073 }
0074
0075 static int i915_deps_grow(struct i915_deps *deps, struct dma_fence *fence,
0076 const struct ttm_operation_ctx *ctx)
0077 {
0078 int ret;
0079
0080 if (deps->num_deps >= deps->fences_size) {
0081 unsigned int new_size = 2 * deps->fences_size;
0082 struct dma_fence **new_fences;
0083
0084 new_size = max(new_size, I915_DEPS_MIN_ALLOC_CHUNK);
0085 new_fences = kmalloc_array(new_size, sizeof(*new_fences), deps->gfp);
0086 if (!new_fences)
0087 goto sync;
0088
0089 memcpy(new_fences, deps->fences,
0090 deps->fences_size * sizeof(*new_fences));
0091 swap(new_fences, deps->fences);
0092 if (new_fences != &deps->single)
0093 kfree(new_fences);
0094 deps->fences_size = new_size;
0095 }
0096 deps->fences[deps->num_deps++] = dma_fence_get(fence);
0097 return 0;
0098
0099 sync:
0100 if (ctx->no_wait_gpu && !dma_fence_is_signaled(fence)) {
0101 ret = -EBUSY;
0102 goto unref;
0103 }
0104
0105 ret = dma_fence_wait(fence, ctx->interruptible);
0106 if (ret)
0107 goto unref;
0108
0109 ret = fence->error;
0110 if (ret)
0111 goto unref;
0112
0113 return 0;
0114
0115 unref:
0116 i915_deps_fini(deps);
0117 return ret;
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 int i915_deps_sync(const struct i915_deps *deps, const struct ttm_operation_ctx *ctx)
0133 {
0134 struct dma_fence **fences = deps->fences;
0135 unsigned int i;
0136 int ret = 0;
0137
0138 for (i = 0; i < deps->num_deps; ++i, ++fences) {
0139 if (ctx->no_wait_gpu && !dma_fence_is_signaled(*fences)) {
0140 ret = -EBUSY;
0141 break;
0142 }
0143
0144 ret = dma_fence_wait(*fences, ctx->interruptible);
0145 if (!ret)
0146 ret = (*fences)->error;
0147 if (ret)
0148 break;
0149 }
0150
0151 return ret;
0152 }
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 int i915_deps_add_dependency(struct i915_deps *deps,
0177 struct dma_fence *fence,
0178 const struct ttm_operation_ctx *ctx)
0179 {
0180 unsigned int i;
0181 int ret;
0182
0183 if (!fence)
0184 return 0;
0185
0186 if (dma_fence_is_signaled(fence)) {
0187 ret = fence->error;
0188 if (ret)
0189 i915_deps_fini(deps);
0190 return ret;
0191 }
0192
0193 for (i = 0; i < deps->num_deps; ++i) {
0194 struct dma_fence *entry = deps->fences[i];
0195
0196 if (!entry->context || entry->context != fence->context)
0197 continue;
0198
0199 if (dma_fence_is_later(fence, entry)) {
0200 dma_fence_put(entry);
0201 deps->fences[i] = dma_fence_get(fence);
0202 }
0203
0204 return 0;
0205 }
0206
0207 return i915_deps_grow(deps, fence, ctx);
0208 }
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 int i915_deps_add_resv(struct i915_deps *deps, struct dma_resv *resv,
0223 const struct ttm_operation_ctx *ctx)
0224 {
0225 struct dma_resv_iter iter;
0226 struct dma_fence *fence;
0227
0228 dma_resv_assert_held(resv);
0229 dma_resv_for_each_fence(&iter, resv, dma_resv_usage_rw(true), fence) {
0230 int ret = i915_deps_add_dependency(deps, fence, ctx);
0231
0232 if (ret)
0233 return ret;
0234 }
0235
0236 return 0;
0237 }