summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_sw_fence.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_sw_fence.c')
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.c141
1 files changed, 134 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index 147420ccf49c..40f4e5efaf83 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -17,6 +17,93 @@
static DEFINE_SPINLOCK(i915_sw_fence_lock);
+enum {
+ DEBUG_FENCE_IDLE = 0,
+ DEBUG_FENCE_NOTIFY,
+};
+
+#ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
+
+static void *i915_sw_fence_debug_hint(void *addr)
+{
+ return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK);
+}
+
+static struct debug_obj_descr i915_sw_fence_debug_descr = {
+ .name = "i915_sw_fence",
+ .debug_hint = i915_sw_fence_debug_hint,
+};
+
+static inline void debug_fence_init(struct i915_sw_fence *fence)
+{
+ debug_object_init(fence, &i915_sw_fence_debug_descr);
+}
+
+static inline void debug_fence_activate(struct i915_sw_fence *fence)
+{
+ debug_object_activate(fence, &i915_sw_fence_debug_descr);
+}
+
+static inline void debug_fence_set_state(struct i915_sw_fence *fence,
+ int old, int new)
+{
+ debug_object_active_state(fence, &i915_sw_fence_debug_descr, old, new);
+}
+
+static inline void debug_fence_deactivate(struct i915_sw_fence *fence)
+{
+ debug_object_deactivate(fence, &i915_sw_fence_debug_descr);
+}
+
+static inline void debug_fence_destroy(struct i915_sw_fence *fence)
+{
+ debug_object_destroy(fence, &i915_sw_fence_debug_descr);
+}
+
+static inline void debug_fence_free(struct i915_sw_fence *fence)
+{
+ debug_object_free(fence, &i915_sw_fence_debug_descr);
+ smp_wmb(); /* flush the change in state before reallocation */
+}
+
+static inline void debug_fence_assert(struct i915_sw_fence *fence)
+{
+ debug_object_assert_init(fence, &i915_sw_fence_debug_descr);
+}
+
+#else
+
+static inline void debug_fence_init(struct i915_sw_fence *fence)
+{
+}
+
+static inline void debug_fence_activate(struct i915_sw_fence *fence)
+{
+}
+
+static inline void debug_fence_set_state(struct i915_sw_fence *fence,
+ int old, int new)
+{
+}
+
+static inline void debug_fence_deactivate(struct i915_sw_fence *fence)
+{
+}
+
+static inline void debug_fence_destroy(struct i915_sw_fence *fence)
+{
+}
+
+static inline void debug_fence_free(struct i915_sw_fence *fence)
+{
+}
+
+static inline void debug_fence_assert(struct i915_sw_fence *fence)
+{
+}
+
+#endif
+
static int __i915_sw_fence_notify(struct i915_sw_fence *fence,
enum i915_sw_fence_notify state)
{
@@ -26,25 +113,37 @@ static int __i915_sw_fence_notify(struct i915_sw_fence *fence,
return fn(fence, state);
}
-static void i915_sw_fence_free(struct kref *kref)
+#ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
+void i915_sw_fence_fini(struct i915_sw_fence *fence)
+{
+ debug_fence_free(fence);
+}
+#endif
+
+static void i915_sw_fence_release(struct kref *kref)
{
struct i915_sw_fence *fence = container_of(kref, typeof(*fence), kref);
WARN_ON(atomic_read(&fence->pending) > 0);
+ debug_fence_destroy(fence);
- if (fence->flags & I915_SW_FENCE_MASK)
+ if (fence->flags & I915_SW_FENCE_MASK) {
__i915_sw_fence_notify(fence, FENCE_FREE);
- else
+ } else {
+ i915_sw_fence_fini(fence);
kfree(fence);
+ }
}
static void i915_sw_fence_put(struct i915_sw_fence *fence)
{
- kref_put(&fence->kref, i915_sw_fence_free);
+ debug_fence_assert(fence);
+ kref_put(&fence->kref, i915_sw_fence_release);
}
static struct i915_sw_fence *i915_sw_fence_get(struct i915_sw_fence *fence)
{
+ debug_fence_assert(fence);
kref_get(&fence->kref);
return fence;
}
@@ -56,6 +155,7 @@ static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
wait_queue_t *pos, *next;
unsigned long flags;
+ debug_fence_deactivate(fence);
atomic_set_release(&fence->pending, -1); /* 0 -> -1 [done] */
/*
@@ -88,23 +188,33 @@ static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
} while (1);
}
spin_unlock_irqrestore(&x->lock, flags);
+
+ debug_fence_assert(fence);
}
static void __i915_sw_fence_complete(struct i915_sw_fence *fence,
struct list_head *continuation)
{
+ debug_fence_assert(fence);
+
if (!atomic_dec_and_test(&fence->pending))
return;
+ debug_fence_set_state(fence, DEBUG_FENCE_IDLE, DEBUG_FENCE_NOTIFY);
+
if (fence->flags & I915_SW_FENCE_MASK &&
__i915_sw_fence_notify(fence, FENCE_COMPLETE) != NOTIFY_DONE)
return;
+ debug_fence_set_state(fence, DEBUG_FENCE_NOTIFY, DEBUG_FENCE_IDLE);
+
__i915_sw_fence_wake_up_all(fence, continuation);
}
static void i915_sw_fence_complete(struct i915_sw_fence *fence)
{
+ debug_fence_assert(fence);
+
if (WARN_ON(i915_sw_fence_done(fence)))
return;
@@ -113,6 +223,7 @@ static void i915_sw_fence_complete(struct i915_sw_fence *fence)
static void i915_sw_fence_await(struct i915_sw_fence *fence)
{
+ debug_fence_assert(fence);
WARN_ON(atomic_inc_return(&fence->pending) <= 1);
}
@@ -123,18 +234,26 @@ void __i915_sw_fence_init(struct i915_sw_fence *fence,
{
BUG_ON((unsigned long)fn & ~I915_SW_FENCE_MASK);
+ debug_fence_init(fence);
+
__init_waitqueue_head(&fence->wait, name, key);
kref_init(&fence->kref);
atomic_set(&fence->pending, 1);
fence->flags = (unsigned long)fn;
}
-void i915_sw_fence_commit(struct i915_sw_fence *fence)
+static void __i915_sw_fence_commit(struct i915_sw_fence *fence)
{
i915_sw_fence_complete(fence);
i915_sw_fence_put(fence);
}
+void i915_sw_fence_commit(struct i915_sw_fence *fence)
+{
+ debug_fence_activate(fence);
+ __i915_sw_fence_commit(fence);
+}
+
static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int flags, void *key)
{
list_del(&wq->task_list);
@@ -206,9 +325,13 @@ static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
unsigned long flags;
int pending;
+ debug_fence_assert(fence);
+
if (i915_sw_fence_done(signaler))
return 0;
+ debug_fence_assert(signaler);
+
/* The dependency graph must be acyclic. */
if (unlikely(i915_sw_fence_check_if_after(fence, signaler)))
return -EINVAL;
@@ -279,7 +402,7 @@ static void timer_i915_sw_fence_wake(unsigned long data)
dma_fence_put(cb->dma);
cb->dma = NULL;
- i915_sw_fence_commit(cb->fence);
+ __i915_sw_fence_commit(cb->fence);
cb->timer.function = NULL;
}
@@ -290,7 +413,7 @@ static void dma_i915_sw_fence_wake(struct dma_fence *dma,
del_timer_sync(&cb->timer);
if (cb->timer.function)
- i915_sw_fence_commit(cb->fence);
+ __i915_sw_fence_commit(cb->fence);
dma_fence_put(cb->dma);
kfree(cb);
@@ -304,6 +427,8 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
struct i915_sw_dma_fence_cb *cb;
int ret;
+ debug_fence_assert(fence);
+
if (dma_fence_is_signaled(dma))
return 0;
@@ -349,6 +474,8 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
struct dma_fence *excl;
int ret = 0, pending;
+ debug_fence_assert(fence);
+
if (write) {
struct dma_fence **shared;
unsigned int count, i;