if (IS_ERR(rq))
return rq;
- err = i915_active_ref(&overlay->last_flip, rq->fence.context, rq);
+ err = i915_active_ref(&overlay->last_flip, rq->timeline, rq);
if (err) {
i915_request_add(rq);
return ERR_PTR(err);
* keep track of the GPU activity within this vma/request, and
* propagate the signal from the request to w->dma.
*/
- err = i915_active_ref(&vma->active, rq->fence.context, rq);
+ err = i915_active_ref(&vma->active, rq->timeline, rq);
if (err)
goto out_request;
if (emit)
err = emit(rq, data);
if (err == 0)
- err = i915_active_ref(&cb->base, rq->fence.context, rq);
+ err = i915_active_ref(&cb->base, rq->timeline, rq);
i915_request_add(rq);
if (err)
/* Queue this switch after current activity by this context. */
err = i915_active_request_set(&tl->last_request, rq);
+ mutex_unlock(&tl->mutex);
if (err)
- goto unlock;
+ return err;
}
- lockdep_assert_held(&tl->mutex);
/*
* Guarantee context image and the timeline remains pinned until the
* words transfer the pinned ce object to tracked active request.
*/
GEM_BUG_ON(i915_active_is_idle(&ce->active));
- err = i915_active_ref(&ce->active, rq->fence.context, rq);
-
-unlock:
- if (rq->timeline != tl)
- mutex_unlock(&tl->mutex);
- return err;
+ return i915_active_ref(&ce->active, rq->timeline, rq);
}
struct i915_request *intel_context_create_request(struct intel_context *ce)
intel_engine_pool_mark_active(struct intel_engine_pool_node *node,
struct i915_request *rq)
{
- return i915_active_ref(&node->active, rq->fence.context, rq);
+ return i915_active_ref(&node->active, rq->timeline, rq);
}
static inline void
mutex_init(&timeline->mutex);
- INIT_ACTIVE_REQUEST(&timeline->last_request);
+ INIT_ACTIVE_REQUEST(&timeline->last_request, &timeline->mutex);
INIT_LIST_HEAD(&timeline->requests);
i915_syncmap_init(&timeline->sync);
* free it after the current request is retired, which ensures that
* all writes into the cacheline from previous requests are complete.
*/
- err = i915_active_ref(&tl->hwsp_cacheline->active,
- tl->fence_context, rq);
+ err = i915_active_ref(&tl->hwsp_cacheline->active, tl, rq);
if (err)
goto err_cacheline;
static int cacheline_ref(struct intel_timeline_cacheline *cl,
struct i915_request *rq)
{
- return i915_active_ref(&cl->active, rq->fence.context, rq);
+ return i915_active_ref(&cl->active, rq->timeline, rq);
}
int intel_timeline_read_hwsp(struct i915_request *from,
tl->seqno = -4u;
+ mutex_lock_nested(&tl->mutex, SINGLE_DEPTH_NESTING);
err = intel_timeline_get_seqno(tl, rq, &seqno[0]);
+ mutex_unlock(&tl->mutex);
if (err) {
i915_request_add(rq);
goto out;
}
hwsp_seqno[0] = tl->hwsp_seqno;
+ mutex_lock_nested(&tl->mutex, SINGLE_DEPTH_NESTING);
err = intel_timeline_get_seqno(tl, rq, &seqno[1]);
+ mutex_unlock(&tl->mutex);
if (err) {
i915_request_add(rq);
goto out;
mutex_init(&timeline->mutex);
- INIT_ACTIVE_REQUEST(&timeline->last_request);
+ INIT_ACTIVE_REQUEST(&timeline->last_request, &timeline->mutex);
INIT_LIST_HEAD(&timeline->requests);
i915_syncmap_init(&timeline->sync);
}
static struct i915_active_request *
-active_instance(struct i915_active *ref, u64 idx)
+active_instance(struct i915_active *ref, struct intel_timeline *tl)
{
struct active_node *node, *prealloc;
struct rb_node **p, *parent;
+ u64 idx = tl->fence_context;
/*
* We track the most recently used timeline to skip a rbtree search
}
node = prealloc;
- i915_active_request_init(&node->base, NULL, node_retire);
+ i915_active_request_init(&node->base, &tl->mutex, NULL, node_retire);
node->ref = ref;
node->timeline = idx;
}
int i915_active_ref(struct i915_active *ref,
- u64 timeline,
+ struct intel_timeline *tl,
struct i915_request *rq)
{
struct i915_active_request *active;
int err;
+ lockdep_assert_held(&tl->mutex);
+
/* Prevent reaping in case we malloc/wait while building the tree */
err = i915_active_acquire(ref);
if (err)
return err;
- active = active_instance(ref, timeline);
+ active = active_instance(ref, tl);
if (!active) {
err = -ENOMEM;
goto out;
goto unwind;
}
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+ node->base.lock =
+ &engine->kernel_context->timeline->mutex;
+#endif
RCU_INIT_POINTER(node->base.request, NULL);
node->base.retire = node_retire;
node->timeline = idx;
{
int err;
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+ lockdep_assert_held(active->lock);
+#endif
+
/* Must maintain ordering wrt previous active requests */
err = i915_request_await_active_request(rq, active);
if (err)
*/
static inline void
i915_active_request_init(struct i915_active_request *active,
+ struct mutex *lock,
struct i915_request *rq,
i915_active_retire_fn retire)
{
RCU_INIT_POINTER(active->request, rq);
INIT_LIST_HEAD(&active->link);
active->retire = retire ?: i915_active_retire_noop;
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+ active->lock = lock;
+#endif
}
-#define INIT_ACTIVE_REQUEST(name) i915_active_request_init((name), NULL, NULL)
+#define INIT_ACTIVE_REQUEST(name, lock) \
+ i915_active_request_init((name), (lock), NULL, NULL)
/**
* i915_active_request_set - updates the tracker to watch the current request
__i915_active_request_set(struct i915_active_request *active,
struct i915_request *request)
{
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+ lockdep_assert_held(active->lock);
+#endif
list_move(&active->link, &request->active_list);
rcu_assign_pointer(active->request, request);
}
} while (0)
int i915_active_ref(struct i915_active *ref,
- u64 timeline,
+ struct intel_timeline *tl,
struct i915_request *rq);
int i915_active_wait(struct i915_active *ref);
struct i915_request __rcu *request;
struct list_head link;
i915_active_retire_fn retire;
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
+ /*
+ * Incorporeal!
+ *
+ * Updates to the i915_active_request must be serialised under a lock
+ * to ensure that the timeline is ordered. Normally, this is the
+ * timeline->mutex, but another mutex may be used so long as it is
+ * done so consistently.
+ *
+ * For lockdep tracking of the above, we store the lock we intend
+ * to always use for updates of this i915_active_request during
+ * construction and assert that is held on every update.
+ */
+ struct mutex *lock;
+#endif
};
struct active_node;
* add the active reference first and queue for it to be dropped
* *last*.
*/
- err = i915_active_ref(&vma->active, rq->fence.context, rq);
+ err = i915_active_ref(&vma->active, rq->timeline, rq);
if (unlikely(err))
return err;
if (flags & EXEC_OBJECT_WRITE) {
if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS))
i915_active_ref(&obj->frontbuffer->write,
- rq->fence.context,
+ rq->timeline,
rq);
reservation_object_add_excl_fence(vma->resv, &rq->fence);
submit,
GFP_KERNEL);
if (err >= 0)
- err = i915_active_ref(&active->base,
- rq->fence.context, rq);
+ err = i915_active_ref(&active->base, rq->timeline, rq);
i915_request_add(rq);
if (err) {
pr_err("Failed to track active ref!\n");