162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright © 2017 Intel Corporation
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the next
1262306a36Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
1362306a36Sopenharmony_ci * Software.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1862306a36Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1962306a36Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2062306a36Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2162306a36Sopenharmony_ci * IN THE SOFTWARE.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <linux/slab.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "i915_syncmap.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include "i915_gem.h" /* GEM_BUG_ON() */
3062306a36Sopenharmony_ci#include "i915_selftest.h"
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define SHIFT ilog2(KSYNCMAP)
3362306a36Sopenharmony_ci#define MASK (KSYNCMAP - 1)
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/*
3662306a36Sopenharmony_ci * struct i915_syncmap is a layer of a radixtree that maps a u64 fence
3762306a36Sopenharmony_ci * context id to the last u32 fence seqno waited upon from that context.
3862306a36Sopenharmony_ci * Unlike lib/radixtree it uses a parent pointer that allows traversal back to
3962306a36Sopenharmony_ci * the root. This allows us to access the whole tree via a single pointer
4062306a36Sopenharmony_ci * to the most recently used layer. We expect fence contexts to be dense
4162306a36Sopenharmony_ci * and most reuse to be on the same i915_gem_context but on neighbouring
4262306a36Sopenharmony_ci * engines (i.e. on adjacent contexts) and reuse the same leaf, a very
4362306a36Sopenharmony_ci * effective lookup cache. If the new lookup is not on the same leaf, we
4462306a36Sopenharmony_ci * expect it to be on the neighbouring branch.
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci * A leaf holds an array of u32 seqno, and has height 0. The bitmap field
4762306a36Sopenharmony_ci * allows us to store whether a particular seqno is valid (i.e. allows us
4862306a36Sopenharmony_ci * to distinguish unset from 0).
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci * A branch holds an array of layer pointers, and has height > 0, and always
5162306a36Sopenharmony_ci * has at least 2 layers (either branches or leaves) below it.
5262306a36Sopenharmony_ci *
5362306a36Sopenharmony_ci * For example,
5462306a36Sopenharmony_ci *	for x in
5562306a36Sopenharmony_ci *	  0 1 2 0x10 0x11 0x200 0x201
5662306a36Sopenharmony_ci *	  0x500000 0x500001 0x503000 0x503001
5762306a36Sopenharmony_ci *	  0xE<<60:
5862306a36Sopenharmony_ci *		i915_syncmap_set(&sync, x, lower_32_bits(x));
5962306a36Sopenharmony_ci * will build a tree like:
6062306a36Sopenharmony_ci *	0xXXXXXXXXXXXXXXXX
6162306a36Sopenharmony_ci *	0-> 0x0000000000XXXXXX
6262306a36Sopenharmony_ci *	|   0-> 0x0000000000000XXX
6362306a36Sopenharmony_ci *	|   |   0-> 0x00000000000000XX
6462306a36Sopenharmony_ci *	|   |   |   0-> 0x000000000000000X 0:0, 1:1, 2:2
6562306a36Sopenharmony_ci *	|   |   |   1-> 0x000000000000001X 0:10, 1:11
6662306a36Sopenharmony_ci *	|   |   2-> 0x000000000000020X 0:200, 1:201
6762306a36Sopenharmony_ci *	|   5-> 0x000000000050XXXX
6862306a36Sopenharmony_ci *	|       0-> 0x000000000050000X 0:500000, 1:500001
6962306a36Sopenharmony_ci *	|       3-> 0x000000000050300X 0:503000, 1:503001
7062306a36Sopenharmony_ci *	e-> 0xe00000000000000X e:e
7162306a36Sopenharmony_ci */
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistruct i915_syncmap {
7462306a36Sopenharmony_ci	u64 prefix;
7562306a36Sopenharmony_ci	unsigned int height;
7662306a36Sopenharmony_ci	unsigned int bitmap;
7762306a36Sopenharmony_ci	struct i915_syncmap *parent;
7862306a36Sopenharmony_ci	/*
7962306a36Sopenharmony_ci	 * Following this header is an array of either seqno or child pointers:
8062306a36Sopenharmony_ci	 * union {
8162306a36Sopenharmony_ci	 *	u32 seqno[KSYNCMAP];
8262306a36Sopenharmony_ci	 *	struct i915_syncmap *child[KSYNCMAP];
8362306a36Sopenharmony_ci	 * };
8462306a36Sopenharmony_ci	 */
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci/**
8862306a36Sopenharmony_ci * i915_syncmap_init -- initialise the #i915_syncmap
8962306a36Sopenharmony_ci * @root: pointer to the #i915_syncmap
9062306a36Sopenharmony_ci */
9162306a36Sopenharmony_civoid i915_syncmap_init(struct i915_syncmap **root)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	BUILD_BUG_ON_NOT_POWER_OF_2(KSYNCMAP);
9462306a36Sopenharmony_ci	BUILD_BUG_ON_NOT_POWER_OF_2(SHIFT);
9562306a36Sopenharmony_ci	BUILD_BUG_ON(KSYNCMAP > BITS_PER_TYPE((*root)->bitmap));
9662306a36Sopenharmony_ci	*root = NULL;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline u32 *__sync_seqno(struct i915_syncmap *p)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	GEM_BUG_ON(p->height);
10262306a36Sopenharmony_ci	return (u32 *)(p + 1);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic inline struct i915_syncmap **__sync_child(struct i915_syncmap *p)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	GEM_BUG_ON(!p->height);
10862306a36Sopenharmony_ci	return (struct i915_syncmap **)(p + 1);
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic inline unsigned int
11262306a36Sopenharmony_ci__sync_branch_idx(const struct i915_syncmap *p, u64 id)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	return (id >> p->height) & MASK;
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic inline unsigned int
11862306a36Sopenharmony_ci__sync_leaf_idx(const struct i915_syncmap *p, u64 id)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	GEM_BUG_ON(p->height);
12162306a36Sopenharmony_ci	return id & MASK;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic inline u64 __sync_branch_prefix(const struct i915_syncmap *p, u64 id)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	return id >> p->height >> SHIFT;
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic inline u64 __sync_leaf_prefix(const struct i915_syncmap *p, u64 id)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	GEM_BUG_ON(p->height);
13262306a36Sopenharmony_ci	return id >> SHIFT;
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic inline bool seqno_later(u32 a, u32 b)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	return (s32)(a - b) >= 0;
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci/**
14162306a36Sopenharmony_ci * i915_syncmap_is_later -- compare against the last know sync point
14262306a36Sopenharmony_ci * @root: pointer to the #i915_syncmap
14362306a36Sopenharmony_ci * @id: the context id (other timeline) we are synchronising to
14462306a36Sopenharmony_ci * @seqno: the sequence number along the other timeline
14562306a36Sopenharmony_ci *
14662306a36Sopenharmony_ci * If we have already synchronised this @root timeline with another (@id) then
14762306a36Sopenharmony_ci * we can omit any repeated or earlier synchronisation requests. If the two
14862306a36Sopenharmony_ci * timelines are already coupled, we can also omit the dependency between the
14962306a36Sopenharmony_ci * two as that is already known via the timeline.
15062306a36Sopenharmony_ci *
15162306a36Sopenharmony_ci * Returns true if the two timelines are already synchronised wrt to @seqno,
15262306a36Sopenharmony_ci * false if not and the synchronisation must be emitted.
15362306a36Sopenharmony_ci */
15462306a36Sopenharmony_cibool i915_syncmap_is_later(struct i915_syncmap **root, u64 id, u32 seqno)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	struct i915_syncmap *p;
15762306a36Sopenharmony_ci	unsigned int idx;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	p = *root;
16062306a36Sopenharmony_ci	if (!p)
16162306a36Sopenharmony_ci		return false;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	if (likely(__sync_leaf_prefix(p, id) == p->prefix))
16462306a36Sopenharmony_ci		goto found;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	/* First climb the tree back to a parent branch */
16762306a36Sopenharmony_ci	do {
16862306a36Sopenharmony_ci		p = p->parent;
16962306a36Sopenharmony_ci		if (!p)
17062306a36Sopenharmony_ci			return false;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci		if (__sync_branch_prefix(p, id) == p->prefix)
17362306a36Sopenharmony_ci			break;
17462306a36Sopenharmony_ci	} while (1);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	/* And then descend again until we find our leaf */
17762306a36Sopenharmony_ci	do {
17862306a36Sopenharmony_ci		if (!p->height)
17962306a36Sopenharmony_ci			break;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci		p = __sync_child(p)[__sync_branch_idx(p, id)];
18262306a36Sopenharmony_ci		if (!p)
18362306a36Sopenharmony_ci			return false;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci		if (__sync_branch_prefix(p, id) != p->prefix)
18662306a36Sopenharmony_ci			return false;
18762306a36Sopenharmony_ci	} while (1);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	*root = p;
19062306a36Sopenharmony_cifound:
19162306a36Sopenharmony_ci	idx = __sync_leaf_idx(p, id);
19262306a36Sopenharmony_ci	if (!(p->bitmap & BIT(idx)))
19362306a36Sopenharmony_ci		return false;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	return seqno_later(__sync_seqno(p)[idx], seqno);
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic struct i915_syncmap *
19962306a36Sopenharmony_ci__sync_alloc_leaf(struct i915_syncmap *parent, u64 id)
20062306a36Sopenharmony_ci{
20162306a36Sopenharmony_ci	struct i915_syncmap *p;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	p = kmalloc(sizeof(*p) + KSYNCMAP * sizeof(u32), GFP_KERNEL);
20462306a36Sopenharmony_ci	if (unlikely(!p))
20562306a36Sopenharmony_ci		return NULL;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	p->parent = parent;
20862306a36Sopenharmony_ci	p->height = 0;
20962306a36Sopenharmony_ci	p->bitmap = 0;
21062306a36Sopenharmony_ci	p->prefix = __sync_leaf_prefix(p, id);
21162306a36Sopenharmony_ci	return p;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistatic inline void __sync_set_seqno(struct i915_syncmap *p, u64 id, u32 seqno)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	unsigned int idx = __sync_leaf_idx(p, id);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	p->bitmap |= BIT(idx);
21962306a36Sopenharmony_ci	__sync_seqno(p)[idx] = seqno;
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic inline void __sync_set_child(struct i915_syncmap *p,
22362306a36Sopenharmony_ci				    unsigned int idx,
22462306a36Sopenharmony_ci				    struct i915_syncmap *child)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	p->bitmap |= BIT(idx);
22762306a36Sopenharmony_ci	__sync_child(p)[idx] = child;
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic noinline int __sync_set(struct i915_syncmap **root, u64 id, u32 seqno)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	struct i915_syncmap *p = *root;
23362306a36Sopenharmony_ci	unsigned int idx;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	if (!p) {
23662306a36Sopenharmony_ci		p = __sync_alloc_leaf(NULL, id);
23762306a36Sopenharmony_ci		if (unlikely(!p))
23862306a36Sopenharmony_ci			return -ENOMEM;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		goto found;
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	/* Caller handled the likely cached case */
24462306a36Sopenharmony_ci	GEM_BUG_ON(__sync_leaf_prefix(p, id) == p->prefix);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	/* Climb back up the tree until we find a common prefix */
24762306a36Sopenharmony_ci	do {
24862306a36Sopenharmony_ci		if (!p->parent)
24962306a36Sopenharmony_ci			break;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci		p = p->parent;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci		if (__sync_branch_prefix(p, id) == p->prefix)
25462306a36Sopenharmony_ci			break;
25562306a36Sopenharmony_ci	} while (1);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	/*
25862306a36Sopenharmony_ci	 * No shortcut, we have to descend the tree to find the right layer
25962306a36Sopenharmony_ci	 * containing this fence.
26062306a36Sopenharmony_ci	 *
26162306a36Sopenharmony_ci	 * Each layer in the tree holds 16 (KSYNCMAP) pointers, either fences
26262306a36Sopenharmony_ci	 * or lower layers. Leaf nodes (height = 0) contain the fences, all
26362306a36Sopenharmony_ci	 * other nodes (height > 0) are internal layers that point to a lower
26462306a36Sopenharmony_ci	 * node. Each internal layer has at least 2 descendents.
26562306a36Sopenharmony_ci	 *
26662306a36Sopenharmony_ci	 * Starting at the top, we check whether the current prefix matches. If
26762306a36Sopenharmony_ci	 * it doesn't, we have gone past our target and need to insert a join
26862306a36Sopenharmony_ci	 * into the tree, and a new leaf node for the target as a descendent
26962306a36Sopenharmony_ci	 * of the join, as well as the original layer.
27062306a36Sopenharmony_ci	 *
27162306a36Sopenharmony_ci	 * The matching prefix means we are still following the right branch
27262306a36Sopenharmony_ci	 * of the tree. If it has height 0, we have found our leaf and just
27362306a36Sopenharmony_ci	 * need to replace the fence slot with ourselves. If the height is
27462306a36Sopenharmony_ci	 * not zero, our slot contains the next layer in the tree (unless
27562306a36Sopenharmony_ci	 * it is empty, in which case we can add ourselves as a new leaf).
27662306a36Sopenharmony_ci	 * As descend the tree the prefix grows (and height decreases).
27762306a36Sopenharmony_ci	 */
27862306a36Sopenharmony_ci	do {
27962306a36Sopenharmony_ci		struct i915_syncmap *next;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci		if (__sync_branch_prefix(p, id) != p->prefix) {
28262306a36Sopenharmony_ci			unsigned int above;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci			/* Insert a join above the current layer */
28562306a36Sopenharmony_ci			next = kzalloc(sizeof(*next) + KSYNCMAP * sizeof(next),
28662306a36Sopenharmony_ci				       GFP_KERNEL);
28762306a36Sopenharmony_ci			if (unlikely(!next))
28862306a36Sopenharmony_ci				return -ENOMEM;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci			/* Compute the height at which these two diverge */
29162306a36Sopenharmony_ci			above = fls64(__sync_branch_prefix(p, id) ^ p->prefix);
29262306a36Sopenharmony_ci			above = round_up(above, SHIFT);
29362306a36Sopenharmony_ci			next->height = above + p->height;
29462306a36Sopenharmony_ci			next->prefix = __sync_branch_prefix(next, id);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci			/* Insert the join into the parent */
29762306a36Sopenharmony_ci			if (p->parent) {
29862306a36Sopenharmony_ci				idx = __sync_branch_idx(p->parent, id);
29962306a36Sopenharmony_ci				__sync_child(p->parent)[idx] = next;
30062306a36Sopenharmony_ci				GEM_BUG_ON(!(p->parent->bitmap & BIT(idx)));
30162306a36Sopenharmony_ci			}
30262306a36Sopenharmony_ci			next->parent = p->parent;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci			/* Compute the idx of the other branch, not our id! */
30562306a36Sopenharmony_ci			idx = p->prefix >> (above - SHIFT) & MASK;
30662306a36Sopenharmony_ci			__sync_set_child(next, idx, p);
30762306a36Sopenharmony_ci			p->parent = next;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci			/* Ascend to the join */
31062306a36Sopenharmony_ci			p = next;
31162306a36Sopenharmony_ci		} else {
31262306a36Sopenharmony_ci			if (!p->height)
31362306a36Sopenharmony_ci				break;
31462306a36Sopenharmony_ci		}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci		/* Descend into the next layer */
31762306a36Sopenharmony_ci		GEM_BUG_ON(!p->height);
31862306a36Sopenharmony_ci		idx = __sync_branch_idx(p, id);
31962306a36Sopenharmony_ci		next = __sync_child(p)[idx];
32062306a36Sopenharmony_ci		if (!next) {
32162306a36Sopenharmony_ci			next = __sync_alloc_leaf(p, id);
32262306a36Sopenharmony_ci			if (unlikely(!next))
32362306a36Sopenharmony_ci				return -ENOMEM;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci			__sync_set_child(p, idx, next);
32662306a36Sopenharmony_ci			p = next;
32762306a36Sopenharmony_ci			break;
32862306a36Sopenharmony_ci		}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci		p = next;
33162306a36Sopenharmony_ci	} while (1);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cifound:
33462306a36Sopenharmony_ci	GEM_BUG_ON(p->prefix != __sync_leaf_prefix(p, id));
33562306a36Sopenharmony_ci	__sync_set_seqno(p, id, seqno);
33662306a36Sopenharmony_ci	*root = p;
33762306a36Sopenharmony_ci	return 0;
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci/**
34162306a36Sopenharmony_ci * i915_syncmap_set -- mark the most recent syncpoint between contexts
34262306a36Sopenharmony_ci * @root: pointer to the #i915_syncmap
34362306a36Sopenharmony_ci * @id: the context id (other timeline) we have synchronised to
34462306a36Sopenharmony_ci * @seqno: the sequence number along the other timeline
34562306a36Sopenharmony_ci *
34662306a36Sopenharmony_ci * When we synchronise this @root timeline with another (@id), we also know
34762306a36Sopenharmony_ci * that we have synchronized with all previous seqno along that timeline. If
34862306a36Sopenharmony_ci * we then have a request to synchronise with the same seqno or older, we can
34962306a36Sopenharmony_ci * omit it, see i915_syncmap_is_later()
35062306a36Sopenharmony_ci *
35162306a36Sopenharmony_ci * Returns 0 on success, or a negative error code.
35262306a36Sopenharmony_ci */
35362306a36Sopenharmony_ciint i915_syncmap_set(struct i915_syncmap **root, u64 id, u32 seqno)
35462306a36Sopenharmony_ci{
35562306a36Sopenharmony_ci	struct i915_syncmap *p = *root;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	/*
35862306a36Sopenharmony_ci	 * We expect to be called in sequence following is_later(id), which
35962306a36Sopenharmony_ci	 * should have preloaded the root for us.
36062306a36Sopenharmony_ci	 */
36162306a36Sopenharmony_ci	if (likely(p && __sync_leaf_prefix(p, id) == p->prefix)) {
36262306a36Sopenharmony_ci		__sync_set_seqno(p, id, seqno);
36362306a36Sopenharmony_ci		return 0;
36462306a36Sopenharmony_ci	}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	return __sync_set(root, id, seqno);
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistatic void __sync_free(struct i915_syncmap *p)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	if (p->height) {
37262306a36Sopenharmony_ci		unsigned int i;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci		while ((i = ffs(p->bitmap))) {
37562306a36Sopenharmony_ci			p->bitmap &= ~0u << i;
37662306a36Sopenharmony_ci			__sync_free(__sync_child(p)[i - 1]);
37762306a36Sopenharmony_ci		}
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	kfree(p);
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/**
38462306a36Sopenharmony_ci * i915_syncmap_free -- free all memory associated with the syncmap
38562306a36Sopenharmony_ci * @root: pointer to the #i915_syncmap
38662306a36Sopenharmony_ci *
38762306a36Sopenharmony_ci * Either when the timeline is to be freed and we no longer need the sync
38862306a36Sopenharmony_ci * point tracking, or when the fences are all known to be signaled and the
38962306a36Sopenharmony_ci * sync point tracking is redundant, we can free the #i915_syncmap to recover
39062306a36Sopenharmony_ci * its allocations.
39162306a36Sopenharmony_ci *
39262306a36Sopenharmony_ci * Will reinitialise the @root pointer so that the #i915_syncmap is ready for
39362306a36Sopenharmony_ci * reuse.
39462306a36Sopenharmony_ci */
39562306a36Sopenharmony_civoid i915_syncmap_free(struct i915_syncmap **root)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	struct i915_syncmap *p;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	p = *root;
40062306a36Sopenharmony_ci	if (!p)
40162306a36Sopenharmony_ci		return;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	while (p->parent)
40462306a36Sopenharmony_ci		p = p->parent;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	__sync_free(p);
40762306a36Sopenharmony_ci	*root = NULL;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
41162306a36Sopenharmony_ci#include "selftests/i915_syncmap.c"
41262306a36Sopenharmony_ci#endif
413