During request construction, we take the timeline->mutex to ensure
exclusive access to the ringbuffer (for command emission) and the
timeline itself (for command ordering). The timeline->mutex should not
be dropped by callers until we release it in i915_request_add().
lockdep provides a pin/unpin lock facility to detect accidental unlocks
inside critical sections, so put it to use for request construction.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190403082132.327-1-chris@chris-wilson.co.uk
        rq->infix = rq->ring->emit; /* end of header; start of user payload */
 
        /* Check that we didn't interrupt ourselves with a new request */
+       lockdep_assert_held(&rq->timeline->mutex);
        GEM_BUG_ON(rq->timeline->seqno != rq->fence.seqno);
+       rq->cookie = lockdep_pin_lock(&rq->timeline->mutex);
+
        return rq;
 
 err_unwind:
                  engine->name, request->fence.context, request->fence.seqno);
 
        lockdep_assert_held(&request->timeline->mutex);
+       lockdep_unpin_lock(&request->timeline->mutex, request->cookie);
+
        trace_i915_request_add(request);
 
        /*
 
 #define I915_REQUEST_H
 
 #include <linux/dma-fence.h>
+#include <linux/lockdep.h>
 
 #include "i915_gem.h"
 #include "i915_scheduler.h"
         */
        unsigned long rcustate;
 
+       /*
+        * We pin the timeline->mutex while constructing the request to
+        * ensure that no caller accidentally drops it during construction.
+        * The timeline->mutex must be held to ensure that only this caller
+        * can use the ring and manipulate the associated timeline during
+        * construction.
+        */
+       struct pin_cookie cookie;
+
        /*
         * Fences for the various phases in the request's lifetime.
         *