@@ -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;
}
@@ -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
*
@@ -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,
@@ -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;