0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <linux/slab.h>
0026
0027 #include "i915_syncmap.h"
0028
0029 #include "i915_gem.h" /* GEM_BUG_ON() */
0030 #include "i915_selftest.h"
0031
0032 #define SHIFT ilog2(KSYNCMAP)
0033 #define MASK (KSYNCMAP - 1)
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 struct i915_syncmap {
0074 u64 prefix;
0075 unsigned int height;
0076 unsigned int bitmap;
0077 struct i915_syncmap *parent;
0078
0079
0080
0081
0082
0083
0084
0085 };
0086
0087
0088
0089
0090
0091 void i915_syncmap_init(struct i915_syncmap **root)
0092 {
0093 BUILD_BUG_ON_NOT_POWER_OF_2(KSYNCMAP);
0094 BUILD_BUG_ON_NOT_POWER_OF_2(SHIFT);
0095 BUILD_BUG_ON(KSYNCMAP > BITS_PER_TYPE((*root)->bitmap));
0096 *root = NULL;
0097 }
0098
0099 static inline u32 *__sync_seqno(struct i915_syncmap *p)
0100 {
0101 GEM_BUG_ON(p->height);
0102 return (u32 *)(p + 1);
0103 }
0104
0105 static inline struct i915_syncmap **__sync_child(struct i915_syncmap *p)
0106 {
0107 GEM_BUG_ON(!p->height);
0108 return (struct i915_syncmap **)(p + 1);
0109 }
0110
0111 static inline unsigned int
0112 __sync_branch_idx(const struct i915_syncmap *p, u64 id)
0113 {
0114 return (id >> p->height) & MASK;
0115 }
0116
0117 static inline unsigned int
0118 __sync_leaf_idx(const struct i915_syncmap *p, u64 id)
0119 {
0120 GEM_BUG_ON(p->height);
0121 return id & MASK;
0122 }
0123
0124 static inline u64 __sync_branch_prefix(const struct i915_syncmap *p, u64 id)
0125 {
0126 return id >> p->height >> SHIFT;
0127 }
0128
0129 static inline u64 __sync_leaf_prefix(const struct i915_syncmap *p, u64 id)
0130 {
0131 GEM_BUG_ON(p->height);
0132 return id >> SHIFT;
0133 }
0134
0135 static inline bool seqno_later(u32 a, u32 b)
0136 {
0137 return (s32)(a - b) >= 0;
0138 }
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 bool i915_syncmap_is_later(struct i915_syncmap **root, u64 id, u32 seqno)
0155 {
0156 struct i915_syncmap *p;
0157 unsigned int idx;
0158
0159 p = *root;
0160 if (!p)
0161 return false;
0162
0163 if (likely(__sync_leaf_prefix(p, id) == p->prefix))
0164 goto found;
0165
0166
0167 do {
0168 p = p->parent;
0169 if (!p)
0170 return false;
0171
0172 if (__sync_branch_prefix(p, id) == p->prefix)
0173 break;
0174 } while (1);
0175
0176
0177 do {
0178 if (!p->height)
0179 break;
0180
0181 p = __sync_child(p)[__sync_branch_idx(p, id)];
0182 if (!p)
0183 return false;
0184
0185 if (__sync_branch_prefix(p, id) != p->prefix)
0186 return false;
0187 } while (1);
0188
0189 *root = p;
0190 found:
0191 idx = __sync_leaf_idx(p, id);
0192 if (!(p->bitmap & BIT(idx)))
0193 return false;
0194
0195 return seqno_later(__sync_seqno(p)[idx], seqno);
0196 }
0197
0198 static struct i915_syncmap *
0199 __sync_alloc_leaf(struct i915_syncmap *parent, u64 id)
0200 {
0201 struct i915_syncmap *p;
0202
0203 p = kmalloc(sizeof(*p) + KSYNCMAP * sizeof(u32), GFP_KERNEL);
0204 if (unlikely(!p))
0205 return NULL;
0206
0207 p->parent = parent;
0208 p->height = 0;
0209 p->bitmap = 0;
0210 p->prefix = __sync_leaf_prefix(p, id);
0211 return p;
0212 }
0213
0214 static inline void __sync_set_seqno(struct i915_syncmap *p, u64 id, u32 seqno)
0215 {
0216 unsigned int idx = __sync_leaf_idx(p, id);
0217
0218 p->bitmap |= BIT(idx);
0219 __sync_seqno(p)[idx] = seqno;
0220 }
0221
0222 static inline void __sync_set_child(struct i915_syncmap *p,
0223 unsigned int idx,
0224 struct i915_syncmap *child)
0225 {
0226 p->bitmap |= BIT(idx);
0227 __sync_child(p)[idx] = child;
0228 }
0229
0230 static noinline int __sync_set(struct i915_syncmap **root, u64 id, u32 seqno)
0231 {
0232 struct i915_syncmap *p = *root;
0233 unsigned int idx;
0234
0235 if (!p) {
0236 p = __sync_alloc_leaf(NULL, id);
0237 if (unlikely(!p))
0238 return -ENOMEM;
0239
0240 goto found;
0241 }
0242
0243
0244 GEM_BUG_ON(__sync_leaf_prefix(p, id) == p->prefix);
0245
0246
0247 do {
0248 if (!p->parent)
0249 break;
0250
0251 p = p->parent;
0252
0253 if (__sync_branch_prefix(p, id) == p->prefix)
0254 break;
0255 } while (1);
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 do {
0279 struct i915_syncmap *next;
0280
0281 if (__sync_branch_prefix(p, id) != p->prefix) {
0282 unsigned int above;
0283
0284
0285 next = kzalloc(sizeof(*next) + KSYNCMAP * sizeof(next),
0286 GFP_KERNEL);
0287 if (unlikely(!next))
0288 return -ENOMEM;
0289
0290
0291 above = fls64(__sync_branch_prefix(p, id) ^ p->prefix);
0292 above = round_up(above, SHIFT);
0293 next->height = above + p->height;
0294 next->prefix = __sync_branch_prefix(next, id);
0295
0296
0297 if (p->parent) {
0298 idx = __sync_branch_idx(p->parent, id);
0299 __sync_child(p->parent)[idx] = next;
0300 GEM_BUG_ON(!(p->parent->bitmap & BIT(idx)));
0301 }
0302 next->parent = p->parent;
0303
0304
0305 idx = p->prefix >> (above - SHIFT) & MASK;
0306 __sync_set_child(next, idx, p);
0307 p->parent = next;
0308
0309
0310 p = next;
0311 } else {
0312 if (!p->height)
0313 break;
0314 }
0315
0316
0317 GEM_BUG_ON(!p->height);
0318 idx = __sync_branch_idx(p, id);
0319 next = __sync_child(p)[idx];
0320 if (!next) {
0321 next = __sync_alloc_leaf(p, id);
0322 if (unlikely(!next))
0323 return -ENOMEM;
0324
0325 __sync_set_child(p, idx, next);
0326 p = next;
0327 break;
0328 }
0329
0330 p = next;
0331 } while (1);
0332
0333 found:
0334 GEM_BUG_ON(p->prefix != __sync_leaf_prefix(p, id));
0335 __sync_set_seqno(p, id, seqno);
0336 *root = p;
0337 return 0;
0338 }
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353 int i915_syncmap_set(struct i915_syncmap **root, u64 id, u32 seqno)
0354 {
0355 struct i915_syncmap *p = *root;
0356
0357
0358
0359
0360
0361 if (likely(p && __sync_leaf_prefix(p, id) == p->prefix)) {
0362 __sync_set_seqno(p, id, seqno);
0363 return 0;
0364 }
0365
0366 return __sync_set(root, id, seqno);
0367 }
0368
0369 static void __sync_free(struct i915_syncmap *p)
0370 {
0371 if (p->height) {
0372 unsigned int i;
0373
0374 while ((i = ffs(p->bitmap))) {
0375 p->bitmap &= ~0u << i;
0376 __sync_free(__sync_child(p)[i - 1]);
0377 }
0378 }
0379
0380 kfree(p);
0381 }
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395 void i915_syncmap_free(struct i915_syncmap **root)
0396 {
0397 struct i915_syncmap *p;
0398
0399 p = *root;
0400 if (!p)
0401 return;
0402
0403 while (p->parent)
0404 p = p->parent;
0405
0406 __sync_free(p);
0407 *root = NULL;
0408 }
0409
0410 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
0411 #include "selftests/i915_syncmap.c"
0412 #endif