diff options
| author | Dave Airlie <airlied@redhat.com> | 2017-03-23 08:47:23 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2017-03-23 08:47:23 +1000 |
| commit | be5df20a34d78d986ddfb6e0fc87e4fa4d05268b (patch) | |
| tree | 0044872cb679ab1415f85e2dc15aacc6c34e44c6 /drivers/gpu/drm | |
| parent | 33d5f513c60d5ccd63f8d06d42b4aa4620f4073f (diff) | |
| parent | c5bd2e14e85d180bc7fb3b8b62ac9348bddaf898 (diff) | |
| download | linux-be5df20a34d78d986ddfb6e0fc87e4fa4d05268b.tar.gz linux-be5df20a34d78d986ddfb6e0fc87e4fa4d05268b.tar.bz2 linux-be5df20a34d78d986ddfb6e0fc87e4fa4d05268b.zip | |
Merge tag 'drm-intel-next-2017-03-20' of git://anongit.freedesktop.org/git/drm-intel into drm-next
More in i915 for 4.12:
- designware i2c fixes from Hans de Goede, in a topic branch shared
with other subsystems (maybe, they didn't confirm, but requested the
pull)
- drop drm_panel usage from the intel dsi vbt panel (Jani)
- vblank evasion improvements and tracing (Maarten and Ville)
- clarify spinlock irq semantics again a bit (Tvrtko)
- new ->pwrite backend hook (right now just for shmem pageche writes),
from Chris
- more planar/ccs work from Ville
- hotplug safe connector iterators everywhere
- userptr fixes (Chris)
- selftests for cache coloring eviction (Matthew Auld)
- extend debugfs drop_caches interface for shrinker testing (Chris)
- baytrail "the rps kills the machine" fix (Chris)
- use new atomic state iterators, a lot (Maarten)
- refactor guc/huc code some (Arkadiusz Hiler)
- tighten breadcrumbs rbtree a bit (Chris)
- improve wrap-around and time handling in rps residency counters
(Mika)
- split reset-in-progress in two flags, backoff and handoff (Chris)
- other misc reset improvements from a few people
- bunch of vgpu interaction fixes with recent code changes
- misc stuff all over, as usual
* tag 'drm-intel-next-2017-03-20' of git://anongit.freedesktop.org/git/drm-intel: (144 commits)
drm/i915: Update DRIVER_DATE to 20170320
drm/i915: Initialise i915_gem_object_create_from_data() directly
drm/i915: Correct error handling for i915_gem_object_create_from_data()
drm/i915: i915_gem_object_create_from_data() doesn't require struct_mutex
drm/i915: Retire an active batch pool object rather than allocate new
drm/i915: Add i810/i815 pci-ids for completeness
drm/i915: Skip execlists_dequeue() early if the list is empty
drm/i915: Stop using obj->obj_exec_link outside of execbuf
drm/i915: Squelch WARN for VLV_COUNTER_CONTROL
drm/i915/glk: Enable pooled EUs for Geminilake
drm/i915: Remove superfluous i915_add_request_no_flush() helper
drm/i915/vgpu: Neuter forcewakes for VGPU more thoroughly
drm/i915: Fix vGPU balloon for ggtt guard page
drm/i915: Avoid use-after-free of ctx in request tracepoints
drm/i915: Assert that the context pin_counts do not overflow
drm/i915: Wait for reset to complete before returning from debugfs/i915_wedged
drm/i915: Restore engine->submit_request before unwedging
drm/i915: Move engine->submit_request selection to a vfunc
drm/i915: Split I915_RESET_IN_PROGRESS into two flags
drm/i915: make context status notifier head be per engine
...
Diffstat (limited to 'drivers/gpu/drm')
63 files changed, 2416 insertions, 1797 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 1ae0bb91ee60..a5cd5dacf055 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -20,6 +20,7 @@ config DRM_I915 select ACPI_VIDEO if ACPI select ACPI_BUTTON if ACPI select SYNC_FILE + select IOSF_MBI help Choose this option if you have a system that has "Intel Graphics Media Accelerator" or "HD Graphics" integrated graphics, diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index b1b580337c7a..2cf04504e494 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -105,8 +105,8 @@ i915-y += dvo_ch7017.o \ intel_dp.o \ intel_dsi.o \ intel_dsi_dcs_backlight.o \ - intel_dsi_panel_vbt.o \ intel_dsi_pll.o \ + intel_dsi_vbt.o \ intel_dvo.o \ intel_hdmi.o \ intel_i2c.o \ diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index e227caf5859e..ce9ac1569cbc 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -160,7 +160,6 @@ struct intel_vgpu { atomic_t running_workload_num; DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); struct i915_gem_context *shadow_ctx; - struct notifier_block shadow_ctx_notifier_block; #if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT) struct { @@ -231,6 +230,7 @@ struct intel_gvt { struct intel_gvt_gtt gtt; struct intel_gvt_opregion opregion; struct intel_gvt_workload_scheduler scheduler; + struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES]; DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS); struct intel_vgpu_type *types; unsigned int num_types; diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index d6b6d0efdd1a..31d2240fdb1f 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -130,12 +130,10 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) static int shadow_context_status_change(struct notifier_block *nb, unsigned long action, void *data) { - struct intel_vgpu *vgpu = container_of(nb, - struct intel_vgpu, shadow_ctx_notifier_block); - struct drm_i915_gem_request *req = - (struct drm_i915_gem_request *)data; - struct intel_gvt_workload_scheduler *scheduler = - &vgpu->gvt->scheduler; + struct drm_i915_gem_request *req = (struct drm_i915_gem_request *)data; + struct intel_gvt *gvt = container_of(nb, struct intel_gvt, + shadow_ctx_notifier_block[req->engine->id]); + struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; struct intel_vgpu_workload *workload = scheduler->current_workload[req->engine->id]; @@ -214,7 +212,7 @@ out: workload->status = ret; if (!IS_ERR_OR_NULL(rq)) - i915_add_request_no_flush(rq); + i915_add_request(rq); mutex_unlock(&dev_priv->drm.struct_mutex); return ret; } @@ -493,15 +491,16 @@ void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu) void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt) { struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; - int i; + struct intel_engine_cs *engine; + enum intel_engine_id i; gvt_dbg_core("clean workload scheduler\n"); - for (i = 0; i < I915_NUM_ENGINES; i++) { - if (scheduler->thread[i]) { - kthread_stop(scheduler->thread[i]); - scheduler->thread[i] = NULL; - } + for_each_engine(engine, gvt->dev_priv, i) { + atomic_notifier_chain_unregister( + &engine->context_status_notifier, + &gvt->shadow_ctx_notifier_block[i]); + kthread_stop(scheduler->thread[i]); } } @@ -509,18 +508,15 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt) { struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; struct workload_thread_param *param = NULL; + struct intel_engine_cs *engine; + enum intel_engine_id i; int ret; - int i; gvt_dbg_core("init workload scheduler\n"); init_waitqueue_head(&scheduler->workload_complete_wq); - for (i = 0; i < I915_NUM_ENGINES; i++) { - /* check ring mask at init time */ - if (!HAS_ENGINE(gvt->dev_priv, i)) - continue; - + for_each_engine(engine, gvt->dev_priv, i) { init_waitqueue_head(&scheduler->waitq[i]); param = kzalloc(sizeof(*param), GFP_KERNEL); @@ -539,6 +535,11 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt) ret = PTR_ERR(scheduler->thread[i]); goto err; } + + gvt->shadow_ctx_notifier_block[i].notifier_call = + shadow_context_status_change; + atomic_notifier_chain_register(&engine->context_status_notifier, + &gvt->shadow_ctx_notifier_block[i]); } return 0; err: @@ -550,9 +551,6 @@ err: void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu) { - atomic_notifier_chain_unregister(&vgpu->shadow_ctx->status_notifier, - &vgpu->shadow_ctx_notifier_block); - i915_gem_context_put_unlocked(vgpu->shadow_ctx); } @@ -567,10 +565,5 @@ int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu) vgpu->shadow_ctx->engine[RCS].initialised = true; - vgpu->shadow_ctx_notifier_block.notifier_call = - shadow_context_status_change; - - atomic_notifier_chain_register(&vgpu->shadow_ctx->status_notifier, - &vgpu->shadow_ctx_notifier_block); return 0; } diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 21b1cd917d81..7af100f84410 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1279,11 +1279,17 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, * space. Parsing should be faster in some cases this way. */ batch_end = cmd + (batch_len / sizeof(*batch_end)); - while (cmd < batch_end) { + do { u32 length; - if (*cmd == MI_BATCH_BUFFER_END) + if (*cmd == MI_BATCH_BUFFER_END) { + if (needs_clflush_after) { + void *ptr = ptr_mask_bits(shadow_batch_obj->mm.mapping); + drm_clflush_virt_range(ptr, + (void *)(cmd + 1) - ptr); + } break; + } desc = find_cmd(engine, *cmd, desc, &default_desc); if (!desc) { @@ -1323,17 +1329,14 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, } cmd += length; - } - - if (cmd >= batch_end) { - DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); - ret = -EINVAL; - } + if (cmd >= batch_end) { + DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); + ret = -EINVAL; + break; + } + } while (1); - if (ret == 0 && needs_clflush_after) - drm_clflush_virt_range(shadow_batch_obj->mm.mapping, batch_len); i915_gem_object_unpin_map(shadow_batch_obj); - return ret; } diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index aa2d726b4349..47e707d83c4d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -27,7 +27,7 @@ */ #include <linux/debugfs.h> -#include <linux/list_sort.h> +#include <linux/sort.h> #include "intel_drv.h" static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node) @@ -204,13 +204,12 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) seq_printf(m, " (frontbuffer: 0x%03x)", frontbuffer_bits); } -static int obj_rank_by_stolen(void *priv, - struct list_head *A, struct list_head *B) +static int obj_rank_by_stolen(const void *A, const void *B) { - struct drm_i915_gem_object *a = - container_of(A, struct drm_i915_gem_object, obj_exec_link); - struct drm_i915_gem_object *b = - container_of(B, struct drm_i915_gem_object, obj_exec_link); + const struct drm_i915_gem_object *a = + *(const struct drm_i915_gem_object **)A; + const struct drm_i915_gem_object *b = + *(const struct drm_i915_gem_object **)B; if (a->stolen->start < b->stolen->start) return -1; @@ -223,49 +222,60 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_device *dev = &dev_priv->drm; + struct drm_i915_gem_object **objects; struct drm_i915_gem_object *obj; u64 total_obj_size, total_gtt_size; - LIST_HEAD(stolen); - int count, ret; + unsigned long total, count, n; + int ret; + + total = READ_ONCE(dev_priv->mm.object_count); + objects = drm_malloc_ab(total, sizeof(*objects)); + if (!objects) + return -ENOMEM; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) - return ret; + goto out; total_obj_size = total_gtt_size = count = 0; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { + if (count == total) + break; + if (obj->stolen == NULL) continue; - list_add(&obj->obj_exec_link, &stolen); - + objects[count++] = obj; total_obj_size += obj->base.size; total_gtt_size += i915_gem_obj_total_ggtt_size(obj); - count++; + } list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) { + if (count == total) + break; + if (obj->stolen == NULL) continue; - list_add(&obj->obj_exec_link, &stolen); - + objects[count++] = obj; total_obj_size += obj->base.size; - count++; } - list_sort(NULL, &stolen, obj_rank_by_stolen); + + sort(objects, count, sizeof(*objects), obj_rank_by_stolen, NULL); + seq_puts(m, "Stolen:\n"); - while (!list_empty(&stolen)) { - obj = list_first_entry(&stolen, typeof(*obj), obj_exec_link); + for (n = 0; n < count; n++) { seq_puts(m, " "); - describe_obj(m, obj); + describe_obj(m, objects[n]); seq_putc(m, '\n'); - list_del_init(&obj->obj_exec_link); } - mutex_unlock(&dev->struct_mutex); - - seq_printf(m, "Total %d objects, %llu bytes, %llu GTT size\n", + seq_printf(m, "Total %lu objects, %llu bytes, %llu GTT size\n", count, total_obj_size, total_gtt_size); - return 0; + + mutex_unlock(&dev->struct_mutex); +out: + drm_free_large(objects); + return ret; } struct file_stats { @@ -1189,7 +1199,8 @@ static int i915_frequency_info(struct seq_file *m, void *unused) } seq_printf(m, "PM IER=0x%08x IMR=0x%08x ISR=0x%08x IIR=0x%08x, MASK=0x%08x\n", pm_ier, pm_imr, pm_isr, pm_iir, pm_mask); - seq_printf(m, "pm_intr_keep: 0x%08x\n", dev_priv->rps.pm_intr_keep); + seq_printf(m, "pm_intrmsk_mbz: 0x%08x\n", + dev_priv->rps.pm_intrmsk_mbz); seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); seq_printf(m, "Render p-state ratio: %d\n", (gt_perf_status & (IS_GEN9(dev_priv) ? 0x1ff00 : 0xff00)) >> 8); @@ -1304,16 +1315,18 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) enum intel_engine_id id; if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) - seq_printf(m, "Wedged\n"); - if (test_bit(I915_RESET_IN_PROGRESS, &dev_priv->gpu_error.flags)) - seq_printf(m, "Reset in progress\n"); + seq_puts(m, "Wedged\n"); + if (test_bit(I915_RESET_BACKOFF, &dev_priv->gpu_error.flags)) + seq_puts(m, "Reset in progress: struct_mutex backoff\n"); + if (test_bit(I915_RESET_HANDOFF, &dev_priv->gpu_error.flags)) + seq_puts(m, "Reset in progress: reset handoff to waiter\n"); if (waitqueue_active(&dev_priv->gpu_error.wait_queue)) - seq_printf(m, "Waiter holding struct mutex\n"); + seq_puts(m, "Waiter holding struct mutex\n"); if (waitqueue_active(&dev_priv->gpu_error.reset_queue)) - seq_printf(m, "struct_mutex blocked for reset\n"); + seq_puts(m, "struct_mutex blocked for reset\n"); if (!i915.enable_hangcheck) { - seq_printf(m, "Hangcheck disabled\n"); + seq_puts(m, "Hangcheck disabled\n"); return 0; } @@ -1393,14 +1406,10 @@ static int ironlake_drpc_info(struct seq_file *m) u32 rgvmodectl, rstdbyctl; u16 crstandvid; - intel_runtime_pm_get(dev_priv); - rgvmodectl = I915_READ(MEMMODECTL); rstdbyctl = I915_READ(RSTDBYCTL); crstandvid = I915_READ16(CRSTANDVID); - intel_runtime_pm_put(dev_priv); - seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN)); seq_printf(m, "Boost freq: %d\n", (rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >> @@ -1464,19 +1473,26 @@ static int i915_forcewake_domains(struct seq_file *m, void *data) return 0; } +static void print_rc6_res(struct seq_file *m, + const char *title, + const i915_reg_t reg) +{ + struct drm_i915_private *dev_priv = node_to_i915(m->private); + + seq_printf(m, "%s %u (%llu us)\n", + title, I915_READ(reg), + intel_rc6_residency_us(dev_priv, reg)); +} + static int vlv_drpc_info(struct seq_file *m) { struct drm_i915_private *dev_priv = node_to_i915(m->private); u32 rpmodectl1, rcctl1, pw_status; - intel_runtime_pm_get(dev_priv); - pw_status = I915_READ(VLV_GTLC_PW_STATUS); rpmodectl1 = I915_READ(GEN6_RP_CONTROL); rcctl1 = I915_READ(GEN6_RC_CONTROL); - intel_runtime_pm_put(dev_priv); - seq_printf(m, "Video Turbo Mode: %s\n", yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO)); seq_printf(m, "Turbo enabled: %s\n", @@ -1494,10 +1510,8 @@ static int vlv_drpc_info(struct seq_file *m) seq_printf(m, "Media Power Well: %s\n", (pw_status & VLV_GTLC_PW_MEDIA_STATUS_MASK) ? "Up" : "Down"); - seq_printf(m, "Render RC6 residency since boot: %u\n", - I915_READ(VLV_GT_RENDER_RC6)); - seq_printf(m, "Media RC6 residency since boot: %u\n", - I915_READ(VLV_GT_MEDIA_RC6)); + print_rc6_res(m, "Render RC6 residency since boot:", VLV_GT_RENDER_RC6); + print_rc6_res(m, "Media RC6 residency since boot:", VLV_GT_MEDIA_RC6); return i915_forcewake_domains(m, NULL); } @@ -1505,21 +1519,12 @@ static int vlv_drpc_info(struct seq_file *m) static int gen6_drpc_info(struct seq_file *m) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; u32 rpmodectl1, gt_core_status, rcctl1, rc6vids = 0; u32 gen9_powergate_enable = 0, gen9_powergate_status = 0; unsigned forcewake_count; - int count = 0, ret; - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - intel_runtime_pm_get(dev_priv); - - spin_lock_irq(&dev_priv->uncore.lock); - forcewake_count = dev_priv->uncore.fw_domain[FW_DOMAIN_ID_RENDER].wake_count; - spin_unlock_irq(&dev_priv->uncore.lock); + int count = 0; + forcewake_count = READ_ONCE(dev_priv->uncore.fw_domain[FW_DOMAIN_ID_RENDER].wake_count); if (forcewake_count) { seq_puts(m, "RC information inaccurate because somebody " "holds a forcewake reference \n"); @@ -1539,13 +1544,11 @@ static int gen6_drpc_info(struct seq_file *m) gen9_powergate_enable = I915_READ(GEN9_PG_ENABLE); gen9_powergate_status = I915_READ(GEN9_PWRGT_DOMAIN_STATUS); } - mutex_unlock(&dev->struct_mutex); + mutex_lock(&dev_priv->rps.hw_lock); sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); mutex_unlock(&dev_priv->rps.hw_lock); - intel_runtime_pm_put(dev_priv); - seq_printf(m, "Video Turbo Mode: %s\n", yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO)); seq_printf(m, "HW control enabled: %s\n", @@ -1601,14 +1604,11 @@ static int gen6_drpc_info(struct seq_file *m) } /* Not exactly sure what this is */ - seq_printf(m, "RC6 \"Locked to RPn\" residency since boot: %u\n", - I915_READ(GEN6_GT_GFX_RC6_LOCKED)); - seq_printf(m, "RC6 residency since boot: %u\n", - I915_READ(GEN6_GT_GFX_RC6)); - seq_printf(m, "RC6+ residency since boot: %u\n", - I915_READ(GEN6_GT_GFX_RC6p)); - seq_printf(m, "RC6++ residency since boot: %u\n", - I915_READ(GEN6_GT_GFX_RC6pp)); + print_rc6_res(m, "RC6 \"Locked to RPn\" residency since boot:", + GEN6_GT_GFX_RC6_LOCKED); + print_rc6_res(m, "RC6 resid |
