[Intel-gfx] [RFC 4/8] drm/i915: Track all user contexts per client

Tvrtko Ursulin
2020-01-10T13:31:02Z

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

We soon want to start answering questions like how much GPU time is the
context belonging to a client which exited still using.

To enable this we start tracking all context belonging to a client on a
separate list, plus we make contexts take a reference on their clients
file_priv.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
drivers/gpu/drm/i915/gem/i915_gem_context.c | 21 ++++++++++++++++++-
.../gpu/drm/i915/gem/i915_gem_context_types.h | 6 ++++++
drivers/gpu/drm/i915/i915_drm_client.c | 3 +++
drivers/gpu/drm/i915/i915_drm_client.h | 5 +++++
4 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index ba3c29a01535..ba8ccc754f20 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -301,8 +301,18 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)

static void i915_gem_context_free(struct i915_gem_context *ctx)
{
+ struct i915_drm_client *client = ctx->client;
+
GEM_BUG_ON(!i915_gem_context_is_closed(ctx));

+ if (client) {
+ spin_lock(&client->ctx_lock);
+ list_del_rcu(&ctx->client_link);
+ spin_unlock(&client->ctx_lock);
+
+ i915_drm_client_put(client);
+ }
+
spin_lock(&ctx->i915->gem.contexts.lock);
list_del(&ctx->link);
spin_unlock(&ctx->i915->gem.contexts.lock);
@@ -772,6 +782,7 @@ static int gem_context_register(struct i915_gem_context *ctx,
struct drm_i915_file_private *fpriv,
u32 *id)
{
+ struct i915_drm_client *client;
struct i915_address_space *vm;
int ret;

@@ -789,9 +800,17 @@ static int gem_context_register(struct i915_gem_context *ctx,

/* And finally expose ourselves to userspace via the idr */
ret = xa_alloc(&fpriv->context_xa, id, ctx, xa_limit_32b, GFP_KERNEL);
- if (ret)
+ if (ret) {
put_pid(fetch_and_zero(&ctx->pid));
+ goto out;
+ }

+ ctx->client = client = i915_drm_client_get(fpriv->client);
+ spin_lock(&client->ctx_lock);
+ list_add_tail_rcu(&ctx->client_link, &client->ctx_list);
+ spin_unlock(&client->ctx_lock);
+
+out:
return ret;
}

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 017ca803ab47..879824159646 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
@@ -104,6 +104,12 @@ struct i915_gem_context {
struct list_head link;
struct llist_node free_link;

+ /** client: struct i915_drm_client */
+ struct i915_drm_client *client;
+
+ /** link: &fpriv.context_list */
+ struct list_head client_link;
+
/**
* @ref: reference count
*
diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c
index 666ec67c77e9..195777b95891 100644
--- a/drivers/gpu/drm/i915/i915_drm_client.c
+++ b/drivers/gpu/drm/i915/i915_drm_client.c
@@ -111,6 +111,9 @@ i915_drm_client_add(struct i915_drm_clients *clients, struct task_struct *task)
return ERR_PTR(-ENOMEM);

kref_init(&client->kref);
+ spin_lock_init(&client->ctx_lock);
+ INIT_LIST_HEAD(&client->ctx_list);
+
client->clients = clients;

ret = xa_alloc_cyclic(&clients->xarray, &client->id, client,
diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h
index 2c692345bc4e..16d8db075a7d 100644
--- a/drivers/gpu/drm/i915/i915_drm_client.h
+++ b/drivers/gpu/drm/i915/i915_drm_client.h
@@ -10,9 +10,11 @@
#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/kref.h>
+#include <linux/list.h>
#include <linux/pid.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
+#include <linux/spinlock.h>
#include <linux/xarray.h>

struct i915_drm_clients {
@@ -30,6 +32,9 @@ struct i915_drm_client {
char *name;
bool closed;

+ spinlock_t ctx_lock;
+ struct list_head ctx_list;
+
struct i915_drm_clients *clients;

struct kobject *root;
--
2.20.1