Skip to content

Commit 096a42d

Browse files
committed
drm/i915/gem: Move obj->lut_list under its own lock
The obj->lut_list is traversed when the object is closed as the file table is destroyed during process termination. As this occurs before we kill any outstanding context if, due to some bug or another, the closure is blocked, then we fail to shootdown any inflight operations potentially leaving the GPU spinning forever. As we only need to guard the list against concurrent closures and insertions, the hold is short and merits being treated as a simple spinlock. Signed-off-by: Chris Wilson <[email protected]> Reviewed-by: Michael J. Ruhl <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 0ba7ffe commit 096a42d

File tree

4 files changed

+20
-12
lines changed

4 files changed

+20
-12
lines changed

drivers/gpu/drm/i915/gem/i915_gem_context.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ static void lut_close(struct i915_gem_context *ctx)
112112
if (!kref_get_unless_zero(&obj->base.refcount))
113113
continue;
114114

115-
rcu_read_unlock();
116-
i915_gem_object_lock(obj);
115+
spin_lock(&obj->lut_lock);
117116
list_for_each_entry(lut, &obj->lut_list, obj_link) {
118117
if (lut->ctx != ctx)
119118
continue;
@@ -124,8 +123,7 @@ static void lut_close(struct i915_gem_context *ctx)
124123
list_del(&lut->obj_link);
125124
break;
126125
}
127-
i915_gem_object_unlock(obj);
128-
rcu_read_lock();
126+
spin_unlock(&obj->lut_lock);
129127

130128
if (&lut->obj_link != &obj->lut_list) {
131129
i915_lut_handle_free(lut);

drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,14 +789,14 @@ static int __eb_add_lut(struct i915_execbuffer *eb,
789789
if (err == 0) { /* And nor has this handle */
790790
struct drm_i915_gem_object *obj = vma->obj;
791791

792-
i915_gem_object_lock(obj);
792+
spin_lock(&obj->lut_lock);
793793
if (idr_find(&eb->file->object_idr, handle) == obj) {
794794
list_add(&lut->obj_link, &obj->lut_list);
795795
} else {
796796
radix_tree_delete(&ctx->handles_vma, handle);
797797
err = -ENOENT;
798798
}
799-
i915_gem_object_unlock(obj);
799+
spin_unlock(&obj->lut_lock);
800800
}
801801
mutex_unlock(&ctx->mutex);
802802
}

drivers/gpu/drm/i915/gem/i915_gem_object.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
6161
INIT_LIST_HEAD(&obj->mm.link);
6262

6363
INIT_LIST_HEAD(&obj->lut_list);
64+
spin_lock_init(&obj->lut_lock);
6465

6566
spin_lock_init(&obj->mmo.lock);
6667
obj->mmo.offsets = RB_ROOT;
@@ -104,21 +105,29 @@ void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file)
104105
{
105106
struct drm_i915_gem_object *obj = to_intel_bo(gem);
106107
struct drm_i915_file_private *fpriv = file->driver_priv;
108+
struct i915_lut_handle bookmark = {};
107109
struct i915_mmap_offset *mmo, *mn;
108110
struct i915_lut_handle *lut, *ln;
109111
LIST_HEAD(close);
110112

111-
i915_gem_object_lock(obj);
113+
spin_lock(&obj->lut_lock);
112114
list_for_each_entry_safe(lut, ln, &obj->lut_list, obj_link) {
113115
struct i915_gem_context *ctx = lut->ctx;
114116

115-
if (ctx->file_priv != fpriv)
116-
continue;
117+
if (ctx && ctx->file_priv == fpriv) {
118+
i915_gem_context_get(ctx);
119+
list_move(&lut->obj_link, &close);
120+
}
117121

118-
i915_gem_context_get(ctx);
119-
list_move(&lut->obj_link, &close);
122+
/* Break long locks, and carefully continue on from this spot */
123+
if (&ln->obj_link != &obj->lut_list) {
124+
list_add_tail(&bookmark.obj_link, &ln->obj_link);
125+
if (cond_resched_lock(&obj->lut_lock))
126+
list_safe_reset_next(&bookmark, ln, obj_link);
127+
__list_del_entry(&bookmark.obj_link);
128+
}
120129
}
121-
i915_gem_object_unlock(obj);
130+
spin_unlock(&obj->lut_lock);
122131

123132
spin_lock(&obj->mmo.lock);
124133
rbtree_postorder_for_each_entry_safe(mmo, mn, &obj->mmo.offsets, offset)

drivers/gpu/drm/i915/gem/i915_gem_object_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ struct drm_i915_gem_object {
121121
* this translation from object to context->handles_vma.
122122
*/
123123
struct list_head lut_list;
124+
spinlock_t lut_lock; /* guards lut_list */
124125

125126
/** Stolen memory for this object, instead of being backed by shmem. */
126127
struct drm_mm_node *stolen;

0 commit comments

Comments
 (0)