diff options
author | 2016-04-11 10:41:07 +0300 | |
---|---|---|
committer | 2016-04-13 08:17:18 +0300 | |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/gpu/drm/i915/i915_debugfs.c | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/gpu/drm/i915/i915_debugfs.c')
-rw-r--r-- | kernel/drivers/gpu/drm/i915/i915_debugfs.c | 1285 |
1 files changed, 970 insertions, 315 deletions
diff --git a/kernel/drivers/gpu/drm/i915/i915_debugfs.c b/kernel/drivers/gpu/drm/i915/i915_debugfs.c index dc55c5196..8aab974b0 100644 --- a/kernel/drivers/gpu/drm/i915/i915_debugfs.c +++ b/kernel/drivers/gpu/drm/i915/i915_debugfs.c @@ -46,11 +46,6 @@ enum { PINNED_LIST, }; -static const char *yesno(int v) -{ - return v ? "yes" : "no"; -} - /* As the drm_debugfs_init() routines are called before dev->dev_private is * allocated we need to hook into the minor for release. */ static int @@ -96,7 +91,7 @@ static int i915_capabilities(struct seq_file *m, void *data) static const char *get_pin_flag(struct drm_i915_gem_object *obj) { - if (i915_gem_obj_is_pinned(obj)) + if (obj->pin_display) return "p"; else return " "; @@ -117,21 +112,42 @@ static inline const char *get_global_flag(struct drm_i915_gem_object *obj) return i915_gem_obj_to_ggtt(obj) ? "g" : " "; } +static u64 i915_gem_obj_total_ggtt_size(struct drm_i915_gem_object *obj) +{ + u64 size = 0; + struct i915_vma *vma; + + list_for_each_entry(vma, &obj->vma_list, vma_link) { + if (i915_is_ggtt(vma->vm) && + drm_mm_node_allocated(&vma->node)) + size += vma->node.size; + } + + return size; +} + static void describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) { + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct intel_engine_cs *ring; struct i915_vma *vma; int pin_count = 0; + int i; - seq_printf(m, "%pK: %s%s%s %8zdKiB %02x %02x %x %x %x%s%s%s", + seq_printf(m, "%pK: %s%s%s%s %8zdKiB %02x %02x [ ", &obj->base, + obj->active ? "*" : " ", get_pin_flag(obj), get_tiling_flag(obj), get_global_flag(obj), obj->base.size / 1024, obj->base.read_domains, - obj->base.write_domain, - i915_gem_request_get_seqno(obj->last_read_req), + obj->base.write_domain); + for_each_ring(ring, dev_priv, i) + seq_printf(m, "%x ", + i915_gem_request_get_seqno(obj->last_read_req[i])); + seq_printf(m, "] %x %x%s%s%s", i915_gem_request_get_seqno(obj->last_write_req), i915_gem_request_get_seqno(obj->last_fenced_req), i915_cache_level_str(to_i915(obj->base.dev), obj->cache_level), @@ -149,28 +165,28 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) if (obj->fence_reg != I915_FENCE_REG_NONE) seq_printf(m, " (fence: %d)", obj->fence_reg); list_for_each_entry(vma, &obj->vma_list, vma_link) { - if (!i915_is_ggtt(vma->vm)) - seq_puts(m, " (pp"); + seq_printf(m, " (%sgtt offset: %08llx, size: %08llx", + i915_is_ggtt(vma->vm) ? "g" : "pp", + vma->node.start, vma->node.size); + if (i915_is_ggtt(vma->vm)) + seq_printf(m, ", type: %u)", vma->ggtt_view.type); else - seq_puts(m, " (g"); - seq_printf(m, "gtt offset: %08llx, size: %08llx, type: %u)", - vma->node.start, vma->node.size, - vma->ggtt_view.type); + seq_puts(m, ")"); } if (obj->stolen) seq_printf(m, " (stolen: %08llx)", obj->stolen->start); - if (obj->pin_mappable || obj->fault_mappable) { + if (obj->pin_display || obj->fault_mappable) { char s[3], *t = s; - if (obj->pin_mappable) + if (obj->pin_display) *t++ = 'p'; if (obj->fault_mappable) *t++ = 'f'; *t = '\0'; seq_printf(m, " (%s mappable)", s); } - if (obj->last_read_req != NULL) + if (obj->last_write_req != NULL) seq_printf(m, " (%s)", - i915_gem_request_get_ring(obj->last_read_req)->name); + i915_gem_request_get_ring(obj->last_write_req)->name); if (obj->frontbuffer_bits) seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits); } @@ -191,7 +207,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = dev->dev_private; struct i915_address_space *vm = &dev_priv->gtt.base; struct i915_vma *vma; - size_t total_obj_size, total_gtt_size; + u64 total_obj_size, total_gtt_size; int count, ret; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -224,7 +240,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) } mutex_unlock(&dev->struct_mutex); - seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n", + seq_printf(m, "Total %d objects, %llu bytes, %llu GTT size\n", count, total_obj_size, total_gtt_size); return 0; } @@ -237,7 +253,11 @@ static int obj_rank_by_stolen(void *priv, struct drm_i915_gem_object *b = container_of(B, struct drm_i915_gem_object, obj_exec_link); - return a->stolen->start - b->stolen->start; + if (a->stolen->start < b->stolen->start) + return -1; + if (a->stolen->start > b->stolen->start) + return 1; + return 0; } static int i915_gem_stolen_list_info(struct seq_file *m, void *data) @@ -246,7 +266,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 = dev->dev_private; struct drm_i915_gem_object *obj; - size_t total_obj_size, total_gtt_size; + u64 total_obj_size, total_gtt_size; LIST_HEAD(stolen); int count, ret; @@ -262,7 +282,7 @@ 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_ggtt_size(obj); + total_gtt_size += i915_gem_obj_total_ggtt_size(obj); count++; } list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) { @@ -285,14 +305,14 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) } mutex_unlock(&dev->struct_mutex); - seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n", + seq_printf(m, "Total %d objects, %llu bytes, %llu GTT size\n", count, total_obj_size, total_gtt_size); return 0; } #define count_objects(list, member) do { \ list_for_each_entry(obj, list, member) { \ - size += i915_gem_obj_ggtt_size(obj); \ + size += i915_gem_obj_total_ggtt_size(obj); \ ++count; \ if (obj->map_and_fenceable) { \ mappable_size += i915_gem_obj_ggtt_size(obj); \ @@ -303,10 +323,10 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) struct file_stats { struct drm_i915_file_private *file_priv; - int count; - size_t total, unbound; - size_t global, shared; - size_t active, inactive; + unsigned long count; + u64 total, unbound; + u64 global, shared; + u64 active, inactive; }; static int per_file_stats(int id, void *ptr, void *data) @@ -361,36 +381,44 @@ static int per_file_stats(int id, void *ptr, void *data) return 0; } -#define print_file_stats(m, name, stats) \ - seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu global, %zu shared, %zu unbound)\n", \ - name, \ - stats.count, \ - stats.total, \ - stats.active, \ - stats.inactive, \ - stats.global, \ - stats.shared, \ - stats.unbound) +#define print_file_stats(m, name, stats) do { \ + if (stats.count) \ + seq_printf(m, "%s: %lu objects, %llu bytes (%llu active, %llu inactive, %llu global, %llu shared, %llu unbound)\n", \ + name, \ + stats.count, \ + stats.total, \ + stats.active, \ + stats.inactive, \ + stats.global, \ + stats.shared, \ + stats.unbound); \ +} while (0) static void print_batch_pool_stats(struct seq_file *m, struct drm_i915_private *dev_priv) { struct drm_i915_gem_object *obj; struct file_stats stats; + struct intel_engine_cs *ring; + int i, j; memset(&stats, 0, sizeof(stats)); - list_for_each_entry(obj, - &dev_priv->mm.batch_pool.cache_list, - batch_pool_list) - per_file_stats(0, obj, &stats); + for_each_ring(ring, dev_priv, i) { + for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) { + list_for_each_entry(obj, + &ring->batch_pool.cache_list[j], + batch_pool_link) + per_file_stats(0, obj, &stats); + } + } - print_file_stats(m, "batch pool", stats); + print_file_stats(m, "[k]batch pool", stats); } #define count_vmas(list, member) do { \ list_for_each_entry(vma, list, member) { \ - size += i915_gem_obj_ggtt_size(vma->obj); \ + size += i915_gem_obj_total_ggtt_size(vma->obj); \ ++count; \ if (vma->obj->map_and_fenceable) { \ mappable_size += i915_gem_obj_ggtt_size(vma->obj); \ @@ -405,7 +433,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 count, mappable_count, purgeable_count; - size_t size, mappable_size, purgeable_size; + u64 size, mappable_size, purgeable_size; struct drm_i915_gem_object *obj; struct i915_address_space *vm = &dev_priv->gtt.base; struct drm_file *file; @@ -422,17 +450,17 @@ static int i915_gem_object_info(struct seq_file *m, void* data) size = count = mappable_size = mappable_count = 0; count_objects(&dev_priv->mm.bound_list, global_list); - seq_printf(m, "%u [%u] objects, %zu [%zu] bytes in gtt\n", + seq_printf(m, "%u [%u] objects, %llu [%llu] bytes in gtt\n", count, mappable_count, size, mappable_size); size = count = mappable_size = mappable_count = 0; count_vmas(&vm->active_list, mm_list); - seq_printf(m, " %u [%u] active objects, %zu [%zu] bytes\n", + seq_printf(m, " %u [%u] active objects, %llu [%llu] bytes\n", count, mappable_count, size, mappable_size); size = count = mappable_size = mappable_count = 0; count_vmas(&vm->inactive_list, mm_list); - seq_printf(m, " %u [%u] inactive objects, %zu [%zu] bytes\n", + seq_printf(m, " %u [%u] inactive objects, %llu [%llu] bytes\n", count, mappable_count, size, mappable_size); size = count = purgeable_size = purgeable_count = 0; @@ -441,7 +469,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) if (obj->madv == I915_MADV_DONTNEED) purgeable_size += obj->base.size, ++purgeable_count; } - seq_printf(m, "%u unbound objects, %zu bytes\n", count, size); + seq_printf(m, "%u unbound objects, %llu bytes\n", count, size); size = count = mappable_size = mappable_count = 0; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { @@ -449,7 +477,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) size += i915_gem_obj_ggtt_size(obj); ++count; } - if (obj->pin_mappable) { + if (obj->pin_display) { mappable_size += i915_gem_obj_ggtt_size(obj); ++mappable_count; } @@ -458,21 +486,19 @@ static int i915_gem_object_info(struct seq_file *m, void* data) ++purgeable_count; } } - seq_printf(m, "%u purgeable objects, %zu bytes\n", + seq_printf(m, "%u purgeable objects, %llu bytes\n", purgeable_count, purgeable_size); - seq_printf(m, "%u pinned mappable objects, %zu bytes\n", + seq_printf(m, "%u pinned mappable objects, %llu bytes\n", mappable_count, mappable_size); - seq_printf(m, "%u fault mappable objects, %zu bytes\n", + seq_printf(m, "%u fault mappable objects, %llu bytes\n", count, size); - seq_printf(m, "%zu [%lu] gtt total\n", + seq_printf(m, "%llu [%llu] gtt total\n", dev_priv->gtt.base.total, - dev_priv->gtt.mappable_end - dev_priv->gtt.base.start); + (u64)dev_priv->gtt.mappable_end - dev_priv->gtt.base.start); seq_putc(m, '\n'); print_batch_pool_stats(m, dev_priv); - - seq_putc(m, '\n'); list_for_each_entry_reverse(file, &dev->filelist, lhead) { struct file_stats stats; struct task_struct *task; @@ -506,7 +532,7 @@ 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 = dev->dev_private; struct drm_i915_gem_object *obj; - size_t total_obj_size, total_gtt_size; + u64 total_obj_size, total_gtt_size; int count, ret; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -522,13 +548,13 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data) describe_obj(m, obj); seq_putc(m, '\n'); total_obj_size += obj->base.size; - total_gtt_size += i915_gem_obj_ggtt_size(obj); + total_gtt_size += i915_gem_obj_total_ggtt_size(obj); count++; } mutex_unlock(&dev->struct_mutex); - seq_printf(m, "Total %d objects, %zu bytes, %zu GTT size\n", + seq_printf(m, "Total %d objects, %llu bytes, %llu GTT size\n", count, total_obj_size, total_gtt_size); return 0; @@ -613,24 +639,39 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; - int count = 0; - int ret; + struct intel_engine_cs *ring; + int total = 0; + int ret, i, j; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - seq_puts(m, "cache:\n"); - list_for_each_entry(obj, - &dev_priv->mm.batch_pool.cache_list, - batch_pool_list) { - seq_puts(m, " "); - describe_obj(m, obj); - seq_putc(m, '\n'); - count++; + for_each_ring(ring, dev_priv, i) { + for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) { + int count; + + count = 0; + list_for_each_entry(obj, + &ring->batch_pool.cache_list[j], + batch_pool_link) + count++; + seq_printf(m, "%s cache[%d]: %d objects\n", + ring->name, j, count); + + list_for_each_entry(obj, + &ring->batch_pool.cache_list[j], + batch_pool_link) { + seq_puts(m, " "); + describe_obj(m, obj); + seq_putc(m, '\n'); + } + + total += count; + } } - seq_printf(m, "total: %d\n", count); + seq_printf(m, "total: %d\n", total); mutex_unlock(&dev->struct_mutex); @@ -643,31 +684,44 @@ static int i915_gem_request_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; - struct drm_i915_gem_request *gem_request; - int ret, count, i; + struct drm_i915_gem_request *req; + int ret, any, i; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - count = 0; + any = 0; for_each_ring(ring, dev_priv, i) { - if (list_empty(&ring->request_list)) + int count; + + count = 0; + list_for_each_entry(req, &ring->request_list, list) + count++; + if (count == 0) continue; - seq_printf(m, "%s requests:\n", ring->name); - list_for_each_entry(gem_request, - &ring->request_list, - list) { - seq_printf(m, " %x @ %d\n", - gem_request->seqno, - (int) (jiffies - gem_request->emitted_jiffies)); + seq_printf(m, "%s requests: %d\n", ring->name, count); + list_for_each_entry(req, &ring->request_list, list) { + struct task_struct *task; + + rcu_read_lock(); + task = NULL; + if (req->pid) + task = pid_task(req->pid, PIDTYPE_PID); + seq_printf(m, " %x @ %d: %s [%d]\n", + req->seqno, + (int) (jiffies - req->emitted_jiffies), + task ? task->comm : "<unknown>", + task ? task->pid : -1); + rcu_read_unlock(); } - count++; + + any++; } mutex_unlock(&dev->struct_mutex); - if (count == 0) + if (any == 0) seq_puts(m, "No requests\n"); return 0; @@ -902,7 +956,6 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data) if (ret) return ret; - seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start); seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); for (i = 0; i < dev_priv->num_fence_regs; i++) { struct drm_i915_gem_object *obj = dev_priv->fence_regs[i].obj; @@ -1091,9 +1144,9 @@ static int i915_frequency_info(struct seq_file *m, void *unused) (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); } else if (IS_GEN6(dev) || (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) || IS_BROADWELL(dev) || IS_GEN9(dev)) { - u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); - u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); - u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + u32 rp_state_limits; + u32 gt_perf_status; + u32 rp_state_cap; u32 rpmodectl, rpinclimit, rpdeclimit; u32 rpstat, cagf, reqf; u32 rpupei, rpcurup, rpprevup; @@ -1101,6 +1154,15 @@ static int i915_frequency_info(struct seq_file *m, void *unused) u32 pm_ier, pm_imr, pm_isr, pm_iir, pm_mask; int max_freq; + rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); + if (IS_BROXTON(dev)) { + rp_state_cap = I915_READ(BXT_RP_STATE_CAP); + gt_perf_status = I915_READ(BXT_GT_PERF_STATUS); + } else { + rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); + } + /* RPSTAT1 is in the GT power well */ ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) @@ -1176,14 +1238,20 @@ static int i915_frequency_info(struct seq_file *m, void *unused) GEN6_CURBSYTAVG_MASK); seq_printf(m, "RP PREV UP: %dus\n", rpprevup & GEN6_CURBSYTAVG_MASK); + seq_printf(m, "Up threshold: %d%%\n", + dev_priv->rps.up_threshold); + seq_printf(m, "RP CUR DOWN EI: %dus\n", rpdownei & GEN6_CURIAVG_MASK); seq_printf(m, "RP CUR DOWN: %dus\n", rpcurdown & GEN6_CURBSYTAVG_MASK); seq_printf(m, "RP PREV DOWN: %dus\n", rpprevdown & GEN6_CURBSYTAVG_MASK); + seq_printf(m, "Down threshold: %d%%\n", + dev_priv->rps.down_threshold); - max_freq = (rp_state_cap & 0xff0000) >> 16; + max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 0 : + rp_state_cap >> 16) & 0xff; max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1); seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); @@ -1193,16 +1261,26 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); - max_freq = rp_state_cap & 0xff; + max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 16 : + rp_state_cap >> 0) & 0xff; max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1); seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); - seq_printf(m, "Max overclocked frequency: %dMHz\n", intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); + seq_printf(m, "Current freq: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); + seq_printf(m, "Actual freq: %d MHz\n", cagf); seq_printf(m, "Idle freq: %d MHz\n", intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq)); + seq_printf(m, "Min freq: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.min_freq)); + seq_printf(m, "Max freq: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); + seq_printf(m, + "efficient (RPe) frequency: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); } else if (IS_VALLEYVIEW(dev)) { u32 freq_sts; @@ -1211,6 +1289,12 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); + seq_printf(m, "actual GPU freq: %d MHz\n", + intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff)); + + seq_printf(m, "current GPU freq: %d MHz\n", + intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); + seq_printf(m, "max GPU freq: %d MHz\n", intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); @@ -1223,14 +1307,15 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "efficient (RPe) frequency: %d MHz\n", intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); - - seq_printf(m, "current GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff)); mutex_unlock(&dev_priv->rps.hw_lock); } else { seq_puts(m, "no P-state info available\n"); } + seq_printf(m, "Current CD clock frequency: %d kHz\n", dev_priv->cdclk_freq); + seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq); + seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq); + out: intel_runtime_pm_put(dev_priv); return ret; @@ -1304,17 +1389,16 @@ static int ironlake_drpc_info(struct seq_file *m) intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); - seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ? - "yes" : "no"); + seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN)); seq_printf(m, "Boost freq: %d\n", (rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >> MEMMODE_BOOST_FREQ_SHIFT); seq_printf(m, "HW control enabled: %s\n", - rgvmodectl & MEMMODE_HWIDLE_EN ? "yes" : "no"); + yesno(rgvmodectl & MEMMODE_HWIDLE_EN)); seq_printf(m, "SW control enabled: %s\n", - rgvmodectl & MEMMODE_SWMODE_EN ? "yes" : "no"); + yesno(rgvmodectl & MEMMODE_SWMODE_EN)); seq_printf(m, "Gated voltage change: %s\n", - rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no"); + yesno(rgvmodectl & MEMMODE_RCLK_GATE)); seq_printf(m, "Starting frequency: P%d\n", (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT); seq_printf(m, "Max P-state: P%d\n", @@ -1323,7 +1407,7 @@ static int ironlake_drpc_info(struct seq_file *m) seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f)); seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f)); seq_printf(m, "Render standby enabled: %s\n", - (rstdbyctl & RCX_SW_EXIT) ? "no" : "yes"); + yesno(!(rstdbyctl & RCX_SW_EXIT))); seq_puts(m, "Current RS state: "); switch (rstdbyctl & RSX_STATUS_MASK) { case RSX_STATUS_ON: @@ -1523,6 +1607,21 @@ static int i915_drpc_info(struct seq_file *m, void *unused) return ironlake_drpc_info(m); } +static int i915_frontbuffer_tracking(struct seq_file *m, void *unused) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + seq_printf(m, "FB tracking busy bits: 0x%08x\n", + dev_priv->fb_tracking.busy_bits); + + seq_printf(m, "FB tracking flip bits: 0x%08x\n", + dev_priv->fb_tracking.flip_bits); + + return 0; +} + static int i915_fbc_status(struct seq_file *m, void *unused) { struct drm_info_node *node = m->private; @@ -1535,51 +1634,20 @@ static int i915_fbc_status(struct seq_file *m, void *unused) } intel_runtime_pm_get(dev_priv); + mutex_lock(&dev_priv->fbc.lock); - if (intel_fbc_enabled(dev)) { + if (intel_fbc_enabled(dev_priv)) seq_puts(m, "FBC enabled\n"); - } else { - seq_puts(m, "FBC disabled: "); - switch (dev_priv->fbc.no_fbc_reason) { - case FBC_OK: - seq_puts(m, "FBC actived, but currently disabled in hardware"); - break; - case FBC_UNSUPPORTED: - seq_puts(m, "unsupported by this chipset"); - break; - case FBC_NO_OUTPUT: - seq_puts(m, "no outputs"); - break; - case FBC_STOLEN_TOO_SMALL: - seq_puts(m, "not enough stolen memory"); - break; - case FBC_UNSUPPORTED_MODE: - seq_puts(m, "mode not supported"); - break; - case FBC_MODE_TOO_LARGE: - seq_puts(m, "mode too large"); - break; - case FBC_BAD_PLANE: - seq_puts(m, "FBC unsupported on plane"); - break; - case FBC_NOT_TILED: - seq_puts(m, "scanout buffer not tiled"); - break; - case FBC_MULTIPLE_PIPES: - seq_puts(m, "multiple pipes are enabled"); - break; - case FBC_MODULE_PARAM: - seq_puts(m, "disabled per module param (default off)"); - break; - case FBC_CHIP_DEFAULT: - seq_puts(m, "disabled per chip default"); - break; - default: - seq_puts(m, "unknown reason"); - } - seq_putc(m, '\n'); - } + else + seq_printf(m, "FBC disabled: %s\n", + intel_no_fbc_reason_str(dev_priv->fbc.no_fbc_reason)); + + if (INTEL_INFO(dev_priv)->gen >= 7) + seq_printf(m, "Compressing: %s\n", + yesno(I915_READ(FBC_STATUS2) & + FBC_COMPRESSION_MASK)); + mutex_unlock(&dev_priv->fbc.lock); intel_runtime_pm_put(dev_priv); return 0; @@ -1593,9 +1661,7 @@ static int i915_fbc_fc_get(void *data, u64 *val) if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev)) return -ENODEV; - drm_modeset_lock_all(dev); *val = dev_priv->fbc.false_color; - drm_modeset_unlock_all(dev); return 0; } @@ -1609,7 +1675,7 @@ static int i915_fbc_fc_set(void *data, u64 val) if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev)) return -ENODEV; - drm_modeset_lock_all(dev); + mutex_lock(&dev_priv->fbc.lock); reg = I915_READ(ILK_DPFC_CONTROL); dev_priv->fbc.false_color = val; @@ -1618,7 +1684,7 @@ static int i915_fbc_fc_set(void *data, u64 val) (reg | FBC_CTL_FALSE_COLOR) : (reg & ~FBC_CTL_FALSE_COLOR)); - drm_modeset_unlock_all(dev); + mutex_unlock(&dev_priv->fbc.lock); return 0; } @@ -1720,8 +1786,9 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) struct drm_i915_private *dev_priv = dev->dev_private; int ret = 0; int gpu_freq, ia_freq; + unsigned int max_gpu_freq, min_gpu_freq; - if (!(IS_GEN6(dev) || IS_GEN7(dev))) { + if (!HAS_CORE_RING_FREQ(dev)) { seq_puts(m, "unsupported on this chipset\n"); return 0; } @@ -1734,17 +1801,27 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) if (ret) goto out; + if (IS_SKYLAKE(dev)) { + /* Convert GT frequency to 50 HZ units */ + min_gpu_freq = + dev_priv->rps.min_freq_softlimit / GEN9_FREQ_SCALER; + max_gpu_freq = + dev_priv->rps.max_freq_softlimit / GEN9_FREQ_SCALER; + } else { + min_gpu_freq = dev_priv->rps.min_freq_softlimit; + max_gpu_freq = dev_priv->rps.max_freq_softlimit; + } + seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n"); - for (gpu_freq = dev_priv->rps.min_freq_softlimit; - gpu_freq <= dev_priv->rps.max_freq_softlimit; - gpu_freq++) { + for (gpu_freq = min_gpu_freq; gpu_freq <= max_gpu_freq; gpu_freq++) { ia_freq = gpu_freq; sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_MIN_FREQ_TABLE, &ia_freq); seq_printf(m, "%d\t\t%d\t\t\t\t%d\n", - intel_gpu_freq(dev_priv, gpu_freq), + intel_gpu_freq(dev_priv, (gpu_freq * + (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1))), ((ia_freq >> 0) & 0xff) * 100, ((ia_freq >> 8) & 0xff) * 100); } @@ -1773,7 +1850,7 @@ static int i915_opregion(struct seq_file *m, void *unused) goto out; if (opregion->header) { - memcpy_fromio(data, opregion->header, OPREGION_SIZE); + memcpy(data, opregion->header, OPREGION_SIZE); seq_write(m, data, OPREGION_SIZE); } @@ -1790,8 +1867,9 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct intel_fbdev *ifbdev = NULL; struct intel_framebuffer *fb; + struct drm_framebuffer *drm_fb; -#ifdef CONFIG_DRM_I915_FBDEV +#ifdef CONFIG_DRM_FBDEV_EMULATION struct drm_i915_private *dev_priv = dev->dev_private; ifbdev = dev_priv->fbdev; @@ -1809,7 +1887,8 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) #endif mutex_lock(&dev->mode_config.fb_lock); - list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) { + drm_for_each_fb(drm_fb, dev) { + fb = to_intel_framebuffer(drm_fb); if (ifbdev && &fb->base == ifbdev->helper.fb) continue; @@ -1917,7 +1996,7 @@ static void i915_dump_lrc_obj(struct seq_file *m, return; } - page = i915_gem_object_get_page(ctx_obj, 1); + page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); if (!WARN_ON(page == NULL)) { reg_state = kmap_atomic(page); @@ -1997,8 +2076,8 @@ static int i915_execlists(struct seq_file *m, void *data) seq_printf(m, "%s\n", ring->name); - status = I915_READ(RING_EXECLIST_STATUS(ring)); - ctx_id = I915_READ(RING_EXECLIST_STATUS(ring) + 4); + status = I915_READ(RING_EXECLIST_STATUS_LO(ring)); + ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring)); seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n", status, ctx_id); @@ -2013,8 +2092,8 @@ static int i915_execlists(struct seq_file *m, void *data) read_pointer, write_pointer); for (i = 0; i < 6; i++) { - status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + 8*i); - ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + 8*i + 4); + status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i)); + ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i)); seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n", i, status, ctx_id); @@ -2156,15 +2235,12 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) if (!ppgtt) return; - seq_printf(m, "Page directories: %d\n", ppgtt->num_pd_pages); - seq_printf(m, "Page tables: %d\n", ppgtt->num_pd_entries); for_each_ring(ring, dev_priv, unused) { seq_printf(m, "%s\n", ring->name); for (i = 0; i < 4; i++) { - u32 offset = 0x270 + i * 8; - u64 pdp = I915_READ(ring->mmio_base + offset + 4); + u64 pdp = I915_READ(GEN8_RING_PDP_UDW(ring, i)); pdp <<= 32; - pdp |= I915_READ(ring->mmio_base + offset); + pdp |= I915_READ(GEN8_RING_PDP_LDW(ring, i)); seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp); } } @@ -2174,7 +2250,6 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; - struct drm_file *file; int i; if (INTEL_INFO(dev)->gen == 6) @@ -2192,18 +2267,11 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; seq_puts(m, "aliasing PPGTT:\n"); - seq_printf(m, "pd gtt offset: 0x%08x\n", ppgtt->pd.pd_offset); + seq_printf(m, "pd gtt offset: 0x%08x\n", ppgtt->pd.base.ggtt_offset); ppgtt->debug_dump(ppgtt, m); } - list_for_each_entry_reverse(file, &dev->filelist, lhead) { - struct drm_i915_file_private *file_priv = file->driver_priv; - - seq_printf(m, "proc: %s\n", - get_pid_task(file->pid, PIDTYPE_PID)->comm); - idr_for_each(&file_priv->context_idr, per_file_ctx, m); - } seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK)); } @@ -2212,6 +2280,7 @@ static int i915_ppgtt_info(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 = dev->dev_private; + struct drm_file *file; int ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) @@ -2223,9 +2292,79 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) else if (INTEL_INFO(dev)->gen >= 6) gen6_ppgtt_info(m, dev); + list_for_each_entry_reverse(file, &dev->filelist, lhead) { + struct drm_i915_file_private *file_priv = file->driver_priv; + struct task_struct *task; + + task = get_pid_task(file->pid, PIDTYPE_PID); + if (!task) { + ret = -ESRCH; + goto out_put; + } + seq_printf(m, "\nproc: %s\n", task->comm); + put_task_struct(task); + idr_for_each(&file_priv->context_idr, per_file_ctx, + (void *)(unsigned long)m); + } + +out_put: intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); + return ret; +} + +static int count_irq_waiters(struct drm_i915_private *i915) +{ + struct intel_engine_cs *ring; + int count = 0; + int i; + + for_each_ring(ring, i915, i) + count += ring->irq_refcount; + + return count; +} + +static int i915_rps_boost_info(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 = dev->dev_private; + struct drm_file *file; + + seq_printf(m, "RPS enabled? %d\n", dev_priv->rps.enabled); + seq_printf(m, "GPU busy? %d\n", dev_priv->mm.busy); + seq_printf(m, "CPU waiting? %d\n", count_irq_waiters(dev_priv)); + seq_printf(m, "Frequency requested %d; min hard:%d, soft:%d; max soft:%d, hard:%d\n", + intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq), + intel_gpu_freq(dev_priv, dev_priv->rps.min_freq), + intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit), + intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit), + intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); + spin_lock(&dev_priv->rps.client_lock); + list_for_each_entry_reverse(file, &dev->filelist, lhead) { + struct drm_i915_file_private *file_priv = file->driver_priv; + struct task_struct *task; + + rcu_read_lock(); + task = pid_task(file->pid, PIDTYPE_PID); + seq_printf(m, "%s [%d]: %d boosts%s\n", + task ? task->comm : "<unknown>", + task ? task->pid : -1, + file_priv->rps.boosts, + list_empty(&file_priv->rps.link) ? "" : ", active"); + rcu_read_unlock(); + } + seq_printf(m, "Semaphore boosts: %d%s\n", + dev_priv->rps.semaphores.boosts, + list_empty(&dev_priv->rps.semaphores.link) ? "" : ", active"); + seq_printf(m, "MMIO flip boosts: %d%s\n", + dev_priv->rps.mmioflips.boosts, + list_empty(&dev_priv->rps.mmioflips.link) ? "" : ", active"); + seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts); + spin_unlock(&dev_priv->rps.client_lock); + return 0; } @@ -2242,6 +2381,147 @@ static int i915_llc(struct seq_file *m, void *data) return 0; } +static int i915_guc_load_status_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_i915_private *dev_priv = node->minor->dev->dev_private; + struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; + u32 tmp, i; + + if (!HAS_GUC_UCODE(dev_priv->dev)) + return 0; + + seq_printf(m, "GuC firmware status:\n"); + seq_printf(m, "\tpath: %s\n", + guc_fw->guc_fw_path); + seq_printf(m, "\tfetch: %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status)); + seq_printf(m, "\tload: %s\n", + intel_guc_fw_status_repr(guc_fw->guc_fw_load_status)); + seq_printf(m, "\tversion wanted: %d.%d\n", + guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted); + seq_printf(m, "\tversion found: %d.%d\n", + guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found); + + tmp = I915_READ(GUC_STATUS); + + seq_printf(m, "\nGuC status 0x%08x:\n", tmp); + seq_printf(m, "\tBootrom status = 0x%x\n", + (tmp & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT); + seq_printf(m, "\tuKernel status = 0x%x\n", + (tmp & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT); + seq_printf(m, "\tMIA Core status = 0x%x\n", + (tmp & GS_MIA_MASK) >> GS_MIA_SHIFT); + seq_puts(m, "\nScratch registers:\n"); + for (i = 0; i < 16; i++) + seq_printf(m, "\t%2d: \t0x%x\n", i, I915_READ(SOFT_SCRATCH(i))); + + return 0; +} + +static void i915_guc_client_info(struct seq_file *m, + struct drm_i915_private *dev_priv, + struct i915_guc_client *client) +{ + struct intel_engine_cs *ring; + uint64_t tot = 0; + uint32_t i; + + seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n", + client->priority, client->ctx_index, client->proc_desc_offset); + seq_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n", + client->doorbell_id, client->doorbell_offset, client->cookie); + seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", + client->wq_size, client->wq_offset, client->wq_tail); + + seq_printf(m, "\tFailed to queue: %u\n", client->q_fail); + seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail); + seq_printf(m, "\tLast submission result: %d\n", client->retcode); + + for_each_ring(ring, dev_priv, i) { + seq_printf(m, "\tSubmissions: %llu %s\n", + client->submissions[i], + ring->name); + tot += client->submissions[i]; + } + seq_printf(m, "\tTotal: %llu\n", tot); +} + +static int i915_guc_info(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 = dev->dev_private; + struct intel_guc guc; + struct i915_guc_client client = {}; + struct intel_engine_cs *ring; + enum intel_ring_id i; + u64 total = 0; + + if (!HAS_GUC_SCHED(dev_priv->dev)) + return 0; + + /* Take a local copy of the GuC data, so we can dump it at leisure */ + spin_lock(&dev_priv->guc.host2guc_lock); + guc = dev_priv->guc; + if (guc.execbuf_client) { + spin_lock(&guc.execbuf_client->wq_lock); + client = *guc.execbuf_client; + spin_unlock(&guc.execbuf_client->wq_lock); + } + spin_unlock(&dev_priv->guc.host2guc_lock); + + 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); + + seq_printf(m, "\nGuC submissions:\n"); + for_each_ring(ring, dev_priv, i) { + seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x %9d\n", + ring->name, guc.submissions[i], + guc.last_seqno[i], guc.last_seqno[i]); + total += guc.submissions[i]; + } + 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, &client); + + /* Add more as required ... */ + + return 0; +} + +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 = dev->dev_private; + struct drm_i915_gem_object *log_obj = dev_priv->guc.log_obj; + u32 *log; + int i = 0, pg; + + if (!log_obj) + return 0; + + for (pg = 0; pg < log_obj->base.size / PAGE_SIZE; pg++) { + log = kmap_atomic(i915_gem_object_get_page(log_obj, pg)); + + 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)); + + kunmap_atomic(log); + } + + seq_putc(m, '\n'); + + return 0; +} + static int i915_edp_psr_status(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; @@ -2290,9 +2570,6 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) } seq_puts(m, "\n"); - seq_printf(m, "Link standby: %s\n", - yesno((bool)dev_priv->psr.link_standby)); - /* CHV PSR has no kind of performance counter */ if (HAS_DDI(dev)) { psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) & @@ -2372,13 +2649,13 @@ static int i915_energy_uJ(struct seq_file *m, void *data) return 0; } -static int i915_pc8_status(struct seq_file *m, void *unused) +static int i915_runtime_pm_status(struct seq_file *m, void *unused) { struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { + if (!HAS_RUNTIME_PM(dev)) { seq_puts(m, "not supported\n"); return 0; } @@ -2386,6 +2663,12 @@ static int i915_pc8_status(struct seq_file *m, void *unused) seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->mm.busy)); seq_printf(m, "IRQs disabled: %s\n", yesno(!intel_irqs_enabled(dev_priv))); +#ifdef CONFIG_PM + seq_printf(m, "Usage count: %d\n", + atomic_read(&dev->dev->power.usage_count)); +#else + seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n"); +#endif return 0; } @@ -2429,6 +2712,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain) return "PORT_DDI_D_2_LANES"; case POWER_DOMAIN_PORT_DDI_D_4_LANES: return "PORT_DDI_D_4_LANES"; + case POWER_DOMAIN_PORT_DDI_E_2_LANES: + return "PORT_DDI_E_2_LANES"; case POWER_DOMAIN_PORT_DSI: return "PORT_DSI"; case POWER_DOMAIN_PORT_CRT: @@ -2449,6 +2734,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain) return "AUX_C"; case POWER_DOMAIN_AUX_D: return "AUX_D"; + case POWER_DOMAIN_GMBUS: + return "GMBUS"; case POWER_DOMAIN_INIT: return "INIT"; default: @@ -2545,11 +2832,13 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc) struct drm_device *dev = node->minor->dev; struct drm_crtc *crtc = &intel_crtc->base; struct intel_encoder *intel_encoder; + struct drm_plane_state *plane_state = crtc->primary->state; + struct drm_framebuffer *fb = plane_state->fb; - if (crtc->primary->fb) + if (fb) seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n", - crtc->primary->fb->base.id, crtc->x, crtc->y, - crtc->primary->fb->width, crtc->primary->fb->height); + fb->base.id, plane_state->src_x >> 16, + plane_state->src_y >> 16, fb->width, fb->height); else seq_puts(m, "\tprimary plane disabled\n"); for_each_encoder_on_crtc(dev, crtc, intel_encoder) @@ -2571,8 +2860,7 @@ static void intel_dp_info(struct seq_file *m, struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]); - seq_printf(m, "\taudio support: %s\n", intel_dp->has_audio ? "yes" : - "no"); + seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio)); if (intel_encoder->type == INTEL_OUTPUT_EDP) intel_panel_info(m, &intel_connector->panel); } @@ -2583,8 +2871,7 @@ static void intel_hdmi_info(struct seq_file *m, struct intel_encoder *intel_encoder = intel_connector->encoder; struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base); - seq_printf(m, "\taudio support: %s\n", intel_hdmi->has_audio ? "yes" : - "no"); + seq_printf(m, "\taudio support: %s\n", yesno(intel_hdmi->has_audio)); } static void intel_lvds_info(struct seq_file *m, @@ -2634,7 +2921,7 @@ static bool cursor_active(struct drm_device *dev, int pipe) u32 state; if (IS_845G(dev) || IS_I865G(dev)) - state = I915_READ(_CURACNTR) & CURSOR_ENABLE; + state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; else state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; @@ -2673,13 +2960,16 @@ static int i915_display_info(struct seq_file *m, void *unused) seq_printf(m, "---------\n"); for_each_intel_crtc(dev, crtc) { bool active; + struct intel_crtc_state *pipe_config; int x, y; + pipe_config = to_intel_crtc_state(crtc->base.state); + seq_printf(m, "CRTC %d: pipe: %c, active=%s (size=%dx%d)\n", crtc->base.base.id, pipe_name(crtc->pipe), - yesno(crtc->active), crtc->config->pipe_src_w, - crtc->config->pipe_src_h); - if (crtc->active) { + yesno(pipe_config->base.active), + pipe_config->pipe_src_w, pipe_config->pipe_src_h); + if (pipe_config->base.active) { intel_crtc_info(m, crtc); active = cursor_position(dev, crtc->pipe, &x, &y); @@ -2869,7 +3159,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused) skl_ddb_entry_size(entry)); } - entry = &ddb->cursor[pipe]; + entry = &ddb->plane[pipe][PLANE_CURSOR]; seq_printf(m, " %-13s%8u%8u%8u\n", "Cursor", entry->start, entry->end, skl_ddb_entry_size(entry)); } @@ -2920,7 +3210,7 @@ static void drrs_status_per_crtc(struct seq_file *m, seq_puts(m, "\n\n"); - if (intel_crtc->config->has_drrs) { + if (to_intel_crtc_state(intel_crtc->base.state)->has_drrs) { struct intel_panel *panel; mutex_lock(&drrs->mutex); @@ -2972,7 +3262,7 @@ static int i915_drrs_status(struct seq_file *m, void *unused) for_each_intel_crtc(dev, intel_crtc) { drm_modeset_lock(&intel_crtc->base.mutex, NULL); - if (intel_crtc->active) { + if (intel_crtc->base.state->active) { active_crtc_cnt++; seq_printf(m, "\nCRTC %d: ", active_crtc_cnt); @@ -3509,55 +3799,40 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, return 0; } -static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev) +static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]); + struct intel_crtc_state *pipe_config; + struct drm_atomic_state *state; + int ret = 0; drm_modeset_lock_all(dev); - /* - * If we use the eDP transcoder we need to make sure that we don't - * bypass the pfit, since otherwise the pipe CRC source won't work. Only - * relevant on hsw with pipe A when using the always-on power well - * routing. - */ - if (crtc->config->cpu_transcoder == TRANSCODER_EDP && - !crtc->config->pch_pfit.enabled) { - crtc->config->pch_pfit.force_thru = true; - - intel_display_power_get(dev_priv, - POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A)); - - dev_priv->display.crtc_disable(&crtc->base); - dev_priv->display.crtc_enable(&crtc->base); + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto out; } - drm_modeset_unlock_all(dev); -} - -static void hsw_undo_trans_edp_pipe_A_crc_wa(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *crtc = - to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]); - drm_modeset_lock_all(dev); - /* - * If we use the eDP transcoder we need to make sure that we don't - * bypass the pfit, since otherwise the pipe CRC source won't work. Only - * relevant on hsw with pipe A when using the always-on power well - * routing. - */ - if (crtc->config->pch_pfit.force_thru) { - crtc->config->pch_pfit.force_thru = false; + state->acquire_ctx = drm_modeset_legacy_acquire_ctx(&crtc->base); + pipe_config = intel_atomic_get_crtc_state(state, crtc); + if (IS_ERR(pipe_config)) { + ret = PTR_ERR(pipe_config); + goto out; + } - dev_priv->display.crtc_disable(&crtc->base); - dev_priv->display.crtc_enable(&crtc->base); + pipe_config->pch_pfit.force_thru = enable; + if (pipe_config->cpu_transcoder == TRANSCODER_EDP && + pipe_config->pch_pfit.enabled != enable) + pipe_config->base.connectors_changed = true; - intel_display_power_put(dev_priv, - POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A)); - } + ret = drm_atomic_commit(state); +out: drm_modeset_unlock_all(dev); + WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret); + if (ret) + drm_atomic_state_free(state); } static int ivb_pipe_crc_ctl_reg(struct drm_device *dev, @@ -3577,7 +3852,7 @@ static int ivb_pipe_crc_ctl_reg(struct drm_device *dev, break; case INTEL_PIPE_CRC_SOURCE_PF: if (IS_HASWELL(dev) && pipe == PIPE_A) - hsw_trans_edp_pipe_A_crc_wa(dev); + hsw_trans_edp_pipe_A_crc_wa(dev, true); *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; break; @@ -3671,7 +3946,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, pipe_name(pipe)); drm_modeset_lock(&crtc->base.mutex, NULL); - if (crtc->active) + if (crtc->base.state->active) intel_wait_for_vblank(dev, pipe); drm_modeset_unlock(&crtc->base.mutex); @@ -3689,7 +3964,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, else if (IS_VALLEYVIEW(dev)) vlv_undo_pipe_scramble_reset(dev, pipe); else if (IS_HASWELL(dev) && pipe == PIPE_A) - hsw_undo_trans_edp_pipe_A_crc_wa(dev); + hsw_trans_edp_pipe_A_crc_wa(dev, false); hsw_enable_ips(crtc); } @@ -3869,11 +4144,203 @@ static const struct file_operations i915_display_crc_ctl_fops = { .write = display_crc_ctl_write }; +static ssize_t i915_displayport_test_active_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + char *input_buffer; + int status = 0; + struct drm_device *dev; + struct drm_connector *connector; + struct list_head *connector_list; + struct intel_dp *intel_dp; + int val = 0; + + dev = ((struct seq_file *)file->private_data)->private; + + connector_list = &dev->mode_config.connector_list; + + if (len == 0) + return 0; + + input_buffer = kmalloc(len + 1, GFP_KERNEL); + if (!input_buffer) + return -ENOMEM; + + 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); + + list_for_each_entry(connector, connector_list, head) { + + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected && + connector->encoder != NULL) { + intel_dp = enc_to_intel_dp(connector->encoder); + status = kstrtoint(input_buffer, 10, &val); + if (status < 0) + goto out; + DRM_DEBUG_DRIVER("Got %d for test active\n", val); + /* To prevent erroneous activation of the compliance + * testing code, only accept an actual value of 1 here + */ + if (val == 1) + intel_dp->compliance_test_active = 1; + else + intel_dp->compliance_test_active = 0; + } + } +out: + kfree(input_buffer); + if (status < 0) + return status; + + *offp += len; + return len; +} + +static int i915_displayport_test_active_show(struct seq_file *m, void *data) +{ + struct drm_device *dev = m->private; + struct drm_connector *connector; + struct list_head *connector_list = &dev->mode_config.connector_list; + struct intel_dp *intel_dp; + + list_for_each_entry(connector, connector_list, head) { + + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected && + connector->encoder != NULL) { + intel_dp = enc_to_intel_dp(connector->encoder); + if (intel_dp->compliance_test_active) + seq_puts(m, "1"); + else + seq_puts(m, "0"); + } else + seq_puts(m, "0"); + } + + return 0; +} + +static int i915_displayport_test_active_open(struct inode *inode, + struct file *file) +{ + struct drm_device *dev = inode->i_private; + + return single_open(file, i915_displayport_test_active_show, dev); +} + +static const struct file_operations i915_displayport_test_active_fops = { + .owner = THIS_MODULE, + .open = i915_displayport_test_active_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = i915_displayport_test_active_write +}; + +static int i915_displayport_test_data_show(struct seq_file *m, void *data) +{ + struct drm_device *dev = m->private; + struct drm_connector *connector; + struct list_head *connector_list = &dev->mode_config.connector_list; + struct intel_dp *intel_dp; + + list_for_each_entry(connector, connector_list, head) { + + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected && + connector->encoder != NULL) { + intel_dp = enc_to_intel_dp(connector->encoder); + seq_printf(m, "%lx", intel_dp->compliance_test_data); + } else + seq_puts(m, "0"); + } + + return 0; +} +static int i915_displayport_test_data_open(struct inode *inode, + struct file *file) +{ + struct drm_device *dev = inode->i_private; + + return single_open(file, i915_displayport_test_data_show, dev); +} + +static const struct file_operations i915_displayport_test_data_fops = { + .owner = THIS_MODULE, + .open = i915_displayport_test_data_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + +static int i915_displayport_test_type_show(struct seq_file *m, void *data) +{ + struct drm_device *dev = m->private; + struct drm_connector *connector; + struct list_head *connector_list = &dev->mode_config.connector_list; + struct intel_dp *intel_dp; + + list_for_each_entry(connector, connector_list, head) { + + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected && + connector->encoder != NULL) { + intel_dp = enc_to_intel_dp(connector->encoder); + seq_printf(m, "%02lx", intel_dp->compliance_test_type); + } else + seq_puts(m, "0"); + } + + return 0; +} + +static int i915_displayport_test_type_open(struct inode *inode, + struct file *file) +{ + struct drm_device *dev = inode->i_private; + + return single_open(file, i915_displayport_test_type_show, dev); +} + +static const struct file_operations i915_displayport_test_type_fops = { + .owner = THIS_MODULE, + .open = i915_displayport_test_type_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) { struct drm_device *dev = m->private; - int num_levels = ilk_wm_max_level(dev) + 1; int level; + int num_levels; + + if (IS_CHERRYVIEW(dev)) + num_levels = 3; + else if (IS_VALLEYVIEW(dev)) + num_levels = 1; + else + num_levels = ilk_wm_max_level(dev) + 1; drm_modeset_lock_all(dev); @@ -3882,9 +4349,9 @@ 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 + * - latencies are in us on gen9/vlv/chv */ - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev)) latency *= 10; else if (level > 0) latency *= 5; @@ -3948,7 +4415,7 @@ static int pri_wm_latency_open(struct inode *inode, struct file *file) { struct drm_device *dev = inode->i_private; - if (HAS_GMCH_DISPLAY(dev)) + if (INTEL_INFO(dev)->gen < 5) return -ENODEV; return single_open(file, pri_wm_latency_show, dev); @@ -3980,11 +4447,18 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, struct seq_file *m = file->private_data; struct drm_device *dev = m->private; uint16_t new[8] = { 0 }; - int num_levels = ilk_wm_max_level(dev) + 1; + int num_levels; int level; int ret; char tmp[32]; + if (IS_CHERRYVIEW(dev)) + num_levels = 3; + else if (IS_VALLEYVIEW(dev)) + num_levels = 1; + else + num_levels = ilk_wm_max_level(dev) + 1; + if (len >= sizeof(tmp)) return -EINVAL; @@ -4473,14 +4947,143 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops, i915_cache_sharing_get, i915_cache_sharing_set, "%llu\n"); +struct sseu_dev_status { + unsigned int slice_total; + unsigned int subslice_total; + unsigned int subslice_per_slice; + unsigned int eu_total; + unsigned int eu_per_subslice; +}; + +static void cherryview_sseu_device_status(struct drm_device *dev, + struct sseu_dev_status *stat) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int ss_max = 2; + int ss; + u32 sig1[ss_max], sig2[ss_max]; + + sig1[0] = I915_READ(CHV_POWER_SS0_SIG1); + sig1[1] = I915_READ(CHV_POWER_SS1_SIG1); + sig2[0] = I915_READ(CHV_POWER_SS0_SIG2); + sig2[1] = I915_READ(CHV_POWER_SS1_SIG2); + + for (ss = 0; ss < ss_max; ss++) { + unsigned int eu_cnt; + + if (sig1[ss] & CHV_SS_PG_ENABLE) + /* skip disabled subslice */ + continue; + + stat->slice_total = 1; + stat->subslice_per_slice++; + eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) + + ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) + + ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) + + ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2); + stat->eu_total += eu_cnt; + stat->eu_per_subslice = max(stat->eu_per_subslice, eu_cnt); + } + stat->subslice_total = stat->subslice_per_slice; +} + +static void gen9_sseu_device_status(struct drm_device *dev, + struct sseu_dev_status *stat) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int s_max = 3, ss_max = 4; + int s, ss; + u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2]; + + /* BXT has a single slice and at most 3 subslices. */ + if (IS_BROXTON(dev)) { + s_max = 1; + ss_max = 3; + } + + for (s = 0; s < s_max; s++) { + s_reg[s] = I915_READ(GEN9_SLICE_PGCTL_ACK(s)); + eu_reg[2*s] = I915_READ(GEN9_SS01_EU_PGCTL_ACK(s)); + eu_reg[2*s + 1] = I915_READ(GEN9_SS23_EU_PGCTL_ACK(s)); + } + + eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK | + GEN9_PGCTL_SSA_EU19_ACK | + GEN9_PGCTL_SSA_EU210_ACK | + GEN9_PGCTL_SSA_EU311_ACK; + eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK | + GEN9_PGCTL_SSB_EU19_ACK | + GEN9_PGCTL_SSB_EU210_ACK | + GEN9_PGCTL_SSB_EU311_ACK; + + for (s = 0; s < s_max; s++) { + unsigned int ss_cnt = 0; + + if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0) + /* skip disabled slice */ + continue; + + stat->slice_total++; + + if (IS_SKYLAKE(dev)) + ss_cnt = INTEL_INFO(dev)->subslice_per_slice; + + for (ss = 0; ss < ss_max; ss++) { + unsigned int eu_cnt; + + if (IS_BROXTON(dev) && + !(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss)))) + /* skip disabled subslice */ + continue; + + if (IS_BROXTON(dev)) + ss_cnt++; + + eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & + eu_mask[ss%2]); + stat->eu_total += eu_cnt; + stat->eu_per_subslice = max(stat->eu_per_subslice, + eu_cnt); + } + + stat->subslice_total += ss_cnt; + stat->subslice_per_slice = max(stat->subslice_per_slice, + ss_cnt); + } +} + +static void broadwell_sseu_device_status(struct drm_device *dev, + struct sseu_dev_status *stat) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int s; + u32 slice_info = I915_READ(GEN8_GT_SLICE_INFO); + + stat->slice_total = hweight32(slice_info & GEN8_LSLICESTAT_MASK); + + if (stat->slice_total) { + stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice; + stat->subslice_total = stat->slice_total * + stat->subslice_per_slice; + stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice; + stat->eu_total = stat->eu_per_subslice * stat->subslice_total; + + /* subtract fused off EU(s) from enabled slice(s) */ + for (s = 0; s < stat->slice_total; s++) { + u8 subslice_7eu = INTEL_INFO(dev)->subslice_7eu[s]; + + stat->eu_total -= hweight8(subslice_7eu); + } + } +} + static int i915_sseu_status(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned int s_tot = 0, ss_tot = 0, ss_per = 0, eu_tot = 0, eu_per = 0; + struct sseu_dev_status stat; - if ((INTEL_INFO(dev)->gen < 8) || IS_BROADWELL(dev)) + if (INTEL_INFO(dev)->gen < 8) return -ENODEV; seq_puts(m, "SSEU Device Info\n"); @@ -4502,79 +5105,24 @@ static int i915_sseu_status(struct seq_file *m, void *unused) yesno(INTEL_INFO(dev)->has_eu_pg)); seq_puts(m, "SSEU Device Status\n"); + memset(&stat, 0, sizeof(stat)); if (IS_CHERRYVIEW(dev)) { - const int ss_max = 2; - int ss; - u32 sig1[ss_max], sig2[ss_max]; - - sig1[0] = I915_READ(CHV_POWER_SS0_SIG1); - sig1[1] = I915_READ(CHV_POWER_SS1_SIG1); - sig2[0] = I915_READ(CHV_POWER_SS0_SIG2); - sig2[1] = I915_READ(CHV_POWER_SS1_SIG2); - - for (ss = 0; ss < ss_max; ss++) { - unsigned int eu_cnt; - - if (sig1[ss] & CHV_SS_PG_ENABLE) - /* skip disabled subslice */ - continue; - - s_tot = 1; - ss_per++; - eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) + - ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) + - ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) + - ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2); - eu_tot += eu_cnt; - eu_per = max(eu_per, eu_cnt); - } - ss_tot = ss_per; - } else if (IS_SKYLAKE(dev)) { - const int s_max = 3, ss_max = 4; - int s, ss; - u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2]; - - s_reg[0] = I915_READ(GEN9_SLICE0_PGCTL_ACK); - s_reg[1] = I915_READ(GEN9_SLICE1_PGCTL_ACK); - s_reg[2] = I915_READ(GEN9_SLICE2_PGCTL_ACK); - eu_reg[0] = I915_READ(GEN9_SLICE0_SS01_EU_PGCTL_ACK); - eu_reg[1] = I915_READ(GEN9_SLICE0_SS23_EU_PGCTL_ACK); - eu_reg[2] = I915_READ(GEN9_SLICE1_SS01_EU_PGCTL_ACK); - eu_reg[3] = I915_READ(GEN9_SLICE1_SS23_EU_PGCTL_ACK); - eu_reg[4] = I915_READ(GEN9_SLICE2_SS01_EU_PGCTL_ACK); - eu_reg[5] = I915_READ(GEN9_SLICE2_SS23_EU_PGCTL_ACK); - eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK | - GEN9_PGCTL_SSA_EU19_ACK | - GEN9_PGCTL_SSA_EU210_ACK | - GEN9_PGCTL_SSA_EU311_ACK; - eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK | - GEN9_PGCTL_SSB_EU19_ACK | - GEN9_PGCTL_SSB_EU210_ACK | - GEN9_PGCTL_SSB_EU311_ACK; - - for (s = 0; s < s_max; s++) { - if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0) - /* skip disabled slice */ - continue; - - s_tot++; - ss_per = INTEL_INFO(dev)->subslice_per_slice; - ss_tot += ss_per; - for (ss = 0; ss < ss_max; ss++) { - unsigned int eu_cnt; - - eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & - eu_mask[ss%2]); - eu_tot += eu_cnt; - eu_per = max(eu_per, eu_cnt); - } - } + cherryview_sseu_device_status(dev, &stat); + } else if (IS_BROADWELL(dev)) { + broadwell_sseu_device_status(dev, &stat); + } else if (INTEL_INFO(dev)->gen >= 9) { + gen9_sseu_device_status(dev, &stat); } - seq_printf(m, " Enabled Slice Total: %u\n", s_tot); - seq_printf(m, " Enabled Subslice Total: %u\n", ss_tot); - seq_printf(m, " Enabled Subslice Per Slice: %u\n", ss_per); - seq_printf(m, " Enabled EU Total: %u\n", eu_tot); - seq_printf(m, " Enabled EU Per Subslice: %u\n", eu_per); + seq_printf(m, " Enabled Slice Total: %u\n", + stat.slice_total); + seq_printf(m, " Enabled Subslice Total: %u\n", + stat.subslice_total); + seq_printf(m, " Enabled Subslice Per Slice: %u\n", + stat.subslice_per_slice); + seq_printf(m, " Enabled EU Total: %u\n", + stat.eu_total); + seq_printf(m, " Enabled EU Per Subslice: %u\n", + stat.eu_per_subslice); return 0; } @@ -4664,11 +5212,15 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS}, {"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS}, {"i915_gem_batch_pool", i915_gem_batch_pool_info, 0}, + {"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_frequency_info", i915_frequency_info, 0}, {"i915_hangcheck_info", i915_hangcheck_info, 0}, {"i915_drpc_info", i915_drpc_info, 0}, {"i915_emon_status", i915_emon_status, 0}, {"i915_ring_freq_table", i915_ring_freq_table, 0}, + {"i915_frontbuffer_tracking", i915_frontbuffer_tracking, 0}, {"i915_fbc_status", i915_fbc_status, 0}, {"i915_ips_status", i915_ips_status, 0}, {"i915_sr_status", i915_sr_status, 0}, @@ -4684,7 +5236,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_edp_psr_status", i915_edp_psr_status, 0}, {"i915_sink_crc_eDP1", i915_sink_crc, 0}, {"i915_energy_uJ", i915_energy_uJ, 0}, - {"i915_pc8_status", i915_pc8_status, 0}, + {"i915_runtime_pm_status", i915_runtime_pm_status, 0}, {"i915_power_domain_info", i915_power_domain_info, 0}, {"i915_display_info", i915_display_info, 0}, {"i915_semaphore_status", i915_semaphore_status, 0}, @@ -4694,6 +5246,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_ddb_info", i915_ddb_info, 0}, {"i915_sseu_status", i915_sseu_status, 0}, {"i915_drrs_status", i915_drrs_status, 0}, + {"i915_rps_boost_info", i915_rps_boost_info, 0}, }; #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) @@ -4716,6 +5269,9 @@ static const struct i915_debugfs_files { {"i915_spr_wm_latency", &i915_spr_wm_latency_fops}, {"i915_cur_wm_latency", &i915_cur_wm_latency_fops}, {"i915_fbc_false_color", &i915_fbc_fc_fops}, + {"i915_dp_test_data", &i915_displayport_test_data_fops}, + {"i915_dp_test_type", &i915_displayport_test_type_fops}, + {"i915_dp_test_active", &i915_displayport_test_active_fops} }; void intel_display_crc_init(struct drm_device *dev) @@ -4783,3 +5339,102 @@ void i915_debugfs_cleanup(struct drm_minor *minor) drm_debugfs_remove_files(info_list, 1, minor); } } + +struct dpcd_block { + /* DPCD dump start address. */ + unsigned int offset; + /* DPCD dump end address, inclusive. If unset, .size will be used. */ + unsigned int end; + /* DPCD dump size. Used if .end is unset. If unset, defaults to 1. */ + size_t size; + /* Only valid for eDP. */ + bool edp; +}; + +static const struct dpcd_block i915_dpcd_debug[] = { + { .offset = DP_DPCD_REV, .size = DP_RECEIVER_CAP_SIZE }, + { .offset = DP_PSR_SUPPORT, .end = DP_PSR_CAPS }, + { .offset = DP_DOWNSTREAM_PORT_0, .size = 16 }, + { .offset = DP_LINK_BW_SET, .end = DP_EDP_CONFIGURATION_SET }, + { .offset = DP_SINK_COUNT, .end = DP_ADJUST_REQUEST_LANE2_3 }, + { .offset = DP_SET_POWER }, + { .offset = DP_EDP_DPCD_REV }, + { .offset = DP_EDP_GENERAL_CAP_1, .end = DP_EDP_GENERAL_CAP_3 }, + { .offset = DP_EDP_DISPLAY_CONTROL_REGISTER, .end = DP_EDP_BACKLIGHT_FREQ_CAP_MAX_LSB }, + { .offset = DP_EDP_DBC_MINIMUM_BRIGHTNESS_SET, .end = DP_EDP_DBC_MAXIMUM_BRIGHTNESS_SET }, +}; + +static int i915_dpcd_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct intel_dp *intel_dp = + enc_to_intel_dp(&intel_attached_encoder(connector)->base); + uint8_t buf[16]; + ssize_t err; + int i; + + if (connector->status != connector_status_connected) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(i915_dpcd_debug); i++) { + const struct dpcd_block *b = &i915_dpcd_debug[i]; + size_t size = b->end ? b->end - b->offset + 1 : (b->size ?: 1); + + if (b->edp && + connector->connector_type != DRM_MODE_CONNECTOR_eDP) + continue; + + /* low tech for now */ + if (WARN_ON(size > sizeof(buf))) + continue; + + err = drm_dp_dpcd_read(&intel_dp->aux, b->offset, buf, size); + if (err <= 0) { + DRM_ERROR("dpcd read (%zu bytes at %u) failed (%zd)\n", + size, b->offset, err); + continue; + } + + seq_printf(m, "%04x: %*ph\n", b->offset, (int) size, buf); + } + + return 0; +} + +static int i915_dpcd_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_dpcd_show, inode->i_private); +} + +static const struct file_operations i915_dpcd_fops = { + .owner = THIS_MODULE, + .open = i915_dpcd_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/** + * i915_debugfs_connector_add - add i915 specific connector debugfs files + * @connector: pointer to a registered drm_connector + * + * Cleanup will be done by drm_connector_unregister() through a call to + * drm_debugfs_connector_remove(). + * + * Returns 0 on success, negative error codes on error. + */ +int i915_debugfs_connector_add(struct drm_connector *connector) +{ + struct dentry *root = connector->debugfs_entry; + + /* The connector must have been registered beforehands. */ + if (!root) + return -ENODEV; + + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector->connector_type == DRM_MODE_CONNECTOR_eDP) + debugfs_create_file("i915_dpcd", S_IRUGO, root, connector, + &i915_dpcd_fops); + + return 0; +} |