* [PATCH 1/3] drm/i915: Group all the global context information together
@ 2017-03-29 18:28 Chris Wilson
2017-03-29 18:28 ` [PATCH 2/3] drm/i915: Allows contexts to be unreferenced locklessly Chris Wilson
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Chris Wilson @ 2017-03-29 18:28 UTC (permalink / raw)
To: intel-gfx
Create a substruct to hold all the global context state under
drm_i915_private.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_debugfs.c | 4 +--
drivers/gpu/drm/i915/i915_drv.c | 2 +-
drivers/gpu/drm/i915/i915_drv.h | 20 +++++++-------
drivers/gpu/drm/i915/i915_gem.c | 1 -
drivers/gpu/drm/i915/i915_gem_context.c | 34 +++++++++++++-----------
drivers/gpu/drm/i915/i915_sysfs.c | 2 +-
drivers/gpu/drm/i915/intel_lrc.c | 2 +-
drivers/gpu/drm/i915/selftests/mock_context.c | 2 +-
drivers/gpu/drm/i915/selftests/mock_gem_device.c | 2 +-
9 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 8a7f57318a87..a75d848901d4 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1956,7 +1956,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
if (ret)
return ret;
- list_for_each_entry(ctx, &dev_priv->context_list, link) {
+ list_for_each_entry(ctx, &dev_priv->contexts.list, link) {
seq_printf(m, "HW context %u ", ctx->hw_id);
if (ctx->pid) {
struct task_struct *task;
@@ -2062,7 +2062,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
if (ret)
return ret;
- list_for_each_entry(ctx, &dev_priv->context_list, link)
+ list_for_each_entry(ctx, &dev_priv->contexts.list, link)
for_each_engine(engine, dev_priv, id)
i915_dump_lrc_obj(m, ctx, engine);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e98f6c90efe0..111874c3a140 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -560,7 +560,7 @@ static void i915_gem_fini(struct drm_i915_private *dev_priv)
i915_gem_drain_freed_objects(dev_priv);
- WARN_ON(!list_empty(&dev_priv->context_list));
+ WARN_ON(!list_empty(&dev_priv->contexts.list));
}
static int i915_load_modeset_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f263715f65c9..45bc9a65ec53 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2287,13 +2287,6 @@ struct drm_i915_private {
DECLARE_HASHTABLE(mm_structs, 7);
struct mutex mm_lock;
- /* The hw wants to have a stable context identifier for the lifetime
- * of the context (for OA, PASID, faults, etc). This is limited
- * in execlists to 21 bits.
- */
- struct ida context_hw_ida;
-#define MAX_CONTEXT_HW_ID (1<<21) /* exclusive */
-
/* Kernel Modesetting */
struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
@@ -2372,8 +2365,17 @@ struct drm_i915_private {
*/
struct mutex av_mutex;
- uint32_t hw_context_size;
- struct list_head context_list;
+ struct {
+ struct list_head list;
+ u32 hw_size;
+
+ /* The hw wants to have a stable context identifier for the
+ * lifetime of the context (for OA, PASID, faults, etc).
+ * This is limited in execlists to 21 bits.
+ */
+ struct ida hw_ida;
+#define MAX_CONTEXT_HW_ID (1<<21) /* exclusive */
+ } contexts;
u32 fdi_rx_config;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 10f2d26cb2a9..fef212821994 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4784,7 +4784,6 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)
if (err)
goto err_dependencies;
- INIT_LIST_HEAD(&dev_priv->context_list);
INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work);
init_llist_head(&dev_priv->mm.free_list);
INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 5aab9f97385c..c0f3acece66a 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -214,7 +214,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
list_del(&ctx->link);
- ida_simple_remove(&ctx->i915->context_hw_ida, ctx->hw_id);
+ ida_simple_remove(&ctx->i915->contexts.hw_ida, ctx->hw_id);
kfree(ctx);
}
@@ -270,7 +270,7 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out)
{
int ret;
- ret = ida_simple_get(&dev_priv->context_hw_ida,
+ ret = ida_simple_get(&dev_priv->contexts.hw_ida,
0, MAX_CONTEXT_HW_ID, GFP_KERNEL);
if (ret < 0) {
/* Contexts are only released when no longer active.
@@ -278,7 +278,7 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out)
* stale contexts and try again.
*/
i915_gem_retire_requests(dev_priv);
- ret = ida_simple_get(&dev_priv->context_hw_ida,
+ ret = ida_simple_get(&dev_priv->contexts.hw_ida,
0, MAX_CONTEXT_HW_ID, GFP_KERNEL);
if (ret < 0)
return ret;
@@ -330,7 +330,7 @@ __create_hw_context(struct drm_i915_private *dev_priv,
}
kref_init(&ctx->ref);
- list_add_tail(&ctx->link, &dev_priv->context_list);
+ list_add_tail(&ctx->link, &dev_priv->contexts.list);
ctx->i915 = dev_priv;
ctx->vma_lut.ht_bits = VMA_HT_BITS;
@@ -344,11 +344,11 @@ __create_hw_context(struct drm_i915_private *dev_priv,
INIT_WORK(&ctx->vma_lut.resize, resize_vma_ht);
- if (dev_priv->hw_context_size) {
+ if (dev_priv->contexts.hw_size) {
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
- obj = alloc_context_obj(dev_priv, dev_priv->hw_context_size);
+ obj = alloc_context_obj(dev_priv, dev_priv->contexts.hw_size);
if (IS_ERR(obj)) {
ret = PTR_ERR(obj);
goto err_lut;
@@ -511,6 +511,8 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv)
if (WARN_ON(dev_priv->kernel_context))
return 0;
+ INIT_LIST_HEAD(&dev_priv->contexts.list);
+
if (intel_vgpu_active(dev_priv) &&
HAS_LOGICAL_RING_CONTEXTS(dev_priv)) {
if (!i915.enable_execlists) {
@@ -521,20 +523,20 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv)
/* Using the simple ida interface, the max is limited by sizeof(int) */
BUILD_BUG_ON(MAX_CONTEXT_HW_ID > INT_MAX);
- ida_init(&dev_priv->context_hw_ida);
+ ida_init(&dev_priv->contexts.hw_ida);
if (i915.enable_execlists) {
/* NB: intentionally left blank. We will allocate our own
* backing objects as we need them, thank you very much */
- dev_priv->hw_context_size = 0;
+ dev_priv->contexts.hw_size = 0;
} else if (HAS_HW_CONTEXTS(dev_priv)) {
- dev_priv->hw_context_size =
+ dev_priv->contexts.hw_size =
round_up(get_context_size(dev_priv),
I915_GTT_PAGE_SIZE);
- if (dev_priv->hw_context_size > (1<<20)) {
+ if (dev_priv->contexts.hw_size > (1<<20)) {
DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",
- dev_priv->hw_context_size);
- dev_priv->hw_context_size = 0;
+ dev_priv->contexts.hw_size);
+ dev_priv->contexts.hw_size = 0;
}
}
@@ -558,7 +560,7 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv)
DRM_DEBUG_DRIVER("%s context support initialized\n",
i915.enable_execlists ? "LR" :
- dev_priv->hw_context_size ? "HW" : "fake");
+ dev_priv->contexts.hw_size ? "HW" : "fake");
return 0;
}
@@ -583,7 +585,7 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv)
if (!i915.enable_execlists) {
struct i915_gem_context *ctx;
- list_for_each_entry(ctx, &dev_priv->context_list, link) {
+ list_for_each_entry(ctx, &dev_priv->contexts.list, link) {
if (!i915_gem_context_is_default(ctx))
continue;
@@ -613,7 +615,7 @@ void i915_gem_context_fini(struct drm_i915_private *dev_priv)
context_close(dctx);
dev_priv->kernel_context = NULL;
- ida_destroy(&dev_priv->context_hw_ida);
+ ida_destroy(&dev_priv->contexts.hw_ida);
}
static int context_idr_cleanup(int id, void *p, void *data)
@@ -1023,7 +1025,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv)
static bool contexts_enabled(struct drm_device *dev)
{
- return i915.enable_execlists || to_i915(dev)->hw_context_size;
+ return i915.enable_execlists || to_i915(dev)->contexts.hw_size;
}
static bool client_is_banned(struct drm_i915_file_private *file_priv)
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index f3fdfda5e558..94929f7fb998 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -214,7 +214,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count);
/* NB: We defer the remapping until we switch to the context */
- list_for_each_entry(ctx, &dev_priv->context_list, link)
+ list_for_each_entry(ctx, &dev_priv->contexts.list, link)
ctx->remap_slice |= (1<<slice);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index c8f7c631fc1f..0596ad517273 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2016,7 +2016,7 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv)
* So to avoid that we reset the context images upon resume. For
* simplicity, we just zero everything out.
*/
- list_for_each_entry(ctx, &dev_priv->context_list, link) {
+ list_for_each_entry(ctx, &dev_priv->contexts.list, link) {
for_each_engine(engine, dev_priv, id) {
struct intel_context *ce = &ctx->engine[engine->id];
u32 *reg;
diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c
index f8b9cc212b02..243325b97d4c 100644
--- a/drivers/gpu/drm/i915/selftests/mock_context.c
+++ b/drivers/gpu/drm/i915/selftests/mock_context.c
@@ -48,7 +48,7 @@ mock_context(struct drm_i915_private *i915,
if (!ctx->vma_lut.ht)
goto err_free;
- ret = ida_simple_get(&i915->context_hw_ida,
+ ret = ida_simple_get(&i915->contexts.hw_ida,
0, MAX_CONTEXT_HW_ID, GFP_KERNEL);
if (ret < 0)
goto err_vma_ht;
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index 6a8258eacdcb..a356db346ac7 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -156,7 +156,7 @@ struct drm_i915_private *mock_gem_device(void)
INIT_LIST_HEAD(&i915->mm.unbound_list);
INIT_LIST_HEAD(&i915->mm.bound_list);
- ida_init(&i915->context_hw_ida);
+ ida_init(&i915->contexts.hw_ida);
INIT_DELAYED_WORK(&i915->gt.retire_work, mock_retire_work_handler);
INIT_DELAYED_WORK(&i915->gt.idle_work, mock_idle_work_handler);
--
2.11.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/3] drm/i915: Allows contexts to be unreferenced locklessly
2017-03-29 18:28 [PATCH 1/3] drm/i915: Group all the global context information together Chris Wilson
@ 2017-03-29 18:28 ` Chris Wilson
2017-03-30 12:57 ` Joonas Lahtinen
2017-03-29 18:28 ` [PATCH 3/3] drm/i915: Enable rcu-only context lookups Chris Wilson
2017-03-30 12:31 ` [PATCH 1/3] drm/i915: Group all the global context information together Joonas Lahtinen
2 siblings, 1 reply; 7+ messages in thread
From: Chris Wilson @ 2017-03-29 18:28 UTC (permalink / raw)
To: intel-gfx
If we move the actual cleanup of the context to a worker, we can allow
the final free to be called from any context and avoid undue latency in
the caller.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/gvt/scheduler.c | 2 +-
drivers/gpu/drm/i915/i915_drv.h | 23 ++---------------------
drivers/gpu/drm/i915/i915_gem_context.c | 32 +++++++++++++++++++++++++++++---
drivers/gpu/drm/i915/i915_gem_context.h | 15 ++++++++++++++-
drivers/gpu/drm/i915/i915_perf.c | 4 ++--
5 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
index d9a735310e75..07db9a5c0293 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -597,7 +597,7 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt)
void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu)
{
- i915_gem_context_put_unlocked(vgpu->shadow_ctx);
+ i915_gem_context_put(vgpu->shadow_ctx);
}
int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 45bc9a65ec53..aa5b7c8969ab 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2367,6 +2367,8 @@ struct drm_i915_private {
struct {
struct list_head list;
+ struct llist_head free_list;
+ struct work_struct free_work;
u32 hw_size;
/* The hw wants to have a stable context identifier for the
@@ -3516,27 +3518,6 @@ i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
return ctx;
}
-static inline struct i915_gem_context *
-i915_gem_context_get(struct i915_gem_context *ctx)
-{
- kref_get(&ctx->ref);
- return ctx;
-}
-
-static inline void i915_gem_context_put(struct i915_gem_context *ctx)
-{
- lockdep_assert_held(&ctx->i915->drm.struct_mutex);
- kref_put(&ctx->ref, i915_gem_context_free);
-}
-
-static inline void i915_gem_context_put_unlocked(struct i915_gem_context *ctx)
-{
- struct mutex *lock = &ctx->i915->drm.struct_mutex;
-
- if (kref_put_mutex(&ctx->ref, i915_gem_context_free, lock))
- mutex_unlock(lock);
-}
-
static inline struct intel_timeline *
i915_gem_context_lookup_timeline(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index c0f3acece66a..3df050ee6ce4 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -184,13 +184,11 @@ static void vma_lut_free(struct i915_gem_context *ctx)
kvfree(lut->ht);
}
-void i915_gem_context_free(struct kref *ctx_ref)
+static void i915_gem_context_free(struct i915_gem_context *ctx)
{
- struct i915_gem_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
int i;
lockdep_assert_held(&ctx->i915->drm.struct_mutex);
- trace_i915_context_free(ctx);
GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
vma_lut_free(ctx);
@@ -218,6 +216,32 @@ void i915_gem_context_free(struct kref *ctx_ref)
kfree(ctx);
}
+static void free_contexts(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, struct drm_i915_private, contexts.free_work);
+ struct llist_node *freed;
+
+ while ((freed = llist_del_all(&dev_priv->contexts.free_list))) {
+ struct i915_gem_context *ctx, *cn;
+
+ mutex_lock(&dev_priv->drm.struct_mutex);
+ llist_for_each_entry_safe(ctx, cn, freed, free_link)
+ i915_gem_context_free(ctx);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
+ }
+}
+
+void i915_gem_context_release(struct kref *ctx_ref)
+{
+ struct i915_gem_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
+ struct drm_i915_private *i915 = ctx->i915;
+
+ trace_i915_context_free(ctx);
+ if (llist_add(&ctx->free_link, &i915->contexts.free_list))
+ queue_work(i915->wq, &i915->contexts.free_work);
+}
+
static struct drm_i915_gem_object *
alloc_context_obj(struct drm_i915_private *dev_priv, u64 size)
{
@@ -512,6 +536,8 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv)
return 0;
INIT_LIST_HEAD(&dev_priv->contexts.list);
+ INIT_WORK(&dev_priv->contexts.free_work, free_contexts);
+ init_llist_head(&dev_priv->contexts.free_list);
if (intel_vgpu_active(dev_priv) &&
HAS_LOGICAL_RING_CONTEXTS(dev_priv)) {
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h
index db5b28a28d75..526a4a87d23c 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -86,6 +86,7 @@ struct i915_gem_context {
/** link: place with &drm_i915_private.context_list */
struct list_head link;
+ struct llist_node free_link;
/**
* @ref: reference count
@@ -279,7 +280,7 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
int i915_switch_context(struct drm_i915_gem_request *req);
int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv);
-void i915_gem_context_free(struct kref *ctx_ref);
+void i915_gem_context_release(struct kref *ctx_ref);
struct i915_gem_context *
i915_gem_context_create_gvt(struct drm_device *dev);
@@ -294,4 +295,16 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
+static inline struct i915_gem_context *
+i915_gem_context_get(struct i915_gem_context *ctx)
+{
+ kref_get(&ctx->ref);
+ return ctx;
+}
+
+static inline void i915_gem_context_put(struct i915_gem_context *ctx)
+{
+ kref_put(&ctx->ref, i915_gem_context_release);
+}
+
#endif /* !__I915_GEM_CONTEXT_H__ */
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 060b171480d5..ce83c3ea10ca 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -1564,7 +1564,7 @@ static void i915_perf_destroy_locked(struct i915_perf_stream *stream)
list_del(&stream->link);
if (stream->ctx)
- i915_gem_context_put_unlocked(stream->ctx);
+ i915_gem_context_put(stream->ctx);
kfree(stream);
}
@@ -1735,7 +1735,7 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv,
kfree(stream);
err_ctx:
if (specific_ctx)
- i915_gem_context_put_unlocked(specific_ctx);
+ i915_gem_context_put(specific_ctx);
err:
return ret;
}
--
2.11.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/3] drm/i915: Enable rcu-only context lookups
2017-03-29 18:28 [PATCH 1/3] drm/i915: Group all the global context information together Chris Wilson
2017-03-29 18:28 ` [PATCH 2/3] drm/i915: Allows contexts to be unreferenced locklessly Chris Wilson
@ 2017-03-29 18:28 ` Chris Wilson
2017-03-30 13:32 ` Joonas Lahtinen
2017-03-30 12:31 ` [PATCH 1/3] drm/i915: Group all the global context information together Joonas Lahtinen
2 siblings, 1 reply; 7+ messages in thread
From: Chris Wilson @ 2017-03-29 18:28 UTC (permalink / raw)
To: intel-gfx
Whilst the contents of the context is still protected by the big
struct_mutex, this is not much of an improvement. It is just one tiny
step towards reducing our BKL.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_drv.h | 16 +++++--
drivers/gpu/drm/i915/i915_gem_context.c | 74 +++++++++++++++---------------
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 21 +++++----
3 files changed, 58 insertions(+), 53 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index aa5b7c8969ab..0d68966673bd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3505,15 +3505,21 @@ void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
struct sg_table *pages);
static inline struct i915_gem_context *
+__i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
+{
+ return idr_find(&file_priv->context_idr, id);
+}
+
+static inline struct i915_gem_context *
i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
{
struct i915_gem_context *ctx;
- lockdep_assert_held(&file_priv->dev_priv->drm.struct_mutex);
-
- ctx = idr_find(&file_priv->context_idr, id);
- if (!ctx)
- return ERR_PTR(-ENOENT);
+ rcu_read_lock();
+ ctx = __i915_gem_context_lookup_rcu(file_priv, id);
+ if (ctx && !kref_get_unless_zero(&ctx->ref))
+ ctx = NULL;
+ rcu_read_unlock();
return ctx;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 3df050ee6ce4..d53efa107c03 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -225,6 +225,8 @@ static void free_contexts(struct work_struct *work)
while ((freed = llist_del_all(&dev_priv->contexts.free_list))) {
struct i915_gem_context *ctx, *cn;
+ synchronize_rcu();
+
mutex_lock(&dev_priv->drm.struct_mutex);
llist_for_each_entry_safe(ctx, cn, freed, free_link)
i915_gem_context_free(ctx);
@@ -1112,20 +1114,19 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
if (args->ctx_id == DEFAULT_CONTEXT_HANDLE)
return -ENOENT;
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- return ret;
-
ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
- if (IS_ERR(ctx)) {
- mutex_unlock(&dev->struct_mutex);
- return PTR_ERR(ctx);
- }
+ if (!ctx)
+ return -ENOENT;
+
+ ret = mutex_lock_interruptible(&dev->struct_mutex);
+ if (ret)
+ goto out;
__destroy_hw_context(ctx, file_priv);
mutex_unlock(&dev->struct_mutex);
- DRM_DEBUG("HW context %d destroyed\n", args->ctx_id);
+out:
+ i915_gem_context_put(ctx);
return 0;
}
@@ -1137,15 +1138,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
struct i915_gem_context *ctx;
int ret;
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- return ret;
-
ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
- if (IS_ERR(ctx)) {
- mutex_unlock(&dev->struct_mutex);
- return PTR_ERR(ctx);
- }
+ if (!ctx)
+ return -ENOENT;
args->size = 0;
switch (args->param) {
@@ -1176,8 +1171,8 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
ret = -EINVAL;
break;
}
- mutex_unlock(&dev->struct_mutex);
+ i915_gem_context_put(ctx);
return ret;
}
@@ -1189,15 +1184,13 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
struct i915_gem_context *ctx;
int ret;
+ ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
+ if (!ctx)
+ return -ENOENT;
+
ret = i915_mutex_lock_interruptible(dev);
if (ret)
- return ret;
-
- ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
- if (IS_ERR(ctx)) {
- mutex_unlock(&dev->struct_mutex);
- return PTR_ERR(ctx);
- }
+ goto out;
switch (args->param) {
case I915_CONTEXT_PARAM_BAN_PERIOD:
@@ -1252,6 +1245,8 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
}
mutex_unlock(&dev->struct_mutex);
+out:
+ i915_gem_context_put(ctx);
return ret;
}
@@ -1269,27 +1264,30 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
if (args->ctx_id == DEFAULT_CONTEXT_HANDLE && !capable(CAP_SYS_ADMIN))
return -EPERM;
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- return ret;
+ ret = -ENOENT;
+ rcu_read_lock();
+ ctx = __i915_gem_context_lookup_rcu(file->driver_priv, args->ctx_id);
+ if (!ctx)
+ goto out;
- ctx = i915_gem_context_lookup(file->driver_priv, args->ctx_id);
- if (IS_ERR(ctx)) {
- mutex_unlock(&dev->struct_mutex);
- return PTR_ERR(ctx);
- }
+ /* We opt for unserialised reads here. This may result in tearing
+ * in the extremely unlikely event of a GPU hang on this context
+ * as we are querying them. If we need that extra layer of protection,
+ * we should wrap the hangstats with a seqlock.
+ */
if (capable(CAP_SYS_ADMIN))
args->reset_count = i915_reset_count(&dev_priv->gpu_error);
else
args->reset_count = 0;
- args->batch_active = ctx->guilty_count;
- args->batch_pending = ctx->active_count;
-
- mutex_unlock(&dev->struct_mutex);
+ args->batch_active = READ_ONCE(ctx->guilty_count);
+ args->batch_pending = READ_ONCE(ctx->active_count);
- return 0;
+ ret = 0;
+out:
+ rcu_read_unlock();
+ return ret;
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 017e27b7c300..26d4b450b7f8 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -597,16 +597,17 @@ static int eb_select_context(struct i915_execbuffer *eb)
struct i915_gem_context *ctx;
ctx = i915_gem_context_lookup(eb->file->driver_priv, eb->args->rsvd1);
- if (unlikely(IS_ERR(ctx)))
- return PTR_ERR(ctx);
+ if (unlikely(!ctx))
+ return -ENOENT;
if (unlikely(i915_gem_context_is_banned(ctx))) {
DRM_DEBUG("Context %u tried to submit while banned\n",
ctx->user_handle);
+ i915_gem_context_put(ctx);
return -EIO;
}
- eb->ctx = i915_gem_context_get(ctx);
+ eb->ctx = ctx;
eb->vm = ctx->ppgtt ? &ctx->ppgtt->base : &eb->i915->ggtt.base;
eb->context_flags = 0;
@@ -2040,7 +2041,6 @@ i915_gem_do_execbuffer(struct drm_device *dev,
if ((args->flags & I915_EXEC_NO_RELOC) == 0)
args->flags |= __EXEC_HAS_RELOC;
eb.exec = exec;
- eb.ctx = NULL;
eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
if (USES_FULL_PPGTT(eb.i915))
eb.invalid_flags |= EXEC_OBJECT_NEEDS_GTT;
@@ -2095,6 +2095,10 @@ i915_gem_do_execbuffer(struct drm_device *dev,
if (eb_create(&eb))
return -ENOMEM;
+ ret = eb_select_context(&eb);
+ if (unlikely(ret))
+ goto err_destroy;
+
/* Take a local wakeref for preparing to dispatch the execbuf as
* we expect to access the hardware fairly frequently in the
* process. Upon first dispatch, we acquire another prolonged
@@ -2102,14 +2106,11 @@ i915_gem_do_execbuffer(struct drm_device *dev,
* 100ms.
*/
intel_runtime_pm_get(eb.i915);
+
ret = i915_mutex_lock_interruptible(dev);
if (ret)
goto err_rpm;
- ret = eb_select_context(&eb);
- if (unlikely(ret))
- goto err_unlock;
-
ret = eb_lookup_vmas(&eb);
if (likely(!ret && args->flags & __EXEC_HAS_RELOC))
ret = eb_relocate(&eb);
@@ -2242,11 +2243,11 @@ i915_gem_do_execbuffer(struct drm_device *dev,
i915_vma_unpin(eb.batch);
err_vma:
eb_release_vma(&eb);
- i915_gem_context_put(eb.ctx);
-err_unlock:
mutex_unlock(&dev->struct_mutex);
err_rpm:
intel_runtime_pm_put(eb.i915);
+ i915_gem_context_put(eb.ctx);
+err_destroy:
eb_destroy(&eb);
if (out_fence_fd != -1)
put_unused_fd(out_fence_fd);
--
2.11.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/3] drm/i915: Group all the global context information together
2017-03-29 18:28 [PATCH 1/3] drm/i915: Group all the global context information together Chris Wilson
2017-03-29 18:28 ` [PATCH 2/3] drm/i915: Allows contexts to be unreferenced locklessly Chris Wilson
2017-03-29 18:28 ` [PATCH 3/3] drm/i915: Enable rcu-only context lookups Chris Wilson
@ 2017-03-30 12:31 ` Joonas Lahtinen
2 siblings, 0 replies; 7+ messages in thread
From: Joonas Lahtinen @ 2017-03-30 12:31 UTC (permalink / raw)
To: Chris Wilson, intel-gfx
On ke, 2017-03-29 at 19:28 +0100, Chris Wilson wrote:
> Create a substruct to hold all the global context state under
> drm_i915_private.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Regards, Joonas
--
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] drm/i915: Allows contexts to be unreferenced locklessly
2017-03-29 18:28 ` [PATCH 2/3] drm/i915: Allows contexts to be unreferenced locklessly Chris Wilson
@ 2017-03-30 12:57 ` Joonas Lahtinen
0 siblings, 0 replies; 7+ messages in thread
From: Joonas Lahtinen @ 2017-03-30 12:57 UTC (permalink / raw)
To: Chris Wilson, intel-gfx
On ke, 2017-03-29 at 19:28 +0100, Chris Wilson wrote:
> If we move the actual cleanup of the context to a worker, we can allow
> the final free to be called from any context and avoid undue latency in
> the caller.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
<SNIP>
> +static void free_contexts(struct work_struct *work)
> +{
> + struct drm_i915_private *dev_priv =
> + container_of(work, struct drm_i915_private, contexts.free_work);
typeof(*dev_priv)? or maybe even *i915 if you dare.
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Regards, Joonas
--
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] drm/i915: Enable rcu-only context lookups
2017-03-29 18:28 ` [PATCH 3/3] drm/i915: Enable rcu-only context lookups Chris Wilson
@ 2017-03-30 13:32 ` Joonas Lahtinen
2017-03-30 13:41 ` Chris Wilson
0 siblings, 1 reply; 7+ messages in thread
From: Joonas Lahtinen @ 2017-03-30 13:32 UTC (permalink / raw)
To: Chris Wilson, intel-gfx
On ke, 2017-03-29 at 19:28 +0100, Chris Wilson wrote:
> Whilst the contents of the context is still protected by the big
> struct_mutex, this is not much of an improvement. It is just one tiny
> step towards reducing our BKL.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
<SNIP>
> + /* We opt for unserialised reads here. This may result in tearing
> + * in the extremely unlikely event of a GPU hang on this context
> + * as we are querying them. If we need that extra layer of protection,
> + * we should wrap the hangstats with a seqlock.
> + */
>
> if (capable(CAP_SYS_ADMIN))
> args->reset_count = i915_reset_count(&dev_priv->gpu_error);
> else
> args->reset_count = 0;
>
Kill the extra newline.
> - args->batch_active = ctx->guilty_count;
> - args->batch_pending = ctx->active_count;
> -
> - mutex_unlock(&dev->struct_mutex);
> + args->batch_active = READ_ONCE(ctx->guilty_count);
> + args->batch_pending = READ_ONCE(ctx->active_count);
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Regards, Joonas
--
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 3/3] drm/i915: Enable rcu-only context lookups
2017-03-30 13:32 ` Joonas Lahtinen
@ 2017-03-30 13:41 ` Chris Wilson
0 siblings, 0 replies; 7+ messages in thread
From: Chris Wilson @ 2017-03-30 13:41 UTC (permalink / raw)
To: Joonas Lahtinen; +Cc: intel-gfx
On Thu, Mar 30, 2017 at 04:32:37PM +0300, Joonas Lahtinen wrote:
> On ke, 2017-03-29 at 19:28 +0100, Chris Wilson wrote:
> > Whilst the contents of the context is still protected by the big
> > struct_mutex, this is not much of an improvement. It is just one tiny
> > step towards reducing our BKL.
> >
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
>
> <SNIP>
>
> > + /* We opt for unserialised reads here. This may result in tearing
> > + * in the extremely unlikely event of a GPU hang on this context
> > + * as we are querying them. If we need that extra layer of protection,
> > + * we should wrap the hangstats with a seqlock.
> > + */
> >
> > if (capable(CAP_SYS_ADMIN))
> > args->reset_count = i915_reset_count(&dev_priv->gpu_error);
> > else
> > args->reset_count = 0;
> >
>
> Kill the extra newline.
Fortunately it was just a mirage introduced by diff.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-03-30 13:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-29 18:28 [PATCH 1/3] drm/i915: Group all the global context information together Chris Wilson
2017-03-29 18:28 ` [PATCH 2/3] drm/i915: Allows contexts to be unreferenced locklessly Chris Wilson
2017-03-30 12:57 ` Joonas Lahtinen
2017-03-29 18:28 ` [PATCH 3/3] drm/i915: Enable rcu-only context lookups Chris Wilson
2017-03-30 13:32 ` Joonas Lahtinen
2017-03-30 13:41 ` Chris Wilson
2017-03-30 12:31 ` [PATCH 1/3] drm/i915: Group all the global context information together Joonas Lahtinen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).