Following the use of dma_fence_signal() from within our interrupt
handler, we need to make guc->wq_lock also irq-safe. This was done
previously as part of the guc scheduler patch (which also started
mixing our fences with the interrupt handler), but is now required to
fix the current guc submission backend.

v3: Use cmpxchg for the solitary adjustments of guc->wq_rsvd

Fixes: 67b807a89230 ("drm/i915: Delay disabling the user interrupt for 
breadcrumbs")
Signed-off-by: Chris Wilson <[email protected]>
Cc: Tvrtko Ursulin <[email protected]>
Cc: Mika Kuoppala <[email protected]>
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index beec88a30347..4a5cee16f901 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -348,7 +348,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request 
*request)
        u32 freespace;
        int ret;
 
-       spin_lock(&client->wq_lock);
+       spin_lock_irq(&client->wq_lock);
        freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size);
        freespace -= client->wq_rsvd;
        if (likely(freespace >= wqi_size)) {
@@ -358,21 +358,28 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request 
*request)
                client->no_wq_space++;
                ret = -EAGAIN;
        }
-       spin_unlock(&client->wq_lock);
+       spin_unlock_irq(&client->wq_lock);
 
        return ret;
 }
 
+static void guc_wq_add_reserved(struct i915_guc_client *client, int delta)
+{
+       unsigned int old, new;
+
+       do {
+               old = client->wq_rsvd;
+               new = old + delta;
+       } while (cmpxchg(&client->wq_rsvd, old, new) != old);
+}
+
 void i915_guc_wq_unreserve(struct drm_i915_gem_request *request)
 {
-       const size_t wqi_size = sizeof(struct guc_wq_item);
+       const int wqi_size = sizeof(struct guc_wq_item);
        struct i915_guc_client *client = request->i915->guc.execbuf_client;
 
        GEM_BUG_ON(READ_ONCE(client->wq_rsvd) < wqi_size);
-
-       spin_lock(&client->wq_lock);
-       client->wq_rsvd -= wqi_size;
-       spin_unlock(&client->wq_lock);
+       guc_wq_add_reserved(client, -wqi_size);
 }
 
 /* Construct a Work Item and append it to the GuC's Work Queue */
@@ -951,10 +958,12 @@ int i915_guc_submission_enable(struct drm_i915_private 
*dev_priv)
                engine->schedule = NULL;
 
                /* Replay the current set of previously submitted requests */
+               spin_lock_irq(&engine->timeline->lock);
                list_for_each_entry(rq, &engine->timeline->requests, link) {
-                       client->wq_rsvd += sizeof(struct guc_wq_item);
+                       guc_wq_add_reserved(client, sizeof(struct guc_wq_item));
                        __i915_guc_submit(rq);
                }
+               spin_unlock_irq(&engine->timeline->lock);
        }
 
        return 0;
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to