Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6083 → Rev 6084

/drivers/video/drm/i915/i915_gpu_error.c
30,10 → 30,6
#include "i915_drv.h"
 
#if 0
static const char *yesno(int v)
{
return v ? "yes" : "no";
}
 
static const char *ring_str(int ring)
{
192,15 → 188,21
struct drm_i915_error_buffer *err,
int count)
{
int i;
 
err_printf(m, " %s [%d]:\n", name, count);
 
while (count--) {
err_printf(m, " %08x %8u %02x %02x %x %x",
err->gtt_offset,
err_printf(m, " %08x_%08x %8u %02x %02x [ ",
upper_32_bits(err->gtt_offset),
lower_32_bits(err->gtt_offset),
err->size,
err->read_domains,
err->write_domain,
err->rseqno, err->wseqno);
err->write_domain);
for (i = 0; i < I915_NUM_RINGS; i++)
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));
242,11 → 244,16
 
static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
struct drm_device *dev,
struct drm_i915_error_ring *ring)
struct drm_i915_error_state *error,
int ring_idx)
{
struct drm_i915_error_ring *ring = &error->ring[ring_idx];
 
if (!ring->valid)
return;
 
err_printf(m, "%s command stream:\n", ring_str(ring_idx));
err_printf(m, " START: 0x%08x\n", ring->start);
err_printf(m, " HEAD: 0x%08x\n", ring->head);
err_printf(m, " TAIL: 0x%08x\n", ring->tail);
err_printf(m, " CTL: 0x%08x\n", ring->ctl);
329,6 → 336,7
struct drm_device *dev = error_priv->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_error_state *error = error_priv->error;
struct drm_i915_error_object *obj;
int i, j, offset, elt;
int max_hangcheck_score;
 
358,8 → 366,15
err_printf(m, "Reset count: %u\n", error->reset_count);
err_printf(m, "Suspend count: %u\n", error->suspend_count);
err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device);
err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
err_printf(m, "EIR: 0x%08x\n", error->eir);
err_printf(m, "IER: 0x%08x\n", error->ier);
if (INTEL_INFO(dev)->gen >= 8) {
for (i = 0; i < 4; i++)
err_printf(m, "GTIER gt %d: 0x%08x\n", i,
error->gtier[i]);
} else if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev))
err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]);
err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
375,6 → 390,11
 
if (INTEL_INFO(dev)->gen >= 6) {
err_printf(m, "ERROR: 0x%08x\n", error->error);
 
if (INTEL_INFO(dev)->gen >= 8)
err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
error->fault_data1, error->fault_data0);
 
err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
}
 
381,24 → 401,22
if (INTEL_INFO(dev)->gen == 7)
err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
 
for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
err_printf(m, "%s command stream:\n", ring_str(i));
i915_ring_error_state(m, dev, &error->ring[i]);
}
for (i = 0; i < ARRAY_SIZE(error->ring); i++)
i915_ring_error_state(m, dev, error, i);
 
if (error->active_bo)
for (i = 0; i < error->vm_count; i++) {
err_printf(m, "vm[%d]\n", i);
 
print_error_buffers(m, "Active",
error->active_bo[0],
error->active_bo_count[0]);
error->active_bo[i],
error->active_bo_count[i]);
 
if (error->pinned_bo)
print_error_buffers(m, "Pinned",
error->pinned_bo[0],
error->pinned_bo_count[0]);
error->pinned_bo[i],
error->pinned_bo_count[i]);
}
 
for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
struct drm_i915_error_object *obj;
 
obj = error->ring[i].batchbuffer;
if (obj) {
err_puts(m, dev_priv->ring[i].name);
406,8 → 424,9
err_printf(m, " (submitted by %s [%d])",
error->ring[i].comm,
error->ring[i].pid);
err_printf(m, " --- gtt_offset = 0x%08x\n",
obj->gtt_offset);
err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
upper_32_bits(obj->gtt_offset),
lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
 
414,7 → 433,8
obj = error->ring[i].wa_batchbuffer;
if (obj) {
err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
dev_priv->ring[i].name, obj->gtt_offset);
dev_priv->ring[i].name,
lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
 
433,22 → 453,28
if ((obj = error->ring[i].ringbuffer)) {
err_printf(m, "%s --- ringbuffer = 0x%08x\n",
dev_priv->ring[i].name,
obj->gtt_offset);
lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
 
if ((obj = error->ring[i].hws_page)) {
err_printf(m, "%s --- HW Status = 0x%08x\n",
dev_priv->ring[i].name,
obj->gtt_offset);
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->ring[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,
obj->pages[0][elt],
obj->pages[0][elt+1],
obj->pages[0][elt+2],
obj->pages[0][elt+3]);
hws_page[elt],
hws_page[elt+1],
hws_page[elt+2],
hws_page[elt+3]);
offset += 16;
}
}
456,11 → 482,24
if ((obj = error->ring[i].ctx)) {
err_printf(m, "%s --- HW Context = 0x%08x\n",
dev_priv->ring[i].name,
obj->gtt_offset);
lower_32_bits(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]);
}
}
 
