drm/i915/guc: Unwind GuC workqueue reservation if request construction fails
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 7 Oct 2016 06:53:27 +0000 (07:53 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 7 Oct 2016 07:27:23 +0000 (08:27 +0100)
We reserve space in the GuC workqueue for submitting the request in the
future. However, if we fail to construct the request, we need to give
that reserved space back to the system.

Fixes: dadd481bfe55 ("drm/i915/guc: Prepare for nonblocking execbuf submission")
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97978
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Michał Winiarski <michal.winiarski@intel.com>
Reviewed-by: Michał Winiarski <michal.winiarski@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20161007065327.24515-4-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_guc_submission.c
drivers/gpu/drm/i915/intel_guc.h
drivers/gpu/drm/i915/intel_lrc.c

index 43358e18d34cb3f5f770bec71a95644dd225ff32..3106dcc06fe93d40361ce19428e5d40178c977fe 100644 (file)
@@ -451,6 +451,18 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request)
        return ret;
 }
 
+void i915_guc_wq_unreserve(struct drm_i915_gem_request *request)
+{
+       const size_t wqi_size = sizeof(struct guc_wq_item);
+       struct i915_guc_client *gc = request->i915->guc.execbuf_client;
+
+       GEM_BUG_ON(READ_ONCE(gc->wq_rsvd) < wqi_size);
+
+       spin_lock(&gc->wq_lock);
+       gc->wq_rsvd -= wqi_size;
+       spin_unlock(&gc->wq_lock);
+}
+
 /* Construct a Work Item and append it to the GuC's Work Queue */
 static void guc_wq_item_append(struct i915_guc_client *gc,
                               struct drm_i915_gem_request *rq)
index b1ba869588114fb58729c218b91322e5a07624ea..5cdf7aa75be501722e4716488f92305c41e0a0a2 100644 (file)
@@ -160,6 +160,7 @@ extern int intel_guc_resume(struct drm_device *dev);
 int i915_guc_submission_init(struct drm_i915_private *dev_priv);
 int i915_guc_submission_enable(struct drm_i915_private *dev_priv);
 int i915_guc_wq_reserve(struct drm_i915_gem_request *rq);
+void i915_guc_wq_unreserve(struct drm_i915_gem_request *request);
 void i915_guc_submission_disable(struct drm_i915_private *dev_priv);
 void i915_guc_submission_fini(struct drm_i915_private *dev_priv);
 
index 44904e298bfc8e5f76e11ccbe8bf702d980e8864..10fcea57e4dd227a506234f50c09c6325795fd0d 100644 (file)
@@ -626,6 +626,10 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
 
        request->ring = ce->ring;
 
+       ret = intel_lr_context_pin(request->ctx, engine);
+       if (ret)
+               return ret;
+
        if (i915.enable_guc_submission) {
                /*
                 * Check that the GuC has space for the request before
@@ -634,21 +638,17 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
                 */
                ret = i915_guc_wq_reserve(request);
                if (ret)
-                       return ret;
+                       goto err_unpin;
        }
 
-       ret = intel_lr_context_pin(request->ctx, engine);
-       if (ret)
-               return ret;
-
        ret = intel_ring_begin(request, 0);
        if (ret)
-               goto err_unpin;
+               goto err_unreserve;
 
        if (!ce->initialised) {
                ret = engine->init_context(request);
                if (ret)
-                       goto err_unpin;
+                       goto err_unreserve;
 
                ce->initialised = true;
        }
@@ -663,6 +663,9 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
        request->reserved_space -= EXECLISTS_REQUEST_SIZE;
        return 0;
 
+err_unreserve:
+       if (i915.enable_guc_submission)
+               i915_guc_wq_unreserve(request);
 err_unpin:
        intel_lr_context_unpin(request->ctx, engine);
        return ret;