[PATCH 6/7] drm/i915: Account ring buffer and context state storage

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Wed Jul 5 14:06:11 UTC 2023


From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>

Account ring buffers and logical context space against the owning client
memory usage stats.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_context.c       | 10 ++++++----
 drivers/gpu/drm/i915/gem/i915_gem_context_types.h | 10 ++++------
 drivers/gpu/drm/i915/gem/selftests/mock_context.c |  2 +-
 drivers/gpu/drm/i915/gt/intel_context.c           |  8 ++++++++
 drivers/gpu/drm/i915/i915_drm_client.c            | 10 ++++++++++
 drivers/gpu/drm/i915/i915_drm_client.h            |  8 ++++++++
 6 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 35cf6608180e..29e0fe7db9ac 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -1268,7 +1268,7 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
 static void i915_gem_context_release_work(struct work_struct *work)
 {
 	struct i915_gem_context *ctx = container_of(work, typeof(*ctx),
-						    release_work);
+						    release_work.work);
 	struct i915_address_space *vm;
 
 	trace_i915_context_free(ctx);
@@ -1288,8 +1288,10 @@ static void i915_gem_context_release_work(struct work_struct *work)
 	if (ctx->pxp_wakeref)
 		intel_runtime_pm_put(&ctx->i915->runtime_pm, ctx->pxp_wakeref);
 
-	if (ctx->client)
+	if (ctx->client) {
 		i915_drm_client_put(ctx->client);
+		ctx->client = NULL;
+	}
 
 	mutex_destroy(&ctx->engines_mutex);
 	mutex_destroy(&ctx->lut_mutex);
@@ -1304,7 +1306,7 @@ void i915_gem_context_release(struct kref *ref)
 {
 	struct i915_gem_context *ctx = container_of(ref, typeof(*ctx), ref);
 
-	queue_work(ctx->i915->wq, &ctx->release_work);
+	queue_rcu_work(ctx->i915->wq, &ctx->release_work);
 }
 
 static inline struct i915_gem_engines *
@@ -1606,7 +1608,7 @@ i915_gem_create_context(struct drm_i915_private *i915,
 	ctx->sched = pc->sched;
 	mutex_init(&ctx->mutex);
 	INIT_LIST_HEAD(&ctx->link);
-	INIT_WORK(&ctx->release_work, i915_gem_context_release_work);
+	INIT_RCU_WORK(&ctx->release_work, i915_gem_context_release_work);
 
 	spin_lock_init(&ctx->stale.lock);
 	INIT_LIST_HEAD(&ctx->stale.engines);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
index c573c067779f..7647de940434 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
@@ -317,13 +317,11 @@ struct i915_gem_context {
 	 * @release_work:
 	 *
 	 * Work item for deferred cleanup, since i915_gem_context_put() tends to
-	 * be called from hardirq context.
-	 *
-	 * FIXME: The only real reason for this is &i915_gem_engines.fence, all
-	 * other callers are from process context and need at most some mild
-	 * shuffling to pull the i915_gem_context_put() call out of a spinlock.
+	 * be called from hardirq context and also so
+	 * i915_drm_client_add_context() can be called from
+	 * intel_context_alloc_state() and safely dereference ctx->client.
 	 */
-	struct work_struct release_work;
+	struct rcu_work release_work;
 
 	/**
 	 * @rcu: rcu_head for deferred freeing.
diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.c b/drivers/gpu/drm/i915/gem/selftests/mock_context.c
index 125584ada282..beb0cc4fce70 100644
--- a/drivers/gpu/drm/i915/gem/selftests/mock_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.c
@@ -24,7 +24,7 @@ mock_context(struct drm_i915_private *i915,
 	kref_init(&ctx->ref);
 	INIT_LIST_HEAD(&ctx->link);
 	ctx->i915 = i915;
-	INIT_WORK(&ctx->release_work, i915_gem_context_release_work);
+	INIT_RCU_WORK(&ctx->release_work, i915_gem_context_release_work);
 
 	mutex_init(&ctx->mutex);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c
index a53b26178f0a..e0229373d9d2 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.c
+++ b/drivers/gpu/drm/i915/gt/intel_context.c
@@ -6,6 +6,7 @@
 #include "gem/i915_gem_context.h"
 #include "gem/i915_gem_pm.h"
 
+#include "i915_drm_client.h"
 #include "i915_drv.h"
 #include "i915_trace.h"
 
@@ -50,6 +51,7 @@ intel_context_create(struct intel_engine_cs *engine)
 
 int intel_context_alloc_state(struct intel_context *ce)
 {
+	struct i915_gem_context *ctx;
 	int err = 0;
 
 	if (mutex_lock_interruptible(&ce->pin_mutex))
@@ -66,6 +68,12 @@ int intel_context_alloc_state(struct intel_context *ce)
 			goto unlock;
 
 		set_bit(CONTEXT_ALLOC_BIT, &ce->flags);
+
+		rcu_read_lock();
+		ctx = rcu_dereference(ce->gem_context);
+		if (ctx && !i915_gem_context_is_closed(ctx))
+			i915_drm_client_add_context(ctx->client, ce);
+		rcu_read_unlock();
 	}
 
 unlock:
diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c
index 2e5e69edc0f9..ffccb6239789 100644
--- a/drivers/gpu/drm/i915/i915_drm_client.c
+++ b/drivers/gpu/drm/i915/i915_drm_client.c
@@ -144,4 +144,14 @@ bool i915_drm_client_remove_object(struct drm_i915_gem_object *obj)
 
 	return true;
 }
+
+void i915_drm_client_add_context(struct i915_drm_client *client,
+				 struct intel_context *ce)
+{
+	if (ce->state)
+		i915_drm_client_add_object(client, ce->state->obj);
+
+	if (ce->ring != ce->engine->legacy.ring && ce->ring->vma)
+		i915_drm_client_add_object(client, ce->ring->vma->obj);
+}
 #endif
diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h
index 5f58fdf7dcb8..39616b10a51f 100644
--- a/drivers/gpu/drm/i915/i915_drm_client.h
+++ b/drivers/gpu/drm/i915/i915_drm_client.h
@@ -14,6 +14,7 @@
 
 #include "i915_file_private.h"
 #include "gem/i915_gem_object_types.h"
+#include "gt/intel_context_types.h"
 
 #define I915_LAST_UABI_ENGINE_CLASS I915_ENGINE_CLASS_COMPUTE
 
@@ -70,6 +71,8 @@ void i915_drm_client_fdinfo(struct drm_printer *p, struct drm_file *file);
 void i915_drm_client_add_object(struct i915_drm_client *client,
 				struct drm_i915_gem_object *obj);
 bool i915_drm_client_remove_object(struct drm_i915_gem_object *obj);
+void i915_drm_client_add_context(struct i915_drm_client *client,
+				 struct intel_context *ce);
 #else
 static inline void i915_drm_client_add_object(struct i915_drm_client *client,
 					      struct drm_i915_gem_object *obj)
@@ -79,6 +82,11 @@ static inline void i915_drm_client_add_object(struct i915_drm_client *client,
 static inline bool i915_drm_client_remove_object(struct drm_i915_gem_object *obj)
 {
 }
+
+static inline void i915_drm_client_add_context(struct i915_drm_client *client,
+					       struct intel_context *ce)
+{
+}
 #endif
 
 #endif /* !__I915_DRM_CLIENT_H__ */
-- 
2.39.2



More information about the Intel-gfx-trybot mailing list