Skip to content

Commit 9c30343

Browse files
minipli-osstursulin
authored andcommitted
drm/i915: Clarify type evolution of uabi_node/uabi_engines
Chaining user engines happens in multiple passes during driver initialization, mutating its type along the way. It starts off with a simple lock-less linked list (struct llist_node/head) populated by intel_engine_add_user() which later gets sorted and converted to an intermediate regular list (struct list_head) just to be converted once more to its final rb-tree structure (struct rb_node/root) in intel_engines_driver_register(). All of these types overlay the uabi_node/uabi_engines members which is unfortunate but safe if one takes care about using the rb-tree based structure only after the conversion has completed. However, mistakes happen and commit 1ec23ed ("drm/i915: Use uabi engines for the default engine map") violated that assumption, as the multiple type evolution was all to easy hidden behind casts papering over it. Make the type evolution of uabi_node/uabi_engines more visible by putting all members into an anonymous union and use the correctly typed member in its various users. This allows us to drop quite some ugly casts and, hopefully, make the evolution of the members better recognisable to avoid future mistakes. Signed-off-by: Mathias Krause <[email protected]> Reviewed-by: Tvrtko Ursulin <[email protected]> Signed-off-by: Tvrtko Ursulin <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 2b562f0 commit 9c30343

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

drivers/gpu/drm/i915/gt/intel_engine_types.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,15 @@ struct intel_engine_cs {
402402

403403
unsigned long context_tag;
404404

405-
struct rb_node uabi_node;
405+
/*
406+
* The type evolves during initialization, see related comment for
407+
* struct drm_i915_private's uabi_engines member.
408+
*/
409+
union {
410+
struct llist_node uabi_llist;
411+
struct list_head uabi_list;
412+
struct rb_node uabi_node;
413+
};
406414

407415
struct intel_sseu sseu;
408416

drivers/gpu/drm/i915/gt/intel_engine_user.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
3838

3939
void intel_engine_add_user(struct intel_engine_cs *engine)
4040
{
41-
llist_add((struct llist_node *)&engine->uabi_node,
42-
(struct llist_head *)&engine->i915->uabi_engines);
41+
llist_add(&engine->uabi_llist, &engine->i915->uabi_engines_llist);
4342
}
4443

4544
static const u8 uabi_classes[] = {
@@ -54,9 +53,9 @@ static int engine_cmp(void *priv, const struct list_head *A,
5453
const struct list_head *B)
5554
{
5655
const struct intel_engine_cs *a =
57-
container_of((struct rb_node *)A, typeof(*a), uabi_node);
56+
container_of(A, typeof(*a), uabi_list);
5857
const struct intel_engine_cs *b =
59-
container_of((struct rb_node *)B, typeof(*b), uabi_node);
58+
container_of(B, typeof(*b), uabi_list);
6059

6160
if (uabi_classes[a->class] < uabi_classes[b->class])
6261
return -1;
@@ -73,7 +72,7 @@ static int engine_cmp(void *priv, const struct list_head *A,
7372

7473
static struct llist_node *get_engines(struct drm_i915_private *i915)
7574
{
76-
return llist_del_all((struct llist_head *)&i915->uabi_engines);
75+
return llist_del_all(&i915->uabi_engines_llist);
7776
}
7877

7978
static void sort_engines(struct drm_i915_private *i915,
@@ -83,9 +82,8 @@ static void sort_engines(struct drm_i915_private *i915,
8382

8483
llist_for_each_safe(pos, next, get_engines(i915)) {
8584
struct intel_engine_cs *engine =
86-
container_of((struct rb_node *)pos, typeof(*engine),
87-
uabi_node);
88-
list_add((struct list_head *)&engine->uabi_node, engines);
85+
container_of(pos, typeof(*engine), uabi_llist);
86+
list_add(&engine->uabi_list, engines);
8987
}
9088
list_sort(NULL, engines, engine_cmp);
9189
}
@@ -213,8 +211,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915)
213211
p = &i915->uabi_engines.rb_node;
214212
list_for_each_safe(it, next, &engines) {
215213
struct intel_engine_cs *engine =
216-
container_of((struct rb_node *)it, typeof(*engine),
217-
uabi_node);
214+
container_of(it, typeof(*engine), uabi_list);
218215

219216
if (intel_gt_has_unrecoverable_error(engine->gt))
220217
continue; /* ignore incomplete engines */

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,22 @@ struct drm_i915_private {
222222
bool mchbar_need_disable;
223223
} gmch;
224224

225-
struct rb_root uabi_engines;
225+
/*
226+
* Chaining user engines happens in multiple stages, starting with a
227+
* simple lock-less linked list created by intel_engine_add_user(),
228+
* which later gets sorted and converted to an intermediate regular
229+
* list, just to be converted once again to its final rb tree structure
230+
* in intel_engines_driver_register().
231+
*
232+
* Make sure to use the right iterator helper, depending on if the code
233+
* in question runs before or after intel_engines_driver_register() --
234+
* for_each_uabi_engine() can only be used afterwards!
235+
*/
236+
union {
237+
struct llist_head uabi_engines_llist;
238+
struct list_head uabi_engines_list;
239+
struct rb_root uabi_engines;
240+
};
226241
unsigned int engine_uabi_class_count[I915_LAST_UABI_ENGINE_CLASS + 1];
227242

228243
/* protects the irq masks */

0 commit comments

Comments
 (0)