if (error->overlay)
intel_overlay_print_error_state(m, error->overlay);
 
475,9 → 514,11
}
 
int i915_error_state_buf_init(struct drm_i915_error_state_buf *ebuf,
struct drm_i915_private *i915,
size_t count, loff_t pos)
{
memset(ebuf, 0, sizeof(*ebuf));
ebuf->i915 = i915;
 
/* We need to have enough room to store any i915_error_state printf
* so that we can move it to start position.
525,6 → 566,7
 
for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
i915_error_object_free(error->ring[i].batchbuffer);
i915_error_object_free(error->ring[i].wa_batchbuffer);
i915_error_object_free(error->ring[i].ringbuffer);
i915_error_object_free(error->ring[i].hws_page);
i915_error_object_free(error->ring[i].ctx);
531,7 → 573,15
kfree(error->ring[i].requests);
}
 
i915_error_object_free(error->semaphore_obj);
 
for (i = 0; i < error->vm_count; 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);
538,24 → 588,56
}
 
static struct drm_i915_error_object *
i915_error_object_create_sized(struct drm_i915_private *dev_priv,
i915_error_object_create(struct drm_i915_private *dev_priv,
struct drm_i915_gem_object *src,
struct i915_address_space *vm,
const int num_pages)
struct i915_address_space *vm)
{
struct drm_i915_error_object *dst;
int i;
u32 reloc_offset;
struct i915_vma *vma = NULL;
int num_pages;
bool use_ggtt;
int i = 0;
u64 reloc_offset;
 
if (src == NULL || src->pages == NULL)
return NULL;
 
num_pages = src->base.size >> PAGE_SHIFT;
 
dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
if (dst == NULL)
return NULL;
 
reloc_offset = dst->gtt_offset = i915_gem_obj_offset(src, vm);
for (i = 0; i < num_pages; i++) {
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);
use_ggtt = (src->cache_level == I915_CACHE_NONE &&
vma && (vma->bound & GLOBAL_BIND) &&
reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end);
 
/* Cannot access stolen address directly, try to use the aperture */
if (src->stolen) {
use_ggtt = true;
 
if (!(vma && vma->bound & GLOBAL_BIND))
goto unwind;
 
reloc_offset = i915_gem_obj_ggtt_offset(src);
if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->gtt.mappable_end)
goto unwind;
}
 
/* Cannot access snooped pages through the aperture */
if (use_ggtt && src->cache_level != I915_CACHE_NONE && !HAS_LLC(dev_priv->dev))
goto unwind;
 
dst->page_count = num_pages;
while (num_pages--) {
unsigned long flags;
void *d;
 
564,10 → 646,7
goto unwind;
 
local_irq_save(flags);
if (src->cache_level == I915_CACHE_NONE &&
reloc_offset < dev_priv->gtt.mappable_end &&
src->has_global_gtt_mapping &&
i915_is_ggtt(vm)) {
if (use_ggtt) {
void __iomem *s;
 
/* Simply ignore tiling or any overlapping fence.
579,14 → 658,6
reloc_offset);
memcpy_fromio(d, s, PAGE_SIZE);
io_mapping_unmap_atomic(s);
} else if (src->stolen) {
unsigned long offset;
 
offset = dev_priv->mm.stolen_base;
offset += src->stolen->start;
offset += i << PAGE_SHIFT;
 
memcpy_fromio(d, (void __iomem *) offset, PAGE_SIZE);
} else {
struct page *page;
void *s;
603,11 → 674,9
}
local_irq_restore(flags);
 
dst->pages[i] = d;
 
dst->pages[i++] = d;
reloc_offset += PAGE_SIZE;
}
dst->page_count = num_pages;
 
return dst;
 
617,22 → 686,21
kfree(dst);
return NULL;
}
#define i915_error_object_create(dev_priv, src, vm) \
i915_error_object_create_sized((dev_priv), (src), (vm), \
(src)->base.size>>PAGE_SHIFT)
 
#define i915_error_ggtt_object_create(dev_priv, src) \
i915_error_object_create_sized((dev_priv), (src), &(dev_priv)->gtt.base, \
(src)->base.size>>PAGE_SHIFT)
i915_error_object_create((dev_priv), (src), &(dev_priv)->gtt.base)
 
static void capture_bo(struct drm_i915_error_buffer *err,
struct drm_i915_gem_object *obj)
struct i915_vma *vma)
{
struct drm_i915_gem_object *obj = vma->obj;
int i;
 
err->size = obj->base.size;
err->name = obj->base.name;
err->rseqno = obj->last_read_seqno;
err->wseqno = obj->last_write_seqno;
err->gtt_offset = i915_gem_obj_ggtt_offset(obj);
for (i = 0; i < I915_NUM_RINGS; i++)
err->rseqno[i] = i915_gem_request_get_seqno(obj->last_read_req[i]);
err->wseqno = i915_gem_request_get_seqno(obj->last_write_req);
err->gtt_offset = vma->node.start;
err->read_domains = obj->base.read_domains;
err->write_domain = obj->base.write_domain;
err->fence_reg = obj->fence_reg;
639,13 → 707,12
err->pinned = 0;
if (i915_gem_obj_is_pinned(obj))
err->pinned = 1;
if (obj->user_pin_count > 0)
err->pinned = -1;
err->tiling = obj->tiling_mode;
err->dirty = obj->dirty;
err->purgeable = obj->madv != I915_MADV_WILLNEED;
err->userptr = obj->userptr.mm != NULL;
err->ring = obj->ring ? obj->ring->id : -1;
err->ring = obj->last_write_req ?
i915_gem_request_get_ring(obj->last_write_req)->id : -1;
err->cache_level = obj->cache_level;
}
 
656,7 → 723,7
int i = 0;
 
list_for_each_entry(vma, head, mm_list) {
capture_bo(err++, vma->obj);
capture_bo(err++, vma);
if (++i == count)
break;
}
665,21 → 732,25
}
 
static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
int count, struct list_head *head)
int count, struct list_head *head,
struct i915_address_space *vm)
{
struct drm_i915_gem_object *obj;
int i = 0;
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) {
if (!i915_gem_obj_is_pinned(obj))
continue;
struct i915_vma *vma;
 
capture_bo(err++, obj);
if (++i == count)
if (err == last)
break;
 
list_for_each_entry(vma, &obj->vma_list, vma_link)
if (vma->vm == vm && vma->pin_count > 0)
capture_bo(err++, vma);
}
 
return i;
return err - first;
}
 
/* Generate a semi-unique error code. The code is not meant to have meaning, The
721,34 → 792,71
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
 
/* Fences */
switch (INTEL_INFO(dev)->gen) {
case 8:
case 7:
case 6:
if (IS_GEN3(dev) || IS_GEN2(dev)) {
for (i = 0; i < dev_priv->num_fence_regs; i++)
error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
break;
case 5:
case 4:
for (i = 0; i < 16; i++)
error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
break;
case 3:
if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
for (i = 0; i < 8; i++)
error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
case 2:
for (i = 0; i < 8; i++)
error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
break;
error->fence[i] = I915_READ(FENCE_REG(i));
} else if (IS_GEN5(dev) || IS_GEN4(dev)) {
for (i = 0; i < dev_priv->num_fence_regs; i++)
error->fence[i] = I915_READ64(FENCE_REG_965_LO(i));
} else if (INTEL_INFO(dev)->gen >= 6) {
for (i = 0; i < dev_priv->num_fence_regs; i++)
error->fence[i] = I915_READ64(FENCE_REG_GEN6_LO(i));
}
}
 
default:
BUG();
 
static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error,
struct intel_engine_cs *ring,
struct drm_i915_error_ring *ering)
{
struct intel_engine_cs *to;
int i;
 
if (!i915_semaphore_is_enabled(dev_priv->dev))
return;
 
if (!error->semaphore_obj)
error->semaphore_obj =
i915_error_ggtt_object_create(dev_priv,
dev_priv->semaphore_obj);
 
for_each_ring(to, dev_priv, i) {
int idx;
u16 signal_offset;
u32 *tmp;
 
if (ring == to)
continue;
 
signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & (PAGE_SIZE - 1))
/ 4;
tmp = error->semaphore_obj->pages[0];
idx = intel_ring_sync_index(ring, to);
 
ering->semaphore_mboxes[idx] = tmp[signal_offset];
ering->semaphore_seqno[idx] = ring->semaphore.sync_seqno[idx];
}
}
 
static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv,
struct intel_engine_cs *ring,
struct drm_i915_error_ring *ering)
{
ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(ring->mmio_base));
ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(ring->mmio_base));
ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
 
if (HAS_VEBOX(dev_priv->dev)) {
ering->semaphore_mboxes[2] =
I915_READ(RING_SYNC_2(ring->mmio_base));
ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
}
}
 
static void i915_record_ring_state(struct drm_device *dev,
struct drm_i915_error_state *error,
struct intel_engine_cs *ring,
struct drm_i915_error_ring *ering)
{
757,20 → 865,12
if (INTEL_INFO(dev)->gen >= 6) {
ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
ering->semaphore_mboxes[0]
= I915_READ(RING_SYNC_0(ring->mmio_base));
ering->semaphore_mboxes[1]
= I915_READ(RING_SYNC_1(ring->mmio_base));
ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
if (INTEL_INFO(dev)->gen >= 8)
gen8_record_semaphore_state(dev_priv, error, ring, ering);
else
gen6_record_semaphore_state(dev_priv, ring, ering);
}
 
if (HAS_VEBOX(dev)) {
ering->semaphore_mboxes[2] =
I915_READ(RING_SYNC_2(ring->mmio_base));
ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
}
 
if (INTEL_INFO(dev)->gen >= 4) {
ering->faddr = I915_READ(RING_DMA_FADD(ring->mmio_base));
ering->ipeir = I915_READ(RING_IPEIR(ring->mmio_base));
787,7 → 887,7
ering->faddr = I915_READ(DMA_FADD_I8XX);
ering->ipeir = I915_READ(IPEIR);
ering->ipehr = I915_READ(IPEHR);
ering->instdone = I915_READ(INSTDONE);
ering->instdone = I915_READ(GEN2_INSTDONE);
}
 
ering->waiting = waitqueue_active(&ring->irq_queue);
794,6 → 894,7
ering->instpm = I915_READ(RING_INSTPM(ring->mmio_base));
ering->seqno = ring->get_seqno(ring, false);
ering->acthd = intel_ring_get_active_head(ring);
ering->start = I915_READ_START(ring);
ering->head = I915_READ_HEAD(ring);
ering->tail = I915_READ_TAIL(ring);
ering->ctl = I915_READ_CTL(ring);
827,9 → 928,6
ering->hws = I915_READ(mmio);
}
 
ering->cpu_ring_head = ring->buffer->head;
ering->cpu_ring_tail = ring->buffer->tail;
 
ering->hangcheck_score = ring->hangcheck.score;
ering->hangcheck_action = ring->hangcheck.action;
 
838,8 → 936,13
 
ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(ring));
 
