aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_debugfs.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-05-30 15:25:28 +1000
committerDave Airlie <airlied@redhat.com>2017-05-30 15:25:28 +1000
commita82256bc026722800d1fdeca5521f1ba487bc2ef (patch)
tree21573b1572fe8e5f0e064ef5f97438da2c409da9 /drivers/gpu/drm/i915/i915_debugfs.c
parentMerge tag 'drm-misc-next-2017-05-26' of git://anongit.freedesktop.org/git/drm-misc into drm-next (diff)
parentdrm/i915: Update DRIVER_DATE to 20170529 (diff)
downloadlinux-dev-a82256bc026722800d1fdeca5521f1ba487bc2ef.tar.xz
linux-dev-a82256bc026722800d1fdeca5521f1ba487bc2ef.zip
Merge tag 'drm-intel-next-2017-05-29' of git://anongit.freedesktop.org/git/drm-intel into drm-next
More stuff for 4.13: - skl+ wm fixes from Mahesh Kumar - some refactor and tests for i915_sw_fence (Chris) - tune execlist/scheduler code (Chris) - g4x,g33 gpu reset improvements (Chris, Mika) - guc code cleanup (Michal Wajdeczko, MichaƂ Winiarski) - dp aux backlight improvements (Puthikorn Voravootivat) - buffer based guc/host communication (Michal Wajdeczko) * tag 'drm-intel-next-2017-05-29' of git://anongit.freedesktop.org/git/drm-intel: (253 commits) drm/i915: Update DRIVER_DATE to 20170529 drm/i915: Keep the forcewake timer alive for 1ms past the most recent use drm/i915/guc: capture GuC logs if FW fails to load drm/i915/guc: Introduce buffer based cmd transport drm/i915/guc: Disable send function on fini drm: Add definition for eDP backlight frequency drm/i915: Drop AUX backlight enable check for backlight control drm/i915: Consolidate #ifdef CONFIG_INTEL_IOMMU drm/i915: Only GGTT vma may be pinned and prevent shrinking drm/i915: Serialize GTT/Aperture accesses on BXT drm/i915: Convert i915_gem_object_ops->flags values to use BIT() drm/i915/selftests: Silence compiler warning in igt_ctx_exec drm/i915/guc: Skip port assign on first iteration of GuC dequeue drm/i915: Remove misleading comment in request_alloc drm/i915/g33: Improve reset reliability Revert "drm/i915: Restore lost "Initialized i915" welcome message" drm/i915/huc: Update GLK HuC version drm/i915: Check for allocation failure drm/i915/guc: Remove action status and statistics from debugfs drm/i915/g4x: Improve gpu reset reliability ...
Diffstat (limited to 'drivers/gpu/drm/i915/i915_debugfs.c')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c255
1 files changed, 141 insertions, 114 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 1c66108f4333..7e0816ccdc21 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2482,8 +2482,6 @@ static void i915_guc_client_info(struct seq_file *m,
client->wq_size, client->wq_offset, client->wq_tail);
seq_printf(m, "\tWork queue full: %u\n", client->no_wq_space);
- seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
- seq_printf(m, "\tLast submission result: %d\n", client->retcode);
for_each_engine(engine, dev_priv, id) {
u64 submissions = client->submissions[id];
@@ -2494,42 +2492,34 @@ static void i915_guc_client_info(struct seq_file *m,
seq_printf(m, "\tTotal: %llu\n", tot);
}
-static int i915_guc_info(struct seq_file *m, void *data)
+static bool check_guc_submission(struct seq_file *m)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
const struct intel_guc *guc = &dev_priv->guc;
- struct intel_engine_cs *engine;
- enum intel_engine_id id;
- u64 total;
if (!guc->execbuf_client) {
seq_printf(m, "GuC submission %s\n",
HAS_GUC_SCHED(dev_priv) ?
"disabled" :
"not supported");
- return 0;
+ return false;
}
+ return true;
+}
+
+static int i915_guc_info(struct seq_file *m, void *data)
+{
+ struct drm_i915_private *dev_priv = node_to_i915(m->private);
+ const struct intel_guc *guc = &dev_priv->guc;
+
+ if (!check_guc_submission(m))
+ return 0;
+
seq_printf(m, "Doorbell map:\n");
seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap);
seq_printf(m, "Doorbell next cacheline: 0x%x\n\n", guc->db_cacheline);
- seq_printf(m, "GuC total action count: %llu\n", guc->action_count);
- seq_printf(m, "GuC action failure count: %u\n", guc->action_fail);
- seq_printf(m, "GuC last action command: 0x%x\n", guc->action_cmd);
- seq_printf(m, "GuC last action status: 0x%x\n", guc->action_status);
- seq_printf(m, "GuC last action error code: %d\n", guc->action_err);
-
- total = 0;
- seq_printf(m, "\nGuC submissions:\n");
- for_each_engine(engine, dev_priv, id) {
- u64 submissions = guc->submissions[id];
- total += submissions;
- seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n",
- engine->name, submissions, guc->last_seqno[id]);
- }
- seq_printf(m, "\t%s: %llu\n", "Total", total);
-
seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client);
i915_guc_client_info(m, dev_priv, guc->execbuf_client);
@@ -2540,36 +2530,99 @@ static int i915_guc_info(struct seq_file *m, void *data)
return 0;
}
-static int i915_guc_log_dump(struct seq_file *m, void *data)
+static int i915_guc_stage_pool(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_i915_gem_object *obj;
- int i = 0, pg;
+ const struct intel_guc *guc = &dev_priv->guc;
+ struct guc_stage_desc *desc = guc->stage_desc_pool_vaddr;
+ struct i915_guc_client *client = guc->execbuf_client;
+ unsigned int tmp;
+ int index;
- if (!dev_priv->guc.log.vma)
+ if (!check_guc_submission(m))
return 0;
- obj = dev_priv->guc.log.vma->obj;
- for (pg = 0; pg < obj->base.size / PAGE_SIZE; pg++) {
- u32 *log = kmap_atomic(i915_gem_object_get_page(obj, pg));
+ for (index = 0; index < GUC_MAX_STAGE_DESCRIPTORS; index++, desc++) {
+ struct intel_engine_cs *engine;
+
+ if (!(desc->attribute & GUC_STAGE_DESC_ATTR_ACTIVE))
+ continue;
+
+ seq_printf(m, "GuC stage descriptor %u:\n", index);
+ seq_printf(m, "\tIndex: %u\n", desc->stage_id);
+ seq_printf(m, "\tAttribute: 0x%x\n", desc->attribute);
+ seq_printf(m, "\tPriority: %d\n", desc->priority);
+ seq_printf(m, "\tDoorbell id: %d\n", desc->db_id);
+ seq_printf(m, "\tEngines used: 0x%x\n",
+ desc->engines_used);
+ seq_printf(m, "\tDoorbell trigger phy: 0x%llx, cpu: 0x%llx, uK: 0x%x\n",
+ desc->db_trigger_phy,
+ desc->db_trigger_cpu,
+ desc->db_trigger_uk);
+ seq_printf(m, "\tProcess descriptor: 0x%x\n",
+ desc->process_desc);
+ seq_printf(m, "\tWorkqueue address: 0x%x, size: 0x%x\n",
+ desc->wq_addr, desc->wq_size);
+ seq_putc(m, '\n');
+
+ for_each_engine_masked(engine, dev_priv, client->engines, tmp) {
+ u32 guc_engine_id = engine->guc_id;
+ struct guc_execlist_context *lrc =
+ &desc->lrc[guc_engine_id];
+
+ seq_printf(m, "\t%s LRC:\n", engine->name);
+ seq_printf(m, "\t\tContext desc: 0x%x\n",
+ lrc->context_desc);
+ seq_printf(m, "\t\tContext id: 0x%x\n", lrc->context_id);
+ seq_printf(m, "\t\tLRCA: 0x%x\n", lrc->ring_lrca);
+ seq_printf(m, "\t\tRing begin: 0x%x\n", lrc->ring_begin);
+ seq_printf(m, "\t\tRing end: 0x%x\n", lrc->ring_end);
+ seq_putc(m, '\n');
+ }
+ }
+
+ return 0;
+}
+
+static int i915_guc_log_dump(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = m->private;
+ struct drm_i915_private *dev_priv = node_to_i915(node);
+ bool dump_load_err = !!node->info_ent->data;
+ struct drm_i915_gem_object *obj = NULL;
+ u32 *log;
+ int i = 0;
+
+ if (dump_load_err)
+ obj = dev_priv->guc.load_err_log;
+ else if (dev_priv->guc.log.vma)
+ obj = dev_priv->guc.log.vma->obj;
- for (i = 0; i < PAGE_SIZE / sizeof(u32); i += 4)
- seq_printf(m, "0x%08x 0x%08x 0x%08x 0x%08x\n",
- *(log + i), *(log + i + 1),
- *(log + i + 2), *(log + i + 3));
+ if (!obj)
+ return 0;
- kunmap_atomic(log);
+ log = i915_gem_object_pin_map(obj, I915_MAP_WC);
+ if (IS_ERR(log)) {
+ DRM_DEBUG("Failed to pin object\n");
+ seq_puts(m, "(log data unaccessible)\n");
+ return PTR_ERR(log);
}
+ for (i = 0; i < obj->base.size / sizeof(u32); i += 4)
+ seq_printf(m, "0x%08x 0x%08x 0x%08x 0x%08x\n",
+ *(log + i), *(log + i + 1),
+ *(log + i + 2), *(log + i + 3));
+
seq_putc(m, '\n');
+ i915_gem_object_unpin_map(obj);
+
return 0;
}
static int i915_guc_log_control_get(void *data, u64 *val)
{
- struct drm_device *dev = data;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = data;
if (!dev_priv->guc.log.vma)
return -EINVAL;
@@ -2581,14 +2634,13 @@ static int i915_guc_log_control_get(void *data, u64 *val)
static int i915_guc_log_control_set(void *data, u64 val)
{
- struct drm_device *dev = data;
- struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_i915_private *dev_priv = data;
int ret;
if (!dev_priv->guc.log.vma)
return -EINVAL;
- ret = mutex_lock_interruptible(&dev->struct_mutex);
+ ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
if (ret)
return ret;
@@ -2596,7 +2648,7 @@ static int i915_guc_log_control_set(void *data, u64 val)
ret = i915_guc_log_control(dev_priv, val);
intel_runtime_pm_put(dev_priv);
- mutex_unlock(&dev->struct_mutex);
+ mutex_unlock(&dev_priv->drm.struct_mutex);
return ret;
}
@@ -2855,7 +2907,8 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
seq_printf(m, "version: %d.%d\n", CSR_VERSION_MAJOR(csr->version),
CSR_VERSION_MINOR(csr->version));
- if (IS_SKYLAKE(dev_priv) && csr->version >= CSR_VERSION(1, 6)) {
+ if (IS_KABYLAKE(dev_priv) ||
+ (IS_SKYLAKE(dev_priv) && csr->version >= CSR_VERSION(1, 6))) {
seq_printf(m, "DC3 -> DC5 count: %d\n",
I915_READ(SKL_CSR_DC3_DC5_COUNT));
seq_printf(m, "DC5 -> DC6 count: %d\n",
@@ -3043,36 +3096,6 @@ static void intel_connector_info(struct seq_file *m,
intel_seq_print_mode(m, 2, mode);
}
-static bool cursor_active(struct drm_i915_private *dev_priv, int pipe)
-{
- u32 state;
-
- if (IS_I845G(dev_priv) || IS_I865G(dev_priv))
- state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
- else
- state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
-
- return state;
-}
-
-static bool cursor_position(struct drm_i915_private *dev_priv,
- int pipe, int *x, int *y)
-{
- u32 pos;
-
- pos = I915_READ(CURPOS(pipe));
-
- *x = (pos >> CURSOR_X_SHIFT) & CURSOR_POS_MASK;
- if (pos & (CURSOR_POS_SIGN << CURSOR_X_SHIFT))
- *x = -*x;
-
- *y = (pos >> CURSOR_Y_SHIFT) & CURSOR_POS_MASK;
- if (pos & (CURSOR_POS_SIGN << CURSOR_Y_SHIFT))
- *y = -*y;
-
- return cursor_active(dev_priv, pipe);
-}
-
static const char *plane_type(enum drm_plane_type type)
{
switch (type) {
@@ -3194,9 +3217,7 @@ static int i915_display_info(struct seq_file *m, void *unused)
seq_printf(m, "CRTC info\n");
seq_printf(m, "---------\n");
for_each_intel_crtc(dev, crtc) {
- bool active;
struct intel_crtc_state *pipe_config;
- int x, y;
drm_modeset_lock(&crtc->base.mutex, NULL);
pipe_config = to_intel_crtc_state(crtc->base.state);
@@ -3208,14 +3229,18 @@ static int i915_display_info(struct seq_file *m, void *unused)
yesno(pipe_config->dither), pipe_config->pipe_bpp);
if (pipe_config->base.active) {
+ struct intel_plane *cursor =
+ to_intel_plane(crtc->base.cursor);
+
intel_crtc_info(m, crtc);
- active = cursor_position(dev_priv, crtc->pipe, &x, &y);
- seq_printf(m, "\tcursor visible? %s, position (%d, %d), size %dx%d, addr 0x%08x, active? %s\n",
- yesno(crtc->cursor_base),
- x, y, crtc->base.cursor->state->crtc_w,
- crtc->base.cursor->state->crtc_h,
- crtc->cursor_addr, yesno(active));
+ seq_printf(m, "\tcursor visible? %s, position (%d, %d), size %dx%d, addr 0x%08x\n",
+ yesno(cursor->base.state->visible),
+ cursor->base.state->crtc_x,
+ cursor->base.state->crtc_y,
+ cursor->base.state->crtc_w,
+ cursor->base.state->crtc_h,
+ cursor->cursor.base);
intel_scaler_info(m, crtc);
intel_plane_info(m, crtc);
}
@@ -3316,7 +3341,7 @@ static int i915_engine_info(struct seq_file *m, void *unused)
if (i915.enable_execlists) {
u32 ptr, read, write;
- struct rb_node *rb;
+ unsigned int idx;
seq_printf(m, "\tExeclist status: 0x%08x %08x\n",
I915_READ(RING_EXECLIST_STATUS_LO(engine)),
@@ -3334,8 +3359,7 @@ static int i915_engine_info(struct seq_file *m, void *unused)
if (read > write)
write += GEN8_CSB_ENTRIES;
while (read < write) {
- unsigned int idx = ++read % GEN8_CSB_ENTRIES;
-
+ idx = ++read % GEN8_CSB_ENTRIES;
seq_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n",
idx,
I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)),
@@ -3343,28 +3367,30 @@ static int i915_engine_info(struct seq_file *m, void *unused)
}
rcu_read_lock();
- rq = READ_ONCE(engine->execlist_port[0].request);
- if (rq) {
- seq_printf(m, "\t\tELSP[0] count=%d, ",
- engine->execlist_port[0].count);
- print_request(m, rq, "rq: ");
- } else {
- seq_printf(m, "\t\tELSP[0] idle\n");
- }
- rq = READ_ONCE(engine->execlist_port[1].request);
- if (rq) {
- seq_printf(m, "\t\tELSP[1] count=%d, ",
- engine->execlist_port[1].count);
- print_request(m, rq, "rq: ");
- } else {
- seq_printf(m, "\t\tELSP[1] idle\n");
+ for (idx = 0; idx < ARRAY_SIZE(engine->execlist_port); idx++) {
+ unsigned int count;
+
+ rq = port_unpack(&engine->execlist_port[idx],
+ &count);
+ if (rq) {
+ seq_printf(m, "\t\tELSP[%d] count=%d, ",
+ idx, count);
+ print_request(m, rq, "rq: ");
+ } else {
+ seq_printf(m, "\t\tELSP[%d] idle\n",
+ idx);
+ }
}
rcu_read_unlock();
spin_lock_irq(&engine->timeline->lock);
- for (rb = engine->execlist_first; rb; rb = rb_next(rb)) {
- rq = rb_entry(rb, typeof(*rq), priotree.node);
- print_request(m, rq, "\t\tQ ");
+ for (rb = engine->execlist_first; rb; rb = rb_next(rb)){
+ struct i915_priolist *p =
+ rb_entry(rb, typeof(*p), node);
+
+ list_for_each_entry(rq, &p->requests,
+ priotree.link)
+ print_request(m, rq, "\t\tQ ");
}
spin_unlock_irq(&engine->timeline->lock);
} else if (INTEL_GEN(dev_priv) > 6) {
@@ -3704,16 +3730,10 @@ static ssize_t i915_displayport_test_active_write(struct file *file,
if (len == 0)
return 0;
- input_buffer = kmalloc(len + 1, GFP_KERNEL);
- if (!input_buffer)
- return -ENOMEM;
+ input_buffer = memdup_user_nul(ubuf, len);
+ if (IS_ERR(input_buffer))
+ return PTR_ERR(input_buffer);
- if (copy_from_user(input_buffer, ubuf, len)) {
- status = -EFAULT;
- goto out;
- }
-
- input_buffer[len] = '\0';
DRM_DEBUG_DRIVER("Copied %d bytes from user\n", (unsigned int)len);
drm_connector_list_iter_begin(dev, &conn_iter);
@@ -3739,7 +3759,6 @@ static ssize_t i915_displayport_test_active_write(struct file *file,
}
}
drm_connector_list_iter_end(&conn_iter);
-out:
kfree(input_buffer);
if (status < 0)
return status;
@@ -3900,6 +3919,8 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
num_levels = 3;
else if (IS_VALLEYVIEW(dev_priv))
num_levels = 1;
+ else if (IS_G4X(dev_priv))
+ num_levels = 3;
else
num_levels = ilk_wm_max_level(dev_priv) + 1;
@@ -3912,8 +3933,10 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
* - WM1+ latency values in 0.5us units
* - latencies are in us on gen9/vlv/chv
*/
- if (INTEL_GEN(dev_priv) >= 9 || IS_VALLEYVIEW(dev_priv) ||
- IS_CHERRYVIEW(dev_priv))
+ if (INTEL_GEN(dev_priv) >= 9 ||
+ IS_VALLEYVIEW(dev_priv) ||
+ IS_CHERRYVIEW(dev_priv) ||
+ IS_G4X(dev_priv))
latency *= 10;
else if (level > 0)
latency *= 5;
@@ -3974,7 +3997,7 @@ static int pri_wm_latency_open(struct inode *inode, struct file *file)
{
struct drm_i915_private *dev_priv = inode->i_private;
- if (INTEL_GEN(dev_priv) < 5)
+ if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
return -ENODEV;
return single_open(file, pri_wm_latency_show, dev_priv);
@@ -4016,6 +4039,8 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
num_levels = 3;
else if (IS_VALLEYVIEW(dev_priv))
num_levels = 1;
+ else if (IS_G4X(dev_priv))
+ num_levels = 3;
else
num_levels = ilk_wm_max_level(dev_priv) + 1;
@@ -4776,6 +4801,8 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_guc_info", i915_guc_info, 0},
{"i915_guc_load_status", i915_guc_load_status_info, 0},
{"i915_guc_log_dump", i915_guc_log_dump, 0},
+ {"i915_guc_load_err_log_dump", i915_guc_log_dump, 0, (void *)1},
+ {"i915_guc_stage_pool", i915_guc_stage_pool, 0},
{"i915_huc_load_status", i915_huc_load_status_info, 0},
{"i915_frequency_info", i915_frequency_info, 0},
{"i915_hangcheck_info", i915_hangcheck_info, 0},