1 1.1 riastrad /* $NetBSD: i915_syncmap.c,v 1.2 2021/12/18 23:45:28 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2017 Intel Corporation 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 8 1.1 riastrad * to deal in the Software without restriction, including without limitation 9 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 11 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 12 1.1 riastrad * 13 1.1 riastrad * The above copyright notice and this permission notice (including the next 14 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 15 1.1 riastrad * Software. 16 1.1 riastrad * 17 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 1.1 riastrad * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 1.1 riastrad * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 1.1 riastrad * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 1.1 riastrad * IN THE SOFTWARE. 24 1.1 riastrad * 25 1.1 riastrad */ 26 1.1 riastrad 27 1.1 riastrad #include <sys/cdefs.h> 28 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: i915_syncmap.c,v 1.2 2021/12/18 23:45:28 riastradh Exp $"); 29 1.1 riastrad 30 1.1 riastrad #include <linux/slab.h> 31 1.1 riastrad 32 1.1 riastrad #include "i915_syncmap.h" 33 1.1 riastrad 34 1.1 riastrad #include "i915_gem.h" /* GEM_BUG_ON() */ 35 1.1 riastrad #include "i915_selftest.h" 36 1.1 riastrad 37 1.1 riastrad #define SHIFT ilog2(KSYNCMAP) 38 1.1 riastrad #define MASK (KSYNCMAP - 1) 39 1.1 riastrad 40 1.1 riastrad /* 41 1.1 riastrad * struct i915_syncmap is a layer of a radixtree that maps a u64 fence 42 1.1 riastrad * context id to the last u32 fence seqno waited upon from that context. 43 1.1 riastrad * Unlike lib/radixtree it uses a parent pointer that allows traversal back to 44 1.1 riastrad * the root. This allows us to access the whole tree via a single pointer 45 1.1 riastrad * to the most recently used layer. We expect fence contexts to be dense 46 1.1 riastrad * and most reuse to be on the same i915_gem_context but on neighbouring 47 1.1 riastrad * engines (i.e. on adjacent contexts) and reuse the same leaf, a very 48 1.1 riastrad * effective lookup cache. If the new lookup is not on the same leaf, we 49 1.1 riastrad * expect it to be on the neighbouring branch. 50 1.1 riastrad * 51 1.1 riastrad * A leaf holds an array of u32 seqno, and has height 0. The bitmap field 52 1.1 riastrad * allows us to store whether a particular seqno is valid (i.e. allows us 53 1.1 riastrad * to distinguish unset from 0). 54 1.1 riastrad * 55 1.1 riastrad * A branch holds an array of layer pointers, and has height > 0, and always 56 1.1 riastrad * has at least 2 layers (either branches or leaves) below it. 57 1.1 riastrad * 58 1.1 riastrad * For example, 59 1.1 riastrad * for x in 60 1.1 riastrad * 0 1 2 0x10 0x11 0x200 0x201 61 1.1 riastrad * 0x500000 0x500001 0x503000 0x503001 62 1.1 riastrad * 0xE<<60: 63 1.1 riastrad * i915_syncmap_set(&sync, x, lower_32_bits(x)); 64 1.1 riastrad * will build a tree like: 65 1.1 riastrad * 0xXXXXXXXXXXXXXXXX 66 1.1 riastrad * 0-> 0x0000000000XXXXXX 67 1.1 riastrad * | 0-> 0x0000000000000XXX 68 1.1 riastrad * | | 0-> 0x00000000000000XX 69 1.1 riastrad * | | | 0-> 0x000000000000000X 0:0, 1:1, 2:2 70 1.1 riastrad * | | | 1-> 0x000000000000001X 0:10, 1:11 71 1.1 riastrad * | | 2-> 0x000000000000020X 0:200, 1:201 72 1.1 riastrad * | 5-> 0x000000000050XXXX 73 1.1 riastrad * | 0-> 0x000000000050000X 0:500000, 1:500001 74 1.1 riastrad * | 3-> 0x000000000050300X 0:503000, 1:503001 75 1.1 riastrad * e-> 0xe00000000000000X e:e 76 1.1 riastrad */ 77 1.1 riastrad 78 1.1 riastrad struct i915_syncmap { 79 1.1 riastrad u64 prefix; 80 1.1 riastrad unsigned int height; 81 1.1 riastrad unsigned int bitmap; 82 1.1 riastrad struct i915_syncmap *parent; 83 1.1 riastrad /* 84 1.1 riastrad * Following this header is an array of either seqno or child pointers: 85 1.1 riastrad * union { 86 1.1 riastrad * u32 seqno[KSYNCMAP]; 87 1.1 riastrad * struct i915_syncmap *child[KSYNCMAP]; 88 1.1 riastrad * }; 89 1.1 riastrad */ 90 1.1 riastrad }; 91 1.1 riastrad 92 1.1 riastrad /** 93 1.1 riastrad * i915_syncmap_init -- initialise the #i915_syncmap 94 1.1 riastrad * @root: pointer to the #i915_syncmap 95 1.1 riastrad */ 96 1.1 riastrad void i915_syncmap_init(struct i915_syncmap **root) 97 1.1 riastrad { 98 1.1 riastrad BUILD_BUG_ON_NOT_POWER_OF_2(KSYNCMAP); 99 1.1 riastrad BUILD_BUG_ON_NOT_POWER_OF_2(SHIFT); 100 1.1 riastrad BUILD_BUG_ON(KSYNCMAP > BITS_PER_TYPE((*root)->bitmap)); 101 1.1 riastrad *root = NULL; 102 1.1 riastrad } 103 1.1 riastrad 104 1.1 riastrad static inline u32 *__sync_seqno(struct i915_syncmap *p) 105 1.1 riastrad { 106 1.1 riastrad GEM_BUG_ON(p->height); 107 1.1 riastrad return (u32 *)(p + 1); 108 1.1 riastrad } 109 1.1 riastrad 110 1.1 riastrad static inline struct i915_syncmap **__sync_child(struct i915_syncmap *p) 111 1.1 riastrad { 112 1.1 riastrad GEM_BUG_ON(!p->height); 113 1.1 riastrad return (struct i915_syncmap **)(p + 1); 114 1.1 riastrad } 115 1.1 riastrad 116 1.1 riastrad static inline unsigned int 117 1.1 riastrad __sync_branch_idx(const struct i915_syncmap *p, u64 id) 118 1.1 riastrad { 119 1.1 riastrad return (id >> p->height) & MASK; 120 1.1 riastrad } 121 1.1 riastrad 122 1.1 riastrad static inline unsigned int 123 1.1 riastrad __sync_leaf_idx(const struct i915_syncmap *p, u64 id) 124 1.1 riastrad { 125 1.1 riastrad GEM_BUG_ON(p->height); 126 1.1 riastrad return id & MASK; 127 1.1 riastrad } 128 1.1 riastrad 129 1.1 riastrad static inline u64 __sync_branch_prefix(const struct i915_syncmap *p, u64 id) 130 1.1 riastrad { 131 1.1 riastrad return id >> p->height >> SHIFT; 132 1.1 riastrad } 133 1.1 riastrad 134 1.1 riastrad static inline u64 __sync_leaf_prefix(const struct i915_syncmap *p, u64 id) 135 1.1 riastrad { 136 1.1 riastrad GEM_BUG_ON(p->height); 137 1.1 riastrad return id >> SHIFT; 138 1.1 riastrad } 139 1.1 riastrad 140 1.1 riastrad static inline bool seqno_later(u32 a, u32 b) 141 1.1 riastrad { 142 1.1 riastrad return (s32)(a - b) >= 0; 143 1.1 riastrad } 144 1.1 riastrad 145 1.1 riastrad /** 146 1.1 riastrad * i915_syncmap_is_later -- compare against the last know sync point 147 1.1 riastrad * @root: pointer to the #i915_syncmap 148 1.1 riastrad * @id: the context id (other timeline) we are synchronising to 149 1.1 riastrad * @seqno: the sequence number along the other timeline 150 1.1 riastrad * 151 1.1 riastrad * If we have already synchronised this @root timeline with another (@id) then 152 1.1 riastrad * we can omit any repeated or earlier synchronisation requests. If the two 153 1.1 riastrad * timelines are already coupled, we can also omit the dependency between the 154 1.1 riastrad * two as that is already known via the timeline. 155 1.1 riastrad * 156 1.1 riastrad * Returns true if the two timelines are already synchronised wrt to @seqno, 157 1.1 riastrad * false if not and the synchronisation must be emitted. 158 1.1 riastrad */ 159 1.1 riastrad bool i915_syncmap_is_later(struct i915_syncmap **root, u64 id, u32 seqno) 160 1.1 riastrad { 161 1.1 riastrad struct i915_syncmap *p; 162 1.1 riastrad unsigned int idx; 163 1.1 riastrad 164 1.1 riastrad p = *root; 165 1.1 riastrad if (!p) 166 1.1 riastrad return false; 167 1.1 riastrad 168 1.1 riastrad if (likely(__sync_leaf_prefix(p, id) == p->prefix)) 169 1.1 riastrad goto found; 170 1.1 riastrad 171 1.1 riastrad /* First climb the tree back to a parent branch */ 172 1.1 riastrad do { 173 1.1 riastrad p = p->parent; 174 1.1 riastrad if (!p) 175 1.1 riastrad return false; 176 1.1 riastrad 177 1.1 riastrad if (__sync_branch_prefix(p, id) == p->prefix) 178 1.1 riastrad break; 179 1.1 riastrad } while (1); 180 1.1 riastrad 181 1.1 riastrad /* And then descend again until we find our leaf */ 182 1.1 riastrad do { 183 1.1 riastrad if (!p->height) 184 1.1 riastrad break; 185 1.1 riastrad 186 1.1 riastrad p = __sync_child(p)[__sync_branch_idx(p, id)]; 187 1.1 riastrad if (!p) 188 1.1 riastrad return false; 189 1.1 riastrad 190 1.1 riastrad if (__sync_branch_prefix(p, id) != p->prefix) 191 1.1 riastrad return false; 192 1.1 riastrad } while (1); 193 1.1 riastrad 194 1.1 riastrad *root = p; 195 1.1 riastrad found: 196 1.1 riastrad idx = __sync_leaf_idx(p, id); 197 1.1 riastrad if (!(p->bitmap & BIT(idx))) 198 1.1 riastrad return false; 199 1.1 riastrad 200 1.1 riastrad return seqno_later(__sync_seqno(p)[idx], seqno); 201 1.1 riastrad } 202 1.1 riastrad 203 1.1 riastrad static struct i915_syncmap * 204 1.1 riastrad __sync_alloc_leaf(struct i915_syncmap *parent, u64 id) 205 1.1 riastrad { 206 1.1 riastrad struct i915_syncmap *p; 207 1.1 riastrad 208 1.1 riastrad p = kmalloc(sizeof(*p) + KSYNCMAP * sizeof(u32), GFP_KERNEL); 209 1.1 riastrad if (unlikely(!p)) 210 1.1 riastrad return NULL; 211 1.1 riastrad 212 1.1 riastrad p->parent = parent; 213 1.1 riastrad p->height = 0; 214 1.1 riastrad p->bitmap = 0; 215 1.1 riastrad p->prefix = __sync_leaf_prefix(p, id); 216 1.1 riastrad return p; 217 1.1 riastrad } 218 1.1 riastrad 219 1.1 riastrad static inline void __sync_set_seqno(struct i915_syncmap *p, u64 id, u32 seqno) 220 1.1 riastrad { 221 1.1 riastrad unsigned int idx = __sync_leaf_idx(p, id); 222 1.1 riastrad 223 1.1 riastrad p->bitmap |= BIT(idx); 224 1.1 riastrad __sync_seqno(p)[idx] = seqno; 225 1.1 riastrad } 226 1.1 riastrad 227 1.1 riastrad static inline void __sync_set_child(struct i915_syncmap *p, 228 1.1 riastrad unsigned int idx, 229 1.1 riastrad struct i915_syncmap *child) 230 1.1 riastrad { 231 1.1 riastrad p->bitmap |= BIT(idx); 232 1.1 riastrad __sync_child(p)[idx] = child; 233 1.1 riastrad } 234 1.1 riastrad 235 1.1 riastrad static noinline int __sync_set(struct i915_syncmap **root, u64 id, u32 seqno) 236 1.1 riastrad { 237 1.1 riastrad struct i915_syncmap *p = *root; 238 1.1 riastrad unsigned int idx; 239 1.1 riastrad 240 1.1 riastrad if (!p) { 241 1.1 riastrad p = __sync_alloc_leaf(NULL, id); 242 1.1 riastrad if (unlikely(!p)) 243 1.1 riastrad return -ENOMEM; 244 1.1 riastrad 245 1.1 riastrad goto found; 246 1.1 riastrad } 247 1.1 riastrad 248 1.1 riastrad /* Caller handled the likely cached case */ 249 1.1 riastrad GEM_BUG_ON(__sync_leaf_prefix(p, id) == p->prefix); 250 1.1 riastrad 251 1.1 riastrad /* Climb back up the tree until we find a common prefix */ 252 1.1 riastrad do { 253 1.1 riastrad if (!p->parent) 254 1.1 riastrad break; 255 1.1 riastrad 256 1.1 riastrad p = p->parent; 257 1.1 riastrad 258 1.1 riastrad if (__sync_branch_prefix(p, id) == p->prefix) 259 1.1 riastrad break; 260 1.1 riastrad } while (1); 261 1.1 riastrad 262 1.1 riastrad /* 263 1.1 riastrad * No shortcut, we have to descend the tree to find the right layer 264 1.1 riastrad * containing this fence. 265 1.1 riastrad * 266 1.1 riastrad * Each layer in the tree holds 16 (KSYNCMAP) pointers, either fences 267 1.1 riastrad * or lower layers. Leaf nodes (height = 0) contain the fences, all 268 1.1 riastrad * other nodes (height > 0) are internal layers that point to a lower 269 1.1 riastrad * node. Each internal layer has at least 2 descendents. 270 1.1 riastrad * 271 1.1 riastrad * Starting at the top, we check whether the current prefix matches. If 272 1.1 riastrad * it doesn't, we have gone past our target and need to insert a join 273 1.1 riastrad * into the tree, and a new leaf node for the target as a descendent 274 1.1 riastrad * of the join, as well as the original layer. 275 1.1 riastrad * 276 1.1 riastrad * The matching prefix means we are still following the right branch 277 1.1 riastrad * of the tree. If it has height 0, we have found our leaf and just 278 1.1 riastrad * need to replace the fence slot with ourselves. If the height is 279 1.1 riastrad * not zero, our slot contains the next layer in the tree (unless 280 1.1 riastrad * it is empty, in which case we can add ourselves as a new leaf). 281 1.1 riastrad * As descend the tree the prefix grows (and height decreases). 282 1.1 riastrad */ 283 1.1 riastrad do { 284 1.1 riastrad struct i915_syncmap *next; 285 1.1 riastrad 286 1.1 riastrad if (__sync_branch_prefix(p, id) != p->prefix) { 287 1.1 riastrad unsigned int above; 288 1.1 riastrad 289 1.1 riastrad /* Insert a join above the current layer */ 290 1.1 riastrad next = kzalloc(sizeof(*next) + KSYNCMAP * sizeof(next), 291 1.1 riastrad GFP_KERNEL); 292 1.1 riastrad if (unlikely(!next)) 293 1.1 riastrad return -ENOMEM; 294 1.1 riastrad 295 1.1 riastrad /* Compute the height at which these two diverge */ 296 1.1 riastrad above = fls64(__sync_branch_prefix(p, id) ^ p->prefix); 297 1.1 riastrad above = round_up(above, SHIFT); 298 1.1 riastrad next->height = above + p->height; 299 1.1 riastrad next->prefix = __sync_branch_prefix(next, id); 300 1.1 riastrad 301 1.1 riastrad /* Insert the join into the parent */ 302 1.1 riastrad if (p->parent) { 303 1.1 riastrad idx = __sync_branch_idx(p->parent, id); 304 1.1 riastrad __sync_child(p->parent)[idx] = next; 305 1.1 riastrad GEM_BUG_ON(!(p->parent->bitmap & BIT(idx))); 306 1.1 riastrad } 307 1.1 riastrad next->parent = p->parent; 308 1.1 riastrad 309 1.1 riastrad /* Compute the idx of the other branch, not our id! */ 310 1.1 riastrad idx = p->prefix >> (above - SHIFT) & MASK; 311 1.1 riastrad __sync_set_child(next, idx, p); 312 1.1 riastrad p->parent = next; 313 1.1 riastrad 314 1.1 riastrad /* Ascend to the join */ 315 1.1 riastrad p = next; 316 1.1 riastrad } else { 317 1.1 riastrad if (!p->height) 318 1.1 riastrad break; 319 1.1 riastrad } 320 1.1 riastrad 321 1.1 riastrad /* Descend into the next layer */ 322 1.1 riastrad GEM_BUG_ON(!p->height); 323 1.1 riastrad idx = __sync_branch_idx(p, id); 324 1.1 riastrad next = __sync_child(p)[idx]; 325 1.1 riastrad if (!next) { 326 1.1 riastrad next = __sync_alloc_leaf(p, id); 327 1.1 riastrad if (unlikely(!next)) 328 1.1 riastrad return -ENOMEM; 329 1.1 riastrad 330 1.1 riastrad __sync_set_child(p, idx, next); 331 1.1 riastrad p = next; 332 1.1 riastrad break; 333 1.1 riastrad } 334 1.1 riastrad 335 1.1 riastrad p = next; 336 1.1 riastrad } while (1); 337 1.1 riastrad 338 1.1 riastrad found: 339 1.1 riastrad GEM_BUG_ON(p->prefix != __sync_leaf_prefix(p, id)); 340 1.1 riastrad __sync_set_seqno(p, id, seqno); 341 1.1 riastrad *root = p; 342 1.1 riastrad return 0; 343 1.1 riastrad } 344 1.1 riastrad 345 1.1 riastrad /** 346 1.1 riastrad * i915_syncmap_set -- mark the most recent syncpoint between contexts 347 1.1 riastrad * @root: pointer to the #i915_syncmap 348 1.1 riastrad * @id: the context id (other timeline) we have synchronised to 349 1.1 riastrad * @seqno: the sequence number along the other timeline 350 1.1 riastrad * 351 1.1 riastrad * When we synchronise this @root timeline with another (@id), we also know 352 1.1 riastrad * that we have synchronized with all previous seqno along that timeline. If 353 1.1 riastrad * we then have a request to synchronise with the same seqno or older, we can 354 1.1 riastrad * omit it, see i915_syncmap_is_later() 355 1.1 riastrad * 356 1.1 riastrad * Returns 0 on success, or a negative error code. 357 1.1 riastrad */ 358 1.1 riastrad int i915_syncmap_set(struct i915_syncmap **root, u64 id, u32 seqno) 359 1.1 riastrad { 360 1.1 riastrad struct i915_syncmap *p = *root; 361 1.1 riastrad 362 1.1 riastrad /* 363 1.1 riastrad * We expect to be called in sequence following is_later(id), which 364 1.1 riastrad * should have preloaded the root for us. 365 1.1 riastrad */ 366 1.1 riastrad if (likely(p && __sync_leaf_prefix(p, id) == p->prefix)) { 367 1.1 riastrad __sync_set_seqno(p, id, seqno); 368 1.1 riastrad return 0; 369 1.1 riastrad } 370 1.1 riastrad 371 1.1 riastrad return __sync_set(root, id, seqno); 372 1.1 riastrad } 373 1.1 riastrad 374 1.1 riastrad static void __sync_free(struct i915_syncmap *p) 375 1.1 riastrad { 376 1.1 riastrad if (p->height) { 377 1.1 riastrad unsigned int i; 378 1.1 riastrad 379 1.1 riastrad while ((i = ffs(p->bitmap))) { 380 1.1 riastrad p->bitmap &= ~0u << i; 381 1.1 riastrad __sync_free(__sync_child(p)[i - 1]); 382 1.1 riastrad } 383 1.1 riastrad } 384 1.1 riastrad 385 1.1 riastrad kfree(p); 386 1.1 riastrad } 387 1.1 riastrad 388 1.1 riastrad /** 389 1.1 riastrad * i915_syncmap_free -- free all memory associated with the syncmap 390 1.1 riastrad * @root: pointer to the #i915_syncmap 391 1.1 riastrad * 392 1.1 riastrad * Either when the timeline is to be freed and we no longer need the sync 393 1.1 riastrad * point tracking, or when the fences are all known to be signaled and the 394 1.1 riastrad * sync point tracking is redundant, we can free the #i915_syncmap to recover 395 1.1 riastrad * its allocations. 396 1.1 riastrad * 397 1.1 riastrad * Will reinitialise the @root pointer so that the #i915_syncmap is ready for 398 1.1 riastrad * reuse. 399 1.1 riastrad */ 400 1.1 riastrad void i915_syncmap_free(struct i915_syncmap **root) 401 1.1 riastrad { 402 1.1 riastrad struct i915_syncmap *p; 403 1.1 riastrad 404 1.1 riastrad p = *root; 405 1.1 riastrad if (!p) 406 1.1 riastrad return; 407 1.1 riastrad 408 1.1 riastrad while (p->parent) 409 1.1 riastrad p = p->parent; 410 1.1 riastrad 411 1.1 riastrad __sync_free(p); 412 1.1 riastrad *root = NULL; 413 1.1 riastrad } 414 1.1 riastrad 415 1.1 riastrad #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) 416 1.1 riastrad #include "selftests/i915_syncmap.c" 417 1.1 riastrad #endif 418