switch (INTEL_INFO(dev)->gen) {
case 8:
if (IS_GEN6(dev))
ering->vm_info.pp_dir_base =
I915_READ(RING_PP_DIR_BASE_READ(ring));
else if (IS_GEN7(dev))
ering->vm_info.pp_dir_base =
I915_READ(RING_PP_DIR_BASE(ring));
else if (INTEL_INFO(dev)->gen >= 8)
for (i = 0; i < 4; i++) {
ering->vm_info.pdp[i] =
I915_READ(GEN8_RING_PDP_UDW(ring, i));
847,18 → 950,8
ering->vm_info.pdp[i] |=
I915_READ(GEN8_RING_PDP_LDW(ring, i));
}
break;
case 7:
ering->vm_info.pp_dir_base =
I915_READ(RING_PP_DIR_BASE(ring));
break;
case 6:
ering->vm_info.pp_dir_base =
I915_READ(RING_PP_DIR_BASE_READ(ring));
break;
}
}
}
 
 
static void i915_gem_record_active_context(struct intel_engine_cs *ring,
873,6 → 966,9
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)) {
ering->ctx = i915_error_ggtt_object_create(dev_priv, obj);
break;
889,6 → 985,7
 
for (i = 0; i < I915_NUM_RINGS; i++) {
struct intel_engine_cs *ring = &dev_priv->ring[i];
struct intel_ringbuffer *rbuf;
 
error->ring[i].pid = -1;
 
897,10 → 994,16
 
error->ring[i].valid = true;
 
i915_record_ring_state(dev, ring, &error->ring[i]);
i915_record_ring_state(dev, error, ring, &error->ring[i]);
 
request = i915_gem_find_active_request(ring);
if (request) {
struct i915_address_space *vm;
 
vm = request->ctx && request->ctx->ppgtt ?
&request->ctx->ppgtt->base :
&dev_priv->gtt.base;
 
/* We need to copy these to an anonymous buffer
* as the simplest method to avoid being overwritten
* by userspace.
908,22 → 1011,18
error->ring[i].batchbuffer =
i915_error_object_create(dev_priv,
request->batch_obj,
request->ctx ?
request->ctx->vm :
&dev_priv->gtt.base);
vm);
 
if (HAS_BROKEN_CS_TLB(dev_priv->dev) &&
ring->scratch.obj)
if (HAS_BROKEN_CS_TLB(dev_priv->dev))
error->ring[i].wa_batchbuffer =
i915_error_ggtt_object_create(dev_priv,
ring->scratch.obj);
 
if (request->file_priv) {
if (request->pid) {
struct task_struct *task;
 
rcu_read_lock();
task = pid_task(request->file_priv->file->pid,
PIDTYPE_PID);
task = pid_task(request->pid, PIDTYPE_PID);
if (task) {
strcpy(error->ring[i].comm, task->comm);
error->ring[i].pid = task->pid;
932,10 → 1031,25
}
}
 
if (i915.enable_execlists) {
/* TODO: This is only a small fix to keep basic error
* capture working, but we need to add more information
* for it to be useful (e.g. dump the context being
* executed).
*/
if (request)
rbuf = request->ctx->engine[ring->id].ringbuf;
else
rbuf = ring->default_context->engine[ring->id].ringbuf;
} else
rbuf = ring->buffer;
 
error->ring[i].cpu_ring_head = rbuf->head;
error->ring[i].cpu_ring_tail = rbuf->tail;
 
error->ring[i].ringbuffer =
i915_error_ggtt_object_create(dev_priv, ring->buffer->obj);
i915_error_ggtt_object_create(dev_priv, rbuf->obj);
 
if (ring->status_page.obj)
error->ring[i].hws_page =
i915_error_ggtt_object_create(dev_priv, ring->status_page.obj);
 
961,7 → 1075,7
erq = &error->ring[i].requests[count++];
erq->seqno = request->seqno;
erq->jiffies = request->emitted_jiffies;
erq->tail = request->tail;
erq->tail = request->postfix;
}
}
}
983,9 → 1097,12
list_for_each_entry(vma, &vm->active_list, mm_list)
i++;
error->active_bo_count[ndx] = i;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
if (i915_gem_obj_is_pinned(obj))
 
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
list_for_each_entry(vma, &obj->vma_list, vma_link)
if (vma->vm == vm && vma->pin_count > 0)
i++;
}
error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx];
 
if (i) {
1004,7 → 1121,7
error->pinned_bo_count[ndx] =
capture_pinned_bo(pinned_bo,
error->pinned_bo_count[ndx],
&dev_priv->mm.bound_list);
&dev_priv->mm.bound_list, vm);
error->active_bo[ndx] = active_bo;
error->pinned_bo[ndx] = pinned_bo;
}
1025,9 → 1142,26
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++);
 
error->vm_count = cnt;
}
}
 
/* Capture all registers which don't fit into another category. */
static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
1034,6 → 1168,7
struct drm_i915_error_state *error)
{
struct drm_device *dev = dev_priv->dev;
int i;
 
/* General organization
* 1. Registers specific to a single generation
1045,7 → 1180,8
 
/* 1: Registers specific to a single generation */
if (IS_VALLEYVIEW(dev)) {
error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
error->gtier[0] = I915_READ(GTIER);
error->ier = I915_READ(VLV_IER);
error->forcewake = I915_READ(FORCEWAKE_VLV);
}
 
1052,6 → 1188,11
if (IS_GEN7(dev))
error->err_int = I915_READ(GEN7_ERR_INT);
 
if (INTEL_INFO(dev)->gen >= 8) {
error->fault_data0 = I915_READ(GEN8_FAULT_TLB_DATA0);
error->fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1);
}
 
if (IS_GEN6(dev)) {
error->forcewake = I915_READ(FORCEWAKE);
error->gab_ctl = I915_READ(GAB_CTL);
1078,16 → 1219,18
if (HAS_HW_CONTEXTS(dev))
error->ccid = I915_READ(CCID);
 
if (HAS_PCH_SPLIT(dev))
error->ier = I915_READ(DEIER) | I915_READ(GTIER);
else {
if (IS_GEN2(dev))
if (INTEL_INFO(dev)->gen >= 8) {
error->ier = I915_READ(GEN8_DE_MISC_IER);
for (i = 0; i < 4; i++)
error->gtier[i] = I915_READ(GEN8_GT_IER(i));
} else if (HAS_PCH_SPLIT(dev)) {
error->ier = I915_READ(DEIER);
error->gtier[0] = I915_READ(GTIER);
} else if (IS_GEN2(dev)) {
error->ier = I915_READ16(IER);
else
} else if (!IS_VALLEYVIEW(dev)) {
error->ier = I915_READ(IER);
}
 
/* 4: Everything else */
error->eir = I915_READ(EIR);
error->pgtbl_er = I915_READ(PGTBL_ER);
 
1106,7 → 1249,8
ecode = i915_error_generate_code(dev_priv, error, &ring_id);
 
len = scnprintf(error->error_msg, sizeof(error->error_msg),
"GPU HANG: ecode %d:0x%08x", ring_id, ecode);
"GPU HANG: ecode %d:%d:0x%08x",
INTEL_INFO(dev)->gen, ring_id, ecode);
 
if (ring_id != -1 && error->ring[ring_id].pid != -1)
len += scnprintf(error->error_msg + len,
1124,6 → 1268,10
static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error)
{
error->iommu = -1;
#ifdef CONFIG_INTEL_IOMMU
error->iommu = intel_iommu_gfx_mapped;
#endif
error->reset_count = i915_reset_count(&dev_priv->gpu_error);
error->suspend_count = dev_priv->suspend_count;
}
1194,13 → 1342,12
struct i915_error_state_file_priv *error_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long flags;
 
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
spin_lock_irq(&dev_priv->gpu_error.lock);
error_priv->error = dev_priv->gpu_error.first_error;
if (error_priv->error)
kref_get(&error_priv->error->ref);
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
spin_unlock_irq(&dev_priv->gpu_error.lock);
 
}
 
1214,28 → 1361,27
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_error_state *error;
unsigned long flags;
 
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
spin_lock_irq(&dev_priv->gpu_error.lock);
error = dev_priv->gpu_error.first_error;
dev_priv->gpu_error.first_error = NULL;
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
spin_unlock_irq(&dev_priv->gpu_error.lock);
 
if (error)
kref_put(&error->ref, i915_error_state_free);
}
#endif
 
const char *i915_cache_level_str(int type)
const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
{
switch (type) {
case I915_CACHE_NONE: return " uncached";
case I915_CACHE_LLC: return " snooped or LLC";
case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
case I915_CACHE_L3_LLC: return " L3+LLC";
case I915_CACHE_WT: return " WT";
default: return "";
}
}
#endif
 
/* NB: please notice the memset */
void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone)
1243,26 → 1389,15
struct drm_i915_private *dev_priv = dev->dev_private;
memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG);
 
switch (INTEL_INFO(dev)->gen) {
case 2:
case 3:
instdone[0] = I915_READ(INSTDONE);
break;
case 4:
case 5:
case 6:
instdone[0] = I915_READ(INSTDONE_I965);
instdone[1] = I915_READ(INSTDONE1);
break;
default:
WARN_ONCE(1, "Unsupported platform\n");
case 7:
case 8:
case 9:
instdone[0] = I915_READ(GEN7_INSTDONE_1);
if (IS_GEN2(dev) || IS_GEN3(dev))
instdone[0] = I915_READ(GEN2_INSTDONE);
else if (IS_GEN4(dev) || IS_GEN5(dev) || IS_GEN6(dev)) {
instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE));
instdone[1] = I915_READ(GEN4_INSTDONE1);
} else if (INTEL_INFO(dev)->gen >= 7) {
instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE));
instdone[1] = I915_READ(GEN7_SC_INSTDONE);
instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE);
instdone[3] = I915_READ(GEN7_ROW_INSTDONE);
break;
}
}