* First class i915_vma
@ 2016-08-05 9:05 Chris Wilson
2016-08-05 9:05 ` [PATCH 01/13] drm/i915: Reduce amount of duplicate buffer information captured on error Chris Wilson
` (13 more replies)
0 siblings, 14 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
For a long time, i915_vma has been the way we actually interact with the
hardware, as opposed to simply using the object as long ago. Accepting
this and using the i915_vma as the primary object for tracking such
interactions leads to a great deal of simplification and allows us to
move more hardware tracking from the object to the vma, fixing a number
of long outstanding bugs.
It just happens that the actual conversion got tied up in the middle of
refreshing the GPU error state...
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/13] drm/i915: Reduce amount of duplicate buffer information captured on error
2016-08-05 9:05 First class i915_vma Chris Wilson
@ 2016-08-05 9:05 ` Chris Wilson
2016-08-05 9:05 ` [PATCH 02/13] drm/i915: Stop the machine whilst capturing the GPU crash dump Chris Wilson
` (12 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
When capturing the error state, we do not need to know about every
address space - just those that are related to the error. We know which
context is active at the time, therefore we know which VM are implicated
in the error. We can then restrict the VM which we report to the
relevant subset.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_drv.h | 9 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 202 ++++++++++++++--------------------
2 files changed, 89 insertions(+), 122 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index feec00f769e1..7054baa92061 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -517,6 +517,7 @@ struct drm_i915_error_state {
int num_waiters;
int hangcheck_score;
enum intel_engine_hangcheck_action hangcheck_action;
+ struct i915_address_space *vm;
int num_requests;
/* our own tracking of ring head and tail */
@@ -586,17 +587,15 @@ struct drm_i915_error_state {
u32 read_domains;
u32 write_domain;
s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
- s32 pinned:2;
u32 tiling:2;
u32 dirty:1;
u32 purgeable:1;
u32 userptr:1;
s32 engine:4;
u32 cache_level:3;
- } **active_bo, **pinned_bo;
-
- u32 *active_bo_count, *pinned_bo_count;
- u32 vm_count;
+ } *active_bo[I915_NUM_ENGINES], *pinned_bo;
+ u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count;
+ struct i915_address_space *active_vm[I915_NUM_ENGINES];
};
struct intel_connector;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index eecb87063c88..ced296983caa 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -42,16 +42,6 @@ static const char *engine_str(int engine)
}
}
-static const char *pin_flag(int pinned)
-{
- if (pinned > 0)
- return " P";
- else if (pinned < 0)
- return " p";
- else
- return "";
-}
-
static const char *tiling_flag(int tiling)
{
switch (tiling) {
@@ -189,7 +179,7 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m,
{
int i;
- err_printf(m, " %s [%d]:\n", name, count);
+ err_printf(m, "%s [%d]:\n", name, count);
while (count--) {
err_printf(m, " %08x_%08x %8u %02x %02x [ ",
@@ -202,7 +192,6 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m,
err_printf(m, "%02x ", err->rseqno[i]);
err_printf(m, "] %02x", err->wseqno);
- err_puts(m, pin_flag(err->pinned));
err_puts(m, tiling_flag(err->tiling));
err_puts(m, dirty_flag(err->dirty));
err_puts(m, purgeable_flag(err->purgeable));
@@ -414,18 +403,25 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
error_print_engine(m, &error->engine[i]);
}
- for (i = 0; i < error->vm_count; i++) {
- err_printf(m, "vm[%d]\n", i);
+ for (i = 0; i < I915_NUM_ENGINES; i++) {
+ if (!error->active_vm[i])
+ break;
- print_error_buffers(m, "Active",
+ err_printf(m, "Active vm[%d]\n", i);
+ for (j = 0; j < I915_NUM_ENGINES; j++) {
+ if (error->engine[j].vm == error->active_vm[i])
+ err_printf(m, " %s\n",
+ dev_priv->engine[j].name);
+ }
+ print_error_buffers(m, " Buffers",
error->active_bo[i],
error->active_bo_count[i]);
-
- print_error_buffers(m, "Pinned",
- error->pinned_bo[i],
- error->pinned_bo_count[i]);
}
+ print_error_buffers(m, "Pinned (global)",
+ error->pinned_bo,
+ error->pinned_bo_count);
+
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
struct drm_i915_error_engine *ee = &error->engine[i];
@@ -626,13 +622,10 @@ static void i915_error_state_free(struct kref *error_ref)
i915_error_object_free(error->semaphore_obj);
- for (i = 0; i < error->vm_count; i++)
+ for (i = 0; i < ARRAY_SIZE(error->active_bo); i++)
kfree(error->active_bo[i]);
-
- kfree(error->active_bo);
- kfree(error->active_bo_count);
kfree(error->pinned_bo);
- kfree(error->pinned_bo_count);
+
kfree(error->overlay);
kfree(error->display);
kfree(error);
@@ -778,9 +771,6 @@ static void capture_bo(struct drm_i915_error_buffer *err,
err->read_domains = obj->base.read_domains;
err->write_domain = obj->base.write_domain;
err->fence_reg = obj->fence_reg;
- err->pinned = 0;
- if (i915_gem_obj_is_pinned(obj))
- err->pinned = 1;
err->tiling = i915_gem_object_get_tiling(obj);
err->dirty = obj->dirty;
err->purgeable = obj->madv != I915_MADV_WILLNEED;
@@ -788,13 +778,17 @@ static void capture_bo(struct drm_i915_error_buffer *err,
err->cache_level = obj->cache_level;
}
-static u32 capture_active_bo(struct drm_i915_error_buffer *err,
- int count, struct list_head *head)
+static u32 capture_error_bo(struct drm_i915_error_buffer *err,
+ int count, struct list_head *head,
+ bool pinned_only)
{
struct i915_vma *vma;
int i = 0;
list_for_each_entry(vma, head, vm_link) {
+ if (pinned_only && !i915_vma_is_pinned(vma))
+ continue;
+
capture_bo(err++, vma);
if (++i == count)
break;
@@ -803,28 +797,6 @@ static u32 capture_active_bo(struct drm_i915_error_buffer *err,
return i;
}
-static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
- int count, struct list_head *head,
- struct i915_address_space *vm)
-{
- struct drm_i915_gem_object *obj;
- struct drm_i915_error_buffer * const first = err;
- struct drm_i915_error_buffer * const last = err + count;
-
- list_for_each_entry(obj, head, global_list) {
- struct i915_vma *vma;
-
- if (err == last)
- break;
-
- list_for_each_entry(vma, &obj->vma_list, obj_link)
- if (vma->vm == vm && i915_vma_is_pinned(vma))
- capture_bo(err++, vma);
- }
-
- return err - first;
-}
-
/* Generate a semi-unique error code. The code is not meant to have meaning, The
* code's only purpose is to try to prevent false duplicated bug reports by
* grossly estimating a GPU error state.
@@ -1062,7 +1034,6 @@ static void error_record_engine_registers(struct drm_i915_error_state *error,
}
}
-
static void i915_gem_record_active_context(struct intel_engine_cs *engine,
struct drm_i915_error_state *error,
struct drm_i915_error_engine *ee)
@@ -1115,10 +1086,9 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
request = i915_gem_find_active_request(engine);
if (request) {
- struct i915_address_space *vm;
struct intel_ring *ring;
- vm = request->ctx->ppgtt ?
+ ee->vm = request->ctx->ppgtt ?
&request->ctx->ppgtt->base : &ggtt->base;
/* We need to copy these to an anonymous buffer
@@ -1128,7 +1098,7 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
ee->batchbuffer =
i915_error_object_create(dev_priv,
request->batch_obj,
- vm);
+ ee->vm);
if (HAS_BROKEN_CS_TLB(dev_priv))
ee->wa_batchbuffer =
@@ -1210,89 +1180,85 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
}
}
-/* FIXME: Since pin count/bound list is global, we duplicate what we capture per
- * VM.
- */
static void i915_gem_capture_vm(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error,
struct i915_address_space *vm,
const int ndx)
{
- struct drm_i915_error_buffer *active_bo = NULL, *pinned_bo = NULL;
- struct drm_i915_gem_object *obj;
+ struct drm_i915_error_buffer *active_bo;
struct i915_vma *vma;
int i;
i = 0;
list_for_each_entry(vma, &vm->active_list, vm_link)
i++;
- error->active_bo_count[ndx] = i;
-
- list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
- list_for_each_entry(vma, &obj->vma_list, obj_link)
- if (vma->vm == vm && i915_vma_is_pinned(vma))
- i++;
- }
- error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx];
- if (i) {
+ active_bo = NULL;
+ if (i)
active_bo = kcalloc(i, sizeof(*active_bo), GFP_ATOMIC);
- if (active_bo)
- pinned_bo = active_bo + error->active_bo_count[ndx];
- }
-
if (active_bo)
- error->active_bo_count[ndx] =
- capture_active_bo(active_bo,
- error->active_bo_count[ndx],
- &vm->active_list);
-
- if (pinned_bo)
- error->pinned_bo_count[ndx] =
- capture_pinned_bo(pinned_bo,
- error->pinned_bo_count[ndx],
- &dev_priv->mm.bound_list, vm);
+ i = capture_error_bo(active_bo, i, &vm->active_list, false);
+ else
+ i = 0;
+
error->active_bo[ndx] = active_bo;
- error->pinned_bo[ndx] = pinned_bo;
+ error->active_bo_count[ndx] = i;
+ error->active_vm[ndx] = vm;
}
-static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
- struct drm_i915_error_state *error)
+static void i915_capture_active_buffers(struct drm_i915_private *dev_priv,
+ struct drm_i915_error_state *error)
{
- struct i915_address_space *vm;
- int cnt = 0, i = 0;
-
- list_for_each_entry(vm, &dev_priv->vm_list, global_link)
- cnt++;
-
- error->active_bo = kcalloc(cnt, sizeof(*error->active_bo), GFP_ATOMIC);
- error->pinned_bo = kcalloc(cnt, sizeof(*error->pinned_bo), GFP_ATOMIC);
- error->active_bo_count = kcalloc(cnt, sizeof(*error->active_bo_count),
- GFP_ATOMIC);
- error->pinned_bo_count = kcalloc(cnt, sizeof(*error->pinned_bo_count),
- GFP_ATOMIC);
-
- if (error->active_bo == NULL ||
- error->pinned_bo == NULL ||
- error->active_bo_count == NULL ||
- error->pinned_bo_count == NULL) {
- kfree(error->active_bo);
- kfree(error->active_bo_count);
- kfree(error->pinned_bo);
- kfree(error->pinned_bo_count);
-
- error->active_bo = NULL;
- error->active_bo_count = NULL;
- error->pinned_bo = NULL;
- error->pinned_bo_count = NULL;
- } else {
- list_for_each_entry(vm, &dev_priv->vm_list, global_link)
- i915_gem_capture_vm(dev_priv, error, vm, i++);
+ int cnt = 0, i, j;
+
+ BUILD_BUG_ON(ARRAY_SIZE(error->engine) > ARRAY_SIZE(error->active_bo));
+ BUILD_BUG_ON(ARRAY_SIZE(error->active_bo) != ARRAY_SIZE(error->active_vm));
+ BUILD_BUG_ON(ARRAY_SIZE(error->active_bo) != ARRAY_SIZE(error->active_bo_count));
- error->vm_count = cnt;
+ for (i = 0; i < I915_NUM_ENGINES; i++) {
+ struct drm_i915_error_engine *ee = &error->engine[i];
+
+ if (!ee->vm)
+ continue;
+
+ for (j = 0; j < i; j++)
+ if (error->engine[j].vm == ee->vm)
+ break;
+ if (j != i)
+ continue;
+
+ i915_gem_capture_vm(dev_priv, error, ee->vm, cnt++);
}
}
+static void i915_capture_pinned_buffers(struct drm_i915_private *dev_priv,
+ struct drm_i915_error_state *error)
+{
+ struct i915_address_space *vm = &dev_priv->ggtt.base;
+ struct drm_i915_error_buffer *bo;
+ struct i915_vma *vma;
+ int i, j;
+
+ i = 0;
+ list_for_each_entry(vma, &vm->active_list, vm_link)
+ i++;
+
+ j = 0;
+ list_for_each_entry(vma, &vm->inactive_list, vm_link)
+ j++;
+
+ bo = NULL;
+ if (i + j)
+ bo = kcalloc(i + j, sizeof(*bo), GFP_ATOMIC);
+ if (!bo)
+ return;
+
+ i = capture_error_bo(bo, i, &vm->active_list, true);
+ j = capture_error_bo(bo + i, j, &vm->inactive_list, true);
+ error->pinned_bo_count = i + j;
+ error->pinned_bo = bo;
+}
+
/* Capture all registers which don't fit into another category. */
static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error)
@@ -1436,10 +1402,12 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
i915_capture_gen_state(dev_priv, error);
i915_capture_reg_state(dev_priv, error);
- i915_gem_capture_buffers(dev_priv, error);
i915_gem_record_fences(dev_priv, error);
i915_gem_record_rings(dev_priv, error);
+ i915_capture_active_buffers(dev_priv, error);
+ i915_capture_pinned_buffers(dev_priv, error);
+
do_gettimeofday(&error->time);
error->overlay = intel_overlay_capture_error_state(dev_priv);
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 02/13] drm/i915: Stop the machine whilst capturing the GPU crash dump
2016-08-05 9:05 First class i915_vma Chris Wilson
2016-08-05 9:05 ` [PATCH 01/13] drm/i915: Reduce amount of duplicate buffer information captured on error Chris Wilson
@ 2016-08-05 9:05 ` Chris Wilson
2016-08-05 18:50 ` Daniel Vetter
2016-08-05 9:05 ` [PATCH 03/13] drm/i915: Scan GGTT active list for context object Chris Wilson
` (11 subsequent siblings)
13 siblings, 1 reply; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
The error state is purposefully racy as we expect it to be called at any
time and so have avoided any locking whilst capturing the crash dump.
However, with multi-engine GPUs and multiple CPUs, those races can
manifest into OOPSes as we attempt to chase dangling pointers freed on
other CPUs. Under discussion are lots of ways to slow down normal
operation in order to protect the post-mortem error capture, but what it
we take the opposite approach and freeze the machine whilst the error
capture runs (note the GPU may still running, but as long as we don't
process any of the results the driver's bookkeeping will be static).
Note that by of itself, this is not a complete fix. It also depends on
the compiler barriers in list_add/list_del to prevent traversing the
lists into the void.
v2: Avoid drm_clflush_pages() inside stop_machine() as it may use
stop_machine() itself for its wbinvd fallback.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/Kconfig | 1 +
drivers/gpu/drm/i915/i915_drv.h | 2 ++
drivers/gpu/drm/i915/i915_gpu_error.c | 48 +++++++++++++++++++++--------------
3 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 7769e469118f..7badcee88ebf 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -4,6 +4,7 @@ config DRM_I915
depends on X86 && PCI
select INTEL_GTT
select INTERVAL_TREE
+ select STOP_MACHINE
# we need shmfs for the swappable backing store, and in particular
# the shmem_readpage() which depends upon tmpfs
select SHMEM
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7054baa92061..9a7ffa49cd1f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -481,6 +481,8 @@ struct drm_i915_error_state {
struct kref ref;
struct timeval time;
+ struct drm_i915_private *i915;
+
char error_msg[128];
bool simulated;
int iommu;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index ced296983caa..b94a59733cf8 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -28,6 +28,7 @@
*/
#include <generated/utsrelease.h>
+#include <linux/stop_machine.h>
#include "i915_drv.h"
static const char *engine_str(int engine)
@@ -684,14 +685,12 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
dst->page_count = num_pages;
while (num_pages--) {
- unsigned long flags;
void *d;
d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
if (d == NULL)
goto unwind;
- local_irq_save(flags);
if (use_ggtt) {
void __iomem *s;
@@ -710,15 +709,10 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
page = i915_gem_object_get_page(src, i);
- drm_clflush_pages(&page, 1);
-
s = kmap_atomic(page);
memcpy(d, s, PAGE_SIZE);
kunmap_atomic(s);
-
- drm_clflush_pages(&page, 1);
}
- local_irq_restore(flags);
dst->pages[i++] = d;
reloc_offset += PAGE_SIZE;
@@ -1371,6 +1365,32 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
error->suspend_count = dev_priv->suspend_count;
}
+static int capture(void *data)
+{
+ struct drm_i915_error_state *error = data;
+
+ /* Ensure that what we readback from memory matches what the GPU sees */
+ wbinvd();
+
+ i915_capture_gen_state(error->i915, error);
+ i915_capture_reg_state(error->i915, error);
+ i915_gem_record_fences(error->i915, error);
+ i915_gem_record_rings(error->i915, error);
+
+ i915_capture_active_buffers(error->i915, error);
+ i915_capture_pinned_buffers(error->i915, error);
+
+ do_gettimeofday(&error->time);
+
+ error->overlay = intel_overlay_capture_error_state(error->i915);
+ error->display = intel_display_capture_error_state(error->i915);
+
+ /* And make sure we don't leave trash in the CPU cache */
+ wbinvd();
+
+ return 0;
+}
+
/**
* i915_capture_error_state - capture an error record for later analysis
* @dev: drm device
@@ -1399,19 +1419,9 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
}
kref_init(&error->ref);
+ error->i915 = dev_priv;
- i915_capture_gen_state(dev_priv, error);
- i915_capture_reg_state(dev_priv, error);
- i915_gem_record_fences(dev_priv, error);
- i915_gem_record_rings(dev_priv, error);
-
- i915_capture_active_buffers(dev_priv, error);
- i915_capture_pinned_buffers(dev_priv, error);
-
- do_gettimeofday(&error->time);
-
- error->overlay = intel_overlay_capture_error_state(dev_priv);
- error->display = intel_display_capture_error_state(dev_priv);
+ stop_machine(capture, error, NULL);
i915_error_capture_msg(dev_priv, error, engine_mask, error_msg);
DRM_INFO("%s\n", error->error_msg);
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 03/13] drm/i915: Scan GGTT active list for context object
2016-08-05 9:05 First class i915_vma Chris Wilson
2016-08-05 9:05 ` [PATCH 01/13] drm/i915: Reduce amount of duplicate buffer information captured on error Chris Wilson
2016-08-05 9:05 ` [PATCH 02/13] drm/i915: Stop the machine whilst capturing the GPU crash dump Chris Wilson
@ 2016-08-05 9:05 ` Chris Wilson
2016-08-05 9:05 ` [PATCH 04/13] drm/i915: Move setting of request->batch into its single callsite Chris Wilson
` (10 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
The goal here is just to reduce the number of different lists we walk
during error capture, and so reduce the burden of having to check for
conflicting updates. Since we have to scan the request list, change the
context lookup from searching the global bound list to the request list.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_gpu_error.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index b94a59733cf8..ef8be7e05cbd 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1033,18 +1033,16 @@ static void i915_gem_record_active_context(struct intel_engine_cs *engine,
struct drm_i915_error_engine *ee)
{
struct drm_i915_private *dev_priv = engine->i915;
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
/* Currently render ring is the only HW context user */
if (engine->id != RCS || !error->ccid)
return;
- list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
- if (!i915_gem_obj_ggtt_bound(obj))
- continue;
-
- if ((error->ccid & PAGE_MASK) == i915_gem_obj_ggtt_offset(obj)) {
- ee->ctx = i915_error_ggtt_object_create(dev_priv, obj);
+ list_for_each_entry(vma, &dev_priv->ggtt.base.active_list, vm_link) {
+ if ((error->ccid & PAGE_MASK) == vma->node.start) {
+ ee->ctx = i915_error_object_create(dev_priv,
+ vma->obj, vma->vm);
break;
}
}
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 04/13] drm/i915: Move setting of request->batch into its single callsite
2016-08-05 9:05 First class i915_vma Chris Wilson
` (2 preceding siblings ...)
2016-08-05 9:05 ` [PATCH 03/13] drm/i915: Scan GGTT active list for context object Chris Wilson
@ 2016-08-05 9:05 ` Chris Wilson
2016-08-05 9:05 ` [PATCH 05/13] drm/i915: Mark unmappable GGTT entries as PIN_HIGH Chris Wilson
` (9 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
request->batch_obj is only set by execbuffer for the convenience of
debugging hangs. By moving that operation to the callsite, we can
simplify all other callers and future patches. We also move the
complications of reference handling of the request->batch_obj next to
where the active tracking is set up for the request.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 10 +++++++++-
drivers/gpu/drm/i915/i915_gem_request.c | 12 +-----------
drivers/gpu/drm/i915/i915_gem_request.h | 8 +++-----
3 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index c494b79ded20..c8d13fea4b25 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1702,6 +1702,14 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
goto err_batch_unpin;
}
+ /* Whilst this request exists, batch_obj will be on the
+ * active_list, and so will hold the active reference. Only when this
+ * request is retired will the the batch_obj be moved onto the
+ * inactive_list and lose its active reference. Hence we do not need
+ * to explicitly hold another reference here.
+ */
+ params->request->batch_obj = params->batch->obj;
+
ret = i915_gem_request_add_to_client(params->request, file);
if (ret)
goto err_request;
@@ -1720,7 +1728,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
ret = execbuf_submit(params, args, &eb->vmas);
err_request:
- __i915_add_request(params->request, params->batch->obj, ret == 0);
+ __i915_add_request(params->request, ret == 0);
err_batch_unpin:
/*
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index b317a672040f..3c70c2708249 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -426,9 +426,7 @@ static void i915_gem_mark_busy(const struct intel_engine_cs *engine)
* request is not being tracked for completion but the work itself is
* going to happen on the hardware. This would be a Bad Thing(tm).
*/
-void __i915_add_request(struct drm_i915_gem_request *request,
- struct drm_i915_gem_object *obj,
- bool flush_caches)
+void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
{
struct intel_engine_cs *engine;
struct intel_ring *ring;
@@ -469,14 +467,6 @@ void __i915_add_request(struct drm_i915_gem_request *request,
request->head = request_start;
- /* Whilst this request exists, batch_obj will be on the
- * active_list, and so will hold the active reference. Only when this
- * request is retired will the the batch_obj be moved onto the
- * inactive_list and lose its active reference. Hence we do not need
- * to explicitly hold another reference here.
- */
- request->batch_obj = obj;
-
/* Seal the request and mark it as pending execution. Note that
* we may inspect this state, without holding any locks, during
* hangcheck. Hence we apply the barrier to ensure that we do not
diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
index 3496e28785e7..24f95a348f16 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.h
+++ b/drivers/gpu/drm/i915/i915_gem_request.h
@@ -218,13 +218,11 @@ static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst,
*pdst = src;
}
-void __i915_add_request(struct drm_i915_gem_request *req,
- struct drm_i915_gem_object *batch_obj,
- bool flush_caches);
+void __i915_add_request(struct drm_i915_gem_request *req, bool flush_caches);
#define i915_add_request(req) \
- __i915_add_request(req, NULL, true)
+ __i915_add_request(req, true)
#define i915_add_request_no_flush(req) \
- __i915_add_request(req, NULL, false)
+ __i915_add_request(req, false)
struct intel_rps_client;
#define NO_WAITBOOST ERR_PTR(-1)
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 05/13] drm/i915: Mark unmappable GGTT entries as PIN_HIGH
2016-08-05 9:05 First class i915_vma Chris Wilson
` (3 preceding siblings ...)
2016-08-05 9:05 ` [PATCH 04/13] drm/i915: Move setting of request->batch into its single callsite Chris Wilson
@ 2016-08-05 9:05 ` Chris Wilson
2016-08-05 9:05 ` [PATCH 06/13] drm/i915: Track pinned vma inside guc Chris Wilson
` (8 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
We allocate a few objects into the GGTT that we never need to access via
the mappable aperture (such as contexts, status pages). We can request
that these are bound high in the VM to increase the amount of mappable
aperture available. However, anything that may be frequently pinned
(such as logical contexts) we want to use the fast search & insert.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/intel_ringbuffer.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 322274a239e4..cae63c4e87a6 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -2093,7 +2093,7 @@ static int intel_ring_context_pin(struct i915_gem_context *ctx,
if (ce->state) {
ret = i915_gem_object_ggtt_pin(ce->state, NULL, 0,
- ctx->ggtt_alignment, 0);
+ ctx->ggtt_alignment, PIN_HIGH);
if (ret)
goto error;
}
@@ -2631,7 +2631,8 @@ static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv,
i915.semaphores = 0;
} else {
i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
+ ret = i915_gem_object_ggtt_pin(obj, NULL,
+ 0, 0, PIN_HIGH);
if (ret != 0) {
i915_gem_object_put(obj);
DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n");
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 06/13] drm/i915: Track pinned vma inside guc
2016-08-05 9:05 First class i915_vma Chris Wilson
` (4 preceding siblings ...)
2016-08-05 9:05 ` [PATCH 05/13] drm/i915: Mark unmappable GGTT entries as PIN_HIGH Chris Wilson
@ 2016-08-05 9:05 ` Chris Wilson
2016-08-05 9:05 ` [PATCH 07/13] drm/i915: Track pinned VMA Chris Wilson
` (7 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
Since the guc allocates and pins and object into the GGTT for its usage,
it is more natural to use that pinned VMA as our resource cookie.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_debugfs.c | 10 +--
drivers/gpu/drm/i915/i915_guc_submission.c | 124 ++++++++++++++---------------
drivers/gpu/drm/i915/intel_guc.h | 9 +--
drivers/gpu/drm/i915/intel_guc_loader.c | 7 +-
4 files changed, 71 insertions(+), 79 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 0620a84d00ca..360ed15a3f60 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2625,15 +2625,15 @@ static int i915_guc_log_dump(struct seq_file *m, void *data)
struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_i915_gem_object *log_obj = dev_priv->guc.log_obj;
- u32 *log;
+ struct drm_i915_gem_object *obj;
int i = 0, pg;
- if (!log_obj)
+ if (!dev_priv->guc.log)
return 0;
- for (pg = 0; pg < log_obj->base.size / PAGE_SIZE; pg++) {
- log = kmap_atomic(i915_gem_object_get_page(log_obj, pg));
+ obj = dev_priv->guc.log->obj;
+ for (pg = 0; pg < obj->base.size / PAGE_SIZE; pg++) {
+ u32 *log = kmap_atomic(i915_gem_object_get_page(obj, pg));
for (i = 0; i < PAGE_SIZE / sizeof(u32); i += 4)
seq_printf(m, "0x%08x 0x%08x 0x%08x 0x%08x\n",
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index 03a5cef353eb..b29e85880995 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -183,7 +183,7 @@ static int guc_update_doorbell_id(struct intel_guc *guc,
struct i915_guc_client *client,
u16 new_id)
{
- struct sg_table *sg = guc->ctx_pool_obj->pages;
+ struct sg_table *sg = guc->ctx_pool->obj->pages;
void *doorbell_bitmap = guc->doorbell_bitmap;
struct guc_doorbell_info *doorbell;
struct guc_context_desc desc;
@@ -325,8 +325,8 @@ static void guc_init_proc_desc(struct intel_guc *guc,
static void guc_init_ctx_desc(struct intel_guc *guc,
struct i915_guc_client *client)
{
- struct drm_i915_gem_object *client_obj = client->client_obj;
struct drm_i915_private *dev_priv = guc_to_i915(guc);
+ struct drm_i915_gem_object *client_obj = client->client->obj;
struct intel_engine_cs *engine;
struct i915_gem_context *ctx = client->owner;
struct guc_context_desc desc;
@@ -380,7 +380,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
* The doorbell, process descriptor, and workqueue are all parts
* of the client object, which the GuC will reference via the GGTT
*/
- gfx_addr = i915_gem_obj_ggtt_offset(client_obj);
+ gfx_addr = client->client->node.start;
desc.db_trigger_phy = sg_dma_address(client_obj->pages->sgl) +
client->doorbell_offset;
desc.db_trigger_cpu = (uintptr_t)client->client_base +
@@ -397,7 +397,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
desc.desc_private = (uintptr_t)client;
/* Pool context is pinned already */
- sg = guc->ctx_pool_obj->pages;
+ sg = guc->ctx_pool->obj->pages;
sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc),
sizeof(desc) * client->ctx_index);
}
@@ -410,7 +410,7 @@ static void guc_fini_ctx_desc(struct intel_guc *guc,
memset(&desc, 0, sizeof(desc));
- sg = guc->ctx_pool_obj->pages;
+ sg = guc->ctx_pool->obj->pages;
sg_pcopy_from_buffer(sg->sgl, sg->nents, &desc, sizeof(desc),
sizeof(desc) * client->ctx_index);
}
@@ -492,7 +492,7 @@ static void guc_add_workqueue_item(struct i915_guc_client *gc,
/* WQ starts from the page after doorbell / process_desc */
wq_page = (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT;
wq_off &= PAGE_SIZE - 1;
- base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, wq_page));
+ base = kmap_atomic(i915_gem_object_get_page(gc->client->obj, wq_page));
wqi = (struct guc_wq_item *)((char *)base + wq_off);
/* Now fill in the 4-word work queue item */
@@ -611,8 +611,8 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq)
*/
/**
- * gem_allocate_guc_obj() - Allocate gem object for GuC usage
- * @dev_priv: driver private data structure
+ * guc_allocate_vma() - Allocate a GGTT VMA for GuC usage
+ * @guc: the guc
* @size: size of object
*
* This is a wrapper to create a gem obj. In order to use it inside GuC, the
@@ -621,45 +621,40 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq)
*
* Return: A drm_i915_gem_object if successful, otherwise NULL.
*/
-static struct drm_i915_gem_object *
-gem_allocate_guc_obj(struct drm_i915_private *dev_priv, u32 size)
+static struct i915_vma *guc_allocate_vma(struct intel_guc *guc, u32 size)
{
+ struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct drm_i915_gem_object *obj;
+ int ret;
obj = i915_gem_object_create(&dev_priv->drm, size);
if (IS_ERR(obj))
- return NULL;
-
- if (i915_gem_object_get_pages(obj)) {
- i915_gem_object_put(obj);
- return NULL;
- }
+ return ERR_CAST(obj);
- if (i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE,
- PIN_OFFSET_BIAS | GUC_WOPCM_TOP)) {
+ ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE,
+ PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
+ if (ret) {
i915_gem_object_put(obj);
- return NULL;
+ return ERR_PTR(ret);
}
/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
- return obj;
+ return i915_gem_obj_to_ggtt(obj);
}
/**
- * gem_release_guc_obj() - Release gem object allocated for GuC usage
- * @obj: gem obj to be released
+ * guc_release_vma() - Release gem object allocated for GuC usage
+ * @vma: gem obj to be released
*/
-static void gem_release_guc_obj(struct drm_i915_gem_object *obj)
+static void guc_release_vma(struct i915_vma *vma)
{
- if (!obj)
+ if (!vma)
return;
- if (i915_gem_obj_is_pinned(obj))
- i915_gem_object_ggtt_unpin(obj);
-
- i915_gem_object_put(obj);
+ i915_vma_unpin(vma);
+ i915_gem_object_put(vma->obj);
}
static void
@@ -686,7 +681,7 @@ guc_client_free(struct drm_i915_private *dev_priv,
kunmap(kmap_to_page(client->client_base));
}
- gem_release_guc_obj(client->client_obj);
+ guc_release_vma(client->client);
if (client->ctx_index != GUC_INVALID_CTX_ID) {
guc_fini_ctx_desc(guc, client);
@@ -757,7 +752,7 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
{
struct i915_guc_client *client;
struct intel_guc *guc = &dev_priv->guc;
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
uint16_t db_id;
client = kzalloc(sizeof(*client), GFP_KERNEL);
@@ -777,13 +772,13 @@ guc_client_alloc(struct drm_i915_private *dev_priv,
}
/* The first page is doorbell/proc_desc. Two followed pages are wq. */
- obj = gem_allocate_guc_obj(dev_priv, GUC_DB_SIZE + GUC_WQ_SIZE);
- if (!obj)
+ vma = guc_allocate_vma(guc, GUC_DB_SIZE + GUC_WQ_SIZE);
+ if (IS_ERR(vma))
goto err;
/* We'll keep just the first (doorbell/proc) page permanently kmap'd. */
- client->client_obj = obj;
- client->client_base = kmap(i915_gem_object_get_page(obj, 0));
+ client->client = vma;
+ client->client_base = kmap(i915_gem_object_get_page(vma->obj, 0));
client->wq_offset = GUC_DB_SIZE;
client->wq_size = GUC_WQ_SIZE;
@@ -825,8 +820,7 @@ err:
static void guc_create_log(struct intel_guc *guc)
{
- struct drm_i915_private *dev_priv = guc_to_i915(guc);
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
unsigned long offset;
uint32_t size, flags;
@@ -842,16 +836,16 @@ static void guc_create_log(struct intel_guc *guc)
GUC_LOG_ISR_PAGES + 1 +
GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT;
- obj = guc->log_obj;
- if (!obj) {
- obj = gem_allocate_guc_obj(dev_priv, size);
- if (!obj) {
+ vma = guc->log;
+ if (!vma) {
+ vma = guc_allocate_vma(guc, size);
+ if (IS_ERR(vma)) {
/* logging will be off */
i915.guc_log_level = -1;
return;
}
- guc->log_obj = obj;
+ guc->log = vma;
}
/* each allocated unit is a page */
@@ -860,7 +854,7 @@ static void guc_create_log(struct intel_guc *guc)
(GUC_LOG_ISR_PAGES << GUC_LOG_ISR_SHIFT) |
(GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT);
- offset = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT; /* in pages */
+ offset = vma->node.start >> PAGE_SHIFT; /* in pages */
guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
}
@@ -889,7 +883,7 @@ static void init_guc_policies(struct guc_policies *policies)
static void guc_create_ads(struct intel_guc *guc)
{
struct drm_i915_private *dev_priv = guc_to_i915(guc);
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
struct guc_ads *ads;
struct guc_policies *policies;
struct guc_mmio_reg_state *reg_state;
@@ -902,16 +896,16 @@ static void guc_create_ads(struct intel_guc *guc)
sizeof(struct guc_mmio_reg_state) +
GUC_S3_SAVE_SPACE_PAGES * PAGE_SIZE;
- obj = guc->ads_obj;
- if (!obj) {
- obj = gem_allocate_guc_obj(dev_priv, PAGE_ALIGN(size));
- if (!obj)
+ vma = guc->ads;
+ if (!vma) {
+ vma = guc_allocate_vma(guc, PAGE_ALIGN(size));
+ if (IS_ERR(vma))
return;
- guc->ads_obj = obj;
+ guc->ads = vma;
}
- page = i915_gem_object_get_page(obj, 0);
+ page = i915_gem_object_get_page(vma->obj, 0);
ads = kmap(page);
/*
@@ -931,8 +925,7 @@ static void guc_create_ads(struct intel_guc *guc)
policies = (void *)ads + sizeof(struct guc_ads);
init_guc_policies(policies);
- ads->scheduler_policies = i915_gem_obj_ggtt_offset(obj) +
- sizeof(struct guc_ads);
+ ads->scheduler_policies = vma->node.start + sizeof(struct guc_ads);
/* MMIO reg state */
reg_state = (void *)policies + sizeof(struct guc_policies);
@@ -960,10 +953,9 @@ static void guc_create_ads(struct intel_guc *guc)
*/
int i915_guc_submission_init(struct drm_i915_private *dev_priv)
{
- const size_t ctxsize = sizeof(struct guc_context_desc);
- const size_t poolsize = GUC_MAX_GPU_CONTEXTS * ctxsize;
- const size_t gemsize = round_up(poolsize, PAGE_SIZE);
struct intel_guc *guc = &dev_priv->guc;
+ struct i915_vma *vma;
+ u32 size;
/* Wipe bitmap & delete client in case of reinitialisation */
bitmap_clear(guc->doorbell_bitmap, 0, GUC_MAX_DOORBELLS);
@@ -972,13 +964,15 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
if (!i915.enable_guc_submission)
return 0; /* not enabled */
- if (guc->ctx_pool_obj)
+ if (guc->ctx_pool)
return 0; /* already allocated */
- guc->ctx_pool_obj = gem_allocate_guc_obj(dev_priv, gemsize);
- if (!guc->ctx_pool_obj)
- return -ENOMEM;
+ size = PAGE_ALIGN(GUC_MAX_GPU_CONTEXTS*sizeof(struct guc_context_desc));
+ vma = guc_allocate_vma(guc, size);
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
+ guc->ctx_pool = vma;
ida_init(&guc->ctx_ids);
guc_create_log(guc);
guc_create_ads(guc);
@@ -1030,16 +1024,16 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
{
struct intel_guc *guc = &dev_priv->guc;
- gem_release_guc_obj(dev_priv->guc.ads_obj);
- guc->ads_obj = NULL;
+ guc_release_vma(guc->ads);
+ guc->ads = NULL;
- gem_release_guc_obj(dev_priv->guc.log_obj);
- guc->log_obj = NULL;
+ guc_release_vma(guc->log);
+ guc->log = NULL;
- if (guc->ctx_pool_obj)
+ if (guc->ctx_pool)
ida_destroy(&guc->ctx_ids);
- gem_release_guc_obj(guc->ctx_pool_obj);
- guc->ctx_pool_obj = NULL;
+ guc_release_vma(guc->ctx_pool);
+ guc->ctx_pool = NULL;
}
/**
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 623cf26cd784..a8da563cadb7 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -63,7 +63,7 @@ struct drm_i915_gem_request;
* retcode: errno from last guc_submit()
*/
struct i915_guc_client {
- struct drm_i915_gem_object *client_obj;
+ struct i915_vma *client;
void *client_base; /* first page (only) of above */
struct i915_gem_context *owner;
struct intel_guc *guc;
@@ -125,11 +125,10 @@ struct intel_guc_fw {
struct intel_guc {
struct intel_guc_fw guc_fw;
uint32_t log_flags;
- struct drm_i915_gem_object *log_obj;
+ struct i915_vma *log;
- struct drm_i915_gem_object *ads_obj;
-
- struct drm_i915_gem_object *ctx_pool_obj;
+ struct i915_vma *ads;
+ struct i915_vma *ctx_pool;
struct ida ctx_ids;
struct i915_guc_client *execbuf_client;
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 3763e30cc165..58ef4418a2ef 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -181,16 +181,15 @@ static void set_guc_init_params(struct drm_i915_private *dev_priv)
i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT;
}
- if (guc->ads_obj) {
- u32 ads = (u32)i915_gem_obj_ggtt_offset(guc->ads_obj)
- >> PAGE_SHIFT;
+ if (guc->ads) {
+ u32 ads = (u32)guc->ads->node.start >> PAGE_SHIFT;
params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT;
params[GUC_CTL_DEBUG] |= GUC_ADS_ENABLED;
}
/* If GuC submission is enabled, set up additional parameters here */
if (i915.enable_guc_submission) {
- u32 pgs = i915_gem_obj_ggtt_offset(dev_priv->guc.ctx_pool_obj);
+ u32 pgs = dev_priv->guc.ctx_pool->node.start;
u32 ctx_in_16 = GUC_MAX_GPU_CONTEXTS / 16;
pgs >>= PAGE_SHIFT;
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 07/13] drm/i915: Track pinned VMA
2016-08-05 9:05 First class i915_vma Chris Wilson
` (5 preceding siblings ...)
2016-08-05 9:05 ` [PATCH 06/13] drm/i915: Track pinned vma inside guc Chris Wilson
@ 2016-08-05 9:05 ` Chris Wilson
2016-08-05 9:05 ` [PATCH 08/13] drm/i915/overlay: Use VMA as the primary tracker for images Chris Wilson
` (6 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
Treat the VMA as the primary struct responsible for tracking bindings
into the GPU's VM. That is we want to treat the VMA returned after we
pin an object into the VM as the cookie we hold and eventually release
when unpinning. Doing so eliminates the ambiguity in pinning the object
and then searching for the relevant pin later.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_debugfs.c | 74 +++++----
drivers/gpu/drm/i915/i915_drv.h | 64 +++-----
drivers/gpu/drm/i915/i915_gem.c | 206 ++++++-------------------
drivers/gpu/drm/i915/i915_gem_context.c | 43 +++---
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 60 ++++----
drivers/gpu/drm/i915/i915_gem_fence.c | 64 ++++----
drivers/gpu/drm/i915/i915_gem_gtt.c | 63 +++++---
drivers/gpu/drm/i915/i915_gem_gtt.h | 14 --
drivers/gpu/drm/i915/i915_gem_render_state.c | 20 +--
drivers/gpu/drm/i915/i915_gem_render_state.h | 2 +-
drivers/gpu/drm/i915/i915_gem_request.c | 10 +-
drivers/gpu/drm/i915/i915_gem_request.h | 2 +-
drivers/gpu/drm/i915/i915_gem_stolen.c | 2 +-
drivers/gpu/drm/i915/i915_gem_tiling.c | 40 +++--
drivers/gpu/drm/i915/i915_gpu_error.c | 58 +++----
drivers/gpu/drm/i915/i915_guc_submission.c | 28 ++--
drivers/gpu/drm/i915/intel_display.c | 57 ++++---
drivers/gpu/drm/i915/intel_drv.h | 5 +-
drivers/gpu/drm/i915/intel_fbc.c | 2 +-
drivers/gpu/drm/i915/intel_fbdev.c | 19 +--
drivers/gpu/drm/i915/intel_guc_loader.c | 29 ++--
drivers/gpu/drm/i915/intel_lrc.c | 115 +++++++-------
drivers/gpu/drm/i915/intel_overlay.c | 43 +++---
drivers/gpu/drm/i915/intel_ringbuffer.c | 218 ++++++++++++++-------------
drivers/gpu/drm/i915/intel_ringbuffer.h | 17 +--
drivers/gpu/drm/i915/intel_sprite.c | 8 +-
26 files changed, 560 insertions(+), 703 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 360ed15a3f60..de312824f9bd 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -111,7 +111,7 @@ static char get_tiling_flag(struct drm_i915_gem_object *obj)
static char get_global_flag(struct drm_i915_gem_object *obj)
{
- return i915_gem_obj_to_ggtt(obj) ? 'g' : ' ';
+ return i915_gem_object_to_ggtt(obj, NULL) ? 'g' : ' ';
}
static char get_pin_mapped_flag(struct drm_i915_gem_object *obj)
@@ -278,7 +278,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj;
- u64 total_obj_size, total_gtt_size;
+ u64 total_obj_size;
LIST_HEAD(stolen);
int count, ret;
@@ -286,7 +286,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
if (ret)
return ret;
- total_obj_size = total_gtt_size = count = 0;
+ total_obj_size = count = 0;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
if (obj->stolen == NULL)
continue;
@@ -294,7 +294,6 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
list_add(&obj->obj_exec_link, &stolen);
total_obj_size += obj->base.size;
- total_gtt_size += i915_gem_obj_total_ggtt_size(obj);
count++;
}
list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
@@ -317,8 +316,8 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
}
mutex_unlock(&dev->struct_mutex);
- seq_printf(m, "Total %d objects, %llu bytes, %llu GTT size\n",
- count, total_obj_size, total_gtt_size);
+ seq_printf(m, "Total %d objects, %llu bytes\n",
+ count, total_obj_size);
return 0;
}
@@ -327,7 +326,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
size += i915_gem_obj_total_ggtt_size(obj); \
++count; \
if (obj->map_and_fenceable) { \
- mappable_size += i915_gem_obj_ggtt_size(obj); \
+ mappable_size += obj->base.size; \
++mappable_count; \
} \
} \
@@ -449,10 +448,10 @@ static void print_context_stats(struct seq_file *m,
#define count_vmas(list, member) do { \
list_for_each_entry(vma, list, member) { \
- size += i915_gem_obj_total_ggtt_size(vma->obj); \
+ size += vma->size; \
++count; \
if (vma->obj->map_and_fenceable) { \
- mappable_size += i915_gem_obj_ggtt_size(vma->obj); \
+ mappable_size += vma->size; \
++mappable_count; \
} \
} \
@@ -515,11 +514,11 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
size = count = mappable_size = mappable_count = 0;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
if (obj->fault_mappable) {
- size += i915_gem_obj_ggtt_size(obj);
+ size += obj->base.size;
++count;
}
if (obj->pin_display) {
- mappable_size += i915_gem_obj_ggtt_size(obj);
+ mappable_size += obj->base.size;
++mappable_count;
}
if (obj->madv == I915_MADV_DONTNEED) {
@@ -587,30 +586,29 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data)
uintptr_t list = (uintptr_t) node->info_ent->data;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj;
- u64 total_obj_size, total_gtt_size;
+ u64 total_obj_size;
int count, ret;
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
- total_obj_size = total_gtt_size = count = 0;
+ total_obj_size = count = 0;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
- if (list == PINNED_LIST && !i915_gem_obj_is_pinned(obj))
+ if (list == PINNED_LIST && !obj->pin_display)
continue;
seq_puts(m, " ");
describe_obj(m, obj);
seq_putc(m, '\n');
total_obj_size += obj->base.size;
- total_gtt_size += i915_gem_obj_total_ggtt_size(obj);
count++;
}
mutex_unlock(&dev->struct_mutex);
- seq_printf(m, "Total %d objects, %llu bytes, %llu GTT size\n",
- count, total_obj_size, total_gtt_size);
+ seq_printf(m, "Total %d objects, %llu bytes\n",
+ count, total_obj_size);
return 0;
}
@@ -2095,38 +2093,36 @@ static void i915_dump_lrc_obj(struct seq_file *m,
struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
- struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
+ struct drm_i915_gem_object *obj = ctx->engine[engine->id].state;
+ struct i915_vma *vma = ctx->engine[engine->id].vma;
struct page *page;
- uint32_t *reg_state;
int j;
- unsigned long ggtt_offset = 0;
seq_printf(m, "CONTEXT: %s %u\n", engine->name, ctx->hw_id);
-
- if (ctx_obj == NULL) {
- seq_puts(m, "\tNot allocated\n");
+ if (!vma) {
+ seq_puts(m, "\tNot bound in GGTT\n");
return;
+ } else {
+ seq_printf(m, "\tBound in GGTT at %x\n",
+ lower_32_bits(vma->node.start));
}
- if (!i915_gem_obj_ggtt_bound(ctx_obj))
- seq_puts(m, "\tNot bound in GGTT\n");
- else
- ggtt_offset = i915_gem_obj_ggtt_offset(ctx_obj);
-
- if (i915_gem_object_get_pages(ctx_obj)) {
- seq_puts(m, "\tFailed to get pages for context object\n");
+ if (i915_gem_object_get_pages(obj)) {
+ seq_puts(m, "\tFailed to get pages for context object\n\n");
return;
}
- page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
- if (!WARN_ON(page == NULL)) {
- reg_state = kmap_atomic(page);
-
+ page = i915_gem_object_get_page(obj, LRC_STATE_PN);
+ if (page) {
+ u32 *reg_state = kmap_atomic(page);
for (j = 0; j < 0x600 / sizeof(u32) / 4; j += 4) {
- seq_printf(m, "\t[0x%08lx] 0x%08x 0x%08x 0x%08x 0x%08x\n",
- ggtt_offset + 4096 + (j * 4),
- reg_state[j], reg_state[j + 1],
- reg_state[j + 2], reg_state[j + 3]);
+ seq_printf(m,
+ "\t[0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ j * 4,
+ reg_state[j],
+ reg_state[j + 1],
+ reg_state[j + 2],
+ reg_state[j + 3]);
}
kunmap_atomic(reg_state);
}
@@ -3246,7 +3242,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
struct page *page;
uint64_t *seqno;
- page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0);
+ page = i915_gem_object_get_page(dev_priv->semaphore_vma->obj, 0);
seqno = (uint64_t *)kmap_atomic(page);
for_each_engine_id(engine, dev_priv, id) {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9a7ffa49cd1f..a2ab4c6f9ba2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -893,8 +893,8 @@ struct i915_gem_context {
struct intel_context {
struct drm_i915_gem_object *state;
+ struct i915_vma *vma;
struct intel_ring *ring;
- struct i915_vma *lrc_vma;
uint32_t *lrc_reg_state;
u64 lrc_desc;
int pin_count;
@@ -1755,7 +1755,7 @@ struct drm_i915_private {
struct pci_dev *bridge_dev;
struct i915_gem_context *kernel_context;
struct intel_engine_cs engine[I915_NUM_ENGINES];
- struct drm_i915_gem_object *semaphore_obj;
+ struct i915_vma *semaphore_vma;
u32 next_seqno;
struct drm_dma_handle *status_page_dmah;
@@ -3067,7 +3067,7 @@ struct drm_i915_gem_object *i915_gem_object_create_from_data(
void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file);
void i915_gem_free_object(struct drm_gem_object *obj);
-int __must_check
+struct i915_vma * __must_check
i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
const struct i915_ggtt_view *view,
u64 size,
@@ -3263,12 +3263,11 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
bool write);
int __must_check
i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write);
-int __must_check
+struct i915_vma * __must_check
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
u32 alignment,
const struct i915_ggtt_view *view);
-void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view);
+void i915_gem_object_unpin_from_display_plane(struct i915_vma *vma);
int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
int align);
int i915_gem_open(struct drm_device *dev, struct drm_file *file);
@@ -3288,63 +3287,34 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *gem_obj, int flags);
-u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
- const struct i915_ggtt_view *view);
-u64 i915_gem_obj_offset(struct drm_i915_gem_object *o,
- struct i915_address_space *vm);
-static inline u64
-i915_gem_obj_ggtt_offset(struct drm_i915_gem_object *o)
-{
- return i915_gem_obj_ggtt_offset_view(o, &i915_ggtt_view_normal);
-}
-
-bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o,
- const struct i915_ggtt_view *view);
-bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
- struct i915_address_space *vm);
-
struct i915_vma *
i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm);
-struct i915_vma *
-i915_gem_obj_to_ggtt_view(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view);
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view);
struct i915_vma *
i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm);
-struct i915_vma *
-i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view);
-
-static inline struct i915_vma *
-i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj)
-{
- return i915_gem_obj_to_ggtt_view(obj, &i915_ggtt_view_normal);
-}
-bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj);
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view);
-/* Some GGTT VM helpers */
static inline struct i915_hw_ppgtt *
i915_vm_to_ppgtt(struct i915_address_space *vm)
{
return container_of(vm, struct i915_hw_ppgtt, base);
}
-static inline bool i915_gem_obj_ggtt_bound(struct drm_i915_gem_object *obj)
+static inline struct i915_vma *
+i915_gem_object_to_ggtt(struct drm_i915_gem_object *obj,
+ const struct i915_ggtt_view *view)
{
- return i915_gem_obj_ggtt_bound_view(obj, &i915_ggtt_view_normal);
+ return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view);
}
-unsigned long
-i915_gem_obj_ggtt_size(struct drm_i915_gem_object *obj);
-
-void i915_gem_object_ggtt_unpin_view(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view);
-static inline void
-i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj)
+static inline unsigned long
+i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
+ const struct i915_ggtt_view *view)
{
- i915_gem_object_ggtt_unpin_view(obj, &i915_ggtt_view_normal);
+ return i915_gem_object_to_ggtt(o, view)->node.start;
}
/* i915_gem_fence.c */
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index f4f8eaa90f2a..cc79af54fd20 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -737,14 +737,15 @@ i915_gem_gtt_pread(struct drm_device *dev,
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
+ struct i915_vma *vma;
struct drm_mm_node node;
char __user *user_data;
uint64_t remain;
uint64_t offset;
int ret;
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
- if (ret) {
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
+ if (IS_ERR(vma)) {
ret = insert_mappable_node(dev_priv, &node, PAGE_SIZE);
if (ret)
goto out;
@@ -757,7 +758,7 @@ i915_gem_gtt_pread(struct drm_device *dev,
i915_gem_object_pin_pages(obj);
} else {
- node.start = i915_gem_obj_ggtt_offset(obj);
+ node.start = vma->node.start;
node.allocated = false;
ret = i915_gem_object_put_fence(obj);
if (ret)
@@ -838,7 +839,7 @@ out_unpin:
i915_gem_object_unpin_pages(obj);
remove_mappable_node(&node);
} else {
- i915_gem_object_ggtt_unpin(obj);
+ i915_vma_unpin(vma);
}
out:
return ret;
@@ -1036,6 +1037,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
{
struct i915_ggtt *ggtt = &i915->ggtt;
struct drm_device *dev = obj->base.dev;
+ struct i915_vma *vma;
struct drm_mm_node node;
uint64_t remain, offset;
char __user *user_data;
@@ -1045,9 +1047,9 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
if (i915_gem_object_is_tiled(obj))
return -EFAULT;
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
PIN_MAPPABLE | PIN_NONBLOCK);
- if (ret) {
+ if (IS_ERR(vma)) {
ret = insert_mappable_node(i915, &node, PAGE_SIZE);
if (ret)
goto out;
@@ -1060,7 +1062,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
i915_gem_object_pin_pages(obj);
} else {
- node.start = i915_gem_obj_ggtt_offset(obj);
+ node.start = vma->node.start;
node.allocated = false;
ret = i915_gem_object_put_fence(obj);
if (ret)
@@ -1148,7 +1150,7 @@ out_unpin:
i915_gem_object_unpin_pages(obj);
remove_mappable_node(&node);
} else {
- i915_gem_object_ggtt_unpin(obj);
+ i915_vma_unpin(vma);
}
out:
return ret;
@@ -1635,9 +1637,9 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
struct drm_i915_gem_object *obj = to_intel_bo(vma->vm_private_data);
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_ggtt_view view = i915_ggtt_view_normal;
bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
+ struct i915_vma *ggtt;
pgoff_t page_offset;
unsigned long pfn;
int ret;
@@ -1670,7 +1672,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
}
/* Use a partial view if the object is bigger than the aperture. */
- if (obj->base.size >= ggtt->mappable_end &&
+ if (obj->base.size >= dev_priv->ggtt.mappable_end &&
!i915_gem_object_is_tiled(obj)) {
static const unsigned int chunk_size = 256; // 1 MiB
@@ -1685,9 +1687,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
}
/* Now pin it into the GTT if needed */
- ret = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE);
- if (ret)
+ ggtt = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE);
+ if (IS_ERR(ggtt)) {
+ ret = PTR_ERR(ggtt);
goto err_unlock;
+ }
ret = i915_gem_object_set_to_gtt_domain(obj, write);
if (ret)
@@ -1698,8 +1702,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
goto err_unpin;
/* Finally, remap it using the new GTT offset */
- pfn = ggtt->mappable_base +
- i915_gem_obj_ggtt_offset_view(obj, &view);
+ pfn = dev_priv->ggtt.mappable_base + ggtt->node.start;
pfn >>= PAGE_SHIFT;
if (unlikely(view.type == I915_GGTT_VIEW_PARTIAL)) {
@@ -1741,7 +1744,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
pfn + page_offset);
}
err_unpin:
- i915_gem_object_ggtt_unpin_view(obj, &view);
+ __i915_vma_unpin(ggtt);
err_unlock:
mutex_unlock(&dev->struct_mutex);
err_rpm:
@@ -3200,7 +3203,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
old_write_domain);
/* And bump the LRU for this access */
- vma = i915_gem_obj_to_ggtt(obj);
+ vma = i915_gem_object_to_ggtt(obj, NULL);
if (vma &&
drm_mm_node_allocated(&vma->node) &&
!i915_vma_is_active(vma))
@@ -3424,11 +3427,12 @@ rpm_put:
* Can be called from an uninterruptible phase (modesetting) and allows
* any flushes to be pipelined (for pageflips).
*/
-int
+struct i915_vma *
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
u32 alignment,
const struct i915_ggtt_view *view)
{
+ struct i915_vma *vma;
u32 old_read_domains, old_write_domain;
int ret;
@@ -3448,19 +3452,23 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
*/
ret = i915_gem_object_set_cache_level(obj,
HAS_WT(obj->base.dev) ? I915_CACHE_WT : I915_CACHE_NONE);
- if (ret)
+ if (ret) {
+ vma = ERR_PTR(ret);
goto err_unpin_display;
+ }
/* As the user may map the buffer once pinned in the display plane
* (e.g. libkms for the bootup splash), we have to ensure that we
* always use map_and_fenceable for all scanout buffers.
*/
- ret = i915_gem_object_ggtt_pin(obj, view, 0, alignment,
+ vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment,
view->type == I915_GGTT_VIEW_NORMAL ?
PIN_MAPPABLE : 0);
- if (ret)
+ if (IS_ERR(vma))
goto err_unpin_display;
+ WARN_ON(obj->pin_display > i915_vma_pin_count(vma));
+
i915_gem_object_flush_cpu_write_domain(obj);
old_write_domain = obj->base.write_domain;
@@ -3476,23 +3484,23 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
old_read_domains,
old_write_domain);
- return 0;
+ return vma;
err_unpin_display:
obj->pin_display--;
- return ret;
+ return vma;
}
void
-i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view)
+i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
{
- if (WARN_ON(obj->pin_display == 0))
+ if (WARN_ON(vma->obj->pin_display == 0))
return;
- i915_gem_object_ggtt_unpin_view(obj, view);
+ vma->obj->pin_display--;
- obj->pin_display--;
+ i915_vma_unpin(vma);
+ WARN_ON(vma->obj->pin_display > i915_vma_pin_count(vma));
}
/**
@@ -3689,27 +3697,25 @@ err:
return ret;
}
-int
+struct i915_vma *
i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view,
+ const struct i915_ggtt_view *ggtt_view,
u64 size,
u64 alignment,
u64 flags)
{
+ struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
struct i915_vma *vma;
int ret;
- if (!view)
- view = &i915_ggtt_view_normal;
-
- vma = i915_gem_obj_lookup_or_create_ggtt_vma(obj, view);
+ vma = i915_gem_obj_lookup_or_create_vma(obj, vm, ggtt_view);
if (IS_ERR(vma))
- return PTR_ERR(vma);
+ return vma;
if (i915_vma_misplaced(vma, size, alignment, flags)) {
if (flags & PIN_NONBLOCK &&
(i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
- return -ENOSPC;
+ return ERR_PTR(-ENOSPC);
WARN(i915_vma_is_pinned(vma),
"bo is already pinned in ggtt with incorrect alignment:"
@@ -3722,17 +3728,14 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
obj->map_and_fenceable);
ret = i915_vma_unbind(vma);
if (ret)
- return ret;
+ return ERR_PTR(ret);
}
- return i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL);
-}
+ ret = i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL);
+ if (ret)
+ return ERR_PTR(ret);
-void
-i915_gem_object_ggtt_unpin_view(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view)
-{
- i915_vma_unpin(i915_gem_obj_to_ggtt_view(obj, view));
+ return vma;
}
static __always_inline unsigned __busy_read_flag(unsigned int id)
@@ -4082,32 +4085,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
intel_runtime_pm_put(dev_priv);
}
-struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm)
-{
- struct i915_vma *vma;
- list_for_each_entry(vma, &obj->vma_list, obj_link) {
- if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL &&
- vma->vm == vm)
- return vma;
- }
- return NULL;
-}
-
-struct i915_vma *i915_gem_obj_to_ggtt_view(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view)
-{
- struct i915_vma *vma;
-
- GEM_BUG_ON(!view);
-
- list_for_each_entry(vma, &obj->vma_list, obj_link)
- if (i915_vma_is_ggtt(vma) &&
- i915_ggtt_view_equal(&vma->ggtt_view, view))
- return vma;
- return NULL;
-}
-
int i915_gem_suspend(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -4575,97 +4552,6 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
}
}
-/* All the new VM stuff */
-u64 i915_gem_obj_offset(struct drm_i915_gem_object *o,
- struct i915_address_space *vm)
-{
- struct drm_i915_private *dev_priv = to_i915(o->base.dev);
- struct i915_vma *vma;
-
- WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base);
-
- list_for_each_entry(vma, &o->vma_list, obj_link) {
- if (i915_vma_is_ggtt(vma) &&
- vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
- continue;
- if (vma->vm == vm)
- return vma->node.start;
- }
-
- WARN(1, "%s vma for this object not found.\n",
- i915_is_ggtt(vm) ? "global" : "ppgtt");
- return -1;
-}
-
-u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
- const struct i915_ggtt_view *view)
-{
- struct i915_vma *vma;
-
- list_for_each_entry(vma, &o->vma_list, obj_link)
- if (i915_vma_is_ggtt(vma) &&
- i915_ggtt_view_equal(&vma->ggtt_view, view))
- return vma->node.start;
-
- WARN(1, "global vma for this object not found. (view=%u)\n", view->type);
- return -1;
-}
-
-bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
- struct i915_address_space *vm)
-{
- struct i915_vma *vma;
-
- list_for_each_entry(vma, &o->vma_list, obj_link) {
- if (i915_vma_is_ggtt(vma) &&
- vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
- continue;
- if (vma->vm == vm && drm_mm_node_allocated(&vma->node))
- return true;
- }
-
- return false;
-}
-
-bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o,
- const struct i915_ggtt_view *view)
-{
- struct i915_vma *vma;
-
- list_for_each_entry(vma, &o->vma_list, obj_link)
- if (i915_vma_is_ggtt(vma) &&
- i915_ggtt_view_equal(&vma->ggtt_view, view) &&
- drm_mm_node_allocated(&vma->node))
- return true;
-
- return false;
-}
-
-unsigned long i915_gem_obj_ggtt_size(struct drm_i915_gem_object *o)
-{
- struct i915_vma *vma;
-
- GEM_BUG_ON(list_empty(&o->vma_list));
-
- list_for_each_entry(vma, &o->vma_list, obj_link) {
- if (i915_vma_is_ggtt(vma) &&
- vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
- return vma->node.size;
- }
-
- return 0;
-}
-
-bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj)
-{
- struct i915_vma *vma;
- list_for_each_entry(vma, &obj->vma_list, obj_link)
- if (i915_vma_is_pinned(vma))
- return true;
-
- return false;
-}
-
/* Like i915_gem_object_get_page(), but mark the returned page dirty */
struct page *
i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index bb72af5320b0..e515050c194b 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -398,8 +398,8 @@ static void i915_gem_context_unpin(struct i915_gem_context *ctx,
} else {
struct intel_context *ce = &ctx->engine[engine->id];
- if (ce->state)
- i915_gem_object_ggtt_unpin(ce->state);
+ if (ce->vma)
+ i915_vma_unpin(ce->vma);
i915_gem_context_put(ctx);
}
@@ -620,9 +620,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_SET_CONTEXT);
- intel_ring_emit(ring,
- i915_gem_obj_ggtt_offset(req->ctx->engine[RCS].state) |
- flags);
+ intel_ring_emit(ring, req->ctx->engine[RCS].vma->node.start | flags);
/*
* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
* WaMiSetContext_Hang:snb,ivb,vlv
@@ -651,7 +649,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
MI_STORE_REGISTER_MEM |
MI_SRM_LRM_GLOBAL_GTT);
intel_ring_emit_reg(ring, last_reg);
- intel_ring_emit(ring, engine->scratch.gtt_offset);
+ intel_ring_emit(ring, engine->scratch->node.start);
intel_ring_emit(ring, MI_NOOP);
}
intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
@@ -756,6 +754,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
struct intel_engine_cs *engine = req->engine;
struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt;
struct i915_gem_context *from;
+ struct i915_vma *vma;
u32 hw_flags;
int ret, i;
@@ -763,10 +762,17 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
return 0;
/* Trying to pin first makes error handling easier. */
- ret = i915_gem_object_ggtt_pin(to->engine[RCS].state, NULL, 0,
+ vma = i915_gem_object_ggtt_pin(to->engine[RCS].state, NULL, 0,
to->ggtt_alignment, 0);
- if (ret)
- return ret;
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
+
+ to->engine[RCS].vma = vma;
+
+ if (WARN_ON(!(vma->flags & I915_VMA_GLOBAL_BIND))) {
+ ret = -ENODEV;
+ goto unpin_vma;
+ }
/*
* Pin can switch back to the default context if we end up calling into
@@ -787,7 +793,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
*/
ret = i915_gem_object_set_to_gtt_domain(to->engine[RCS].state, false);
if (ret)
- goto unpin_out;
+ goto unpin_vma;
if (needs_pd_load_pre(ppgtt, engine, to)) {
/* Older GENs and non render rings still want the load first,
@@ -797,7 +803,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
trace_switch_mm(engine, to);
ret = ppgtt->switch_mm(ppgtt, req);
if (ret)
- goto unpin_out;
+ goto unpin_vma;
}
if (!to->engine[RCS].initialised || i915_gem_context_is_default(to))
@@ -814,7 +820,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
if (to != from || (hw_flags & MI_FORCE_RESTORE)) {
ret = mi_set_context(req, hw_flags);
if (ret)
- goto unpin_out;
+ goto unpin_vma;
}
/* The backing object for the context is done after switching to the
@@ -824,8 +830,6 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
* MI_SET_CONTEXT instead of when the next seqno has completed.
*/
if (from != NULL) {
- struct drm_i915_gem_object *obj = from->engine[RCS].state;
-
/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
* whole damn pipeline, we don't need to explicitly mark the
* object dirty. The only exception is that the context must be
@@ -833,11 +837,10 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
* able to defer doing this until we know the object would be
* swapped, but there is no way to do that yet.
*/
- obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
- i915_vma_move_to_active(i915_gem_obj_to_ggtt(obj), req, 0);
-
+ i915_vma_move_to_active(from->engine[RCS].vma, req, 0);
/* obj is kept alive until the next request by its active ref */
- i915_gem_object_ggtt_unpin(obj);
+ i915_vma_unpin(from->engine[RCS].vma);
+
i915_gem_context_put(from);
}
engine->last_context = i915_gem_context_get(to);
@@ -882,8 +885,8 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
return 0;
-unpin_out:
- i915_gem_object_ggtt_unpin(to->engine[RCS].state);
+unpin_vma:
+ i915_vma_unpin(vma);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index c8d13fea4b25..160867f48f91 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -180,8 +180,8 @@ eb_lookup_vmas(struct eb_vmas *eb,
* from the (obj, vm) we don't run the risk of creating
* duplicated vmas for the same vm.
*/
- vma = i915_gem_obj_lookup_or_create_vma(obj, vm);
- if (IS_ERR(vma)) {
+ vma = i915_gem_obj_lookup_or_create_vma(obj, vm, NULL);
+ if (unlikely(IS_ERR(vma))) {
DRM_DEBUG("Failed to lookup VMA\n");
ret = PTR_ERR(vma);
goto err;
@@ -349,30 +349,34 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
struct drm_i915_gem_relocation_entry *reloc,
uint64_t target_offset)
{
- struct drm_device *dev = obj->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
+ struct i915_vma *vma;
uint64_t delta = relocation_target(reloc, target_offset);
uint64_t offset;
void __iomem *reloc_page;
int ret;
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
+
ret = i915_gem_object_set_to_gtt_domain(obj, true);
if (ret)
- return ret;
+ goto unpin;
ret = i915_gem_object_put_fence(obj);
if (ret)
- return ret;
+ goto unpin;
/* Map the page containing the relocation we're going to perform. */
- offset = i915_gem_obj_ggtt_offset(obj);
+ offset = vma->node.start;
offset += reloc->offset;
reloc_page = io_mapping_map_atomic_wc(ggtt->mappable,
offset & PAGE_MASK);
iowrite32(lower_32_bits(delta), reloc_page + offset_in_page(offset));
- if (INTEL_INFO(dev)->gen >= 8) {
+ if (INTEL_GEN(dev_priv) >= 8) {
offset += sizeof(uint32_t);
if (offset_in_page(offset) == 0) {
@@ -388,7 +392,9 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
io_mapping_unmap_atomic(reloc_page);
- return 0;
+unpin:
+ i915_vma_unpin(vma);
+ return ret;
}
static void
@@ -1281,7 +1287,7 @@ i915_reset_gen7_sol_offsets(struct drm_i915_gem_request *req)
return 0;
}
-static struct i915_vma*
+static struct i915_vma *
i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
struct drm_i915_gem_exec_object2 *shadow_exec_entry,
struct drm_i915_gem_object *batch_obj,
@@ -1305,31 +1311,30 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
batch_start_offset,
batch_len,
is_master);
- if (ret)
+ if (ret) {
+ if (ret == -EACCES) /* unhandled chained batch */
+ vma = NULL;
+ else
+ vma = ERR_PTR(ret);
goto err;
+ }
- ret = i915_gem_object_ggtt_pin(shadow_batch_obj, NULL, 0, 0, 0);
- if (ret)
+ vma = i915_gem_object_ggtt_pin(shadow_batch_obj, NULL, 0, 0, 0);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
goto err;
-
- i915_gem_object_unpin_pages(shadow_batch_obj);
+ }
memset(shadow_exec_entry, 0, sizeof(*shadow_exec_entry));
- vma = i915_gem_obj_to_ggtt(shadow_batch_obj);
vma->exec_entry = shadow_exec_entry;
vma->exec_entry->flags = __EXEC_OBJECT_HAS_PIN;
i915_gem_object_get(shadow_batch_obj);
list_add_tail(&vma->exec_list, &eb->vmas);
- return vma;
-
err:
i915_gem_object_unpin_pages(shadow_batch_obj);
- if (ret == -EACCES) /* unhandled chained batch */
- return NULL;
- else
- return ERR_PTR(ret);
+ return vma;
}
static int
@@ -1677,6 +1682,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
* hsw should have this fixed, but bdw mucks it up again. */
if (dispatch_flags & I915_DISPATCH_SECURE) {
struct drm_i915_gem_object *obj = params->batch->obj;
+ struct i915_vma *vma;
/*
* So on first glance it looks freaky that we pin the batch here
@@ -1688,11 +1694,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
* fitting due to fragmentation.
* So this is actually safe.
*/
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
- if (ret)
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
goto err;
+ }
- params->batch = i915_gem_obj_to_ggtt(obj);
+ params->batch = vma;
}
/* Allocate a request for this batch buffer nice and early. */
@@ -1708,7 +1716,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
* inactive_list and lose its active reference. Hence we do not need
* to explicitly hold another reference here.
*/
- params->request->batch_obj = params->batch->obj;
+ params->request->batch = params->batch;
ret = i915_gem_request_add_to_client(params->request, file);
if (ret)
diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c
index 9e8173fe2a09..fdd7137a3ebf 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence.c
@@ -85,22 +85,16 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
POSTING_READ(fence_reg_lo);
if (obj) {
- u32 size = i915_gem_obj_ggtt_size(obj);
unsigned int tiling = i915_gem_object_get_tiling(obj);
unsigned int stride = i915_gem_object_get_stride(obj);
- uint64_t val;
-
- /* Adjust fence size to match tiled area */
- if (tiling != I915_TILING_NONE) {
- uint32_t row_size = stride *
- (tiling == I915_TILING_Y ? 32 : 8);
- size = (size / row_size) * row_size;
- }
-
- val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) &
- 0xfffff000) << 32;
- val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000;
- val |= (uint64_t)((stride / 128) - 1) << fence_pitch_shift;
+ struct i915_vma *vma = i915_gem_object_to_ggtt(obj, NULL);
+ u32 row_size = stride * (tiling == I915_TILING_Y ? 32 : 8);
+ u32 size = (u32)vma->node.size / row_size * row_size;
+ u64 val;
+
+ val = ((vma->node.start + size - 4096) & 0xfffff000) << 32;
+ val |= vma->node.start & 0xfffff000;
+ val |= (u64)((stride / 128) - 1) << fence_pitch_shift;
if (tiling == I915_TILING_Y)
val |= 1 << I965_FENCE_TILING_Y_SHIFT;
val |= I965_FENCE_REG_VALID;
@@ -123,17 +117,19 @@ static void i915_write_fence_reg(struct drm_device *dev, int reg,
u32 val;
if (obj) {
- u32 size = i915_gem_obj_ggtt_size(obj);
+ struct i915_vma *vma = i915_gem_object_to_ggtt(obj, NULL);
unsigned int tiling = i915_gem_object_get_tiling(obj);
unsigned int stride = i915_gem_object_get_stride(obj);
int pitch_val;
int tile_width;
- WARN((i915_gem_obj_ggtt_offset(obj) & ~I915_FENCE_START_MASK) ||
- (size & -size) != size ||
- (i915_gem_obj_ggtt_offset(obj) & (size - 1)),
- "object 0x%08llx [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n",
- i915_gem_obj_ggtt_offset(obj), obj->map_and_fenceable, size);
+ WARN((vma->node.start & ~I915_FENCE_START_MASK) ||
+ !is_power_of_2(vma->node.size) ||
+ (vma->node.start & (vma->node.size - 1)),
+ "object 0x%08lx [fenceable? %d] not 1M or pot-size (0x%08lx) aligned\n",
+ (long)vma->node.start,
+ obj->map_and_fenceable,
+ (long)vma->node.size);
if (tiling == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
tile_width = 128;
@@ -144,10 +140,10 @@ static void i915_write_fence_reg(struct drm_device *dev, int reg,
pitch_val = stride / tile_width;
pitch_val = ffs(pitch_val) - 1;
- val = i915_gem_obj_ggtt_offset(obj);
+ val = vma->node.start;
if (tiling == I915_TILING_Y)
val |= 1 << I830_FENCE_TILING_Y_SHIFT;
- val |= I915_FENCE_SIZE_BITS(size);
+ val |= I915_FENCE_SIZE_BITS(vma->node.size);
val |= pitch_val << I830_FENCE_PITCH_SHIFT;
val |= I830_FENCE_REG_VALID;
} else
@@ -164,24 +160,24 @@ static void i830_write_fence_reg(struct drm_device *dev, int reg,
uint32_t val;
if (obj) {
- u32 size = i915_gem_obj_ggtt_size(obj);
+ struct i915_vma *vma = i915_gem_object_to_ggtt(obj, NULL);
unsigned int tiling = i915_gem_object_get_tiling(obj);
unsigned int stride = i915_gem_object_get_stride(obj);
uint32_t pitch_val;
- WARN((i915_gem_obj_ggtt_offset(obj) & ~I830_FENCE_START_MASK) ||
- (size & -size) != size ||
- (i915_gem_obj_ggtt_offset(obj) & (size - 1)),
- "object 0x%08llx not 512K or pot-size 0x%08x aligned\n",
- i915_gem_obj_ggtt_offset(obj), size);
+ WARN((vma->node.start & ~I830_FENCE_START_MASK) ||
+ !is_power_of_2(vma->node.size) ||
+ (vma->node.start & (vma->node.size - 1)),
+ "object 0x%08lx not 512K or pot-size 0x%08lx aligned\n",
+ (long)vma->node.start, (long)vma->node.size);
pitch_val = stride / 128;
pitch_val = ffs(pitch_val) - 1;
- val = i915_gem_obj_ggtt_offset(obj);
+ val = vma->node.start;
if (tiling == I915_TILING_Y)
val |= 1 << I830_FENCE_TILING_Y_SHIFT;
- val |= I830_FENCE_SIZE_BITS(size);
+ val |= I830_FENCE_SIZE_BITS(vma->node.size);
val |= pitch_val << I830_FENCE_PITCH_SHIFT;
val |= I830_FENCE_REG_VALID;
} else
@@ -435,13 +431,7 @@ bool
i915_gem_object_pin_fence(struct drm_i915_gem_object *obj)
{
if (obj->fence_reg != I915_FENCE_REG_NONE) {
- struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
- struct i915_vma *ggtt_vma = i915_gem_obj_to_ggtt(obj);
-
- WARN_ON(!ggtt_vma ||
- dev_priv->fence_regs[obj->fence_reg].pin_count >
- i915_vma_pin_count(ggtt_vma));
- dev_priv->fence_regs[obj->fence_reg].pin_count++;
+ to_i915(obj->base.dev)->fence_regs[obj->fence_reg].pin_count++;
return true;
} else
return false;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 8b4f2f35019c..7c9f654d515a 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3350,14 +3350,10 @@ __i915_gem_vma_create(struct drm_i915_gem_object *obj,
GEM_BUG_ON(vm->closed);
- if (WARN_ON(i915_is_ggtt(vm) != !!view))
- return ERR_PTR(-EINVAL);
-
vma = kmem_cache_zalloc(to_i915(obj->base.dev)->vmas, GFP_KERNEL);
if (vma == NULL)
return ERR_PTR(-ENOMEM);
- INIT_LIST_HEAD(&vma->obj_link);
INIT_LIST_HEAD(&vma->exec_list);
for (i = 0; i < ARRAY_SIZE(vma->last_read); i++)
init_request_active(&vma->last_read[i], i915_vma_retire);
@@ -3366,8 +3362,7 @@ __i915_gem_vma_create(struct drm_i915_gem_object *obj,
vma->obj = obj;
vma->size = obj->base.size;
- if (i915_is_ggtt(vm)) {
- vma->flags |= I915_VMA_GGTT;
+ if (view) {
vma->ggtt_view = *view;
if (view->type == I915_GGTT_VIEW_PARTIAL) {
vma->size = view->params.partial.size;
@@ -3377,46 +3372,66 @@ __i915_gem_vma_create(struct drm_i915_gem_object *obj,
intel_rotation_info_size(&view->params.rotated);
vma->size <<= PAGE_SHIFT;
}
+ }
+
+ if (i915_is_ggtt(vm)) {
+ vma->flags |= I915_VMA_GGTT;
} else {
i915_ppgtt_get(i915_vm_to_ppgtt(vm));
}
list_add_tail(&vma->obj_link, &obj->vma_list);
-
return vma;
}
+static inline bool vma_matches(struct i915_vma *vma,
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view)
+{
+ if (vma->vm != vm)
+ return false;
+
+ if (!i915_vma_is_ggtt(vma))
+ return true;
+
+ if (!view)
+ return vma->ggtt_view.type == 0;
+
+ if (vma->ggtt_view.type != view->type)
+ return false;
+
+ return memcmp(&vma->ggtt_view.params,
+ &view->params,
+ sizeof(view->params)) == 0;
+}
+
struct i915_vma *
-i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm)
+i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view)
{
struct i915_vma *vma;
- vma = i915_gem_obj_to_vma(obj, vm);
- if (!vma)
- vma = __i915_gem_vma_create(obj, vm,
- i915_is_ggtt(vm) ? &i915_ggtt_view_normal : NULL);
+ list_for_each_entry_reverse(vma, &obj->vma_list, obj_link)
+ if (vma_matches(vma, vm, view))
+ return vma;
- return vma;
+ return NULL;
}
struct i915_vma *
-i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
- const struct i915_ggtt_view *view)
+i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
+ struct i915_address_space *vm,
+ const struct i915_ggtt_view *view)
{
- struct drm_device *dev = obj->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
- struct i915_vma *vma = i915_gem_obj_to_ggtt_view(obj, view);
-
- GEM_BUG_ON(!view);
+ struct i915_vma *vma;
+ vma = i915_gem_obj_to_vma(obj, vm, view);
if (!vma)
- vma = __i915_gem_vma_create(obj, &ggtt->base, view);
+ vma = __i915_gem_vma_create(obj, vm, view);
GEM_BUG_ON(i915_vma_is_closed(vma));
return vma;
-
}
static struct scatterlist *
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index cc56206a1600..c54ae2323df3 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -608,20 +608,6 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev);
int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
-static inline bool
-i915_ggtt_view_equal(const struct i915_ggtt_view *a,
- const struct i915_ggtt_view *b)
-{
- if (WARN_ON(!a || !b))
- return false;
-
- if (a->type != b->type)
- return false;
- if (a->type != I915_GGTT_VIEW_NORMAL)
- return !memcmp(&a->params, &b->params, sizeof(a->params));
- return true;
-}
-
/* Flags used by pin/bind&friends. */
#define PIN_NONBLOCK BIT(0)
#define PIN_MAPPABLE BIT(1)
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
index 57fd767a2d79..f0eb218541f8 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.c
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
@@ -31,7 +31,7 @@
struct render_state {
const struct intel_renderstate_rodata *rodata;
struct drm_i915_gem_object *obj;
- u64 ggtt_offset;
+ struct i915_vma *vma;
u32 aux_batch_size;
u32 aux_batch_offset;
};
@@ -92,7 +92,7 @@ static int render_state_setup(struct render_state *so)
u32 s = rodata->batch[i];
if (i * 4 == rodata->reloc[reloc_index]) {
- u64 r = s + so->ggtt_offset;
+ u64 r = s + so->vma->node.start,
s = lower_32_bits(r);
if (has_64bit_reloc) {
if (i + 1 >= rodata->batch_items ||
@@ -191,17 +191,17 @@ int i915_gem_render_state_init(struct drm_i915_gem_request *req)
if (IS_ERR(so.obj))
return PTR_ERR(so.obj);
- ret = i915_gem_object_ggtt_pin(so.obj, NULL, 0, 0, 0);
- if (ret)
+ so.vma = i915_gem_object_ggtt_pin(so.obj, NULL, 0, 0, 0);
+ if (IS_ERR(so.vma)) {
+ ret = PTR_ERR(so.vma);
goto err_obj;
-
- so.ggtt_offset = i915_gem_obj_ggtt_offset(so.obj);
+ }
ret = render_state_setup(&so);
if (ret)
goto err_unpin;
- ret = req->engine->emit_bb_start(req, so.ggtt_offset,
+ ret = req->engine->emit_bb_start(req, so.vma->node.start,
so.rodata->batch_items * 4,
I915_DISPATCH_SECURE);
if (ret)
@@ -209,7 +209,7 @@ int i915_gem_render_state_init(struct drm_i915_gem_request *req)
if (so.aux_batch_size > 8) {
ret = req->engine->emit_bb_start(req,
- (so.ggtt_offset +
+ (so.vma->node.start +
so.aux_batch_offset),
so.aux_batch_size,
I915_DISPATCH_SECURE);
@@ -217,9 +217,9 @@ int i915_gem_render_state_init(struct drm_i915_gem_request *req)
goto err_unpin;
}
- i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), req, 0);
+ i915_vma_move_to_active(so.vma, req, 0);
err_unpin:
- i915_gem_object_ggtt_unpin(so.obj);
+ i915_vma_unpin(so.vma);
err_obj:
i915_gem_object_put(so.obj);
return ret;
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.h b/drivers/gpu/drm/i915/i915_gem_render_state.h
index c44fca8599bb..18cce3f06e9c 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.h
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.h
@@ -24,7 +24,7 @@
#ifndef _I915_GEM_RENDER_STATE_H_
#define _I915_GEM_RENDER_STATE_H_
-#include <linux/types.h>
+struct drm_i915_gem_request;
int i915_gem_render_state_init(struct drm_i915_gem_request *req);
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index 3c70c2708249..948031f2cd03 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -428,18 +428,12 @@ static void i915_gem_mark_busy(const struct intel_engine_cs *engine)
*/
void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches)
{
- struct intel_engine_cs *engine;
- struct intel_ring *ring;
+ struct intel_engine_cs *engine = request->engine;
+ struct intel_ring *ring = request->ring;
u32 request_start;
u32 reserved_tail;
int ret;
- if (WARN_ON(!request))
- return;
-
- engine = request->engine;
- ring = request->ring;
-
/*
* To ensure that this call will not fail, space for its emissions
* should already have been reserved in the ring buffer. Let the ring
diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
index 24f95a348f16..c404a9ea0659 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.h
+++ b/drivers/gpu/drm/i915/i915_gem_request.h
@@ -111,7 +111,7 @@ struct drm_i915_gem_request {
/** Batch buffer related to this request if any (used for
* error state dump only).
*/
- struct drm_i915_gem_object *batch_obj;
+ struct i915_vma *batch;
struct list_head active_list;
/** Time at which this request was emitted, in jiffies. */
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 13279610eeec..c3dcfb724966 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -685,7 +685,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
if (gtt_offset == I915_GTT_OFFSET_NONE)
return obj;
- vma = i915_gem_obj_lookup_or_create_vma(obj, &ggtt->base);
+ vma = i915_gem_obj_lookup_or_create_vma(obj, &ggtt->base, NULL);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto err;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index f4b984de83b5..6dabc97d2a81 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -117,34 +117,45 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
}
/* Is the current GTT allocation valid for the change in tiling? */
-static bool
+static int
i915_gem_object_fence_ok(struct drm_i915_gem_object *obj, int tiling_mode)
{
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+ struct i915_vma *vma;
u32 size;
if (tiling_mode == I915_TILING_NONE)
- return true;
+ return 0;
if (INTEL_GEN(dev_priv) >= 4)
- return true;
+ return 0;
+
+ vma = i915_gem_object_to_ggtt(obj, NULL);
+ if (!vma)
+ return 0;
+
+ if (!obj->map_and_fenceable)
+ return 0;
if (IS_GEN3(dev_priv)) {
- if (i915_gem_obj_ggtt_offset(obj) & ~I915_FENCE_START_MASK)
- return false;
+ if (vma->node.start & ~I915_FENCE_START_MASK)
+ goto bad;
} else {
- if (i915_gem_obj_ggtt_offset(obj) & ~I830_FENCE_START_MASK)
- return false;
+ if (vma->node.start & ~I830_FENCE_START_MASK)
+ goto bad;
}
size = i915_gem_get_ggtt_size(dev_priv, obj->base.size, tiling_mode);
- if (i915_gem_obj_ggtt_size(obj) != size)
- return false;
+ if (vma->node.size < size)
+ goto bad;
- if (i915_gem_obj_ggtt_offset(obj) & (size - 1))
- return false;
+ if (vma->node.start & (size - 1))
+ goto bad;
- return true;
+ return 0;
+
+bad:
+ return i915_vma_unbind(vma);
}
/**
@@ -234,10 +245,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
* has to also include the unfenced register the GPU uses
* whilst executing a fenced command for an untiled object.
*/
- if (obj->map_and_fenceable &&
- !i915_gem_object_fence_ok(obj, args->tiling_mode))
- ret = i915_vma_unbind(i915_gem_obj_to_ggtt(obj));
-
+ ret = i915_gem_object_fence_ok(obj, args->tiling_mode);
if (ret == 0) {
if (obj->pages &&
obj->madv == I915_MADV_WILLNEED &&
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index ef8be7e05cbd..d39dbcda770c 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -634,46 +634,42 @@ static void i915_error_state_free(struct kref *error_ref)
static struct drm_i915_error_object *
i915_error_object_create(struct drm_i915_private *dev_priv,
- struct drm_i915_gem_object *src,
- struct i915_address_space *vm)
+ struct i915_vma *vma)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
+ struct drm_i915_gem_object *src;
struct drm_i915_error_object *dst;
- struct i915_vma *vma = NULL;
int num_pages;
bool use_ggtt;
int i = 0;
u64 reloc_offset;
- if (src == NULL || src->pages == NULL)
+ if (!vma)
+ return NULL;
+
+ src = vma->obj;
+ if (!src->pages)
return NULL;
num_pages = src->base.size >> PAGE_SHIFT;
dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
- if (dst == NULL)
+ if (!dst)
return NULL;
- if (i915_gem_obj_bound(src, vm))
- dst->gtt_offset = i915_gem_obj_offset(src, vm);
- else
- dst->gtt_offset = -1;
-
- reloc_offset = dst->gtt_offset;
- if (i915_is_ggtt(vm))
- vma = i915_gem_obj_to_ggtt(src);
+ reloc_offset = dst->gtt_offset = vma->node.start;
use_ggtt = (src->cache_level == I915_CACHE_NONE &&
- vma && (vma->flags & I915_VMA_GLOBAL_BIND) &&
+ (vma->flags & I915_VMA_GLOBAL_BIND) &&
reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
/* Cannot access stolen address directly, try to use the aperture */
if (src->stolen) {
use_ggtt = true;
- if (!(vma && vma->flags & I915_VMA_GLOBAL_BIND))
+ if (!(vma->flags & I915_VMA_GLOBAL_BIND))
goto unwind;
- reloc_offset = i915_gem_obj_ggtt_offset(src);
+ reloc_offset = vma->node.start;
if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end)
goto unwind;
}
@@ -726,8 +722,6 @@ unwind:
kfree(dst);
return NULL;
}
-#define i915_error_ggtt_object_create(dev_priv, src) \
- i915_error_object_create((dev_priv), (src), &(dev_priv)->ggtt.base)
/* The error capture is special as tries to run underneath the normal
* locking rules - so we use the raw version of the i915_gem_active lookup.
@@ -1041,8 +1035,7 @@ static void i915_gem_record_active_context(struct intel_engine_cs *engine,
list_for_each_entry(vma, &dev_priv->ggtt.base.active_list, vm_link) {
if ((error->ccid & PAGE_MASK) == vma->node.start) {
- ee->ctx = i915_error_object_create(dev_priv,
- vma->obj, vma->vm);
+ ee->ctx = i915_error_object_create(dev_priv, vma);
break;
}
}
@@ -1055,11 +1048,8 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
struct drm_i915_gem_request *request;
int i, count;
- if (dev_priv->semaphore_obj) {
- error->semaphore_obj =
- i915_error_ggtt_object_create(dev_priv,
- dev_priv->semaphore_obj);
- }
+ error->semaphore_obj =
+ i915_error_object_create(dev_priv, dev_priv->semaphore_vma);
for (i = 0; i < I915_NUM_ENGINES; i++) {
struct intel_engine_cs *engine = &dev_priv->engine[i];
@@ -1089,13 +1079,12 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
*/
ee->batchbuffer =
i915_error_object_create(dev_priv,
- request->batch_obj,
- ee->vm);
+ request->batch);
if (HAS_BROKEN_CS_TLB(dev_priv))
ee->wa_batchbuffer =
- i915_error_ggtt_object_create(dev_priv,
- engine->scratch.obj);
+ i915_error_object_create(dev_priv,
+ engine->scratch);
if (request->pid) {
struct task_struct *task;
@@ -1116,16 +1105,15 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
ee->cpu_ring_head = ring->head;
ee->cpu_ring_tail = ring->tail;
ee->ringbuffer =
- i915_error_ggtt_object_create(dev_priv,
- ring->obj);
+ i915_error_object_create(dev_priv, ring->vma);
}
ee->hws_page =
- i915_error_ggtt_object_create(dev_priv,
- engine->status_page.obj);
+ i915_error_object_create(dev_priv,
+ engine->status_page.vma);
- ee->wa_ctx = i915_error_ggtt_object_create(dev_priv,
- engine->wa_ctx.obj);
+ ee->wa_ctx =
+ i915_error_object_create(dev_priv, engine->wa_ctx.vma);
i915_gem_record_active_context(engine, error, ee);
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index b29e85880995..c74ebf5aa0e9 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -343,7 +343,6 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
for_each_engine(engine, dev_priv) {
struct intel_context *ce = &ctx->engine[engine->id];
struct guc_execlist_context *lrc = &desc.lrc[engine->guc_id];
- struct drm_i915_gem_object *obj;
/* TODO: We have a design issue to be solved here. Only when we
* receive the first batch, we know which engine is used by the
@@ -352,23 +351,20 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
* for now who owns a GuC client. But for future owner of GuC
* client, need to make sure lrc is pinned prior to enter here.
*/
- if (!ce->state)
+ if (!ce->vma)
break; /* XXX: continue? */
lrc->context_desc = lower_32_bits(ce->lrc_desc);
/* The state page is after PPHWSP */
- gfx_addr = i915_gem_obj_ggtt_offset(ce->state);
+ gfx_addr = ce->vma->node.start;
lrc->ring_lcra = gfx_addr + LRC_STATE_PN * PAGE_SIZE;
lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
(engine->guc_id << GUC_ELC_ENGINE_OFFSET);
- obj = ce->ring->obj;
- gfx_addr = i915_gem_obj_ggtt_offset(obj);
-
- lrc->ring_begin = gfx_addr;
- lrc->ring_end = gfx_addr + obj->base.size - 1;
- lrc->ring_next_free_location = gfx_addr;
+ lrc->ring_begin = ce->ring->vma->node.start;
+ lrc->ring_end = gfx_addr + ce->ring->vma->node.size - 1;
+ lrc->ring_next_free_location = lrc->ring_begin;
lrc->ring_current_tail_pointer_value = 0;
desc.engines_used |= (1 << engine->guc_id);
@@ -625,23 +621,23 @@ static struct i915_vma *guc_allocate_vma(struct intel_guc *guc, u32 size)
{
struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct drm_i915_gem_object *obj;
- int ret;
+ struct i915_vma *vma;
obj = i915_gem_object_create(&dev_priv->drm, size);
if (IS_ERR(obj))
return ERR_CAST(obj);
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE,
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE,
PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
- if (ret) {
+ if (IS_ERR(vma)) {
i915_gem_object_put(obj);
- return ERR_PTR(ret);
+ return vma;
}
/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
- return i915_gem_obj_to_ggtt(obj);
+ return vma;
}
/**
@@ -1056,7 +1052,7 @@ int intel_guc_suspend(struct drm_device *dev)
/* any value greater than GUC_POWER_D0 */
data[1] = GUC_POWER_D1;
/* first page is shared data with GuC */
- data[2] = i915_gem_obj_ggtt_offset(ctx->engine[RCS].state);
+ data[2] = ctx->engine[RCS].vma->node.start;
return host2guc_action(guc, data, ARRAY_SIZE(data));
}
@@ -1081,7 +1077,7 @@ int intel_guc_resume(struct drm_device *dev)
data[0] = HOST2GUC_ACTION_EXIT_S_STATE;
data[1] = GUC_POWER_D0;
/* first page is shared data with GuC */
- data[2] = i915_gem_obj_ggtt_offset(ctx->engine[RCS].state);
+ data[2] = ctx->engine[RCS].vma->node.start;
return host2guc_action(guc, data, ARRAY_SIZE(data));
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9cbf5431c1e3..15129c65d65d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2206,14 +2206,14 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv
}
}
-int
-intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
- unsigned int rotation)
+struct i915_vma *
+intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
{
struct drm_device *dev = fb->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct i915_ggtt_view view;
+ struct i915_vma *vma;
u32 alignment;
int ret;
@@ -2240,10 +2240,11 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
*/
intel_runtime_pm_get(dev_priv);
- ret = i915_gem_object_pin_to_display_plane(obj, alignment,
- &view);
- if (ret)
+ vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
goto err_pm;
+ }
/* Install a fence for tiled scan-out. Pre-i965 always needs a
* fence, whereas 965+ only requires a fence if using
@@ -2270,19 +2271,20 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
}
intel_runtime_pm_put(dev_priv);
- return 0;
+ return vma;
err_unpin:
- i915_gem_object_unpin_from_display_plane(obj, &view);
+ i915_gem_object_unpin_from_display_plane(vma);
err_pm:
intel_runtime_pm_put(dev_priv);
- return ret;
+ return ERR_PTR(ret);
}
void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
{
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct i915_ggtt_view view;
+ struct i915_vma *vma;
WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
@@ -2291,7 +2293,8 @@ void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
if (view.type == I915_GGTT_VIEW_NORMAL)
i915_gem_object_unpin_fence(obj);
- i915_gem_object_unpin_from_display_plane(obj, &view);
+ vma = i915_gem_object_to_ggtt(obj, &view);
+ i915_gem_object_unpin_from_display_plane(vma);
}
/*
@@ -2552,7 +2555,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
continue;
obj = intel_fb_obj(fb);
- if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) {
+ if (i915_gem_object_ggtt_offset(obj, NULL) == plane_config->base) {
drm_framebuffer_reference(fb);
goto valid_fb;
}
@@ -2709,11 +2712,11 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
if (INTEL_INFO(dev)->gen >= 4) {
I915_WRITE(DSPSURF(plane),
- i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+ i915_gem_object_ggtt_offset(obj, NULL) + intel_crtc->dspaddr_offset);
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
I915_WRITE(DSPLINOFF(plane), linear_offset);
} else
- I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + linear_offset);
+ I915_WRITE(DSPADDR(plane), i915_gem_object_ggtt_offset(obj, NULL) + linear_offset);
POSTING_READ(reg);
}
@@ -2813,7 +2816,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
I915_WRITE(DSPSURF(plane),
- i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+ i915_gem_object_ggtt_offset(obj, NULL) + intel_crtc->dspaddr_offset);
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
} else {
@@ -2846,7 +2849,7 @@ u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb,
intel_plane->base.state->rotation);
- vma = i915_gem_obj_to_ggtt_view(obj, &view);
+ vma = i915_gem_object_to_ggtt(obj, &view);
if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
view.type))
return -1;
@@ -11325,7 +11328,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
MI_SRM_LRM_GLOBAL_GTT);
intel_ring_emit_reg(ring, DERRMR);
- intel_ring_emit(ring, req->engine->scratch.gtt_offset + 256);
+ intel_ring_emit(ring, req->engine->scratch->node.start + 256);
if (IS_GEN8(dev)) {
intel_ring_emit(ring, 0);
intel_ring_emit(ring, MI_NOOP);
@@ -11577,6 +11580,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
struct intel_engine_cs *engine;
bool mmio_flip;
struct drm_i915_gem_request *request;
+ struct i915_vma *vma;
int ret;
/*
@@ -11685,9 +11689,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
mmio_flip = use_mmio_flip(engine, obj);
- ret = intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
- if (ret)
+ vma = intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
goto cleanup_pending;
+ }
work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary),
obj, 0);
@@ -14040,7 +14046,11 @@ intel_prepare_plane_fb(struct drm_plane *plane,
if (ret)
DRM_DEBUG_KMS("failed to attach phys object\n");
} else {
- ret = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
+ struct i915_vma *vma;
+
+ vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
+ if (IS_ERR(vma))
+ ret = PTR_ERR(vma);
}
if (ret == 0) {
@@ -14396,7 +14406,7 @@ intel_update_cursor_plane(struct drm_plane *plane,
if (!obj)
addr = 0;
else if (!INTEL_INFO(dev)->cursor_needs_physical)
- addr = i915_gem_obj_ggtt_offset(obj);
+ addr = i915_gem_object_ggtt_offset(obj, NULL);
else
addr = obj->phys_handle->busaddr;
@@ -16228,7 +16238,6 @@ void intel_modeset_gem_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *c;
struct drm_i915_gem_object *obj;
- int ret;
intel_init_gt_powersave(dev_priv);
@@ -16242,15 +16251,17 @@ void intel_modeset_gem_init(struct drm_device *dev)
* for this.
*/
for_each_crtc(dev, c) {
+ struct i915_vma *vma;
+
obj = intel_fb_obj(c->primary->fb);
if (obj == NULL)
continue;
mutex_lock(&dev->struct_mutex);
- ret = intel_pin_and_fence_fb_obj(c->primary->fb,
+ vma = intel_pin_and_fence_fb_obj(c->primary->fb,
c->primary->state->rotation);
mutex_unlock(&dev->struct_mutex);
- if (ret) {
+ if (IS_ERR(vma)) {
DRM_ERROR("failed to pin boot fb on pipe %d\n",
to_intel_crtc(c)->pipe);
drm_framebuffer_unreference(c->primary->fb);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e54e6c205f41..6265c1f65e25 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -183,6 +183,7 @@ struct intel_framebuffer {
struct intel_fbdev {
struct drm_fb_helper helper;
struct intel_framebuffer *fb;
+ struct i915_vma *vma;
async_cookie_t cookie;
int preferred_bpp;
};
@@ -1217,8 +1218,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
void intel_release_load_detect_pipe(struct drm_connector *connector,
struct intel_load_detect_pipe *old,
struct drm_modeset_acquire_ctx *ctx);
-int intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
- unsigned int rotation);
+struct i915_vma *
+intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
struct drm_framebuffer *
__intel_framebuffer_create(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 85adc2b92594..c2ef71a1215e 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -737,7 +737,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
/* FIXME: We lack the proper locking here, so only run this on the
* platforms that need. */
if (IS_GEN(dev_priv, 5, 6))
- cache->fb.ilk_ggtt_offset = i915_gem_obj_ggtt_offset(obj);
+ cache->fb.ilk_ggtt_offset = i915_gem_object_ggtt_offset(obj, NULL);
cache->fb.pixel_format = fb->pixel_format;
cache->fb.stride = fb->pitches[0];
cache->fb.fence_reg = obj->fence_reg;
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 0436b4869d57..692bf75db3bd 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -188,7 +188,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
struct fb_info *info;
struct drm_framebuffer *fb;
struct i915_vma *vma;
- struct drm_i915_gem_object *obj;
bool prealloc = false;
void __iomem *vaddr;
int ret;
@@ -216,17 +215,17 @@ static int intelfb_create(struct drm_fb_helper *helper,
sizes->fb_height = intel_fb->base.height;
}
- obj = intel_fb->obj;
-
mutex_lock(&dev->struct_mutex);
/* Pin the GGTT vma for our access via info->screen_base.
* This also validates that any existing fb inherited from the
* BIOS is suitable for own access.
*/
- ret = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0));
- if (ret)
+ vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0));
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
goto out_unlock;
+ }
info = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(info)) {
@@ -246,8 +245,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &intelfb_ops;
- vma = i915_gem_obj_to_ggtt(obj);
-
/* setup aperture base/size for vesafb takeover */
info->apertures->ranges[0].base = dev->mode_config.fb_base;
info->apertures->ranges[0].size = ggtt->mappable_end;
@@ -274,14 +271,14 @@ static int intelfb_create(struct drm_fb_helper *helper,
* If the object is stolen however, it will be full of whatever
* garbage was left in there.
*/
- if (ifbdev->fb->obj->stolen && !prealloc)
+ if (intel_fb->obj->stolen && !prealloc)
memset_io(info->screen_base, 0, info->screen_size);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
- DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08llx, bo %p\n",
- fb->width, fb->height,
- i915_gem_obj_ggtt_offset(obj), obj);
+ DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08llx\n",
+ fb->width, fb->height, vma->node.start);
+ ifbdev->vma = vma;
mutex_unlock(&dev->struct_mutex);
vga_switcheroo_client_fb_set(dev->pdev, info);
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c
index 58ef4418a2ef..9f30d1e8f575 100644
--- a/drivers/gpu/drm/i915/intel_guc_loader.c
+++ b/drivers/gpu/drm/i915/intel_guc_loader.c
@@ -237,12 +237,12 @@ static inline bool guc_ucode_response(struct drm_i915_private *dev_priv,
* Note that GuC needs the CSS header plus uKernel code to be copied by the
* DMA engine in one operation, whereas the RSA signature is loaded via MMIO.
*/
-static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
+static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv,
+ struct i915_vma *vma)
{
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
- struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj;
unsigned long offset;
- struct sg_table *sg = fw_obj->pages;
+ struct sg_table *sg = vma->obj->pages;
u32 status, rsa[UOS_RSA_SCRATCH_MAX_COUNT];
int i, ret = 0;
@@ -259,7 +259,7 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size);
/* Set the source address for the new blob */
- offset = i915_gem_obj_ggtt_offset(fw_obj) + guc_fw->header_offset;
+ offset = vma->node.start + guc_fw->header_offset;
I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset));
I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF);
@@ -314,6 +314,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
{
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
struct drm_device *dev = &dev_priv->drm;
+ struct i915_vma *vma;
int ret;
ret = i915_gem_object_set_to_gtt_domain(guc_fw->guc_fw_obj, false);
@@ -322,10 +323,10 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
return ret;
}
- ret = i915_gem_object_ggtt_pin(guc_fw->guc_fw_obj, NULL, 0, 0, 0);
- if (ret) {
- DRM_DEBUG_DRIVER("pin failed %d\n", ret);
- return ret;
+ vma = i915_gem_object_ggtt_pin(guc_fw->guc_fw_obj, NULL, 0, 0, 0);
+ if (IS_ERR(vma)) {
+ DRM_DEBUG_DRIVER("pin failed %d\n", (int)PTR_ERR(vma));
+ return PTR_ERR(vma);
}
/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
@@ -368,7 +369,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
set_guc_init_params(dev_priv);
- ret = guc_ucode_xfer_dma(dev_priv);
+ ret = guc_ucode_xfer_dma(dev_priv, vma);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -376,7 +377,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
* We keep the object pages for reuse during resume. But we can unpin it
* now that DMA has completed, so it doesn't continue to take up space.
*/
- i915_gem_object_ggtt_unpin(guc_fw->guc_fw_obj);
+ i915_vma_unpin(vma);
return ret;
}
@@ -660,12 +661,8 @@ fail:
DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n",
guc_fw->guc_fw_path, err);
- mutex_lock(&dev->struct_mutex);
- obj = guc_fw->guc_fw_obj;
- if (obj)
- i915_gem_object_put(obj);
+ i915_gem_object_put_unlocked(guc_fw->guc_fw_obj);
guc_fw->guc_fw_obj = NULL;
- mutex_unlock(&dev->struct_mutex);
release_firmware(fw); /* OK even if fw is NULL */
guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL;
@@ -746,7 +743,7 @@ void intel_guc_fini(struct drm_device *dev)
if (guc_fw->guc_fw_obj)
i915_gem_object_put(guc_fw->guc_fw_obj);
guc_fw->guc_fw_obj = NULL;
- mutex_unlock(&dev->struct_mutex);
guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
+ mutex_unlock(&dev->struct_mutex);
}
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 309c5d9b1c57..c52987813c3c 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -315,7 +315,7 @@ intel_lr_context_descriptor_update(struct i915_gem_context *ctx,
desc = ctx->desc_template; /* bits 3-4 */
desc |= engine->ctx_desc_template; /* bits 0-11 */
- desc |= ce->lrc_vma->node.start + LRC_PPHWSP_PN * PAGE_SIZE;
+ desc |= ce->vma->node.start + LRC_PPHWSP_PN * PAGE_SIZE;
/* bits 12-31 */
desc |= (u64)ctx->hw_id << GEN8_CTX_ID_SHIFT; /* bits 32-52 */
@@ -765,6 +765,7 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx,
{
struct drm_i915_private *dev_priv = ctx->i915;
struct intel_context *ce = &ctx->engine[engine->id];
+ struct i915_vma *vma;
void *vaddr;
u32 *lrc_reg_state;
int ret;
@@ -774,16 +775,18 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx,
if (ce->pin_count++)
return 0;
- ret = i915_gem_object_ggtt_pin(ce->state, NULL,
+ vma = i915_gem_object_ggtt_pin(ce->state, NULL,
0, GEN8_LR_CONTEXT_ALIGN,
PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
- if (ret)
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
goto err;
+ }
- vaddr = i915_gem_object_pin_map(ce->state);
+ vaddr = i915_gem_object_pin_map(vma->obj);
if (IS_ERR(vaddr)) {
ret = PTR_ERR(vaddr);
- goto unpin_ctx_obj;
+ goto unpin_vma;
}
lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
@@ -792,12 +795,12 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx,
if (ret)
goto unpin_map;
- ce->lrc_vma = i915_gem_obj_to_ggtt(ce->state);
+ ce->vma = vma;
intel_lr_context_descriptor_update(ctx, engine);
lrc_reg_state[CTX_RING_BUFFER_START+1] = ce->ring->vma->node.start;
ce->lrc_reg_state = lrc_reg_state;
- ce->state->dirty = true;
+ vma->obj->dirty = true;
/* Invalidate GuC TLB. */
if (i915.enable_guc_submission)
@@ -807,9 +810,9 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx,
return 0;
unpin_map:
- i915_gem_object_unpin_map(ce->state);
-unpin_ctx_obj:
- i915_gem_object_ggtt_unpin(ce->state);
+ i915_gem_object_unpin_map(vma->obj);
+unpin_vma:
+ __i915_vma_unpin(vma);
err:
ce->pin_count = 0;
return ret;
@@ -829,9 +832,9 @@ void intel_lr_context_unpin(struct i915_gem_context *ctx,
intel_ring_unpin(ce->ring);
i915_gem_object_unpin_map(ce->state);
- i915_gem_object_ggtt_unpin(ce->state);
+ i915_vma_unpin(ce->vma);
- ce->lrc_vma = NULL;
+ ce->vma = NULL;
ce->lrc_desc = 0;
ce->lrc_reg_state = NULL;
@@ -919,7 +922,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine,
wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT));
wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
- wa_ctx_emit(batch, index, engine->scratch.gtt_offset + 256);
+ wa_ctx_emit(batch, index, engine->scratch->node.start + 256);
wa_ctx_emit(batch, index, 0);
wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1));
@@ -937,7 +940,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine,
wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8 |
MI_SRM_LRM_GLOBAL_GTT));
wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
- wa_ctx_emit(batch, index, engine->scratch.gtt_offset + 256);
+ wa_ctx_emit(batch, index, engine->scratch->node.start + 256);
wa_ctx_emit(batch, index, 0);
return index;
@@ -998,7 +1001,7 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *engine,
/* WaClearSlmSpaceAtContextSwitch:bdw,chv */
/* Actual scratch location is at 128 bytes offset */
- scratch_addr = engine->scratch.gtt_offset + 2*CACHELINE_BYTES;
+ scratch_addr = engine->scratch->node.start + 2*CACHELINE_BYTES;
wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6));
wa_ctx_emit(batch, index, (PIPE_CONTROL_FLUSH_L3 |
@@ -1078,7 +1081,7 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine,
/* Actual scratch location is at 128 bytes offset */
if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_A0)) {
uint32_t scratch_addr
- = engine->scratch.gtt_offset + 2*CACHELINE_BYTES;
+ = engine->scratch->node.start + 2*CACHELINE_BYTES;
wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6));
wa_ctx_emit(batch, index, (PIPE_CONTROL_FLUSH_L3 |
@@ -1168,47 +1171,41 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine,
return wa_ctx_end(wa_ctx, *offset = index, 1);
}
-static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *engine, u32 size)
+static struct i915_vma *
+lrc_setup_wa_ctx_obj(struct intel_engine_cs *engine, u32 size)
{
- int ret;
+ struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
- engine->wa_ctx.obj = i915_gem_object_create(&engine->i915->drm,
- PAGE_ALIGN(size));
- if (IS_ERR(engine->wa_ctx.obj)) {
- DRM_DEBUG_DRIVER("alloc LRC WA ctx backing obj failed.\n");
- ret = PTR_ERR(engine->wa_ctx.obj);
- engine->wa_ctx.obj = NULL;
- return ret;
- }
+ obj = i915_gem_object_create(&engine->i915->drm, PAGE_ALIGN(size));
+ if (IS_ERR(obj))
+ return ERR_CAST(obj);
- ret = i915_gem_object_ggtt_pin(engine->wa_ctx.obj, NULL,
- 0, PAGE_SIZE, 0);
- if (ret) {
- DRM_DEBUG_DRIVER("pin LRC WA ctx backing obj failed: %d\n",
- ret);
- i915_gem_object_put(engine->wa_ctx.obj);
- return ret;
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE, 0);
+ if (IS_ERR(vma)) {
+ i915_gem_object_put(obj);
+ return vma;
}
- return 0;
+ return vma;
}
static void lrc_destroy_wa_ctx_obj(struct intel_engine_cs *engine)
{
- if (engine->wa_ctx.obj) {
- i915_gem_object_ggtt_unpin(engine->wa_ctx.obj);
- i915_gem_object_put(engine->wa_ctx.obj);
- engine->wa_ctx.obj = NULL;
+ if (engine->wa_ctx.vma) {
+ i915_vma_unpin(engine->wa_ctx.vma);
+ i915_gem_object_put(engine->wa_ctx.vma->obj);
+ engine->wa_ctx.vma = NULL;
}
}
static int intel_init_workaround_bb(struct intel_engine_cs *engine)
{
- int ret;
+ struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx;
uint32_t *batch;
uint32_t offset;
struct page *page;
- struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx;
+ int ret;
WARN_ON(engine->id != RCS);
@@ -1220,20 +1217,22 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine)
}
/* some WA perform writes to scratch page, ensure it is valid */
- if (engine->scratch.obj == NULL) {
+ if (!engine->scratch) {
DRM_ERROR("scratch page not allocated for %s\n", engine->name);
return -EINVAL;
}
- ret = lrc_setup_wa_ctx_obj(engine, PAGE_SIZE);
- if (ret) {
+ wa_ctx->vma = lrc_setup_wa_ctx_obj(engine, PAGE_SIZE);
+ if (IS_ERR(wa_ctx->vma)) {
+ ret = PTR_ERR(wa_ctx->vma);
DRM_DEBUG_DRIVER("Failed to setup context WA page: %d\n", ret);
return ret;
}
- page = i915_gem_object_get_dirty_page(wa_ctx->obj, 0);
+ page = i915_gem_object_get_dirty_page(wa_ctx->vma->obj, 0);
batch = kmap_atomic(page);
offset = 0;
+ ret = 0;
if (IS_GEN8(engine->i915)) {
ret = gen8_init_indirectctx_bb(engine,
@@ -1488,7 +1487,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
{
struct intel_ring *ring = request->ring;
struct intel_engine_cs *engine = request->engine;
- u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+ u32 scratch_addr = engine->scratch->node.start + 2 * CACHELINE_BYTES;
bool vf_flush_wa = false, dc_flush_wa = false;
u32 flags = 0;
int ret;
@@ -1700,9 +1699,9 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
intel_engine_cleanup_common(engine);
- if (engine->status_page.obj) {
- i915_gem_object_unpin_map(engine->status_page.obj);
- engine->status_page.obj = NULL;
+ if (engine->status_page.vma) {
+ i915_gem_object_unpin_map(engine->status_page.vma->obj);
+ engine->status_page.vma = NULL;
}
intel_lr_context_unpin(dev_priv->kernel_context, engine);
@@ -1747,19 +1746,19 @@ logical_ring_default_irqs(struct intel_engine_cs *engine)
}
static int
-lrc_setup_hws(struct intel_engine_cs *engine,
- struct drm_i915_gem_object *dctx_obj)
+lrc_setup_hws(struct intel_engine_cs *engine, struct i915_vma *vma)
{
+#define HWS_OFFSET (LRC_PPHWSP_PN * PAGE_SIZE)
void *hws;
/* The HWSP is part of the default context object in LRC mode. */
- engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(dctx_obj) +
- LRC_PPHWSP_PN * PAGE_SIZE;
- hws = i915_gem_object_pin_map(dctx_obj);
+ hws = i915_gem_object_pin_map(vma->obj);
if (IS_ERR(hws))
return PTR_ERR(hws);
- engine->status_page.page_addr = hws + LRC_PPHWSP_PN * PAGE_SIZE;
- engine->status_page.obj = dctx_obj;
+
+ engine->status_page.page_addr = hws + HWS_OFFSET;
+ engine->status_page.gfx_addr = vma->node.start + HWS_OFFSET;
+ engine->status_page.vma = vma;
return 0;
}
@@ -1820,7 +1819,7 @@ logical_ring_init(struct intel_engine_cs *engine)
}
/* And setup the hardware status page. */
- ret = lrc_setup_hws(engine, dctx->engine[engine->id].state);
+ ret = lrc_setup_hws(engine, dctx->engine[engine->id].vma);
if (ret) {
DRM_ERROR("Failed to set up hws %s: %d\n", engine->name, ret);
goto error;
@@ -2025,9 +2024,9 @@ populate_lr_context(struct i915_gem_context *ctx,
RING_INDIRECT_CTX(engine->mmio_base), 0);
ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET,
RING_INDIRECT_CTX_OFFSET(engine->mmio_base), 0);
- if (engine->wa_ctx.obj) {
+ if (engine->wa_ctx.vma) {
struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx;
- uint32_t ggtt_offset = i915_gem_obj_ggtt_offset(wa_ctx->obj);
+ u32 ggtt_offset = wa_ctx->vma->node.start;
reg_state[CTX_RCS_INDIRECT_CTX+1] =
(ggtt_offset + wa_ctx->indirect_ctx.offset * sizeof(uint32_t)) |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 90f3ab424e01..0b39b4c76be4 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -171,8 +171,8 @@ struct overlay_registers {
struct intel_overlay {
struct drm_i915_private *i915;
struct intel_crtc *crtc;
- struct drm_i915_gem_object *vid_bo;
- struct drm_i915_gem_object *old_vid_bo;
+ struct drm_i915_gem_object *vid_bo, *old_vid_bo;
+ struct i915_vma *vid_vma, *old_vid_vma;
bool active;
bool pfit_active;
u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
@@ -322,7 +322,7 @@ static void intel_overlay_release_old_vid_tail(struct i915_gem_active *active,
i915_gem_track_fb(obj, NULL,
INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
- i915_gem_object_ggtt_unpin(obj);
+ i915_gem_object_unpin_from_display_plane(overlay->old_vid_vma);
i915_gem_object_put(obj);
overlay->old_vid_bo = NULL;
@@ -333,14 +333,14 @@ static void intel_overlay_off_tail(struct i915_gem_active *active,
{
struct intel_overlay *overlay =
container_of(active, typeof(*overlay), last_flip);
- struct drm_i915_gem_object *obj = overlay->vid_bo;
/* never have the overlay hw on without showing a frame */
- if (WARN_ON(!obj))
+ if (WARN_ON(overlay->vid_vma))
return;
- i915_gem_object_ggtt_unpin(obj);
- i915_gem_object_put(obj);
+ i915_gem_object_unpin_from_display_plane(overlay->vid_vma);
+ i915_gem_object_put(overlay->vid_bo);
+ overlay->vid_vma = NULL;
overlay->vid_bo = NULL;
overlay->crtc->overlay = NULL;
@@ -744,6 +744,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
struct drm_i915_private *dev_priv = overlay->i915;
u32 swidth, swidthsw, sheight, ostride;
enum pipe pipe = overlay->crtc->pipe;
+ struct i915_vma *vma;
lockdep_assert_held(&dev_priv->drm.struct_mutex);
WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
@@ -752,10 +753,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
if (ret != 0)
return ret;
- ret = i915_gem_object_pin_to_display_plane(new_bo, 0,
+ vma = i915_gem_object_pin_to_display_plane(new_bo, 0,
&i915_ggtt_view_normal);
- if (ret != 0)
- return ret;
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
ret = i915_gem_object_put_fence(new_bo);
if (ret)
@@ -798,7 +799,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
swidth = params->src_w;
swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width);
sheight = params->src_h;
- iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_Y, ®s->OBUF_0Y);
+ iowrite32(vma->node.start + params->offset_Y, ®s->OBUF_0Y);
ostride = params->stride_Y;
if (params->format & I915_OVERLAY_YUV_PLANAR) {
@@ -812,8 +813,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
params->src_w/uv_hscale);
swidthsw |= max_t(u32, tmp_U, tmp_V) << 16;
sheight |= (params->src_h/uv_vscale) << 16;
- iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_U, ®s->OBUF_0U);
- iowrite32(i915_gem_obj_ggtt_offset(new_bo) + params->offset_V, ®s->OBUF_0V);
+ iowrite32(vma->node.start + params->offset_U, ®s->OBUF_0U);
+ iowrite32(vma->node.start + params->offset_V, ®s->OBUF_0V);
ostride |= params->stride_UV << 16;
}
@@ -838,14 +839,16 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
INTEL_FRONTBUFFER_OVERLAY(pipe));
overlay->old_vid_bo = overlay->vid_bo;
+ overlay->old_vid_vma = overlay->vid_vma;
overlay->vid_bo = new_bo;
+ overlay->vid_vma = vma;
intel_frontbuffer_flip(dev_priv, INTEL_FRONTBUFFER_OVERLAY(pipe));
return 0;
out_unpin:
- i915_gem_object_ggtt_unpin(new_bo);
+ i915_gem_object_unpin_from_display_plane(vma);
return ret;
}
@@ -1368,6 +1371,7 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
struct intel_overlay *overlay;
struct drm_i915_gem_object *reg_bo;
struct overlay_registers __iomem *regs;
+ struct i915_vma *vma = NULL;
int ret;
if (!HAS_OVERLAY(dev_priv))
@@ -1401,13 +1405,14 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
}
overlay->flip_addr = reg_bo->phys_handle->busaddr;
} else {
- ret = i915_gem_object_ggtt_pin(reg_bo, NULL,
+ vma = i915_gem_object_ggtt_pin(reg_bo, NULL,
0, PAGE_SIZE, PIN_MAPPABLE);
- if (ret) {
+ if (IS_ERR(vma)) {
DRM_ERROR("failed to pin overlay register bo\n");
+ ret = PTR_ERR(vma);
goto out_free_bo;
}
- overlay->flip_addr = i915_gem_obj_ggtt_offset(reg_bo);
+ overlay->flip_addr = vma->node.start;
ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
if (ret) {
@@ -1439,8 +1444,8 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
return;
out_unpin_bo:
- if (!OVERLAY_NEEDS_PHYSICAL(dev_priv))
- i915_gem_object_ggtt_unpin(reg_bo);
+ if (vma)
+ i915_vma_unpin(vma);
out_free_bo:
i915_gem_object_put(reg_bo);
out_free:
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index cae63c4e87a6..ba1c19921fca 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -176,7 +176,7 @@ intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req)
{
struct intel_ring *ring = req->ring;
u32 scratch_addr =
- req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+ req->engine->scratch->node.start + 2 * CACHELINE_BYTES;
int ret;
ret = intel_ring_begin(req, 6);
@@ -212,7 +212,7 @@ gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
{
struct intel_ring *ring = req->ring;
u32 scratch_addr =
- req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+ req->engine->scratch->node.start + 2 * CACHELINE_BYTES;
u32 flags = 0;
int ret;
@@ -286,7 +286,7 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
{
struct intel_ring *ring = req->ring;
u32 scratch_addr =
- req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+ req->engine->scratch->node.start + 2 * CACHELINE_BYTES;
u32 flags = 0;
int ret;
@@ -370,7 +370,8 @@ gen8_emit_pipe_control(struct drm_i915_gem_request *req,
static int
gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode)
{
- u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+ u32 scratch_addr =
+ req->engine->scratch->node.start + 2 * CACHELINE_BYTES;
u32 flags = 0;
int ret;
@@ -531,7 +532,7 @@ static int init_ring_common(struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv = engine->i915;
struct intel_ring *ring = engine->buffer;
- struct drm_i915_gem_object *obj = ring->obj;
+ struct i915_vma *vma = ring->vma;
int ret = 0;
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
@@ -571,7 +572,7 @@ static int init_ring_common(struct intel_engine_cs *engine)
* registers with the above sequence (the readback of the HEAD registers
* also enforces ordering), otherwise the hw might lose the new ring
* register values. */
- I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj));
+ I915_WRITE_START(engine, vma->node.start);
/* WaClearRingBufHeadRegAtInit:ctg,elk */
if (I915_READ_HEAD(engine))
@@ -586,16 +587,15 @@ static int init_ring_common(struct intel_engine_cs *engine)
/* If the head is still not zero, the ring is dead */
if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 &&
- I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) &&
+ I915_READ_START(engine) == vma->node.start &&
(I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) {
DRM_ERROR("%s initialization failed "
- "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n",
+ "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08x]\n",
engine->name,
I915_READ_CTL(engine),
I915_READ_CTL(engine) & RING_VALID,
I915_READ_HEAD(engine), I915_READ_TAIL(engine),
- I915_READ_START(engine),
- (unsigned long)i915_gem_obj_ggtt_offset(obj));
+ I915_READ_START(engine), (u32)vma->node.start);
ret = -EIO;
goto out;
}
@@ -615,20 +615,21 @@ out:
void intel_fini_pipe_control(struct intel_engine_cs *engine)
{
- if (engine->scratch.obj == NULL)
+ if (!engine->scratch)
return;
- i915_gem_object_ggtt_unpin(engine->scratch.obj);
- i915_gem_object_put(engine->scratch.obj);
- engine->scratch.obj = NULL;
+ i915_vma_unpin(engine->scratch);
+ i915_gem_object_put(engine->scratch->obj);
+ engine->scratch = NULL;
}
int intel_init_pipe_control(struct intel_engine_cs *engine, int size)
{
struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
int ret;
- WARN_ON(engine->scratch.obj);
+ WARN_ON(engine->scratch);
obj = i915_gem_object_create_stolen(&engine->i915->drm, size);
if (!obj)
@@ -639,18 +640,19 @@ int intel_init_pipe_control(struct intel_engine_cs *engine, int size)
goto err;
}
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 4096, PIN_HIGH);
- if (ret)
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 4096, PIN_HIGH);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
goto err_unref;
+ }
- engine->scratch.obj = obj;
- engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj);
- DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
- engine->name, engine->scratch.gtt_offset);
+ engine->scratch = vma;
+ DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08llx\n",
+ engine->name, (long long)vma->node.start);
return 0;
err_unref:
- i915_gem_object_put(engine->scratch.obj);
+ i915_gem_object_put(obj);
err:
return ret;
}
@@ -1300,10 +1302,13 @@ static void render_ring_cleanup(struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv = engine->i915;
- if (dev_priv->semaphore_obj) {
- i915_gem_object_ggtt_unpin(dev_priv->semaphore_obj);
- i915_gem_object_put(dev_priv->semaphore_obj);
- dev_priv->semaphore_obj = NULL;
+ if (dev_priv->semaphore_vma) {
+ struct drm_i915_gem_object *obj = dev_priv->semaphore_vma->obj;
+
+ i915_vma_unpin(dev_priv->semaphore_vma);
+ dev_priv->semaphore_vma = NULL;
+
+ i915_gem_object_put(obj);
}
intel_fini_pipe_control(engine);
@@ -1764,7 +1769,7 @@ i830_emit_bb_start(struct drm_i915_gem_request *req,
unsigned int dispatch_flags)
{
struct intel_ring *ring = req->ring;
- u32 cs_offset = req->engine->scratch.gtt_offset;
+ u32 cs_offset = req->engine->scratch->node.start;
int ret;
ret = intel_ring_begin(req, 6);
@@ -1853,67 +1858,68 @@ static void cleanup_phys_status_page(struct intel_engine_cs *engine)
static void cleanup_status_page(struct intel_engine_cs *engine)
{
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
- obj = engine->status_page.obj;
- if (obj == NULL)
+ vma = engine->status_page.vma;
+ if (!vma)
return;
+ engine->status_page.vma = NULL;
- kunmap(sg_page(obj->pages->sgl));
- i915_gem_object_ggtt_unpin(obj);
- i915_gem_object_put(obj);
- engine->status_page.obj = NULL;
+ kunmap(sg_page(vma->obj->pages->sgl));
+ i915_vma_unpin(vma);
}
static int init_status_page(struct intel_engine_cs *engine)
{
- struct drm_i915_gem_object *obj = engine->status_page.obj;
+ struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
+ unsigned int flags;
+ int ret;
- if (obj == NULL) {
- unsigned flags;
- int ret;
+ if (engine->status_page.vma)
+ return 0;
- obj = i915_gem_object_create(&engine->i915->drm, 4096);
- if (IS_ERR(obj)) {
- DRM_ERROR("Failed to allocate status page\n");
- return PTR_ERR(obj);
- }
+ obj = i915_gem_object_create(&engine->i915->drm, 4096);
+ if (IS_ERR(obj)) {
+ DRM_ERROR("Failed to allocate status page\n");
+ return PTR_ERR(obj);
+ }
- ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
- if (ret)
- goto err_unref;
-
- flags = 0;
- if (!HAS_LLC(engine->i915))
- /* On g33, we cannot place HWS above 256MiB, so
- * restrict its pinning to the low mappable arena.
- * Though this restriction is not documented for
- * gen4, gen5, or byt, they also behave similarly
- * and hang if the HWS is placed at the top of the
- * GTT. To generalise, it appears that all !llc
- * platforms have issues with us placing the HWS
- * above the mappable region (even though we never
- * actualy map it).
- */
- flags |= PIN_MAPPABLE;
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, 4096, flags);
- if (ret) {
-err_unref:
- i915_gem_object_put(obj);
- return ret;
- }
+ ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
+ if (ret)
+ goto err_unref;
- engine->status_page.obj = obj;
+ flags = 0;
+ if (!HAS_LLC(engine->i915))
+ /* On g33, we cannot place HWS above 256MiB, so
+ * restrict its pinning to the low mappable arena.
+ * Though this restriction is not documented for
+ * gen4, gen5, or byt, they also behave similarly
+ * and hang if the HWS is placed at the top of the
+ * GTT. To generalise, it appears that all !llc
+ * platforms have issues with us placing the HWS
+ * above the mappable region (even though we never
+ * actualy map it).
+ */
+ flags |= PIN_MAPPABLE;
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 4096, flags);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
+ goto err_unref;
}
- engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
+ engine->status_page.vma = vma;
+ engine->status_page.gfx_addr = vma->node.start;
engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
- memset(engine->status_page.page_addr, 0, PAGE_SIZE);
DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
engine->name, engine->status_page.gfx_addr);
return 0;
+
+err_unref:
+ i915_gem_object_put(obj);
+ return ret;
}
static int init_phys_status_page(struct intel_engine_cs *engine)
@@ -1937,15 +1943,16 @@ int intel_ring_pin(struct intel_ring *ring)
{
struct drm_i915_private *dev_priv = ring->engine->i915;
struct drm_i915_gem_object *obj = ring->obj;
+ struct i915_vma *vma;
/* Ring wraparound at offset 0 sometimes hangs. No idea why. */
unsigned flags = PIN_OFFSET_BIAS | 4096;
void *addr;
int ret;
if (HAS_LLC(dev_priv) && !obj->stolen) {
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE, flags);
- if (ret)
- return ret;
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE, flags);
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
ret = i915_gem_object_set_to_cpu_domain(obj, true);
if (ret)
@@ -1957,10 +1964,10 @@ int intel_ring_pin(struct intel_ring *ring)
goto err_unpin;
}
} else {
- ret = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE,
+ vma = i915_gem_object_ggtt_pin(obj, NULL, 0, PAGE_SIZE,
flags | PIN_MAPPABLE);
- if (ret)
- return ret;
+ if (IS_ERR(vma))
+ return PTR_ERR(vma);
ret = i915_gem_object_set_to_gtt_domain(obj, true);
if (ret)
@@ -1969,8 +1976,7 @@ int intel_ring_pin(struct intel_ring *ring)
/* Access through the GTT requires the device to be awake. */
assert_rpm_wakelock_held(dev_priv);
- addr = (void __force *)
- i915_vma_pin_iomap(i915_gem_obj_to_ggtt(obj));
+ addr = (void __force *)i915_vma_pin_iomap(vma);
if (IS_ERR(addr)) {
ret = PTR_ERR(addr);
goto err_unpin;
@@ -1978,11 +1984,11 @@ int intel_ring_pin(struct intel_ring *ring)
}
ring->vaddr = addr;
- ring->vma = i915_gem_obj_to_ggtt(obj);
+ ring->vma = vma;
return 0;
err_unpin:
- i915_gem_object_ggtt_unpin(obj);
+ i915_vma_unpin(vma);
return ret;
}
@@ -1997,7 +2003,7 @@ void intel_ring_unpin(struct intel_ring *ring)
i915_vma_unpin_iomap(ring->vma);
ring->vaddr = NULL;
- i915_gem_object_ggtt_unpin(ring->obj);
+ i915_vma_unpin(ring->vma);
ring->vma = NULL;
}
@@ -2092,10 +2098,14 @@ static int intel_ring_context_pin(struct i915_gem_context *ctx,
return 0;
if (ce->state) {
- ret = i915_gem_object_ggtt_pin(ce->state, NULL, 0,
+ struct i915_vma *vma;
+
+ vma = i915_gem_object_ggtt_pin(ce->state, NULL, 0,
ctx->ggtt_alignment, PIN_HIGH);
- if (ret)
+ if (vma)
goto error;
+
+ ce->vma = vma;
}
/* The kernel context is only used as a placeholder for flushing the
@@ -2126,8 +2136,8 @@ static void intel_ring_context_unpin(struct i915_gem_context *ctx,
if (--ce->pin_count)
return;
- if (ce->state)
- i915_gem_object_ggtt_unpin(ce->state);
+ if (ce->vma)
+ i915_vma_unpin(ce->vma);
i915_gem_context_put(ctx);
}
@@ -2389,8 +2399,8 @@ void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno)
if (HAS_VEBOX(dev_priv))
I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
}
- if (dev_priv->semaphore_obj) {
- struct drm_i915_gem_object *obj = dev_priv->semaphore_obj;
+ if (dev_priv->semaphore_vma) {
+ struct drm_i915_gem_object *obj = dev_priv->semaphore_vma->obj;
struct page *page = i915_gem_object_get_dirty_page(obj, 0);
void *semaphores = kmap(page);
memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
@@ -2618,36 +2628,36 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode)
static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv,
struct intel_engine_cs *engine)
{
- struct drm_i915_gem_object *obj;
- int ret, i;
+ int i;
if (!i915.semaphores)
return;
- if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore_obj) {
+ if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore_vma) {
+ struct drm_i915_gem_object *obj;
+ struct i915_vma *vma = ERR_PTR(-ENODEV);
+
obj = i915_gem_object_create(&dev_priv->drm, 4096);
- if (IS_ERR(obj)) {
- DRM_ERROR("Failed to allocate semaphore bo. Disabling semaphores\n");
- i915.semaphores = 0;
- } else {
+ if (!IS_ERR(obj)) {
i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
- ret = i915_gem_object_ggtt_pin(obj, NULL,
+ vma = i915_gem_object_ggtt_pin(obj, NULL,
0, 0, PIN_HIGH);
- if (ret != 0) {
+ }
+
+ if (IS_ERR(vma)) {
+ if (!IS_ERR(obj))
i915_gem_object_put(obj);
- DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n");
- i915.semaphores = 0;
- } else {
- dev_priv->semaphore_obj = obj;
- }
+
+ DRM_ERROR("Failed to pin semaphore bo. Disabling semaphores\n");
+ i915.semaphores = 0;
+ return;
}
- }
- if (!i915.semaphores)
- return;
+ dev_priv->semaphore_vma = vma;
+ }
if (INTEL_GEN(dev_priv) >= 8) {
- u64 offset = i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj);
+ u64 offset = dev_priv->semaphore_vma->node.start;
engine->semaphore.sync_to = gen8_ring_sync_to;
engine->semaphore.signal = gen8_xcs_signal;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 43e545e44352..a5d8d567b33b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -26,10 +26,10 @@
*/
#define I915_RING_FREE_SPACE 64
-struct intel_hw_status_page {
+struct intel_hw_status_page {
u32 *page_addr;
unsigned int gfx_addr;
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
};
#define I915_READ_TAIL(engine) I915_READ(RING_TAIL((engine)->mmio_base))
@@ -57,10 +57,10 @@ struct intel_hw_status_page {
#define GEN8_SEMAPHORE_OFFSET(__from, __to) \
(((__from) * I915_NUM_ENGINES + (__to)) * gen8_semaphore_seqno_size)
#define GEN8_SIGNAL_OFFSET(__ring, to) \
- (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
+ (dev_priv->semaphore_vma->node.start + \
GEN8_SEMAPHORE_OFFSET((__ring)->id, (to)))
#define GEN8_WAIT_OFFSET(__ring, from) \
- (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
+ (dev_priv->semaphore_vma->node.start + \
GEN8_SEMAPHORE_OFFSET(from, (__ring)->id))
enum intel_engine_hangcheck_action {
@@ -85,8 +85,8 @@ struct intel_engine_hangcheck {
struct intel_ring {
struct drm_i915_gem_object *obj;
- void *vaddr;
struct i915_vma *vma;
+ void *vaddr;
struct intel_engine_cs *engine;
struct list_head link;
@@ -129,7 +129,7 @@ struct i915_ctx_workarounds {
u32 offset;
u32 size;
} indirect_ctx, per_ctx;
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
};
struct drm_i915_gem_request;
@@ -319,10 +319,7 @@ struct intel_engine_cs {
struct intel_engine_hangcheck hangcheck;
- struct {
- struct drm_i915_gem_object *obj;
- u32 gtt_offset;
- } scratch;
+ struct i915_vma *scratch;
bool needs_cmd_parser;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 5beafd4bc1c1..010d69810657 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -477,8 +477,8 @@ vlv_update_plane(struct drm_plane *dplane,
I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
I915_WRITE(SPCNTR(pipe, plane), sprctl);
- I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
- sprsurf_offset);
+ I915_WRITE(SPSURF(pipe, plane),
+ i915_gem_object_ggtt_offset(obj, NULL) + sprsurf_offset);
POSTING_READ(SPSURF(pipe, plane));
}
@@ -617,7 +617,7 @@ ivb_update_plane(struct drm_plane *plane,
I915_WRITE(SPRSCALE(pipe), sprscale);
I915_WRITE(SPRCTL(pipe), sprctl);
I915_WRITE(SPRSURF(pipe),
- i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
+ i915_gem_object_ggtt_offset(obj, NULL) + sprsurf_offset);
POSTING_READ(SPRSURF(pipe));
}
@@ -746,7 +746,7 @@ ilk_update_plane(struct drm_plane *plane,
I915_WRITE(DVSSCALE(pipe), dvsscale);
I915_WRITE(DVSCNTR(pipe), dvscntr);
I915_WRITE(DVSSURF(pipe),
- i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
+ i915_gem_object_ggtt_offset(obj, NULL) + dvssurf_offset);
POSTING_READ(DVSSURF(pipe));
}
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 08/13] drm/i915/overlay: Use VMA as the primary tracker for images
2016-08-05 9:05 First class i915_vma Chris Wilson
` (6 preceding siblings ...)
2016-08-05 9:05 ` [PATCH 07/13] drm/i915: Track pinned VMA Chris Wilson
@ 2016-08-05 9:05 ` Chris Wilson
2016-08-05 9:06 ` [PATCH 09/13] drm/i915: Print the batchbuffer offset next to BBADDR in error state Chris Wilson
` (5 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:05 UTC (permalink / raw)
To: intel-gfx
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/intel_overlay.c | 31 +++++++++++++------------------
1 file changed, 13 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 0b39b4c76be4..0753cb34527d 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -171,8 +171,7 @@ struct overlay_registers {
struct intel_overlay {
struct drm_i915_private *i915;
struct intel_crtc *crtc;
- struct drm_i915_gem_object *vid_bo, *old_vid_bo;
- struct i915_vma *vid_vma, *old_vid_vma;
+ struct i915_vma *vma, *old_vma;
bool active;
bool pfit_active;
u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
@@ -317,15 +316,14 @@ static void intel_overlay_release_old_vid_tail(struct i915_gem_active *active,
{
struct intel_overlay *overlay =
container_of(active, typeof(*overlay), last_flip);
- struct drm_i915_gem_object *obj = overlay->old_vid_bo;
- i915_gem_track_fb(obj, NULL,
+ i915_gem_track_fb(overlay->old_vma->obj, NULL,
INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
- i915_gem_object_unpin_from_display_plane(overlay->old_vid_vma);
- i915_gem_object_put(obj);
+ i915_gem_object_unpin_from_display_plane(overlay->old_vma);
+ i915_gem_object_put(overlay->old_vma->obj);
- overlay->old_vid_bo = NULL;
+ overlay->old_vma = NULL;
}
static void intel_overlay_off_tail(struct i915_gem_active *active,
@@ -335,13 +333,12 @@ static void intel_overlay_off_tail(struct i915_gem_active *active,
container_of(active, typeof(*overlay), last_flip);
/* never have the overlay hw on without showing a frame */
- if (WARN_ON(overlay->vid_vma))
+ if (WARN_ON(overlay->vma))
return;
- i915_gem_object_unpin_from_display_plane(overlay->vid_vma);
- i915_gem_object_put(overlay->vid_bo);
- overlay->vid_vma = NULL;
- overlay->vid_bo = NULL;
+ i915_gem_object_unpin_from_display_plane(overlay->vma);
+ i915_gem_object_put(overlay->vma->obj);
+ overlay->vma = NULL;
overlay->crtc->overlay = NULL;
overlay->crtc = NULL;
@@ -421,7 +418,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
/* Only wait if there is actually an old frame to release to
* guarantee forward progress.
*/
- if (!overlay->old_vid_bo)
+ if (!overlay->old_vma)
return 0;
if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
@@ -835,13 +832,11 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
if (ret)
goto out_unpin;
- i915_gem_track_fb(overlay->vid_bo, new_bo,
+ i915_gem_track_fb(overlay->vma->obj, new_bo,
INTEL_FRONTBUFFER_OVERLAY(pipe));
- overlay->old_vid_bo = overlay->vid_bo;
- overlay->old_vid_vma = overlay->vid_vma;
- overlay->vid_bo = new_bo;
- overlay->vid_vma = vma;
+ overlay->old_vma = overlay->vma;
+ overlay->vma = vma;
intel_frontbuffer_flip(dev_priv, INTEL_FRONTBUFFER_OVERLAY(pipe));
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 09/13] drm/i915: Print the batchbuffer offset next to BBADDR in error state
2016-08-05 9:05 First class i915_vma Chris Wilson
` (7 preceding siblings ...)
2016-08-05 9:05 ` [PATCH 08/13] drm/i915/overlay: Use VMA as the primary tracker for images Chris Wilson
@ 2016-08-05 9:06 ` Chris Wilson
2016-08-05 9:06 ` [PATCH 10/13] drm/i915: Move per-request pid from request to ctx Chris Wilson
` (4 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:06 UTC (permalink / raw)
To: intel-gfx
It is useful when looking at captured error states to check the recorded
BBADDR register (the address of the last batchbuffer instruction loaded)
against the expected offset of the batch buffer, and so do a quick check
that (a) the capture is true or (b) HEAD hasn't wandered off into the
badlands.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_gpu_error.c | 13 ++++++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a2ab4c6f9ba2..68595ae7e50a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -552,6 +552,7 @@ struct drm_i915_error_state {
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
+ u64 gtt_size;
u32 *pages[0];
} *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index d39dbcda770c..b1f7dbf69e98 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -243,6 +243,14 @@ static void error_print_engine(struct drm_i915_error_state_buf *m,
err_printf(m, " IPEIR: 0x%08x\n", ee->ipeir);
err_printf(m, " IPEHR: 0x%08x\n", ee->ipehr);
err_printf(m, " INSTDONE: 0x%08x\n", ee->instdone);
+ if (ee->batchbuffer) {
+ u64 start = ee->batchbuffer->gtt_offset;
+ u64 end = start + ee->batchbuffer->gtt_size;
+
+ err_printf(m, " batch: [0x%08x %08x, 0x%08x %08x]\n",
+ upper_32_bits(start), lower_32_bits(start),
+ upper_32_bits(end), lower_32_bits(end));
+ }
if (INTEL_GEN(m->i915) >= 4) {
err_printf(m, " BBADDR: 0x%08x %08x\n",
(u32)(ee->bbaddr>>32), (u32)ee->bbaddr);
@@ -657,7 +665,10 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
if (!dst)
return NULL;
- reloc_offset = dst->gtt_offset = vma->node.start;
+ dst->gtt_offset = vma->node.start;
+ dst->gtt_size = vma->node.size;
+
+ reloc_offset = dst->gtt_offset;
use_ggtt = (src->cache_level == I915_CACHE_NONE &&
(vma->flags & I915_VMA_GLOBAL_BIND) &&
reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 10/13] drm/i915: Move per-request pid from request to ctx
2016-08-05 9:05 First class i915_vma Chris Wilson
` (8 preceding siblings ...)
2016-08-05 9:06 ` [PATCH 09/13] drm/i915: Print the batchbuffer offset next to BBADDR in error state Chris Wilson
@ 2016-08-05 9:06 ` Chris Wilson
2016-08-05 9:06 ` [PATCH 11/13] drm/i915: Store the active context object on all engines upon error Chris Wilson
` (3 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:06 UTC (permalink / raw)
To: intel-gfx
Since contexts are not currently shared between userspace processes, we
have an exact correspondence between context creator and guilty batch
submitter. Therefore we can save some per-batch work by inspecting the
context->pid upon error instead. Note that we take the context's
creator's pid rather than the file's pid in order to better track fd
passed over sockets.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_debugfs.c | 25 ++++++++++++++++---------
drivers/gpu/drm/i915/i915_drv.h | 2 ++
drivers/gpu/drm/i915/i915_gem_context.c | 4 ++++
drivers/gpu/drm/i915/i915_gem_request.c | 5 -----
drivers/gpu/drm/i915/i915_gem_request.h | 3 ---
drivers/gpu/drm/i915/i915_gpu_error.c | 13 ++++++++++---
6 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index de312824f9bd..10f7210f1298 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -556,6 +556,8 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
print_context_stats(m, dev_priv);
list_for_each_entry_reverse(file, &dev->filelist, lhead) {
struct file_stats stats;
+ struct drm_i915_file_private *file_priv = file->driver_priv;
+ struct drm_i915_gem_request *request;
struct task_struct *task;
memset(&stats, 0, sizeof(stats));
@@ -569,10 +571,17 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
* still alive (e.g. get_pid(current) => fork() => exit()).
* Therefore, we need to protect this ->comm access using RCU.
*/
+ mutex_lock(&dev->struct_mutex);
+ request = list_first_entry_or_null(&file_priv->mm.request_list,
+ struct drm_i915_gem_request,
+ client_list);
rcu_read_lock();
- task = pid_task(file->pid, PIDTYPE_PID);
+ task = pid_task(request && request->ctx->pid ?
+ request->ctx->pid : file->pid,
+ PIDTYPE_PID);
print_file_stats(m, task ? task->comm : "<unknown>", stats);
rcu_read_unlock();
+ mutex_unlock(&dev->struct_mutex);
}
mutex_unlock(&dev->filelist_mutex);
@@ -753,12 +762,11 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
seq_printf(m, "%s requests: %d\n", engine->name, count);
list_for_each_entry(req, &engine->request_list, link) {
+ struct pid *pid = req->ctx->pid;
struct task_struct *task;
rcu_read_lock();
- task = NULL;
- if (req->pid)
- task = pid_task(req->pid, PIDTYPE_PID);
+ task = pid ? pid_task(pid, PIDTYPE_PID) : NULL;
seq_printf(m, " %x @ %d: %s [%d]\n",
req->fence.seqno,
(int) (jiffies - req->emitted_jiffies),
@@ -2050,18 +2058,17 @@ static int i915_context_status(struct seq_file *m, void *unused)
list_for_each_entry(ctx, &dev_priv->context_list, link) {
seq_printf(m, "HW context %u ", ctx->hw_id);
- if (IS_ERR(ctx->file_priv)) {
- seq_puts(m, "(deleted) ");
- } else if (ctx->file_priv) {
- struct pid *pid = ctx->file_priv->file->pid;
+ if (ctx->pid) {
struct task_struct *task;
- task = get_pid_task(pid, PIDTYPE_PID);
+ task = get_pid_task(ctx->pid, PIDTYPE_PID);
if (task) {
seq_printf(m, "(%s [%d]) ",
task->comm, task->pid);
put_task_struct(task);
}
+ } else if (IS_ERR(ctx->file_priv)) {
+ seq_puts(m, "(deleted) ");
} else {
seq_puts(m, "(kernel) ");
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 68595ae7e50a..370a4c9eea70 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -560,6 +560,7 @@ struct drm_i915_error_state {
struct drm_i915_error_request {
long jiffies;
+ pid_t pid;
u32 seqno;
u32 tail;
} *requests;
@@ -880,6 +881,7 @@ struct i915_gem_context {
struct drm_i915_private *i915;
struct drm_i915_file_private *file_priv;
struct i915_hw_ppgtt *ppgtt;
+ struct pid *pid;
struct i915_ctx_hang_stats hang_stats;
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index e515050c194b..408a818c61f2 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -158,6 +158,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
i915_gem_object_put(ce->state);
}
+ put_pid(ctx->pid);
list_del(&ctx->link);
ida_simple_remove(&ctx->i915->context_hw_ida, ctx->hw_id);
@@ -300,6 +301,9 @@ __create_hw_context(struct drm_device *dev,
ret = DEFAULT_CONTEXT_HANDLE;
ctx->file_priv = file_priv;
+ if (file_priv)
+ ctx->pid = get_task_pid(current, PIDTYPE_PID);
+
ctx->user_handle = ret;
/* NB: Mark all slices as needing a remap so that when the context first
* loads it will restore whatever remap state already exists. If there
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index 948031f2cd03..ad055d60b9f3 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -137,8 +137,6 @@ int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
list_add_tail(&req->client_list, &file_priv->mm.request_list);
spin_unlock(&file_priv->mm.lock);
- req->pid = get_pid(task_pid(current));
-
return 0;
}
@@ -154,9 +152,6 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request)
list_del(&request->client_list);
request->file_priv = NULL;
spin_unlock(&file_priv->mm.lock);
-
- put_pid(request->pid);
- request->pid = NULL;
}
void i915_gem_retire_noop(struct i915_gem_active *active,
diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
index c404a9ea0659..467161c9c56d 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.h
+++ b/drivers/gpu/drm/i915/i915_gem_request.h
@@ -127,9 +127,6 @@ struct drm_i915_gem_request {
/** file_priv list entry for this request */
struct list_head client_list;
- /** process identifier submitting this request */
- struct pid *pid;
-
/**
* The ELSP only accepts two elements at a time, so we queue
* context/tail pairs on a given queue (ring->execlist_queue) until the
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index b1f7dbf69e98..462262ffec79 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -460,7 +460,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
dev_priv->engine[i].name,
ee->num_requests);
for (j = 0; j < ee->num_requests; j++) {
- err_printf(m, " seqno 0x%08x, emitted %ld, tail 0x%08x\n",
+ err_printf(m, " pid %d, seqno 0x%08x, emitted %ld, tail 0x%08x\n",
+ ee->requests[j].pid,
ee->requests[j].seqno,
ee->requests[j].jiffies,
ee->requests[j].tail);
@@ -1080,6 +1081,7 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
request = i915_gem_find_active_request(engine);
if (request) {
struct intel_ring *ring;
+ struct pid *pid;
ee->vm = request->ctx->ppgtt ?
&request->ctx->ppgtt->base : &ggtt->base;
@@ -1097,11 +1099,12 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
i915_error_object_create(dev_priv,
engine->scratch);
- if (request->pid) {
+ pid = request->ctx->pid;
+ if (pid) {
struct task_struct *task;
rcu_read_lock();
- task = pid_task(request->pid, PIDTYPE_PID);
+ task = pid_task(pid, PIDTYPE_PID);
if (task) {
strcpy(ee->comm, task->comm);
ee->pid = task->pid;
@@ -1167,6 +1170,10 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
erq->seqno = request->fence.seqno;
erq->jiffies = request->emitted_jiffies;
erq->tail = request->postfix;
+
+ rcu_read_lock();
+ erq->pid = request->ctx ? pid_nr(request->ctx->pid) : 0;
+ rcu_read_unlock();
}
}
}
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 11/13] drm/i915: Store the active context object on all engines upon error
2016-08-05 9:05 First class i915_vma Chris Wilson
` (9 preceding siblings ...)
2016-08-05 9:06 ` [PATCH 10/13] drm/i915: Move per-request pid from request to ctx Chris Wilson
@ 2016-08-05 9:06 ` Chris Wilson
2016-08-05 9:06 ` [PATCH 12/13] drm/i915: Only record active and pending requests upon a GPU hang Chris Wilson
` (2 subsequent siblings)
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:06 UTC (permalink / raw)
To: intel-gfx
With execlists, we have context objects everywhere, not just RCS. So
store them for post-mortem debugging.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_gpu_error.c | 25 ++++---------------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 462262ffec79..abfbd99dae96 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1034,25 +1034,6 @@ static void error_record_engine_registers(struct drm_i915_error_state *error,
}
}
-static void i915_gem_record_active_context(struct intel_engine_cs *engine,
- struct drm_i915_error_state *error,
- struct drm_i915_error_engine *ee)
-{
- struct drm_i915_private *dev_priv = engine->i915;
- struct i915_vma *vma;
-
- /* Currently render ring is the only HW context user */
- if (engine->id != RCS || !error->ccid)
- return;
-
- list_for_each_entry(vma, &dev_priv->ggtt.base.active_list, vm_link) {
- if ((error->ccid & PAGE_MASK) == vma->node.start) {
- ee->ctx = i915_error_object_create(dev_priv, vma);
- break;
- }
- }
-}
-
static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error)
{
@@ -1099,6 +1080,10 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
i915_error_object_create(dev_priv,
engine->scratch);
+ ee->ctx =
+ i915_error_object_create(dev_priv,
+ request->ctx->engine[i].vma);
+
pid = request->ctx->pid;
if (pid) {
struct task_struct *task;
@@ -1129,8 +1114,6 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
ee->wa_ctx =
i915_error_object_create(dev_priv, engine->wa_ctx.vma);
- i915_gem_record_active_context(engine, error, ee);
-
count = 0;
list_for_each_entry(request, &engine->request_list, link)
count++;
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 12/13] drm/i915: Only record active and pending requests upon a GPU hang
2016-08-05 9:05 First class i915_vma Chris Wilson
` (10 preceding siblings ...)
2016-08-05 9:06 ` [PATCH 11/13] drm/i915: Store the active context object on all engines upon error Chris Wilson
@ 2016-08-05 9:06 ` Chris Wilson
2016-08-05 9:06 ` [PATCH 13/13] drm/i915: Compress GPU objects in error state Chris Wilson
2016-08-05 9:09 ` ✗ Ro.CI.BAT: failure for series starting with [01/13] drm/i915: Reduce amount of duplicate buffer information captured on error Patchwork
13 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:06 UTC (permalink / raw)
To: intel-gfx
There is no other state pertaining to the completed requests in the
hang, other than gleamed through the ringbuffer, so including the
expired requests in the list of outstanding requests simply adds noise.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_gpu_error.c | 105 +++++++++++++++++++---------------
1 file changed, 58 insertions(+), 47 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index abfbd99dae96..6078f47d4bc0 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1034,12 +1034,65 @@ static void error_record_engine_registers(struct drm_i915_error_state *error,
}
}
+static void engine_record_requests(struct intel_engine_cs *engine,
+ struct drm_i915_gem_request *first,
+ struct drm_i915_error_engine *ee)
+{
+ struct drm_i915_gem_request *request;
+ int count;
+
+ count = 0;
+ request = first;
+ list_for_each_entry_from(request, &engine->request_list, link)
+ count++;
+
+ ee->requests = NULL;
+ kcalloc(count, sizeof(*ee->requests),
+ GFP_ATOMIC);
+ if (ee->requests == NULL)
+ return;
+ ee->num_requests = count;
+
+ count = 0;
+ request = first;
+ list_for_each_entry_from(request, &engine->request_list, link) {
+ struct drm_i915_error_request *erq;
+
+ if (count >= ee->num_requests) {
+ /*
+ * If the ring request list was changed in
+ * between the point where the error request
+ * list was created and dimensioned and this
+ * point then just exit early to avoid crashes.
+ *
+ * We don't need to communicate that the
+ * request list changed state during error
+ * state capture and that the error state is
+ * slightly incorrect as a consequence since we
+ * are typically only interested in the request
+ * list state at the point of error state
+ * capture, not in any changes happening during
+ * the capture.
+ */
+ break;
+ }
+
+ erq = &ee->requests[count++];
+ erq->seqno = request->fence.seqno;
+ erq->jiffies = request->emitted_jiffies;
+ erq->tail = request->tail;
+
+ rcu_read_lock();
+ erq->pid = request->ctx ? pid_nr(request->ctx->pid) : 0;
+ rcu_read_unlock();
+ }
+}
+
static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
- struct drm_i915_gem_request *request;
- int i, count;
+ int i;
error->semaphore_obj =
i915_error_object_create(dev_priv, dev_priv->semaphore_vma);
@@ -1047,6 +1100,7 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
for (i = 0; i < I915_NUM_ENGINES; i++) {
struct intel_engine_cs *engine = &dev_priv->engine[i];
struct drm_i915_error_engine *ee = &error->engine[i];
+ struct drm_i915_gem_request *request;
ee->pid = -1;
ee->engine_id = -1;
@@ -1105,6 +1159,8 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
ee->cpu_ring_tail = ring->tail;
ee->ringbuffer =
i915_error_object_create(dev_priv, ring->vma);
+
+ engine_record_requests(engine, request, ee);
}
ee->hws_page =
@@ -1113,51 +1169,6 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
ee->wa_ctx =
i915_error_object_create(dev_priv, engine->wa_ctx.vma);
-
- count = 0;
- list_for_each_entry(request, &engine->request_list, link)
- count++;
-
- ee->num_requests = count;
- ee->requests =
- kcalloc(count, sizeof(*ee->requests), GFP_ATOMIC);
- if (!ee->requests) {
- ee->num_requests = 0;
- continue;
- }
-
- count = 0;
- list_for_each_entry(request, &engine->request_list, link) {
- struct drm_i915_error_request *erq;
-
- if (count >= ee->num_requests) {
- /*
- * If the ring request list was changed in
- * between the point where the error request
- * list was created and dimensioned and this
- * point then just exit early to avoid crashes.
- *
- * We don't need to communicate that the
- * request list changed state during error
- * state capture and that the error state is
- * slightly incorrect as a consequence since we
- * are typically only interested in the request
- * list state at the point of error state
- * capture, not in any changes happening during
- * the capture.
- */
- break;
- }
-
- erq = &ee->requests[count++];
- erq->seqno = request->fence.seqno;
- erq->jiffies = request->emitted_jiffies;
- erq->tail = request->postfix;
-
- rcu_read_lock();
- erq->pid = request->ctx ? pid_nr(request->ctx->pid) : 0;
- rcu_read_unlock();
- }
}
}
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 13/13] drm/i915: Compress GPU objects in error state
2016-08-05 9:05 First class i915_vma Chris Wilson
` (11 preceding siblings ...)
2016-08-05 9:06 ` [PATCH 12/13] drm/i915: Only record active and pending requests upon a GPU hang Chris Wilson
@ 2016-08-05 9:06 ` Chris Wilson
2016-08-05 18:56 ` Daniel Vetter
2016-08-05 9:09 ` ✗ Ro.CI.BAT: failure for series starting with [01/13] drm/i915: Reduce amount of duplicate buffer information captured on error Patchwork
13 siblings, 1 reply; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 9:06 UTC (permalink / raw)
To: intel-gfx
Our error states are quickly growing, pinning kernel memory with them.
The majority of the space is taken up by the error objects. These
compress well using zlib and without decode are mostly meaningless, so
encoding them does not hinder quickly parsing the error state for
familiarity.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/Kconfig | 1 +
drivers/gpu/drm/i915/i915_drv.h | 4 +-
drivers/gpu/drm/i915/i915_gem_gtt.c | 10 ++
drivers/gpu/drm/i915/i915_gem_gtt.h | 2 +
drivers/gpu/drm/i915/i915_gpu_error.c | 271 +++++++++++++++++-----------------
5 files changed, 148 insertions(+), 140 deletions(-)
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 7badcee88ebf..c8ea20526aef 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -5,6 +5,7 @@ config DRM_I915
select INTEL_GTT
select INTERVAL_TREE
select STOP_MACHINE
+ select ZLIB_DEFLATE
# we need shmfs for the swappable backing store, and in particular
# the shmem_readpage() which depends upon tmpfs
select SHMEM
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 370a4c9eea70..edc1e6d6be0d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -534,6 +534,7 @@ struct drm_i915_error_state {
u32 tail;
u32 head;
u32 ctl;
+ u32 mode;
u32 hws;
u32 ipeir;
u32 ipehr;
@@ -550,9 +551,10 @@ struct drm_i915_error_state {
u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
struct drm_i915_error_object {
- int page_count;
u64 gtt_offset;
u64 gtt_size;
+ int page_count;
+ int unused;
u32 *pages[0];
} *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 7c9f654d515a..c45e7f456cea 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2737,6 +2737,15 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
if (ret)
return ret;
+ /* Reserve a mappable slot for our lockless error capture */
+ ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
+ &ggtt->gpu_error,
+ 4096, 0, -1,
+ 0, ggtt->mappable_end,
+ 0, 0);
+ if (ret)
+ return ret;
+
/* Clear any non-preallocated blocks */
drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) {
DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
@@ -2804,6 +2813,7 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv)
if (drm_mm_initialized(&ggtt->base.mm)) {
intel_vgt_deballoon(dev_priv);
+ drm_mm_remove_node(&ggtt->gpu_error);
drm_mm_takedown(&ggtt->base.mm);
list_del(&ggtt->base.global_link);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index c54ae2323df3..010e10c0b62b 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -428,6 +428,8 @@ struct i915_ggtt {
bool do_idle_maps;
int mtrr;
+
+ struct drm_mm_node gpu_error;
};
struct i915_hw_ppgtt {
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 6078f47d4bc0..f036584e55e3 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -29,6 +29,7 @@
#include <generated/utsrelease.h>
#include <linux/stop_machine.h>
+#include <linux/zlib.h>
#include "i915_drv.h"
static const char *engine_str(int engine)
@@ -237,6 +238,8 @@ static void error_print_engine(struct drm_i915_error_state_buf *m,
err_printf(m, " HEAD: 0x%08x\n", ee->head);
err_printf(m, " TAIL: 0x%08x\n", ee->tail);
err_printf(m, " CTL: 0x%08x\n", ee->ctl);
+ err_printf(m, " MODE: 0x%08x [idle? %d]\n",
+ ee->mode, !!(ee->mode & MODE_IDLE));
err_printf(m, " HWS: 0x%08x\n", ee->hws);
err_printf(m, " ACTHD: 0x%08x %08x\n",
(u32)(ee->acthd>>32), (u32)ee->acthd);
@@ -307,18 +310,46 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
va_end(args);
}
+static bool
+ascii85_encode(u32 in, char *out)
+{
+ int i;
+
+ if (in == 0)
+ return false;
+
+ out[5] = '\0';
+ for (i = 5; i--; ) {
+ out[i] = '!' + in % 85;
+ in /= 85;
+ }
+
+ return true;
+}
+
static void print_error_obj(struct drm_i915_error_state_buf *m,
struct drm_i915_error_object *obj)
{
- int page, offset, elt;
+ char out[6];
+ int page;
+
+ err_puts(m, ":"); /* indicate compressed data */
+ for (page = 0; page < obj->page_count; page++) {
+ int i, len;
+
+ len = PAGE_SIZE;
+ if (page == obj->page_count - 1)
+ len -= obj->unused;
+ len = (len + 3) / 4;
- for (page = offset = 0; page < obj->page_count; page++) {
- for (elt = 0; elt < PAGE_SIZE/4; elt++) {
- err_printf(m, "%08x : %08x\n", offset,
- obj->pages[page][elt]);
- offset += 4;
+ for (i = 0; i < len; i++) {
+ if (ascii85_encode(obj->pages[page][i], out))
+ err_puts(m, out);
+ else
+ err_puts(m, "z");
}
}
+ err_puts(m, "\n");
}
int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
@@ -328,8 +359,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_error_state *error = error_priv->error;
struct drm_i915_error_object *obj;
- int i, j, offset, elt;
int max_hangcheck_score;
+ int i, j;
if (!error) {
err_printf(m, "no error state collected\n");
@@ -481,75 +512,33 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
}
if ((obj = ee->ringbuffer)) {
- err_printf(m, "%s --- ringbuffer = 0x%08x\n",
- dev_priv->engine[i].name,
- lower_32_bits(obj->gtt_offset));
+ err_printf(m, "%s --- ringbuffer = 0x%08llx\n",
+ dev_priv->engine[i].name, obj->gtt_offset);
print_error_obj(m, obj);
}
- if ((obj = ee->hws_page)) {
- u64 hws_offset = obj->gtt_offset;
- u32 *hws_page = &obj->pages[0][0];
-
- if (i915.enable_execlists) {
- hws_offset += LRC_PPHWSP_PN * PAGE_SIZE;
- hws_page = &obj->pages[LRC_PPHWSP_PN][0];
- }
- err_printf(m, "%s --- HW Status = 0x%08llx\n",
- dev_priv->engine[i].name, hws_offset);
- offset = 0;
- for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
- err_printf(m, "[%04x] %08x %08x %08x %08x\n",
- offset,
- hws_page[elt],
- hws_page[elt+1],
- hws_page[elt+2],
- hws_page[elt+3]);
- offset += 16;
- }
+ if ((obj = ee->wa_ctx)) {
+ err_printf(m, "%s --- WA Context = 0x%08llx\n",
+ dev_priv->engine[i].name, obj->gtt_offset);
+ print_error_obj(m, obj);
}
- obj = ee->wa_ctx;
- if (obj) {
- u64 wa_ctx_offset = obj->gtt_offset;
- u32 *wa_ctx_page = &obj->pages[0][0];
- struct intel_engine_cs *engine = &dev_priv->engine[RCS];
- u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size +
- engine->wa_ctx.per_ctx.size);
-
- err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n",
- dev_priv->engine[i].name, wa_ctx_offset);
- offset = 0;
- for (elt = 0; elt < wa_ctx_size; elt += 4) {
- err_printf(m, "[%04x] %08x %08x %08x %08x\n",
- offset,
- wa_ctx_page[elt + 0],
- wa_ctx_page[elt + 1],
- wa_ctx_page[elt + 2],
- wa_ctx_page[elt + 3]);
- offset += 16;
- }
+ if ((obj = ee->hws_page)) {
+ err_printf(m, "%s --- HW Status = 0x%08llx\n",
+ dev_priv->engine[i].name, obj->gtt_offset);
+ print_error_obj(m, obj);
}
if ((obj = ee->ctx)) {
- err_printf(m, "%s --- HW Context = 0x%08x\n",
- dev_priv->engine[i].name,
- lower_32_bits(obj->gtt_offset));
+ err_printf(m, "%s --- HW Context = 0x%08llx\n",
+ dev_priv->engine[i].name, obj->gtt_offset);
print_error_obj(m, obj);
}
}
if ((obj = error->semaphore_obj)) {
- err_printf(m, "Semaphore page = 0x%08x\n",
- lower_32_bits(obj->gtt_offset));
- for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
- err_printf(m, "[%04x] %08x %08x %08x %08x\n",
- elt * 4,
- obj->pages[0][elt],
- obj->pages[0][elt+1],
- obj->pages[0][elt+2],
- obj->pages[0][elt+3]);
- }
+ err_printf(m, "Semaphore page = 0x%08llx\n", obj->gtt_offset);
+ print_error_obj(m, obj);
}
if (error->overlay)
@@ -605,7 +594,7 @@ static void i915_error_object_free(struct drm_i915_error_object *obj)
return;
for (page = 0; page < obj->page_count; page++)
- kfree(obj->pages[page]);
+ free_page((unsigned long)obj->pages[page]);
kfree(obj);
}
@@ -641,98 +630,107 @@ static void i915_error_state_free(struct kref *error_ref)
kfree(error);
}
+static int compress_page(struct z_stream_s *zstream,
+ void *src,
+ struct drm_i915_error_object *dst)
+{
+ zstream->next_in = src;
+ zstream->avail_in = PAGE_SIZE;
+
+ do {
+ if (zstream->avail_out == 0) {
+ unsigned long page;
+
+ page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN);
+ if (!page)
+ return -ENOMEM;
+
+ dst->pages[dst->page_count++] = (void *)page;
+
+ zstream->next_out = (void *)page;
+ zstream->avail_out = PAGE_SIZE;
+ }
+
+ if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK)
+ return -EIO;
+
+#if 0
+ if (zstream->total_out > zstream->total_in)
+ return -E2BIG;
+#endif
+ } while (zstream->avail_in);
+
+ return 0;
+}
+
static struct drm_i915_error_object *
-i915_error_object_create(struct drm_i915_private *dev_priv,
+i915_error_object_create(struct drm_i915_private *i915,
struct i915_vma *vma)
{
- struct i915_ggtt *ggtt = &dev_priv->ggtt;
- struct drm_i915_gem_object *src;
+ struct i915_ggtt *ggtt = &i915->ggtt;
+ const u64 slot = ggtt->gpu_error.start;
struct drm_i915_error_object *dst;
- int num_pages;
- bool use_ggtt;
- int i = 0;
- u64 reloc_offset;
+ struct z_stream_s zstream;
+ unsigned long num_pages;
+ struct sgt_iter iter;
+ dma_addr_t dma;
if (!vma)
return NULL;
- src = vma->obj;
- if (!src->pages)
- return NULL;
-
- num_pages = src->base.size >> PAGE_SHIFT;
-
- dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
+ num_pages = vma->size >> PAGE_SHIFT;
+ num_pages = 10 * num_pages * sizeof(u32 *) >> 3;
+ dst = kmalloc(sizeof(*dst) + num_pages, GFP_ATOMIC | __GFP_NOWARN);
if (!dst)
return NULL;
dst->gtt_offset = vma->node.start;
- dst->gtt_size = vma->node.size;
+ dst->page_count = 0;
+ dst->unused = 0;
+
+ memset(&zstream, 0, sizeof(zstream));
+ zstream.workspace = kmalloc(zlib_deflate_workspacesize(MAX_WBITS,
+ MAX_MEM_LEVEL),
+ GFP_ATOMIC | __GFP_NOWARN);
+ if (!zstream.workspace ||
+ zlib_deflateInit(&zstream, Z_DEFAULT_COMPRESSION) != Z_OK) {
+ kfree(zstream.workspace);
+ kfree(dst);
+ return NULL;
+ }
- reloc_offset = dst->gtt_offset;
- use_ggtt = (src->cache_level == I915_CACHE_NONE &&
- (vma->flags & I915_VMA_GLOBAL_BIND) &&
- reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
+ for_each_sgt_dma(dma, iter,
+ vma->ggtt_view.pages ?: vma->obj->pages) {
+ int ret;
+ void *s;
- /* Cannot access stolen address directly, try to use the aperture */
- if (src->stolen) {
- use_ggtt = true;
+ ggtt->base.insert_page(&ggtt->base, dma, slot,
+ I915_CACHE_NONE, 0);
- if (!(vma->flags & I915_VMA_GLOBAL_BIND))
- goto unwind;
+ s = (void *__force)
+ io_mapping_map_atomic_wc(ggtt->mappable, slot);
+ ret = compress_page(&zstream, s, dst);
+ io_mapping_unmap_atomic(s);
- reloc_offset = vma->node.start;
- if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end)
+ if (ret)
goto unwind;
}
+ zlib_deflate(&zstream, Z_FINISH);
+ dst->unused = zstream.avail_out;
+out:
+ zlib_deflateEnd(&zstream);
+ kfree(zstream.workspace);
- /* Cannot access snooped pages through the aperture */
- if (use_ggtt && src->cache_level != I915_CACHE_NONE &&
- !HAS_LLC(dev_priv))
- goto unwind;
-
- dst->page_count = num_pages;
- while (num_pages--) {
- void *d;
-
- d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
- if (d == NULL)
- goto unwind;
-
- if (use_ggtt) {
- void __iomem *s;
-
- /* Simply ignore tiling or any overlapping fence.
- * It's part of the error state, and this hopefully
- * captures what the GPU read.
- */
-
- s = io_mapping_map_atomic_wc(ggtt->mappable,
- reloc_offset);
- memcpy_fromio(d, s, PAGE_SIZE);
- io_mapping_unmap_atomic(s);
- } else {
- struct page *page;
- void *s;
-
- page = i915_gem_object_get_page(src, i);
-
- s = kmap_atomic(page);
- memcpy(d, s, PAGE_SIZE);
- kunmap_atomic(s);
- }
-
- dst->pages[i++] = d;
- reloc_offset += PAGE_SIZE;
- }
+ ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE, true);
return dst;
unwind:
- while (i--)
- kfree(dst->pages[i]);
+ while (dst->page_count--)
+ free_page((unsigned long)dst->pages[dst->page_count]);
kfree(dst);
- return NULL;
+ dst = NULL;
+ goto out;
}
/* The error capture is special as tries to run underneath the normal
@@ -979,6 +977,8 @@ static void error_record_engine_registers(struct drm_i915_error_state *error,
ee->head = I915_READ_HEAD(engine);
ee->tail = I915_READ_TAIL(engine);
ee->ctl = I915_READ_CTL(engine);
+ if (INTEL_GEN(dev_priv) > 2)
+ ee->mode = I915_READ_MODE(engine);
if (I915_NEED_GFX_HWS(dev_priv)) {
i915_reg_t mmio;
@@ -1367,9 +1367,6 @@ static int capture(void *data)
{
struct drm_i915_error_state *error = data;
- /* Ensure that what we readback from memory matches what the GPU sees */
- wbinvd();
-
i915_capture_gen_state(error->i915, error);
i915_capture_reg_state(error->i915, error);
i915_gem_record_fences(error->i915, error);
@@ -1383,9 +1380,6 @@ static int capture(void *data)
error->overlay = intel_overlay_capture_error_state(error->i915);
error->display = intel_display_capture_error_state(error->i915);
- /* And make sure we don't leave trash in the CPU cache */
- wbinvd();
-
return 0;
}
@@ -1459,7 +1453,6 @@ void i915_error_state_get(struct drm_device *dev,
if (error_priv->error)
kref_get(&error_priv->error->ref);
spin_unlock_irq(&dev_priv->gpu_error.lock);
-
}
void i915_error_state_put(struct i915_error_state_file_priv *error_priv)
--
2.8.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* ✗ Ro.CI.BAT: failure for series starting with [01/13] drm/i915: Reduce amount of duplicate buffer information captured on error
2016-08-05 9:05 First class i915_vma Chris Wilson
` (12 preceding siblings ...)
2016-08-05 9:06 ` [PATCH 13/13] drm/i915: Compress GPU objects in error state Chris Wilson
@ 2016-08-05 9:09 ` Patchwork
13 siblings, 0 replies; 21+ messages in thread
From: Patchwork @ 2016-08-05 9:09 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
== Series Details ==
Series: series starting with [01/13] drm/i915: Reduce amount of duplicate buffer information captured on error
URL : https://patchwork.freedesktop.org/series/10705/
State : failure
== Summary ==
Applying: drm/i915: Reduce amount of duplicate buffer information captured on error
Using index info to reconstruct a base tree...
M drivers/gpu/drm/i915/i915_drv.h
M drivers/gpu/drm/i915/i915_gpu_error.c
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/i915/i915_gpu_error.c
CONFLICT (content): Merge conflict in drivers/gpu/drm/i915/i915_gpu_error.c
Auto-merging drivers/gpu/drm/i915/i915_drv.h
error: Failed to merge in the changes.
Patch failed at 0001 drm/i915: Reduce amount of duplicate buffer information captured on error
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 02/13] drm/i915: Stop the machine whilst capturing the GPU crash dump
2016-08-05 9:05 ` [PATCH 02/13] drm/i915: Stop the machine whilst capturing the GPU crash dump Chris Wilson
@ 2016-08-05 18:50 ` Daniel Vetter
2016-08-05 19:01 ` Chris Wilson
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2016-08-05 18:50 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
On Fri, Aug 05, 2016 at 10:05:53AM +0100, Chris Wilson wrote:
> The error state is purposefully racy as we expect it to be called at any
> time and so have avoided any locking whilst capturing the crash dump.
> However, with multi-engine GPUs and multiple CPUs, those races can
> manifest into OOPSes as we attempt to chase dangling pointers freed on
> other CPUs. Under discussion are lots of ways to slow down normal
> operation in order to protect the post-mortem error capture, but what it
> we take the opposite approach and freeze the machine whilst the error
> capture runs (note the GPU may still running, but as long as we don't
> process any of the results the driver's bookkeeping will be static).
>
> Note that by of itself, this is not a complete fix. It also depends on
> the compiler barriers in list_add/list_del to prevent traversing the
> lists into the void.
The other important bit I think are NULL checks. I think the commit
message should mention that too.
>
> v2: Avoid drm_clflush_pages() inside stop_machine() as it may use
> stop_machine() itself for its wbinvd fallback.
Droppingt he clflush from error capture seems like a pretty big
regression, at least at a glance. Why does this not result in piles of
corrupted error state captures?
I guess since we need to flush on incoherent platforms before gpu access
anyway this is mostly true (as long as userspace doesn't do something
silly), but I think it should be captured in a comment at the place of the
clflush.
-Daniel
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
> drivers/gpu/drm/i915/Kconfig | 1 +
> drivers/gpu/drm/i915/i915_drv.h | 2 ++
> drivers/gpu/drm/i915/i915_gpu_error.c | 48 +++++++++++++++++++++--------------
> 3 files changed, 32 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
> index 7769e469118f..7badcee88ebf 100644
> --- a/drivers/gpu/drm/i915/Kconfig
> +++ b/drivers/gpu/drm/i915/Kconfig
> @@ -4,6 +4,7 @@ config DRM_I915
> depends on X86 && PCI
> select INTEL_GTT
> select INTERVAL_TREE
> + select STOP_MACHINE
> # we need shmfs for the swappable backing store, and in particular
> # the shmem_readpage() which depends upon tmpfs
> select SHMEM
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 7054baa92061..9a7ffa49cd1f 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -481,6 +481,8 @@ struct drm_i915_error_state {
> struct kref ref;
> struct timeval time;
>
> + struct drm_i915_private *i915;
> +
> char error_msg[128];
> bool simulated;
> int iommu;
> diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> index ced296983caa..b94a59733cf8 100644
> --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> @@ -28,6 +28,7 @@
> */
>
> #include <generated/utsrelease.h>
> +#include <linux/stop_machine.h>
> #include "i915_drv.h"
>
> static const char *engine_str(int engine)
> @@ -684,14 +685,12 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
>
> dst->page_count = num_pages;
> while (num_pages--) {
> - unsigned long flags;
> void *d;
>
> d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
> if (d == NULL)
> goto unwind;
>
> - local_irq_save(flags);
> if (use_ggtt) {
> void __iomem *s;
>
> @@ -710,15 +709,10 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
>
> page = i915_gem_object_get_page(src, i);
>
> - drm_clflush_pages(&page, 1);
> -
> s = kmap_atomic(page);
> memcpy(d, s, PAGE_SIZE);
> kunmap_atomic(s);
> -
> - drm_clflush_pages(&page, 1);
> }
> - local_irq_restore(flags);
>
> dst->pages[i++] = d;
> reloc_offset += PAGE_SIZE;
> @@ -1371,6 +1365,32 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
> error->suspend_count = dev_priv->suspend_count;
> }
>
> +static int capture(void *data)
> +{
> + struct drm_i915_error_state *error = data;
> +
> + /* Ensure that what we readback from memory matches what the GPU sees */
> + wbinvd();
> +
> + i915_capture_gen_state(error->i915, error);
> + i915_capture_reg_state(error->i915, error);
> + i915_gem_record_fences(error->i915, error);
> + i915_gem_record_rings(error->i915, error);
> +
> + i915_capture_active_buffers(error->i915, error);
> + i915_capture_pinned_buffers(error->i915, error);
> +
> + do_gettimeofday(&error->time);
> +
> + error->overlay = intel_overlay_capture_error_state(error->i915);
> + error->display = intel_display_capture_error_state(error->i915);
> +
> + /* And make sure we don't leave trash in the CPU cache */
> + wbinvd();
> +
> + return 0;
> +}
> +
> /**
> * i915_capture_error_state - capture an error record for later analysis
> * @dev: drm device
> @@ -1399,19 +1419,9 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv,
> }
>
> kref_init(&error->ref);
> + error->i915 = dev_priv;
>
> - i915_capture_gen_state(dev_priv, error);
> - i915_capture_reg_state(dev_priv, error);
> - i915_gem_record_fences(dev_priv, error);
> - i915_gem_record_rings(dev_priv, error);
> -
> - i915_capture_active_buffers(dev_priv, error);
> - i915_capture_pinned_buffers(dev_priv, error);
> -
> - do_gettimeofday(&error->time);
> -
> - error->overlay = intel_overlay_capture_error_state(dev_priv);
> - error->display = intel_display_capture_error_state(dev_priv);
> + stop_machine(capture, error, NULL);
>
> i915_error_capture_msg(dev_priv, error, engine_mask, error_msg);
> DRM_INFO("%s\n", error->error_msg);
> --
> 2.8.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 13/13] drm/i915: Compress GPU objects in error state
2016-08-05 9:06 ` [PATCH 13/13] drm/i915: Compress GPU objects in error state Chris Wilson
@ 2016-08-05 18:56 ` Daniel Vetter
2016-08-05 19:15 ` Chris Wilson
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2016-08-05 18:56 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
On Fri, Aug 05, 2016 at 10:06:04AM +0100, Chris Wilson wrote:
> Our error states are quickly growing, pinning kernel memory with them.
> The majority of the space is taken up by the error objects. These
> compress well using zlib and without decode are mostly meaningless, so
> encoding them does not hinder quickly parsing the error state for
> familiarity.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Seems to also contain a wholesale rework of the capture logic using a ggtt
mappable entry. Would explain why the missing clflush isn't an issue for
you. Imo best if that part is reordered as the first patch (or at least
before stop_machine, which requires the removal of cflush), and then the
zlib on top.
On the idea itself, since I have no clue: How do we uncompress these
again? Patched intel_error_decode, or can zlib deal with in-line streams?
-Daniel
> ---
> drivers/gpu/drm/i915/Kconfig | 1 +
> drivers/gpu/drm/i915/i915_drv.h | 4 +-
> drivers/gpu/drm/i915/i915_gem_gtt.c | 10 ++
> drivers/gpu/drm/i915/i915_gem_gtt.h | 2 +
> drivers/gpu/drm/i915/i915_gpu_error.c | 271 +++++++++++++++++-----------------
> 5 files changed, 148 insertions(+), 140 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
> index 7badcee88ebf..c8ea20526aef 100644
> --- a/drivers/gpu/drm/i915/Kconfig
> +++ b/drivers/gpu/drm/i915/Kconfig
> @@ -5,6 +5,7 @@ config DRM_I915
> select INTEL_GTT
> select INTERVAL_TREE
> select STOP_MACHINE
> + select ZLIB_DEFLATE
> # we need shmfs for the swappable backing store, and in particular
> # the shmem_readpage() which depends upon tmpfs
> select SHMEM
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 370a4c9eea70..edc1e6d6be0d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -534,6 +534,7 @@ struct drm_i915_error_state {
> u32 tail;
> u32 head;
> u32 ctl;
> + u32 mode;
> u32 hws;
> u32 ipeir;
> u32 ipehr;
> @@ -550,9 +551,10 @@ struct drm_i915_error_state {
> u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
>
> struct drm_i915_error_object {
> - int page_count;
> u64 gtt_offset;
> u64 gtt_size;
> + int page_count;
> + int unused;
> u32 *pages[0];
> } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index 7c9f654d515a..c45e7f456cea 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -2737,6 +2737,15 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv)
> if (ret)
> return ret;
>
> + /* Reserve a mappable slot for our lockless error capture */
> + ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
> + &ggtt->gpu_error,
> + 4096, 0, -1,
> + 0, ggtt->mappable_end,
> + 0, 0);
> + if (ret)
> + return ret;
> +
> /* Clear any non-preallocated blocks */
> drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) {
> DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
> @@ -2804,6 +2813,7 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv)
> if (drm_mm_initialized(&ggtt->base.mm)) {
> intel_vgt_deballoon(dev_priv);
>
> + drm_mm_remove_node(&ggtt->gpu_error);
> drm_mm_takedown(&ggtt->base.mm);
> list_del(&ggtt->base.global_link);
> }
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> index c54ae2323df3..010e10c0b62b 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> @@ -428,6 +428,8 @@ struct i915_ggtt {
> bool do_idle_maps;
>
> int mtrr;
> +
> + struct drm_mm_node gpu_error;
> };
>
> struct i915_hw_ppgtt {
> diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> index 6078f47d4bc0..f036584e55e3 100644
> --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> @@ -29,6 +29,7 @@
>
> #include <generated/utsrelease.h>
> #include <linux/stop_machine.h>
> +#include <linux/zlib.h>
> #include "i915_drv.h"
>
> static const char *engine_str(int engine)
> @@ -237,6 +238,8 @@ static void error_print_engine(struct drm_i915_error_state_buf *m,
> err_printf(m, " HEAD: 0x%08x\n", ee->head);
> err_printf(m, " TAIL: 0x%08x\n", ee->tail);
> err_printf(m, " CTL: 0x%08x\n", ee->ctl);
> + err_printf(m, " MODE: 0x%08x [idle? %d]\n",
> + ee->mode, !!(ee->mode & MODE_IDLE));
> err_printf(m, " HWS: 0x%08x\n", ee->hws);
> err_printf(m, " ACTHD: 0x%08x %08x\n",
> (u32)(ee->acthd>>32), (u32)ee->acthd);
> @@ -307,18 +310,46 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
> va_end(args);
> }
>
> +static bool
> +ascii85_encode(u32 in, char *out)
> +{
> + int i;
> +
> + if (in == 0)
> + return false;
> +
> + out[5] = '\0';
> + for (i = 5; i--; ) {
> + out[i] = '!' + in % 85;
> + in /= 85;
> + }
> +
> + return true;
> +}
> +
> static void print_error_obj(struct drm_i915_error_state_buf *m,
> struct drm_i915_error_object *obj)
> {
> - int page, offset, elt;
> + char out[6];
> + int page;
> +
> + err_puts(m, ":"); /* indicate compressed data */
> + for (page = 0; page < obj->page_count; page++) {
> + int i, len;
> +
> + len = PAGE_SIZE;
> + if (page == obj->page_count - 1)
> + len -= obj->unused;
> + len = (len + 3) / 4;
>
> - for (page = offset = 0; page < obj->page_count; page++) {
> - for (elt = 0; elt < PAGE_SIZE/4; elt++) {
> - err_printf(m, "%08x : %08x\n", offset,
> - obj->pages[page][elt]);
> - offset += 4;
> + for (i = 0; i < len; i++) {
> + if (ascii85_encode(obj->pages[page][i], out))
> + err_puts(m, out);
> + else
> + err_puts(m, "z");
> }
> }
> + err_puts(m, "\n");
> }
>
> int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
> @@ -328,8 +359,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
> struct drm_i915_private *dev_priv = to_i915(dev);
> struct drm_i915_error_state *error = error_priv->error;
> struct drm_i915_error_object *obj;
> - int i, j, offset, elt;
> int max_hangcheck_score;
> + int i, j;
>
> if (!error) {
> err_printf(m, "no error state collected\n");
> @@ -481,75 +512,33 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
> }
>
> if ((obj = ee->ringbuffer)) {
> - err_printf(m, "%s --- ringbuffer = 0x%08x\n",
> - dev_priv->engine[i].name,
> - lower_32_bits(obj->gtt_offset));
> + err_printf(m, "%s --- ringbuffer = 0x%08llx\n",
> + dev_priv->engine[i].name, obj->gtt_offset);
> print_error_obj(m, obj);
> }
>
> - if ((obj = ee->hws_page)) {
> - u64 hws_offset = obj->gtt_offset;
> - u32 *hws_page = &obj->pages[0][0];
> -
> - if (i915.enable_execlists) {
> - hws_offset += LRC_PPHWSP_PN * PAGE_SIZE;
> - hws_page = &obj->pages[LRC_PPHWSP_PN][0];
> - }
> - err_printf(m, "%s --- HW Status = 0x%08llx\n",
> - dev_priv->engine[i].name, hws_offset);
> - offset = 0;
> - for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
> - err_printf(m, "[%04x] %08x %08x %08x %08x\n",
> - offset,
> - hws_page[elt],
> - hws_page[elt+1],
> - hws_page[elt+2],
> - hws_page[elt+3]);
> - offset += 16;
> - }
> + if ((obj = ee->wa_ctx)) {
> + err_printf(m, "%s --- WA Context = 0x%08llx\n",
> + dev_priv->engine[i].name, obj->gtt_offset);
> + print_error_obj(m, obj);
> }
>
> - obj = ee->wa_ctx;
> - if (obj) {
> - u64 wa_ctx_offset = obj->gtt_offset;
> - u32 *wa_ctx_page = &obj->pages[0][0];
> - struct intel_engine_cs *engine = &dev_priv->engine[RCS];
> - u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size +
> - engine->wa_ctx.per_ctx.size);
> -
> - err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n",
> - dev_priv->engine[i].name, wa_ctx_offset);
> - offset = 0;
> - for (elt = 0; elt < wa_ctx_size; elt += 4) {
> - err_printf(m, "[%04x] %08x %08x %08x %08x\n",
> - offset,
> - wa_ctx_page[elt + 0],
> - wa_ctx_page[elt + 1],
> - wa_ctx_page[elt + 2],
> - wa_ctx_page[elt + 3]);
> - offset += 16;
> - }
> + if ((obj = ee->hws_page)) {
> + err_printf(m, "%s --- HW Status = 0x%08llx\n",
> + dev_priv->engine[i].name, obj->gtt_offset);
> + print_error_obj(m, obj);
> }
>
> if ((obj = ee->ctx)) {
> - err_printf(m, "%s --- HW Context = 0x%08x\n",
> - dev_priv->engine[i].name,
> - lower_32_bits(obj->gtt_offset));
> + err_printf(m, "%s --- HW Context = 0x%08llx\n",
> + dev_priv->engine[i].name, obj->gtt_offset);
> print_error_obj(m, obj);
> }
> }
>
> if ((obj = error->semaphore_obj)) {
> - err_printf(m, "Semaphore page = 0x%08x\n",
> - lower_32_bits(obj->gtt_offset));
> - for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
> - err_printf(m, "[%04x] %08x %08x %08x %08x\n",
> - elt * 4,
> - obj->pages[0][elt],
> - obj->pages[0][elt+1],
> - obj->pages[0][elt+2],
> - obj->pages[0][elt+3]);
> - }
> + err_printf(m, "Semaphore page = 0x%08llx\n", obj->gtt_offset);
> + print_error_obj(m, obj);
> }
>
> if (error->overlay)
> @@ -605,7 +594,7 @@ static void i915_error_object_free(struct drm_i915_error_object *obj)
> return;
>
> for (page = 0; page < obj->page_count; page++)
> - kfree(obj->pages[page]);
> + free_page((unsigned long)obj->pages[page]);
>
> kfree(obj);
> }
> @@ -641,98 +630,107 @@ static void i915_error_state_free(struct kref *error_ref)
> kfree(error);
> }
>
> +static int compress_page(struct z_stream_s *zstream,
> + void *src,
> + struct drm_i915_error_object *dst)
> +{
> + zstream->next_in = src;
> + zstream->avail_in = PAGE_SIZE;
> +
> + do {
> + if (zstream->avail_out == 0) {
> + unsigned long page;
> +
> + page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN);
> + if (!page)
> + return -ENOMEM;
> +
> + dst->pages[dst->page_count++] = (void *)page;
> +
> + zstream->next_out = (void *)page;
> + zstream->avail_out = PAGE_SIZE;
> + }
> +
> + if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK)
> + return -EIO;
> +
> +#if 0
> + if (zstream->total_out > zstream->total_in)
> + return -E2BIG;
> +#endif
> + } while (zstream->avail_in);
> +
> + return 0;
> +}
> +
> static struct drm_i915_error_object *
> -i915_error_object_create(struct drm_i915_private *dev_priv,
> +i915_error_object_create(struct drm_i915_private *i915,
> struct i915_vma *vma)
> {
> - struct i915_ggtt *ggtt = &dev_priv->ggtt;
> - struct drm_i915_gem_object *src;
> + struct i915_ggtt *ggtt = &i915->ggtt;
> + const u64 slot = ggtt->gpu_error.start;
> struct drm_i915_error_object *dst;
> - int num_pages;
> - bool use_ggtt;
> - int i = 0;
> - u64 reloc_offset;
> + struct z_stream_s zstream;
> + unsigned long num_pages;
> + struct sgt_iter iter;
> + dma_addr_t dma;
>
> if (!vma)
> return NULL;
>
> - src = vma->obj;
> - if (!src->pages)
> - return NULL;
> -
> - num_pages = src->base.size >> PAGE_SHIFT;
> -
> - dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
> + num_pages = vma->size >> PAGE_SHIFT;
> + num_pages = 10 * num_pages * sizeof(u32 *) >> 3;
> + dst = kmalloc(sizeof(*dst) + num_pages, GFP_ATOMIC | __GFP_NOWARN);
> if (!dst)
> return NULL;
>
> dst->gtt_offset = vma->node.start;
> - dst->gtt_size = vma->node.size;
> + dst->page_count = 0;
> + dst->unused = 0;
> +
> + memset(&zstream, 0, sizeof(zstream));
> + zstream.workspace = kmalloc(zlib_deflate_workspacesize(MAX_WBITS,
> + MAX_MEM_LEVEL),
> + GFP_ATOMIC | __GFP_NOWARN);
> + if (!zstream.workspace ||
> + zlib_deflateInit(&zstream, Z_DEFAULT_COMPRESSION) != Z_OK) {
> + kfree(zstream.workspace);
> + kfree(dst);
> + return NULL;
> + }
>
> - reloc_offset = dst->gtt_offset;
> - use_ggtt = (src->cache_level == I915_CACHE_NONE &&
> - (vma->flags & I915_VMA_GLOBAL_BIND) &&
> - reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
> + for_each_sgt_dma(dma, iter,
> + vma->ggtt_view.pages ?: vma->obj->pages) {
> + int ret;
> + void *s;
>
> - /* Cannot access stolen address directly, try to use the aperture */
> - if (src->stolen) {
> - use_ggtt = true;
> + ggtt->base.insert_page(&ggtt->base, dma, slot,
> + I915_CACHE_NONE, 0);
>
> - if (!(vma->flags & I915_VMA_GLOBAL_BIND))
> - goto unwind;
> + s = (void *__force)
> + io_mapping_map_atomic_wc(ggtt->mappable, slot);
> + ret = compress_page(&zstream, s, dst);
> + io_mapping_unmap_atomic(s);
>
> - reloc_offset = vma->node.start;
> - if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end)
> + if (ret)
> goto unwind;
> }
> + zlib_deflate(&zstream, Z_FINISH);
> + dst->unused = zstream.avail_out;
> +out:
> + zlib_deflateEnd(&zstream);
> + kfree(zstream.workspace);
>
> - /* Cannot access snooped pages through the aperture */
> - if (use_ggtt && src->cache_level != I915_CACHE_NONE &&
> - !HAS_LLC(dev_priv))
> - goto unwind;
> -
> - dst->page_count = num_pages;
> - while (num_pages--) {
> - void *d;
> -
> - d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
> - if (d == NULL)
> - goto unwind;
> -
> - if (use_ggtt) {
> - void __iomem *s;
> -
> - /* Simply ignore tiling or any overlapping fence.
> - * It's part of the error state, and this hopefully
> - * captures what the GPU read.
> - */
> -
> - s = io_mapping_map_atomic_wc(ggtt->mappable,
> - reloc_offset);
> - memcpy_fromio(d, s, PAGE_SIZE);
> - io_mapping_unmap_atomic(s);
> - } else {
> - struct page *page;
> - void *s;
> -
> - page = i915_gem_object_get_page(src, i);
> -
> - s = kmap_atomic(page);
> - memcpy(d, s, PAGE_SIZE);
> - kunmap_atomic(s);
> - }
> -
> - dst->pages[i++] = d;
> - reloc_offset += PAGE_SIZE;
> - }
> + ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE, true);
>
> return dst;
>
> unwind:
> - while (i--)
> - kfree(dst->pages[i]);
> + while (dst->page_count--)
> + free_page((unsigned long)dst->pages[dst->page_count]);
> kfree(dst);
> - return NULL;
> + dst = NULL;
> + goto out;
> }
>
> /* The error capture is special as tries to run underneath the normal
> @@ -979,6 +977,8 @@ static void error_record_engine_registers(struct drm_i915_error_state *error,
> ee->head = I915_READ_HEAD(engine);
> ee->tail = I915_READ_TAIL(engine);
> ee->ctl = I915_READ_CTL(engine);
> + if (INTEL_GEN(dev_priv) > 2)
> + ee->mode = I915_READ_MODE(engine);
>
> if (I915_NEED_GFX_HWS(dev_priv)) {
> i915_reg_t mmio;
> @@ -1367,9 +1367,6 @@ static int capture(void *data)
> {
> struct drm_i915_error_state *error = data;
>
> - /* Ensure that what we readback from memory matches what the GPU sees */
> - wbinvd();
> -
> i915_capture_gen_state(error->i915, error);
> i915_capture_reg_state(error->i915, error);
> i915_gem_record_fences(error->i915, error);
> @@ -1383,9 +1380,6 @@ static int capture(void *data)
> error->overlay = intel_overlay_capture_error_state(error->i915);
> error->display = intel_display_capture_error_state(error->i915);
>
> - /* And make sure we don't leave trash in the CPU cache */
> - wbinvd();
> -
> return 0;
> }
>
> @@ -1459,7 +1453,6 @@ void i915_error_state_get(struct drm_device *dev,
> if (error_priv->error)
> kref_get(&error_priv->error->ref);
> spin_unlock_irq(&dev_priv->gpu_error.lock);
> -
> }
>
> void i915_error_state_put(struct i915_error_state_file_priv *error_priv)
> --
> 2.8.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 02/13] drm/i915: Stop the machine whilst capturing the GPU crash dump
2016-08-05 18:50 ` Daniel Vetter
@ 2016-08-05 19:01 ` Chris Wilson
2016-08-05 19:57 ` Daniel Vetter
0 siblings, 1 reply; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 19:01 UTC (permalink / raw)
To: Daniel Vetter; +Cc: intel-gfx
On Fri, Aug 05, 2016 at 08:50:11PM +0200, Daniel Vetter wrote:
> On Fri, Aug 05, 2016 at 10:05:53AM +0100, Chris Wilson wrote:
> > The error state is purposefully racy as we expect it to be called at any
> > time and so have avoided any locking whilst capturing the crash dump.
> > However, with multi-engine GPUs and multiple CPUs, those races can
> > manifest into OOPSes as we attempt to chase dangling pointers freed on
> > other CPUs. Under discussion are lots of ways to slow down normal
> > operation in order to protect the post-mortem error capture, but what it
> > we take the opposite approach and freeze the machine whilst the error
> > capture runs (note the GPU may still running, but as long as we don't
> > process any of the results the driver's bookkeeping will be static).
> >
> > Note that by of itself, this is not a complete fix. It also depends on
> > the compiler barriers in list_add/list_del to prevent traversing the
> > lists into the void.
>
> The other important bit I think are NULL checks. I think the commit
> message should mention that too.
Not so convinced here. My idea for GPU error capture is that we
basically grab the bad request and then probe from there. The only list
(and pointer chasing) I want to walk in a dangerous manner is the request
list. Everything we need to report should be derivable from that
request, and as the request is reachable from the list we know it is
intact. I guess we could err on !request->fence.refcount and run away.
> > v2: Avoid drm_clflush_pages() inside stop_machine() as it may use
> > stop_machine() itself for its wbinvd fallback.
>
> Droppingt he clflush from error capture seems like a pretty big
> regression, at least at a glance. Why does this not result in piles of
> corrupted error state captures?
We replace the clflush with an ever bigger complete cache flush.
However...
> I guess since we need to flush on incoherent platforms before gpu access
> anyway this is mostly true (as long as userspace doesn't do something
> silly), but I think it should be captured in a comment at the place of the
> clflush.
Indeed. All the data we read has been flushed out of the cpu caches.
If not, then right there is a reason for a hang. It's moot as I
propose just using the GTT for accessing every page since it is the only
universal method we have - and it has been my preference for GPU capture
because it gives us coherent data as the GPU would see it. We only
stopped doing so more recently when the batches were not accessible from
the GTT.
-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] 21+ messages in thread
* Re: [PATCH 13/13] drm/i915: Compress GPU objects in error state
2016-08-05 18:56 ` Daniel Vetter
@ 2016-08-05 19:15 ` Chris Wilson
2016-08-05 19:58 ` Daniel Vetter
0 siblings, 1 reply; 21+ messages in thread
From: Chris Wilson @ 2016-08-05 19:15 UTC (permalink / raw)
To: Daniel Vetter; +Cc: intel-gfx
On Fri, Aug 05, 2016 at 08:56:57PM +0200, Daniel Vetter wrote:
> On Fri, Aug 05, 2016 at 10:06:04AM +0100, Chris Wilson wrote:
> > Our error states are quickly growing, pinning kernel memory with them.
> > The majority of the space is taken up by the error objects. These
> > compress well using zlib and without decode are mostly meaningless, so
> > encoding them does not hinder quickly parsing the error state for
> > familiarity.
> >
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
>
> Seems to also contain a wholesale rework of the capture logic using a ggtt
> mappable entry. Would explain why the missing clflush isn't an issue for
> you.
No. clflush was replaced by wbinvd, which is dropped here because it is
no longer required.
> Imo best if that part is reordered as the first patch (or at least
> before stop_machine, which requires the removal of cflush), and then the
> zlib on top.
>
> On the idea itself, since I have no clue: How do we uncompress these
> again? Patched intel_error_decode, or can zlib deal with in-line streams?
intel_error_decode was updated to handle the compressed streams.
commit d4c3cd4d04ab7f317d3429708d19cd5fc4d0f5fa
Author: Chris Wilson <chris@chris-wilson.co.uk>
AuthorDate: Fri Oct 31 11:27:21 2014 +0000
Commit: Chris Wilson <chris@chris-wilson.co.uk>
CommitDate: Thu Dec 31 22:10:11 2015 +0000
intel_error_decode: Inflate compressed error state
-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] 21+ messages in thread
* Re: [PATCH 02/13] drm/i915: Stop the machine whilst capturing the GPU crash dump
2016-08-05 19:01 ` Chris Wilson
@ 2016-08-05 19:57 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2016-08-05 19:57 UTC (permalink / raw)
To: Chris Wilson, Daniel Vetter, intel-gfx
On Fri, Aug 05, 2016 at 08:01:58PM +0100, Chris Wilson wrote:
> On Fri, Aug 05, 2016 at 08:50:11PM +0200, Daniel Vetter wrote:
> > On Fri, Aug 05, 2016 at 10:05:53AM +0100, Chris Wilson wrote:
> > > The error state is purposefully racy as we expect it to be called at any
> > > time and so have avoided any locking whilst capturing the crash dump.
> > > However, with multi-engine GPUs and multiple CPUs, those races can
> > > manifest into OOPSes as we attempt to chase dangling pointers freed on
> > > other CPUs. Under discussion are lots of ways to slow down normal
> > > operation in order to protect the post-mortem error capture, but what it
> > > we take the opposite approach and freeze the machine whilst the error
> > > capture runs (note the GPU may still running, but as long as we don't
> > > process any of the results the driver's bookkeeping will be static).
> > >
> > > Note that by of itself, this is not a complete fix. It also depends on
> > > the compiler barriers in list_add/list_del to prevent traversing the
> > > lists into the void.
> >
> > The other important bit I think are NULL checks. I think the commit
> > message should mention that too.
>
> Not so convinced here. My idea for GPU error capture is that we
> basically grab the bad request and then probe from there. The only list
> (and pointer chasing) I want to walk in a dangerous manner is the request
> list. Everything we need to report should be derivable from that
> request, and as the request is reachable from the list we know it is
> intact. I guess we could err on !request->fence.refcount and run away.
Yeah, this story is more convincing, would be good to add it.
-Daniel
>
> > > v2: Avoid drm_clflush_pages() inside stop_machine() as it may use
> > > stop_machine() itself for its wbinvd fallback.
> >
> > Droppingt he clflush from error capture seems like a pretty big
> > regression, at least at a glance. Why does this not result in piles of
> > corrupted error state captures?
>
> We replace the clflush with an ever bigger complete cache flush.
>
> However...
>
> > I guess since we need to flush on incoherent platforms before gpu access
> > anyway this is mostly true (as long as userspace doesn't do something
> > silly), but I think it should be captured in a comment at the place of the
> > clflush.
>
> Indeed. All the data we read has been flushed out of the cpu caches.
> If not, then right there is a reason for a hang. It's moot as I
> propose just using the GTT for accessing every page since it is the only
> universal method we have - and it has been my preference for GPU capture
> because it gives us coherent data as the GPU would see it. We only
> stopped doing so more recently when the batches were not accessible from
> the GTT.
> -Chris
>
> --
> Chris Wilson, Intel Open Source Technology Centre
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 13/13] drm/i915: Compress GPU objects in error state
2016-08-05 19:15 ` Chris Wilson
@ 2016-08-05 19:58 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2016-08-05 19:58 UTC (permalink / raw)
To: Chris Wilson, Daniel Vetter, intel-gfx
On Fri, Aug 05, 2016 at 08:15:42PM +0100, Chris Wilson wrote:
> On Fri, Aug 05, 2016 at 08:56:57PM +0200, Daniel Vetter wrote:
> > On Fri, Aug 05, 2016 at 10:06:04AM +0100, Chris Wilson wrote:
> > > Our error states are quickly growing, pinning kernel memory with them.
> > > The majority of the space is taken up by the error objects. These
> > > compress well using zlib and without decode are mostly meaningless, so
> > > encoding them does not hinder quickly parsing the error state for
> > > familiarity.
> > >
> > > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> >
> > Seems to also contain a wholesale rework of the capture logic using a ggtt
> > mappable entry. Would explain why the missing clflush isn't an issue for
> > you.
>
> No. clflush was replaced by wbinvd, which is dropped here because it is
> no longer required.
Indeed, I missed that, makes all sense. Still should be split up I think
since it's quite a bit a change.
> > Imo best if that part is reordered as the first patch (or at least
> > before stop_machine, which requires the removal of cflush), and then the
> > zlib on top.
> >
> > On the idea itself, since I have no clue: How do we uncompress these
> > again? Patched intel_error_decode, or can zlib deal with in-line streams?
>
> intel_error_decode was updated to handle the compressed streams.
>
> commit d4c3cd4d04ab7f317d3429708d19cd5fc4d0f5fa
> Author: Chris Wilson <chris@chris-wilson.co.uk>
> AuthorDate: Fri Oct 31 11:27:21 2014 +0000
> Commit: Chris Wilson <chris@chris-wilson.co.uk>
> CommitDate: Thu Dec 31 22:10:11 2015 +0000
>
> intel_error_decode: Inflate compressed error state
Oh, entirely missed that too ;-) Still would be good to add that to the
commit message.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2016-08-05 19:58 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-05 9:05 First class i915_vma Chris Wilson
2016-08-05 9:05 ` [PATCH 01/13] drm/i915: Reduce amount of duplicate buffer information captured on error Chris Wilson
2016-08-05 9:05 ` [PATCH 02/13] drm/i915: Stop the machine whilst capturing the GPU crash dump Chris Wilson
2016-08-05 18:50 ` Daniel Vetter
2016-08-05 19:01 ` Chris Wilson
2016-08-05 19:57 ` Daniel Vetter
2016-08-05 9:05 ` [PATCH 03/13] drm/i915: Scan GGTT active list for context object Chris Wilson
2016-08-05 9:05 ` [PATCH 04/13] drm/i915: Move setting of request->batch into its single callsite Chris Wilson
2016-08-05 9:05 ` [PATCH 05/13] drm/i915: Mark unmappable GGTT entries as PIN_HIGH Chris Wilson
2016-08-05 9:05 ` [PATCH 06/13] drm/i915: Track pinned vma inside guc Chris Wilson
2016-08-05 9:05 ` [PATCH 07/13] drm/i915: Track pinned VMA Chris Wilson
2016-08-05 9:05 ` [PATCH 08/13] drm/i915/overlay: Use VMA as the primary tracker for images Chris Wilson
2016-08-05 9:06 ` [PATCH 09/13] drm/i915: Print the batchbuffer offset next to BBADDR in error state Chris Wilson
2016-08-05 9:06 ` [PATCH 10/13] drm/i915: Move per-request pid from request to ctx Chris Wilson
2016-08-05 9:06 ` [PATCH 11/13] drm/i915: Store the active context object on all engines upon error Chris Wilson
2016-08-05 9:06 ` [PATCH 12/13] drm/i915: Only record active and pending requests upon a GPU hang Chris Wilson
2016-08-05 9:06 ` [PATCH 13/13] drm/i915: Compress GPU objects in error state Chris Wilson
2016-08-05 18:56 ` Daniel Vetter
2016-08-05 19:15 ` Chris Wilson
2016-08-05 19:58 ` Daniel Vetter
2016-08-05 9:09 ` ✗ Ro.CI.BAT: failure for series starting with [01/13] drm/i915: Reduce amount of duplicate buffer information captured on error Patchwork
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox