From df0700e53047662c167836bd6fdeea55d5d8dcfa Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 Sep 2017 20:24:24 +0100 Subject: drm/i915: Disable snooping (userptr, set-cache-level) on gen4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original gen4 has an issue where writes (both render and blt) into snoopable pages are lost. We've previously worked around this in userspace (ddx, igt) by simply not requesting snoopable buffers, but upon rediscovering this problem for a third time, make the kernel reject such requests with -ENODEV. This disables snooping on userspace buffers for i965g and i965gm (original gen4) machines. Signed-off-by: Chris Wilson Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170906192424.26970-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_pci.c | 2 ++ drivers/gpu/drm/i915/intel_device_info.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 881b5d6708aa..e95baf3c4314 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -168,6 +168,7 @@ static const struct intel_device_info intel_i965g_info __initconst = { .platform = INTEL_I965G, .has_overlay = 1, .hws_needs_physical = 1, + .has_snoop = false, }; static const struct intel_device_info intel_i965gm_info __initconst = { @@ -177,6 +178,7 @@ static const struct intel_device_info intel_i965gm_info __initconst = { .has_overlay = 1, .supports_tv = 1, .hws_needs_physical = 1, + .has_snoop = false, }; static const struct intel_device_info intel_g45_info __initconst = { diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index b17f7045c8f8..43831b09b47a 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -412,8 +412,6 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) else if (INTEL_INFO(dev_priv)->gen >= 9) gen9_sseu_info_init(dev_priv); - WARN_ON(info->has_snoop != !info->has_llc); - DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask); DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); DRM_DEBUG_DRIVER("subslice total: %u\n", -- cgit v1.2.3 From 5602452e4c9943a81c9cd049d10d37d3f137b0c0 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 3 Aug 2017 10:14:17 +0100 Subject: drm/i915: Use __sg_alloc_table_from_pages for userptr allocations With the addition of __sg_alloc_table_from_pages we can control the maximum coalescing size and eliminate a separate path for allocating backing store here. Similar to 871dfbd67d4e ("drm/i915: Allow compaction upto SWIOTLB max segment size") this enables more compact sg lists to be created and so has a beneficial effect on workloads with many and/or large objects of this class. v2: * Rename helper to i915_sg_segment_size and fix swiotlb override. * Commit message update. v3: * Actually include the swiotlb override fix. v4: * Regroup parameters a bit. (Chris Wilson) v5: * Rebase for swiotlb_max_segment. * Add DMA map failure handling as in abb0deacb5a6 ("drm/i915: Fallback to single PAGE_SIZE segments for DMA remapping"). v6: Handle swiotlb_max_segment() returning 1. (Joonas Lahtinen) v7: Rebase. v8: Commit spelling fix. Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Cc: linux-kernel@vger.kernel.org Reviewed-by: Chris Wilson Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170803091417.23677-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 15 +++++++ drivers/gpu/drm/i915/i915_gem.c | 6 +-- drivers/gpu/drm/i915/i915_gem_userptr.c | 79 ++++++++++++--------------------- 3 files changed, 45 insertions(+), 55 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c1aef3a1ceb9..2b08bbf608aa 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2828,6 +2828,21 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg) (((__iter).curr += PAGE_SIZE) < (__iter).max) || \ ((__iter) = __sgt_iter(__sg_next((__iter).sgp), false), 0)) +static inline unsigned int i915_sg_segment_size(void) +{ + unsigned int size = swiotlb_max_segment(); + + if (size == 0) + return SCATTERLIST_MAX_SEGMENT; + + size = rounddown(size, PAGE_SIZE); + /* swiotlb_max_segment_size can return 1 byte when it means one page. */ + if (size < PAGE_SIZE) + size = PAGE_SIZE; + + return size; +} + static inline const struct intel_device_info * intel_info(const struct drm_i915_private *dev_priv) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1545a4ef09c4..4dffebae5601 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2303,7 +2303,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) struct sgt_iter sgt_iter; struct page *page; unsigned long last_pfn = 0; /* suppress gcc warning */ - unsigned int max_segment; + unsigned int max_segment = i915_sg_segment_size(); gfp_t noreclaim; int ret; @@ -2314,10 +2314,6 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); - max_segment = swiotlb_max_segment(); - if (!max_segment) - max_segment = rounddown(UINT_MAX, PAGE_SIZE); - st = kmalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index f152a38d7079..2ce078e8c763 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -399,64 +399,42 @@ struct get_pages_work { struct task_struct *task; }; -#if IS_ENABLED(CONFIG_SWIOTLB) -#define swiotlb_active() swiotlb_nr_tbl() -#else -#define swiotlb_active() 0 -#endif - -static int -st_set_pages(struct sg_table **st, struct page **pvec, int num_pages) -{ - struct scatterlist *sg; - int ret, n; - - *st = kmalloc(sizeof(**st), GFP_KERNEL); - if (*st == NULL) - return -ENOMEM; - - if (swiotlb_active()) { - ret = sg_alloc_table(*st, num_pages, GFP_KERNEL); - if (ret) - goto err; - - for_each_sg((*st)->sgl, sg, num_pages, n) - sg_set_page(sg, pvec[n], PAGE_SIZE, 0); - } else { - ret = sg_alloc_table_from_pages(*st, pvec, num_pages, - 0, num_pages << PAGE_SHIFT, - GFP_KERNEL); - if (ret) - goto err; - } - - return 0; - -err: - kfree(*st); - *st = NULL; - return ret; -} - static struct sg_table * -__i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj, - struct page **pvec, int num_pages) +__i915_gem_userptr_alloc_pages(struct drm_i915_gem_object *obj, + struct page **pvec, int num_pages) { - struct sg_table *pages; + unsigned int max_segment = i915_sg_segment_size(); + struct sg_table *st; int ret; - ret = st_set_pages(&pages, pvec, num_pages); - if (ret) + st = kmalloc(sizeof(*st), GFP_KERNEL); + if (!st) + return ERR_PTR(-ENOMEM); + +alloc_table: + ret = __sg_alloc_table_from_pages(st, pvec, num_pages, + 0, num_pages << PAGE_SHIFT, + max_segment, + GFP_KERNEL); + if (ret) { + kfree(st); return ERR_PTR(ret); + } - ret = i915_gem_gtt_prepare_pages(obj, pages); + ret = i915_gem_gtt_prepare_pages(obj, st); if (ret) { - sg_free_table(pages); - kfree(pages); + sg_free_table(st); + + if (max_segment > PAGE_SIZE) { + max_segment = PAGE_SIZE; + goto alloc_table; + } + + kfree(st); return ERR_PTR(ret); } - return pages; + return st; } static int @@ -540,7 +518,8 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) struct sg_table *pages = ERR_PTR(ret); if (pinned == npages) { - pages = __i915_gem_userptr_set_pages(obj, pvec, npages); + pages = __i915_gem_userptr_alloc_pages(obj, pvec, + npages); if (!IS_ERR(pages)) { __i915_gem_object_set_pages(obj, pages); pinned = 0; @@ -661,7 +640,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) pages = __i915_gem_userptr_get_pages_schedule(obj); active = pages == ERR_PTR(-EAGAIN); } else { - pages = __i915_gem_userptr_set_pages(obj, pvec, num_pages); + pages = __i915_gem_userptr_alloc_pages(obj, pvec, num_pages); active = !IS_ERR(pages); } if (active) -- cgit v1.2.3 From 0b4d7cbff2be27c89617e1ca60a546019f7ff276 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 17 Aug 2017 19:15:22 +0530 Subject: drm/i915: Fixed point fixed16 wrapper cleanup As per suggestion from Jani, cleanup the code. Cleanup includes - Instead of left shifting & check, compare with U32/16_MAX - Use typecast instead of clamp_t Signed-off-by: Mahesh Kumar Cc: Jani Nikula Reviewed-by: Jani Nikula Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170817134529.2839-2-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2b08bbf608aa..2f12373d2f54 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -126,7 +126,7 @@ static inline uint_fixed_16_16_t u32_to_fixed16(uint32_t val) { uint_fixed_16_16_t fp; - WARN_ON(val >> 16); + WARN_ON(val > U16_MAX); fp.val = val << 16; return fp; @@ -163,8 +163,8 @@ static inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1, static inline uint_fixed_16_16_t clamp_u64_to_fixed16(uint64_t val) { uint_fixed_16_16_t fp; - WARN_ON(val >> 32); - fp.val = clamp_t(uint32_t, val, 0, ~0); + WARN_ON(val > U32_MAX); + fp.val = (uint32_t) val; return fp; } @@ -181,8 +181,8 @@ static inline uint32_t mul_round_up_u32_fixed16(uint32_t val, intermediate_val = (uint64_t) val * mul.val; intermediate_val = DIV_ROUND_UP_ULL(intermediate_val, 1 << 16); - WARN_ON(intermediate_val >> 32); - return clamp_t(uint32_t, intermediate_val, 0, ~0); + WARN_ON(intermediate_val > U32_MAX); + return (uint32_t) intermediate_val; } static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val, @@ -211,8 +211,8 @@ static inline uint32_t div_round_up_u32_fixed16(uint32_t val, interm_val = (uint64_t)val << 16; interm_val = DIV_ROUND_UP_ULL(interm_val, d.val); - WARN_ON(interm_val >> 32); - return clamp_t(uint32_t, interm_val, 0, ~0); + WARN_ON(interm_val > U32_MAX); + return (uint32_t) interm_val; } static inline uint_fixed_16_16_t mul_u32_fixed16(uint32_t val, -- cgit v1.2.3 From 7e452fdbfca85cd279ecb0d8e9ab6fdd1e8c97fc Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 17 Aug 2017 19:15:23 +0530 Subject: drm/i915/skl+: Optimize WM calculation Plane configuration parameters doesn't change for each WM-level calculation. Currently we compute same parameters 8 times for each wm-level. This patch optimizes it by calculating these parameters in beginning & reuse during each level-wm calculation. Changes since V1: - rebase on top of Rodrigo's series for CNL Signed-off-by: Mahesh Kumar Acked-by: Maarten Lankhorst Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170817134529.2839-3-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 14 +++ drivers/gpu/drm/i915/intel_pm.c | 190 ++++++++++++++++++++++------------------ 2 files changed, 119 insertions(+), 85 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2f12373d2f54..0df2b0f620f7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1837,6 +1837,20 @@ struct skl_wm_level { uint8_t plane_res_l; }; +/* Stores plane specific WM parameters */ +struct skl_wm_params { + bool x_tiled, y_tiled; + bool rc_surface; + uint32_t width; + uint8_t cpp; + uint32_t plane_pixel_rate; + uint32_t y_min_scanlines; + uint32_t plane_bytes_per_line; + uint_fixed_16_16_t plane_blocks_per_line; + uint_fixed_16_16_t y_tile_minimum; + uint32_t linetime_us; +}; + /* * This struct helps tracking the state needed for runtime PM, which puts the * device in PCI D3 state. Notice that when this happens, nothing on the diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0201816a4229..2dd3af3debe9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4376,134 +4376,146 @@ skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cstate, downscale_amount); } -static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, - struct intel_crtc_state *cstate, - const struct intel_plane_state *intel_pstate, - uint16_t ddb_allocation, - int level, - uint16_t *out_blocks, /* out */ - uint8_t *out_lines, /* out */ - bool *enabled /* out */) +static int +skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, + struct intel_crtc_state *cstate, + const struct intel_plane_state *intel_pstate, + struct skl_wm_params *wp) { struct intel_plane *plane = to_intel_plane(intel_pstate->base.plane); const struct drm_plane_state *pstate = &intel_pstate->base; const struct drm_framebuffer *fb = pstate->fb; - uint32_t latency = dev_priv->wm.skl_latency[level]; - uint_fixed_16_16_t method1, method2; - uint_fixed_16_16_t plane_blocks_per_line; - uint_fixed_16_16_t selected_result; uint32_t interm_pbpl; - uint32_t plane_bytes_per_line; - uint32_t res_blocks, res_lines; - uint8_t cpp; - uint32_t width = 0; - uint32_t plane_pixel_rate; - uint_fixed_16_16_t y_tile_minimum; - uint32_t y_min_scanlines; struct intel_atomic_state *state = to_intel_atomic_state(cstate->base.state); bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state); - bool y_tiled, x_tiled; - if (latency == 0 || - !intel_wm_plane_visible(cstate, intel_pstate)) { - *enabled = false; + if (!intel_wm_plane_visible(cstate, intel_pstate)) return 0; - } - y_tiled = fb->modifier == I915_FORMAT_MOD_Y_TILED || - fb->modifier == I915_FORMAT_MOD_Yf_TILED || - fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || - fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; - x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED; - - /* Display WA #1141: kbl,cfl */ - if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && - dev_priv->ipc_enabled) - latency += 4; - - if (apply_memory_bw_wa && x_tiled) - latency += 15; + wp->y_tiled = fb->modifier == I915_FORMAT_MOD_Y_TILED || + fb->modifier == I915_FORMAT_MOD_Yf_TILED || + fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || + fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; + wp->x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED; + wp->rc_surface = fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || + fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; if (plane->id == PLANE_CURSOR) { - width = intel_pstate->base.crtc_w; + wp->width = intel_pstate->base.crtc_w; } else { /* * Src coordinates are already rotated by 270 degrees for * the 90/270 degree plane rotation cases (to match the * GTT mapping), hence no need to account for rotation here. */ - width = drm_rect_width(&intel_pstate->base.src) >> 16; + wp->width = drm_rect_width(&intel_pstate->base.src) >> 16; } - cpp = (fb->format->format == DRM_FORMAT_NV12) ? fb->format->cpp[1] : - fb->format->cpp[0]; - plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); + wp->cpp = (fb->format->format == DRM_FORMAT_NV12) ? fb->format->cpp[1] : + fb->format->cpp[0]; + wp->plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, + intel_pstate); if (drm_rotation_90_or_270(pstate->rotation)) { - switch (cpp) { + switch (wp->cpp) { case 1: - y_min_scanlines = 16; + wp->y_min_scanlines = 16; break; case 2: - y_min_scanlines = 8; + wp->y_min_scanlines = 8; break; case 4: - y_min_scanlines = 4; + wp->y_min_scanlines = 4; break; default: - MISSING_CASE(cpp); + MISSING_CASE(wp->cpp); return -EINVAL; } } else { - y_min_scanlines = 4; + wp->y_min_scanlines = 4; } if (apply_memory_bw_wa) - y_min_scanlines *= 2; + wp->y_min_scanlines *= 2; - plane_bytes_per_line = width * cpp; - if (y_tiled) { - interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line * - y_min_scanlines, 512); + wp->plane_bytes_per_line = wp->width * wp->cpp; + if (wp->y_tiled) { + interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line * + wp->y_min_scanlines, 512); if (INTEL_GEN(dev_priv) >= 10) interm_pbpl++; - plane_blocks_per_line = div_fixed16(interm_pbpl, - y_min_scanlines); - } else if (x_tiled && INTEL_GEN(dev_priv) == 9) { - interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line, 512); - plane_blocks_per_line = u32_to_fixed16(interm_pbpl); + wp->plane_blocks_per_line = div_fixed16(interm_pbpl, + wp->y_min_scanlines); + } else if (wp->x_tiled && IS_GEN9(dev_priv)) { + interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line, 512); + wp->plane_blocks_per_line = u32_to_fixed16(interm_pbpl); } else { - interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; - plane_blocks_per_line = u32_to_fixed16(interm_pbpl); + interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line, 512) + 1; + wp->plane_blocks_per_line = u32_to_fixed16(interm_pbpl); } - method1 = skl_wm_method1(dev_priv, plane_pixel_rate, cpp, latency); - method2 = skl_wm_method2(plane_pixel_rate, + wp->y_tile_minimum = mul_u32_fixed16(wp->y_min_scanlines, + wp->plane_blocks_per_line); + wp->linetime_us = fixed16_to_u32_round_up( + intel_get_linetime_us(cstate)); + + return 0; +} + +static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + struct intel_crtc_state *cstate, + const struct intel_plane_state *intel_pstate, + uint16_t ddb_allocation, + int level, + const struct skl_wm_params *wp, + uint16_t *out_blocks, /* out */ + uint8_t *out_lines, /* out */ + bool *enabled /* out */) +{ + const struct drm_plane_state *pstate = &intel_pstate->base; + uint32_t latency = dev_priv->wm.skl_latency[level]; + uint_fixed_16_16_t method1, method2; + uint_fixed_16_16_t selected_result; + uint32_t res_blocks, res_lines; + struct intel_atomic_state *state = + to_intel_atomic_state(cstate->base.state); + bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state); + + if (latency == 0 || + !intel_wm_plane_visible(cstate, intel_pstate)) { + *enabled = false; + return 0; + } + + /* Display WA #1141: kbl,cfl */ + if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && + dev_priv->ipc_enabled) + latency += 4; + + if (apply_memory_bw_wa && wp->x_tiled) + latency += 15; + + method1 = skl_wm_method1(dev_priv, wp->plane_pixel_rate, + wp->cpp, latency); + method2 = skl_wm_method2(wp->plane_pixel_rate, cstate->base.adjusted_mode.crtc_htotal, latency, - plane_blocks_per_line); - - y_tile_minimum = mul_u32_fixed16(y_min_scanlines, - plane_blocks_per_line); + wp->plane_blocks_per_line); - if (y_tiled) { - selected_result = max_fixed16(method2, y_tile_minimum); + if (wp->y_tiled) { + selected_result = max_fixed16(method2, wp->y_tile_minimum); } else { - uint32_t linetime_us; - - linetime_us = fixed16_to_u32_round_up( - intel_get_linetime_us(cstate)); - if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) && - (plane_bytes_per_line / 512 < 1)) + if ((wp->cpp * cstate->base.adjusted_mode.crtc_htotal / + 512 < 1) && (wp->plane_bytes_per_line / 512 < 1)) selected_result = method2; else if (ddb_allocation >= - fixed16_to_u32_round_up(plane_blocks_per_line)) + fixed16_to_u32_round_up(wp->plane_blocks_per_line)) selected_result = min_fixed16(method1, method2); - else if (latency >= linetime_us) + else if (latency >= wp->linetime_us) selected_result = min_fixed16(method1, method2); else selected_result = method1; @@ -4511,19 +4523,18 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, res_blocks = fixed16_to_u32_round_up(selected_result) + 1; res_lines = div_round_up_fixed16(selected_result, - plane_blocks_per_line); + wp->plane_blocks_per_line); /* Display WA #1125: skl,bxt,kbl,glk */ - if (level == 0 && - (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || - fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) - res_blocks += fixed16_to_u32_round_up(y_tile_minimum); + if (level == 0 && wp->rc_surface) + res_blocks += fixed16_to_u32_round_up(wp->y_tile_minimum); /* Display WA #1126: skl,bxt,kbl,glk */ if (level >= 1 && level <= 7) { - if (y_tiled) { - res_blocks += fixed16_to_u32_round_up(y_tile_minimum); - res_lines += y_min_scanlines; + if (wp->y_tiled) { + res_blocks += fixed16_to_u32_round_up( + wp->y_tile_minimum); + res_lines += wp->y_min_scanlines; } else { res_blocks++; } @@ -4561,6 +4572,7 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb, struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate, + const struct skl_wm_params *wm_params, struct skl_plane_wm *wm) { struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); @@ -4584,6 +4596,7 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, intel_pstate, ddb_blocks, level, + wm_params, &result->plane_res_b, &result->plane_res_l, &result->plane_en); @@ -4648,11 +4661,18 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); enum plane_id plane_id = to_intel_plane(plane)->id; + struct skl_wm_params wm_params; wm = &pipe_wm->planes[plane_id]; + memset(&wm_params, 0, sizeof(struct skl_wm_params)); + + ret = skl_compute_plane_wm_params(dev_priv, cstate, + intel_pstate, &wm_params); + if (ret) + return ret; ret = skl_compute_wm_levels(dev_priv, ddb, cstate, - intel_pstate, wm); + intel_pstate, &wm_params, wm); if (ret) return ret; skl_compute_transition_wm(cstate, &wm->trans_wm); -- cgit v1.2.3 From ca47667f523e588318f89c735e127c256de6cb16 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 17 Aug 2017 19:15:24 +0530 Subject: drm/i915/gen10: Calculate and enable transition WM GEN > 9 require transition WM to be programmed if IPC is enabled. This patch calculates & enable transition WM for supported platforms. If transition WM is enabled, Plane read requests are sent at high priority until filling above the transition watermark, then the requests are sent at lower priority until dropping below the level-0 WM. The lower priority requests allow other memory clients to have better memory access. transition minimum is the minimum amount needed for trans_wm to work to ensure the demote does not happen before enough data has been read to meet the level 0 watermark requirements. transition amount is configurable value. Higher values will tend to cause longer periods of high priority reads followed by longer periods of lower priority reads. Tuning to lower values will tend to cause shorter periods of high and lower priority reads. Keeping transition amount to 10 in this patch, as suggested by HW team. Changes since V1: - Address review comments from Maarten Signed-off-by: Mahesh Kumar Acked-by: Maarten Lankhorst Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170817134529.2839-4-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 52 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2dd3af3debe9..3168a5577773 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4630,12 +4630,56 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) } static void skl_compute_transition_wm(struct intel_crtc_state *cstate, + struct skl_wm_params *wp, + struct skl_wm_level *wm_l0, + uint16_t ddb_allocation, struct skl_wm_level *trans_wm /* out */) { + struct drm_device *dev = cstate->base.crtc->dev; + const struct drm_i915_private *dev_priv = to_i915(dev); + uint16_t trans_min, trans_y_tile_min; + const uint16_t trans_amount = 10; /* This is configurable amount */ + uint16_t trans_offset_b, res_blocks; + if (!cstate->base.active) + goto exit; + + /* Transition WM are not recommended by HW team for GEN9 */ + if (INTEL_GEN(dev_priv) <= 9) + goto exit; + + /* Transition WM don't make any sense if ipc is disabled */ + if (!dev_priv->ipc_enabled) + goto exit; + + if (INTEL_GEN(dev_priv) >= 10) + trans_min = 4; + + trans_offset_b = trans_min + trans_amount; + + if (wp->y_tiled) { + trans_y_tile_min = (uint16_t) mul_round_up_u32_fixed16(2, + wp->y_tile_minimum); + res_blocks = max(wm_l0->plane_res_b, trans_y_tile_min) + + trans_offset_b; + } else { + res_blocks = wm_l0->plane_res_b + trans_offset_b; + + /* WA BUG:1938466 add one block for non y-tile planes */ + if (IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_A0)) + res_blocks += 1; + + } + + res_blocks += 1; + + if (res_blocks < ddb_allocation) { + trans_wm->plane_res_b = res_blocks; + trans_wm->plane_en = true; return; + } - /* Until we know more, just disable transition WMs */ +exit: trans_wm->plane_en = false; } @@ -4662,8 +4706,11 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, to_intel_plane_state(pstate); enum plane_id plane_id = to_intel_plane(plane)->id; struct skl_wm_params wm_params; + enum pipe pipe = to_intel_crtc(cstate->base.crtc)->pipe; + uint16_t ddb_blocks; wm = &pipe_wm->planes[plane_id]; + ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]); memset(&wm_params, 0, sizeof(struct skl_wm_params)); ret = skl_compute_plane_wm_params(dev_priv, cstate, @@ -4675,7 +4722,8 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, intel_pstate, &wm_params, wm); if (ret) return ret; - skl_compute_transition_wm(cstate, &wm->trans_wm); + skl_compute_transition_wm(cstate, &wm_params, &wm->wm[0], + ddb_blocks, &wm->trans_wm); } pipe_wm->linetime = skl_compute_linetime_wm(cstate); -- cgit v1.2.3 From 446e850c38d9092688df3f1e5d610f3bff2a4152 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 17 Aug 2017 19:15:25 +0530 Subject: drm/i915/glk: IPC linetime watermark workaround for GLK IF IPC is enabled LINETIME_WM value should be half of calculated value line time = ROUNDDOWN(1/2 * Calculated Line Time) Earlier code was rounding-up the value, But updated Bspec says we should take the ROUNDDOWN. This patch corrects that as well. Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170817134529.2839-5-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3168a5577773..629ad54e2797 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4622,9 +4622,10 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) linetime_wm = fixed16_to_u32_round_up(mul_u32_fixed16(8, linetime_us)); - /* Display WA #1135: bxt. */ - if (IS_BROXTON(dev_priv) && dev_priv->ipc_enabled) - linetime_wm = DIV_ROUND_UP(linetime_wm, 2); + /* Display WA #1135: bxt:ALL GLK:ALL */ + if ((IS_BROXTON(dev_priv) || IS_GEMINILAKE(dev_priv)) && + dev_priv->ipc_enabled) + linetime_wm /= 2; return linetime_wm; } -- cgit v1.2.3 From d86ba628ce4bfd83c987e4dab9d917cbb3622854 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 17 Aug 2017 19:15:26 +0530 Subject: drm/i915/cnl: Extend WM workaround with IPC for CNL CNL:A & CNL:B have same workaround as KBL to increase wm level latency by 4us if IPC is enabled. Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170817134529.2839-6-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 629ad54e2797..f2911de69ea9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4492,7 +4492,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, } /* Display WA #1141: kbl,cfl */ - if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && + if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || + IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_B0)) && dev_priv->ipc_enabled) latency += 4; -- cgit v1.2.3 From e57f1c02155f4f108b9d3ba2bed687e8e9f95e18 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Thu, 17 Aug 2017 19:15:27 +0530 Subject: drm/i915/gen9+: Add has_ipc flag in device info structure New Isochronous Priority Control (IPC) capability is introduced in newer GEN platforms. This patch adds a device info flag to indicate if platform supports IPC. Patch also sets this flag in supported platforms. Signed-off-by: Mahesh Kumar Cc: Chris Wilson Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170817134529.2839-7-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 5 ++++- drivers/gpu/drm/i915/i915_pci.c | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0df2b0f620f7..63ca2ffcafef 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -798,7 +798,8 @@ struct intel_csr { func(cursor_needs_physical); \ func(hws_needs_physical); \ func(overlay_needs_physical); \ - func(supports_tv); + func(supports_tv); \ + func(has_ipc); struct sseu_dev_info { u8 slice_mask; @@ -3119,6 +3120,8 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm) #define HAS_64BIT_RELOC(dev_priv) ((dev_priv)->info.has_64bit_reloc) +#define HAS_IPC(dev_priv) ((dev_priv)->info.has_ipc) + /* * For now, anything with a GuC requires uCode loading, and then supports * command submission once loaded. But these are logically independent diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index e95baf3c4314..129877b94c20 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -482,6 +482,7 @@ static const struct intel_device_info intel_skylake_gt4_info __initconst = { .has_full_48bit_ppgtt = 1, \ .has_reset_engine = 1, \ .has_snoop = true, \ + .has_ipc = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS, \ BDW_COLORS @@ -505,6 +506,7 @@ static const struct intel_device_info intel_geminilake_info __initconst = { .platform = INTEL_KABYLAKE, \ .has_csr = 1, \ .has_guc = 1, \ + .has_ipc = 1, \ .ddb_size = 896 static const struct intel_device_info intel_kabylake_gt1_info __initconst = { @@ -530,6 +532,7 @@ static const struct intel_device_info intel_kabylake_gt3_info __initconst = { .platform = INTEL_COFFEELAKE, \ .has_csr = 1, \ .has_guc = 1, \ + .has_ipc = 1, \ .ddb_size = 896 static const struct intel_device_info intel_coffeelake_gt1_info __initconst = { @@ -556,6 +559,7 @@ static const struct intel_device_info intel_cannonlake_gt2_info __initconst = { .gt = 2, .ddb_size = 1024, .has_csr = 1, + .has_ipc = 1, .color = { .degamma_lut_size = 0, .gamma_lut_size = 1024 } }; -- cgit v1.2.3 From 2503a0fef214ddadfdf5844d62453591de35586f Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 17 Aug 2017 19:15:28 +0530 Subject: drm/i915/bxt+: Enable IPC support This patch adds IPC support. This patch also enables IPC in all supported platforms based on has_ipc flag. IPC (Isochronous Priority Control) is the hardware feature, which dynamically controls the memory read priority of Display. When IPC is enabled, plane read requests are sent at high priority until filling above the transition watermark, then the requests are sent at lower priority until dropping below the level 0 watermark. The lower priority requests allow other memory clients to have better memory access. When IPC is disabled, all plane read requests are sent at high priority. Changes since V1: - Remove commandline parameter to disable ipc - Address Paulo's comments Changes since V2: - Address review comments - Set ipc_enabled flag Changes since V3: - move ipc_enabled flag assignment inside intel_ipc_enable function Changes since V4: - Re-enable IPC after suspend/resume Changes since V5: - Enable IPC for all gen >=9 except SKL Changes since V6: - fix commit msg - after resume program IPC based on SW state. Changes since V7: - Modify IPC support check based on HAS_IPC macro (suggested by Chris) Signed-off-by: Mahesh Kumar Cc: Chris Wilson Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170817134529.2839-8-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 4 +++- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 24 ++++++++++++++++++++++++ 5 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ff70fc45ba7c..5c111ea96e80 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1341,7 +1341,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) intel_runtime_pm_enable(dev_priv); - dev_priv->ipc_enabled = false; + intel_init_ipc(dev_priv); if (IS_ENABLED(CONFIG_DRM_I915_DEBUG)) DRM_INFO("DRM_I915_DEBUG enabled\n"); @@ -2609,6 +2609,8 @@ static int intel_runtime_resume(struct device *kdev) if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) intel_hpd_init(dev_priv); + intel_enable_ipc(dev_priv); + enable_rpm_wakeref_asserts(dev_priv); if (ret) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2eff98cdcfad..9a73ea0a3293 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6949,6 +6949,7 @@ enum { #define DISP_FBC_WM_DIS (1<<15) #define DISP_ARB_CTL2 _MMIO(0x45004) #define DISP_DATA_PARTITION_5_6 (1<<6) +#define DISP_IPC_ENABLE (1<<3) #define DBUF_CTL _MMIO(0x45008) #define DBUF_POWER_REQUEST (1<<31) #define DBUF_POWER_STATE (1<<30) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5291e08f3436..844efd45fed3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15255,6 +15255,7 @@ void intel_display_resume(struct drm_device *dev) if (!ret) ret = __intel_display_resume(dev, state, &ctx); + intel_enable_ipc(dev_priv); drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 463ed152e6b1..307807672896 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1898,6 +1898,8 @@ bool ilk_disable_lp_wm(struct drm_device *dev); int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6); int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, struct intel_crtc_state *cstate); +void intel_init_ipc(struct drm_i915_private *dev_priv); +void intel_enable_ipc(struct drm_i915_private *dev_priv); static inline int intel_enable_rc6(void) { return i915.enable_rc6; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f2911de69ea9..fa9055a4f790 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5824,6 +5824,30 @@ void intel_update_watermarks(struct intel_crtc *crtc) dev_priv->display.update_wm(crtc); } +void intel_enable_ipc(struct drm_i915_private *dev_priv) +{ + u32 val; + + val = I915_READ(DISP_ARB_CTL2); + + if (dev_priv->ipc_enabled) + val |= DISP_IPC_ENABLE; + else + val &= ~DISP_IPC_ENABLE; + + I915_WRITE(DISP_ARB_CTL2, val); +} + +void intel_init_ipc(struct drm_i915_private *dev_priv) +{ + dev_priv->ipc_enabled = false; + if (!HAS_IPC(dev_priv)) + return; + + dev_priv->ipc_enabled = true; + intel_enable_ipc(dev_priv); +} + /* * Lock protecting IPS related data structures */ -- cgit v1.2.3 From d2d4f39b1e6407323e568c174e17b022b8f98a40 Mon Sep 17 00:00:00 2001 From: "Kumar, Mahesh" Date: Thu, 17 Aug 2017 19:15:29 +0530 Subject: drm/i915/skl+: debugfs entry to control IPC This patch creates an entry in debugfs to check the status of IPC. This can also be used to enable/disable IPC in supported platforms. Changes since V1: - fix use of HAS_IPC - use kstrtobool_from_user (Maarten) - drm_info log, while enabling IPC (Maarten) Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20170817134529.2839-9-mahesh1.kumar@intel.com [mlankhorst: enableddisabled -> yesno to match ipc write] --- drivers/gpu/drm/i915/i915_debugfs.c | 54 ++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 48572b157222..8d432e50a196 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3522,6 +3522,57 @@ static int i915_wa_registers(struct seq_file *m, void *unused) return 0; } +static int i915_ipc_status_show(struct seq_file *m, void *data) +{ + struct drm_i915_private *dev_priv = m->private; + + seq_printf(m, "Isochronous Priority Control: %s\n", + yesno(dev_priv->ipc_enabled)); + return 0; +} + +static int i915_ipc_status_open(struct inode *inode, struct file *file) +{ + struct drm_i915_private *dev_priv = inode->i_private; + + if (!HAS_IPC(dev_priv)) + return -ENODEV; + + return single_open(file, i915_ipc_status_show, dev_priv); +} + +static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct drm_i915_private *dev_priv = m->private; + int ret; + bool enable; + + ret = kstrtobool_from_user(ubuf, len, &enable); + if (ret < 0) + return ret; + + intel_runtime_pm_get(dev_priv); + if (!dev_priv->ipc_enabled && enable) + DRM_INFO("Enabling IPC: WM will be proper only after next commit\n"); + dev_priv->wm.distrust_bios_wm = true; + dev_priv->ipc_enabled = enable; + intel_enable_ipc(dev_priv); + intel_runtime_pm_put(dev_priv); + + return len; +} + +static const struct file_operations i915_ipc_status_fops = { + .owner = THIS_MODULE, + .open = i915_ipc_status_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = i915_ipc_status_write +}; + static int i915_ddb_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -4858,7 +4909,8 @@ static const struct i915_debugfs_files { {"i915_dp_test_type", &i915_displayport_test_type_fops}, {"i915_dp_test_active", &i915_displayport_test_active_fops}, {"i915_guc_log_control", &i915_guc_log_control_fops}, - {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops} + {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}, + {"i915_ipc_status", &i915_ipc_status_fops} }; int i915_debugfs_register(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From d7a133d886b45651e36e7065998b1413d379ac1f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Sep 2017 14:44:41 +0100 Subject: drm/i915: Disable mmio debugging during user access If the user bypasses i915 and accesses mmio directly, that easily confuses our automatic mmio debugging (any error we then detect is likely to be as a result of the user). Since we expect userspace to open debugfs/i915_forcewake_user if i915.ko is loaded and they want mmio access, that makes the opportune time to disable our debugging for duration of the bypass. v2: Move the fiddling of uncore internals to uncore.c References: https://bugs.freedesktop.org/show_bug.cgi?id=102543 Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20170907134441.12881-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 19 ++++++++------ drivers/gpu/drm/i915/intel_uncore.c | 51 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_uncore.h | 10 ++++++++ 3 files changed, 72 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8d432e50a196..6338018f655d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1421,6 +1421,9 @@ static int i915_forcewake_domains(struct seq_file *m, void *data) struct intel_uncore_forcewake_domain *fw_domain; unsigned int tmp; + seq_printf(m, "user.bypass_count = %u\n", + i915->uncore.user_forcewake.count); + for_each_fw_domain(fw_domain, i915, tmp) seq_printf(m, "%s.wake_count = %u\n", intel_uncore_forcewake_domain_to_str(fw_domain->id), @@ -4724,26 +4727,26 @@ static int i915_sseu_status(struct seq_file *m, void *unused) static int i915_forcewake_open(struct inode *inode, struct file *file) { - struct drm_i915_private *dev_priv = inode->i_private; + struct drm_i915_private *i915 = inode->i_private; - if (INTEL_GEN(dev_priv) < 6) + if (INTEL_GEN(i915) < 6) return 0; - intel_runtime_pm_get(dev_priv); - intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + intel_runtime_pm_get(i915); + intel_uncore_forcewake_user_get(i915); return 0; } static int i915_forcewake_release(struct inode *inode, struct file *file) { - struct drm_i915_private *dev_priv = inode->i_private; + struct drm_i915_private *i915 = inode->i_private; - if (INTEL_GEN(dev_priv) < 6) + if (INTEL_GEN(i915) < 6) return 0; - intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); - intel_runtime_pm_put(dev_priv); + intel_uncore_forcewake_user_put(i915); + intel_runtime_pm_put(i915); return 0; } diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 0529af7cfbb8..1b38eb94d461 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -489,6 +489,57 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +/** + * intel_uncore_forcewake_user_get - claim forcewake on behalf of userspace + * @dev_priv: i915 device instance + * + * This function is a wrapper around intel_uncore_forcewake_get() to acquire + * the GT powerwell and in the process disable our debugging for the + * duration of userspace's bypass. + */ +void intel_uncore_forcewake_user_get(struct drm_i915_private *dev_priv) +{ + spin_lock_irq(&dev_priv->uncore.lock); + if (!dev_priv->uncore.user_forcewake.count++) { + intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); + + /* Save and disable mmio debugging for the user bypass */ + dev_priv->uncore.user_forcewake.saved_mmio_check = + dev_priv->uncore.unclaimed_mmio_check; + dev_priv->uncore.user_forcewake.saved_mmio_debug = + i915.mmio_debug; + + dev_priv->uncore.unclaimed_mmio_check = 0; + i915.mmio_debug = 0; + } + spin_unlock_irq(&dev_priv->uncore.lock); +} + +/** + * intel_uncore_forcewake_user_put - release forcewake on behalf of userspace + * @dev_priv: i915 device instance + * + * This function complements intel_uncore_forcewake_user_get() and releases + * the GT powerwell taken on behalf of the userspace bypass. + */ +void intel_uncore_forcewake_user_put(struct drm_i915_private *dev_priv) +{ + spin_lock_irq(&dev_priv->uncore.lock); + if (!--dev_priv->uncore.user_forcewake.count) { + if (intel_uncore_unclaimed_mmio(dev_priv)) + dev_info(dev_priv->drm.dev, + "Invalid mmio detected during user access\n"); + + dev_priv->uncore.unclaimed_mmio_check = + dev_priv->uncore.user_forcewake.saved_mmio_check; + i915.mmio_debug = + dev_priv->uncore.user_forcewake.saved_mmio_debug; + + intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); + } + spin_unlock_irq(&dev_priv->uncore.lock); +} + /** * intel_uncore_forcewake_get__locked - grab forcewake domain references * @dev_priv: i915 device instance diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index 5f90278da461..03786f931905 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -102,6 +102,13 @@ struct intel_uncore { i915_reg_t reg_ack; } fw_domain[FW_DOMAIN_ID_COUNT]; + struct { + unsigned int count; + + int saved_mmio_check; + int saved_mmio_debug; + } user_forcewake; + int unclaimed_mmio_check; }; @@ -144,6 +151,9 @@ void intel_uncore_forcewake_get__locked(struct drm_i915_private *dev_priv, void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv, enum forcewake_domains domains); +void intel_uncore_forcewake_user_get(struct drm_i915_private *dev_priv); +void intel_uncore_forcewake_user_put(struct drm_i915_private *dev_priv); + int intel_wait_for_register(struct drm_i915_private *dev_priv, i915_reg_t reg, u32 mask, -- cgit v1.2.3 From 750fae232480fee9d799eaced198ec98c20769a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 7 Sep 2017 17:32:03 +0300 Subject: i915: Fix obj size vs. alignment for drm_pci_alloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_pci_alloc() refuses to cooperate if the passed alignment exceeds the object size. So round up the obj size to the next power of two as well to make this actually work. Obviously things work just fine as long as the size was a power of two to begin with. However kms_cursor_crc doesn't always use power of two sizes so we hit a failure when we try to allocate the phys memory. Testcase: igt/kms_cursor_crc Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170907143203.13055-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4dffebae5601..822719fa1b52 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -179,7 +179,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) * the alignment of the buddy allocation will naturally match. */ phys = drm_pci_alloc(obj->base.dev, - obj->base.size, + roundup_pow_of_two(obj->base.size), roundup_pow_of_two(obj->base.size)); if (!phys) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From c5ba5b24657e473b1c64b0a614b168a635a2c935 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Sep 2017 19:45:20 +0100 Subject: drm/i915: Apply the GTT write flush for all !llc machines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We also see the delayed GTT write issue on i915g/i915gm, so let's presume that it is a universal problem for all !llc machines, and that we just haven't yet noticed on g33, gen4 and gen5 machines. v2: Use a register that exists on all platforms Testcase: igt/gem_mmap_gtt/coherency # i915gm References: https://bugs.freedesktop.org/show_bug.cgi?id=102577 Signed-off-by: Chris Wilson Cc: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170907184520.5032-1-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 822719fa1b52..f445587c1a4b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -694,10 +694,10 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) switch (obj->base.write_domain) { case I915_GEM_DOMAIN_GTT: - if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv)) { + if (!HAS_LLC(dev_priv)) { intel_runtime_pm_get(dev_priv); spin_lock_irq(&dev_priv->uncore.lock); - POSTING_READ_FW(RING_ACTHD(dev_priv->engine[RCS]->mmio_base)); + POSTING_READ_FW(RING_HEAD(dev_priv->engine[RCS]->mmio_base)); spin_unlock_irq(&dev_priv->uncore.lock); intel_runtime_pm_put(dev_priv); } -- cgit v1.2.3 From efc886cb135595c7bec481a32d000dce865b7971 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Thu, 7 Sep 2017 08:40:04 -0700 Subject: drm/i915: Transform WaInPlaceDecompressionHang into a simple reg write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Afaict, GEN9_GAMT_ECO_REG_RW_IA does not live in the context, so writing it on every context creation is overkill (and wrong). v2: Missing end parenthesis Cc: Chris Wilson Cc: Mika Kuoppala Cc: Rodrigo Vivi Signed-off-by: Oscar Mateo Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/1504798809-5653-1-git-send-email-oscar.mateo@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_engine_cs.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index b8e9a234af2d..674d686286b1 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -985,8 +985,9 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) /* WaInPlaceDecompressionHang:skl */ if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); /* WaDisableLSQCROPERFforOCL:skl */ ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); @@ -1059,8 +1060,9 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine) /* WaInPlaceDecompressionHang:bxt */ if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); return 0; } @@ -1093,8 +1095,9 @@ static int cnl_init_workarounds(struct intel_engine_cs *engine) GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE); /* WaInPlaceDecompressionHang:cnl */ - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); /* WaPushConstantDereferenceHoldDisable:cnl */ WA_SET_BIT(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE); @@ -1147,8 +1150,9 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine) GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); /* WaInPlaceDecompressionHang:kbl */ - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); /* WaDisableLSQCROPERFforOCL:kbl */ ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); @@ -1200,8 +1204,9 @@ static int cfl_init_workarounds(struct intel_engine_cs *engine) GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); /* WaInPlaceDecompressionHang:cfl */ - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); return 0; } -- cgit v1.2.3 From 6cf20a0128fab5368937d719bcd9ec1b233491b7 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Thu, 7 Sep 2017 08:40:05 -0700 Subject: drm/i915: Transform WaDisableI2mCycleOnWRPort into a simple reg write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GAMT_CHKN_BIT_REG does not live in the context. Cc: Chris Wilson Cc: Mika Kuoppala Cc: Rodrigo Vivi Signed-off-by: Oscar Mateo Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/1504798809-5653-2-git-send-email-oscar.mateo@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_engine_cs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 674d686286b1..0fb012369077 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1072,10 +1072,11 @@ static int cnl_init_workarounds(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->i915; int ret; - /* WaDisableI2mCycleOnWRPort: cnl (pre-prod) */ + /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */ if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) - WA_SET_BIT(GAMT_CHKN_BIT_REG, - GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT); + I915_WRITE(GAMT_CHKN_BIT_REG, + (I915_READ(GAMT_CHKN_BIT_REG) | + GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT)); /* WaForceContextSaveRestoreNonCoherent:cnl */ WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0, -- cgit v1.2.3 From b27f59010f27628f1d96e746fdf7e6e916c451d5 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Thu, 7 Sep 2017 08:40:06 -0700 Subject: drm/i915: WaPushConstantDereferenceHoldDisable needs to modify a masked register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So do it correctly. Cc: Chris Wilson Cc: Mika Kuoppala Cc: Rodrigo Vivi Signed-off-by: Oscar Mateo Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/1504798809-5653-3-git-send-email-oscar.mateo@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_engine_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 0fb012369077..6e24711c106c 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1101,7 +1101,7 @@ static int cnl_init_workarounds(struct intel_engine_cs *engine) GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); /* WaPushConstantDereferenceHoldDisable:cnl */ - WA_SET_BIT(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE); + WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE); /* FtrEnableFastAnisoL1BankingFix: cnl */ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, CNL_FAST_ANISO_L1_BANKING_FIX); -- cgit v1.2.3 From 4827c547c51f81579edb8f3958d53c15e0a3f662 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Thu, 7 Sep 2017 08:40:07 -0700 Subject: drm/i915: Transform WaDisableGafsUnitClkGating into a simple reg write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GEN7_UCGCTL4 does not live in the context. v2: Missing parenthesis Cc: Chris Wilson Cc: Mika Kuoppala Cc: Rodrigo Vivi Signed-off-by: Oscar Mateo Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/1504798809-5653-4-git-send-email-oscar.mateo@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_engine_cs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 6e24711c106c..48c7eb36d633 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -981,7 +981,8 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) GEN9_GAPS_TSV_CREDIT_DISABLE)); /* WaDisableGafsUnitClkGating:skl */ - WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | + GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); /* WaInPlaceDecompressionHang:skl */ if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) @@ -1143,7 +1144,8 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine) GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); /* WaDisableGafsUnitClkGating:kbl */ - WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | + GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); /* WaDisableSbeCacheDispatchPortSharing:kbl */ WA_SET_BIT_MASKED( @@ -1197,7 +1199,8 @@ static int cfl_init_workarounds(struct intel_engine_cs *engine) GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); /* WaDisableGafsUnitClkGating:cfl */ - WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | + GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); /* WaDisableSbeCacheDispatchPortSharing:cfl */ WA_SET_BIT_MASKED( -- cgit v1.2.3 From c6ea497c40b46aaf77d9018e27b26bffdbdac6f7 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Thu, 7 Sep 2017 08:40:08 -0700 Subject: drm/i915: Transform WaDisableDynamicCreditSharing into a simple register write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GAMT_CHKN_BIT_REG does not live in the context image. Cc: Chris Wilson Cc: Mika Kuoppala Cc: Rodrigo Vivi Signed-off-by: Oscar Mateo Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/1504798809-5653-5-git-send-email-oscar.mateo@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_engine_cs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 48c7eb36d633..0701ddb68b6a 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1130,8 +1130,9 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine) /* WaDisableDynamicCreditSharing:kbl */ if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) - WA_SET_BIT(GAMT_CHKN_BIT_REG, - GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); + I915_WRITE(GAMT_CHKN_BIT_REG, + (I915_READ(GAMT_CHKN_BIT_REG) | + GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING)); /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) -- cgit v1.2.3 From 212154ba4d1c31ad828b8e1e2d4ecd4adcb02796 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Thu, 7 Sep 2017 08:40:09 -0700 Subject: drm/i915: Transform WaDisablePooledEuLoadBalancingFix into a simple register write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FF_SLICE_CS_CHICKEN2 does not belong to the context image. Cc: Chris Wilson Cc: Mika Kuoppala Cc: Rodrigo Vivi Signed-off-by: Oscar Mateo Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/1504798809-5653-6-git-send-email-oscar.mateo@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_engine_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 0701ddb68b6a..3ae89a9d6241 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1024,8 +1024,8 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine) /* WaDisablePooledEuLoadBalancingFix:bxt */ if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { - WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2, - GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); + I915_WRITE(FF_SLICE_CS_CHICKEN2, + _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); } /* WaDisableSbeCacheDispatchPortSharing:bxt */ -- cgit v1.2.3 From 5d5fe176155e6cfa4a53accb90e4010baa5266d0 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Tue, 15 Aug 2017 13:20:51 +0800 Subject: drm/i915/kvmgt: Sanitize PCI bar emulation For PCI, 64bit bar consumes two BAR registers, but this doesn't mean both of two BAR are valid. Actually the second BAR is regarded as reserved in this case. So we shouldn't emulate the second BAR. Signed-off-by: Changbin Du Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/kvmgt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 83e88c70272a..9201db0892f1 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -661,7 +661,6 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, buf, count); break; case VFIO_PCI_BAR0_REGION_INDEX: - case VFIO_PCI_BAR1_REGION_INDEX: if (is_write) { uint64_t bar0_start = intel_vgpu_get_bar0_addr(vgpu); @@ -674,6 +673,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, bar0_start + pos, buf, count); } break; + case VFIO_PCI_BAR1_REGION_INDEX: case VFIO_PCI_BAR2_REGION_INDEX: case VFIO_PCI_BAR3_REGION_INDEX: case VFIO_PCI_BAR4_REGION_INDEX: -- cgit v1.2.3 From f090a00df9ecdab5d066b099c1797e0070e27a36 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Tue, 15 Aug 2017 13:14:04 +0800 Subject: drm/i915/gvt: Add emulation for BAR2 (aperture) with normal file RW approach For vfio-pci, if the region support MMAP then it should support both mmap and normal file access. The user-space is free to choose which is being used. For qemu, we just need add 'x-no-mmap=on' for vfio-pci option. Currently GVTg only support MMAP for BAR2. So GVTg will not work when user turn on x-no-mmap option. This patch added file style access for BAR2, aka the GPU aperture. We map the entire aperture partition of active vGPU to kernel space when guest driver try to enable PCI Memory Space. Then we redirect the file RW operation from kvmgt to this mapped area. Link: https://bugzilla.redhat.com/show_bug.cgi?id=1458032 Signed-off-by: Changbin Du Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cfg_space.c | 26 +++++++++++++++----- drivers/gpu/drm/i915/gvt/gvt.h | 8 ++++++ drivers/gpu/drm/i915/gvt/kvmgt.c | 42 +++++++++++++++++++------------- drivers/gpu/drm/i915/gvt/mmio.c | 47 ++++++++++++++++++++++++++++++++++-- 4 files changed, 98 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index 40af17ec6312..be0dd8534993 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -110,13 +110,25 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, static int map_aperture(struct intel_vgpu *vgpu, bool map) { - u64 first_gfn, first_mfn; + phys_addr_t aperture_pa = vgpu_aperture_pa_base(vgpu); + unsigned long aperture_sz = vgpu_aperture_sz(vgpu); + u64 first_gfn; u64 val; int ret; if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) return 0; + if (map) { + vgpu->gm.aperture_va = memremap(aperture_pa, aperture_sz, + MEMREMAP_WC); + if (!vgpu->gm.aperture_va) + return -ENOMEM; + } else { + memunmap(vgpu->gm.aperture_va); + vgpu->gm.aperture_va = NULL; + } + val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2]; if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); @@ -124,14 +136,16 @@ static int map_aperture(struct intel_vgpu *vgpu, bool map) val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT; - first_mfn = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT; ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn, - first_mfn, - vgpu_aperture_sz(vgpu) >> - PAGE_SHIFT, map); - if (ret) + aperture_pa >> PAGE_SHIFT, + aperture_sz >> PAGE_SHIFT, + map); + if (ret) { + memunmap(vgpu->gm.aperture_va); + vgpu->gm.aperture_va = NULL; return ret; + } vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map; return 0; diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 44b719eda8c4..2fe22e1b517c 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -80,6 +80,7 @@ struct intel_gvt_device_info { struct intel_vgpu_gm { u64 aperture_sz; u64 hidden_sz; + void *aperture_va; struct drm_mm_node low_gm_node; struct drm_mm_node high_gm_node; }; @@ -474,6 +475,13 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes); +static inline u64 intel_vgpu_get_bar_gpa(struct intel_vgpu *vgpu, int bar) +{ + /* We are 64bit bar. */ + return (*(u64 *)(vgpu->cfg_space.virtual_cfg_space + bar)) & + PCI_BASE_ADDRESS_MEM_MASK; +} + void intel_gvt_clean_opregion(struct intel_gvt *gvt); int intel_gvt_init_opregion(struct intel_gvt *gvt); diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 9201db0892f1..ae65268efce3 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -609,21 +609,20 @@ static void intel_vgpu_release_work(struct work_struct *work) __intel_vgpu_release(vgpu); } -static uint64_t intel_vgpu_get_bar0_addr(struct intel_vgpu *vgpu) +static uint64_t intel_vgpu_get_bar_addr(struct intel_vgpu *vgpu, int bar) { u32 start_lo, start_hi; u32 mem_type; - int pos = PCI_BASE_ADDRESS_0; - start_lo = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + pos)) & + start_lo = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + bar)) & PCI_BASE_ADDRESS_MEM_MASK; - mem_type = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + pos)) & + mem_type = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + bar)) & PCI_BASE_ADDRESS_MEM_TYPE_MASK; switch (mem_type) { case PCI_BASE_ADDRESS_MEM_TYPE_64: start_hi = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space - + pos + 4)); + + bar + 4)); break; case PCI_BASE_ADDRESS_MEM_TYPE_32: case PCI_BASE_ADDRESS_MEM_TYPE_1M: @@ -637,6 +636,21 @@ static uint64_t intel_vgpu_get_bar0_addr(struct intel_vgpu *vgpu) return ((u64)start_hi << 32) | start_lo; } +static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, uint64_t off, + void *buf, unsigned int count, bool is_write) +{ + uint64_t bar_start = intel_vgpu_get_bar_addr(vgpu, bar); + int ret; + + if (is_write) + ret = intel_gvt_ops->emulate_mmio_write(vgpu, + bar_start + off, buf, count); + else + ret = intel_gvt_ops->emulate_mmio_read(vgpu, + bar_start + off, buf, count); + return ret; +} + static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, size_t count, loff_t *ppos, bool is_write) { @@ -661,20 +675,14 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, buf, count); break; case VFIO_PCI_BAR0_REGION_INDEX: - if (is_write) { - uint64_t bar0_start = intel_vgpu_get_bar0_addr(vgpu); - - ret = intel_gvt_ops->emulate_mmio_write(vgpu, - bar0_start + pos, buf, count); - } else { - uint64_t bar0_start = intel_vgpu_get_bar0_addr(vgpu); - - ret = intel_gvt_ops->emulate_mmio_read(vgpu, - bar0_start + pos, buf, count); - } + ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_0, pos, + buf, count, is_write); break; - case VFIO_PCI_BAR1_REGION_INDEX: case VFIO_PCI_BAR2_REGION_INDEX: + ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_2, pos, + buf, count, is_write); + break; + case VFIO_PCI_BAR1_REGION_INDEX: case VFIO_PCI_BAR3_REGION_INDEX: case VFIO_PCI_BAR4_REGION_INDEX: case VFIO_PCI_BAR5_REGION_INDEX: diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 980ec8906b1e..1e1310f50289 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -45,8 +45,7 @@ */ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa) { - u64 gttmmio_gpa = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0) & - ~GENMASK(3, 0); + u64 gttmmio_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_0); return gpa - gttmmio_gpa; } @@ -57,6 +56,38 @@ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa) (reg >= gvt->device_info.gtt_start_offset \ && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt)) +static bool vgpu_gpa_is_aperture(struct intel_vgpu *vgpu, uint64_t gpa) +{ + u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2); + u64 aperture_sz = vgpu_aperture_sz(vgpu); + + return gpa >= aperture_gpa && gpa < aperture_gpa + aperture_sz; +} + +static int vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t gpa, + void *pdata, unsigned int size, bool is_read) +{ + u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2); + u64 offset = gpa - aperture_gpa; + + if (!vgpu_gpa_is_aperture(vgpu, gpa + size - 1)) { + gvt_vgpu_err("Aperture rw out of range, offset %llx, size %d\n", + offset, size); + return -EINVAL; + } + + if (!vgpu->gm.aperture_va) { + gvt_vgpu_err("BAR is not enabled\n"); + return -ENXIO; + } + + if (is_read) + memcpy(pdata, vgpu->gm.aperture_va + offset, size); + else + memcpy(vgpu->gm.aperture_va + offset, pdata, size); + return 0; +} + static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa, void *p_data, unsigned int bytes, bool read) { @@ -133,6 +164,12 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa, } mutex_lock(&gvt->lock); + if (vgpu_gpa_is_aperture(vgpu, pa)) { + ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, true); + mutex_unlock(&gvt->lock); + return ret; + } + if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { struct intel_vgpu_guest_page *gp; @@ -224,6 +261,12 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa, mutex_lock(&gvt->lock); + if (vgpu_gpa_is_aperture(vgpu, pa)) { + ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, false); + mutex_unlock(&gvt->lock); + return ret; + } + if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { struct intel_vgpu_guest_page *gp; -- cgit v1.2.3 From 0a53bc07f044c4c51eb0dc1386c504db80ca8d00 Mon Sep 17 00:00:00 2001 From: fred gao Date: Fri, 18 Aug 2017 15:41:06 +0800 Subject: drm/i915/gvt: Separate cmd scan from request allocation Currently i915 request structure and shadow ring buffer are allocated before command scan, so it will have to restore to previous states once any error happens afterwards in the long dispatch_workload path. This patch is to introduce a reserved ring buffer created at the beginning of vGPU initialization. Workload will be coped to this reserved buffer and be scanned first, the i915 request and shadow ring buffer are only allocated after the result of scan is successful. To balance the memory usage and buffer alloc time, the coming bigger ring buffer will be reallocated and kept until more bigger buffer is coming. v2: - use kmalloc for the smaller ring buffer, realloc if required. (Zhenyu) v3: - remove the dynamically allocated ring buffer. (Zhenyu) v4: - code style polish. - kfree previous allocated buffer once kmalloc failed. (Zhenyu) Signed-off-by: fred gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 31 ++++++++----- drivers/gpu/drm/i915/gvt/execlist.c | 30 +++++++++++++ drivers/gpu/drm/i915/gvt/gvt.h | 3 ++ drivers/gpu/drm/i915/gvt/scheduler.c | 84 ++++++++++++++++++++++++----------- 4 files changed, 110 insertions(+), 38 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 72b97ce525e8..e53efc0524f4 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -2603,7 +2603,8 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload) { struct intel_vgpu *vgpu = workload->vgpu; unsigned long gma_head, gma_tail, gma_top, guest_rb_size; - u32 *cs; + void *shadow_ring_buffer_va; + int ring_id = workload->ring_id; int ret; guest_rb_size = _RING_CTL_BUF_SIZE(workload->rb_ctl); @@ -2616,34 +2617,42 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload) gma_tail = workload->rb_start + workload->rb_tail; gma_top = workload->rb_start + guest_rb_size; - /* allocate shadow ring buffer */ - cs = intel_ring_begin(workload->req, workload->rb_len / sizeof(u32)); - if (IS_ERR(cs)) - return PTR_ERR(cs); + if (workload->rb_len > vgpu->reserve_ring_buffer_size[ring_id]) { + void *va = vgpu->reserve_ring_buffer_va[ring_id]; + /* realloc the new ring buffer if needed */ + vgpu->reserve_ring_buffer_va[ring_id] = + krealloc(va, workload->rb_len, GFP_KERNEL); + if (!vgpu->reserve_ring_buffer_va[ring_id]) { + gvt_vgpu_err("fail to alloc reserve ring buffer\n"); + return -ENOMEM; + } + vgpu->reserve_ring_buffer_size[ring_id] = workload->rb_len; + } + + shadow_ring_buffer_va = vgpu->reserve_ring_buffer_va[ring_id]; /* get shadow ring buffer va */ - workload->shadow_ring_buffer_va = cs; + workload->shadow_ring_buffer_va = shadow_ring_buffer_va; /* head > tail --> copy head <-> top */ if (gma_head > gma_tail) { ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, - gma_head, gma_top, cs); + gma_head, gma_top, shadow_ring_buffer_va); if (ret < 0) { gvt_vgpu_err("fail to copy guest ring buffer\n"); return ret; } - cs += ret / sizeof(u32); + shadow_ring_buffer_va += ret; gma_head = workload->rb_start; } /* copy head or start <-> tail */ - ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, gma_head, gma_tail, cs); + ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, gma_head, gma_tail, + shadow_ring_buffer_va); if (ret < 0) { gvt_vgpu_err("fail to copy guest ring buffer\n"); return ret; } - cs += ret / sizeof(u32); - intel_ring_advance(workload->req, cs); return 0; } diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 91b4300f3b39..1e2c27704be5 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -820,10 +820,21 @@ static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask) void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu) { + enum intel_engine_id i; + struct intel_engine_cs *engine; + clean_workloads(vgpu, ALL_ENGINES); kmem_cache_destroy(vgpu->workloads); + + for_each_engine(engine, vgpu->gvt->dev_priv, i) { + kfree(vgpu->reserve_ring_buffer_va[i]); + vgpu->reserve_ring_buffer_va[i] = NULL; + vgpu->reserve_ring_buffer_size[i] = 0; + } + } +#define RESERVE_RING_BUFFER_SIZE ((1 * PAGE_SIZE)/8) int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) { enum intel_engine_id i; @@ -843,7 +854,26 @@ int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) if (!vgpu->workloads) return -ENOMEM; + /* each ring has a shadow ring buffer until vgpu destroyed */ + for_each_engine(engine, vgpu->gvt->dev_priv, i) { + vgpu->reserve_ring_buffer_va[i] = + kmalloc(RESERVE_RING_BUFFER_SIZE, GFP_KERNEL); + if (!vgpu->reserve_ring_buffer_va[i]) { + gvt_vgpu_err("fail to alloc reserve ring buffer\n"); + goto out; + } + vgpu->reserve_ring_buffer_size[i] = RESERVE_RING_BUFFER_SIZE; + } return 0; +out: + for_each_engine(engine, vgpu->gvt->dev_priv, i) { + if (vgpu->reserve_ring_buffer_size[i]) { + kfree(vgpu->reserve_ring_buffer_va[i]); + vgpu->reserve_ring_buffer_va[i] = NULL; + vgpu->reserve_ring_buffer_size[i] = 0; + } + } + return -ENOMEM; } void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu, diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 2fe22e1b517c..031868f08e1c 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -166,6 +166,9 @@ struct intel_vgpu { struct list_head workload_q_head[I915_NUM_ENGINES]; struct kmem_cache *workloads; atomic_t running_workload_num; + /* 1/2K for each reserve ring buffer */ + void *reserve_ring_buffer_va[I915_NUM_ENGINES]; + int reserve_ring_buffer_size[I915_NUM_ENGINES]; DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); struct i915_gem_context *shadow_ctx; DECLARE_BITMAP(shadow_ctx_desc_updated, I915_NUM_ENGINES); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 391800d2067b..0e480f59f659 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -201,6 +201,34 @@ static void shadow_context_descriptor_update(struct i915_gem_context *ctx, ce->lrc_desc = desc; } +static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + void *shadow_ring_buffer_va; + u32 *cs; + + /* allocate shadow ring buffer */ + cs = intel_ring_begin(workload->req, workload->rb_len / sizeof(u32)); + if (IS_ERR(cs)) { + gvt_vgpu_err("fail to alloc size =%ld shadow ring buffer\n", + workload->rb_len); + return PTR_ERR(cs); + } + + shadow_ring_buffer_va = workload->shadow_ring_buffer_va; + + /* get shadow ring buffer va */ + workload->shadow_ring_buffer_va = cs; + + memcpy(cs, shadow_ring_buffer_va, + workload->rb_len); + + cs += workload->rb_len / sizeof(u32); + intel_ring_advance(workload->req, cs); + + return 0; +} + /** * intel_gvt_scan_and_shadow_workload - audit the workload by scanning and * shadow it as well, include ringbuffer,wa_ctx and ctx. @@ -214,8 +242,10 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) int ring_id = workload->ring_id; struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; + struct intel_engine_cs *engine = dev_priv->engine[ring_id]; struct drm_i915_gem_request *rq; struct intel_vgpu *vgpu = workload->vgpu; + struct intel_ring *ring; int ret; lockdep_assert_held(&dev_priv->drm.struct_mutex); @@ -231,17 +261,6 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) shadow_context_descriptor_update(shadow_ctx, dev_priv->engine[ring_id]); - rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); - if (IS_ERR(rq)) { - gvt_vgpu_err("fail to allocate gem request\n"); - ret = PTR_ERR(rq); - goto out; - } - - gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq); - - workload->req = i915_gem_request_get(rq); - ret = intel_gvt_scan_and_shadow_ringbuffer(workload); if (ret) goto out; @@ -253,10 +272,37 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) goto out; } + /* pin shadow context by gvt even the shadow context will be pinned + * when i915 alloc request. That is because gvt will update the guest + * context from shadow context when workload is completed, and at that + * moment, i915 may already unpined the shadow context to make the + * shadow_ctx pages invalid. So gvt need to pin itself. After update + * the guest context, gvt can unpin the shadow_ctx safely. + */ + ring = engine->context_pin(engine, shadow_ctx); + if (IS_ERR(ring)) { + ret = PTR_ERR(ring); + gvt_vgpu_err("fail to pin shadow context\n"); + goto out; + } + ret = populate_shadow_context(workload); if (ret) goto out; + rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); + if (IS_ERR(rq)) { + gvt_vgpu_err("fail to allocate gem request\n"); + ret = PTR_ERR(rq); + goto out; + } + + gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq); + + workload->req = i915_gem_request_get(rq); + ret = copy_workload_to_ring_buffer(workload); + if (ret) + goto out; workload->shadowed = true; out: @@ -269,8 +315,6 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; struct intel_engine_cs *engine = dev_priv->engine[ring_id]; - struct intel_vgpu *vgpu = workload->vgpu; - struct intel_ring *ring; int ret = 0; gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n", @@ -288,20 +332,6 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) goto out; } - /* pin shadow context by gvt even the shadow context will be pinned - * when i915 alloc request. That is because gvt will update the guest - * context from shadow context when workload is completed, and at that - * moment, i915 may already unpined the shadow context to make the - * shadow_ctx pages invalid. So gvt need to pin itself. After update - * the guest context, gvt can unpin the shadow_ctx safely. - */ - ring = engine->context_pin(engine, shadow_ctx); - if (IS_ERR(ring)) { - ret = PTR_ERR(ring); - gvt_vgpu_err("fail to pin shadow context\n"); - goto out; - } - out: if (ret) workload->status = ret; -- cgit v1.2.3 From a3cfdca920b274618d6046d85a474308ee28e5bb Mon Sep 17 00:00:00 2001 From: fred gao Date: Fri, 18 Aug 2017 15:41:07 +0800 Subject: drm/i915/gvt: Add error handling for intel_gvt_scan_and_shadow_workload When an error occurs after shadow_indirect_ctx, this patch is to do the proper cleanup and rollback to the original states for shadowed indirect context before the workload is abandoned. v2: - split the mixed several error paths for better review. (Zhenyu) v3: - no return check for clean up functions. (Changbin) v4: - expose and reuse the existing release_shadow_wa_ctx. (Zhenyu) v5: - move the release function to scheduler.c file. (Zhenyu) v6: - move error handling code of intel_gvt_scan_and_shadow_workload to here. (Zhenyu) Signed-off-by: fred gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 9 --------- drivers/gpu/drm/i915/gvt/scheduler.c | 28 +++++++++++++++++++++------- drivers/gpu/drm/i915/gvt/scheduler.h | 1 + 3 files changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 1e2c27704be5..cbb2e8da1c7a 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -489,15 +489,6 @@ static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) } } -static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) -{ - if (!wa_ctx->indirect_ctx.obj) - return; - - i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj); - i915_gem_object_put(wa_ctx->indirect_ctx.obj); -} - static int complete_execlist_workload(struct intel_vgpu_workload *workload) { struct intel_vgpu *vgpu = workload->vgpu; diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 0e480f59f659..29171961af5e 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -229,6 +229,15 @@ static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload) return 0; } +void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + if (!wa_ctx->indirect_ctx.obj) + return; + + i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj); + i915_gem_object_put(wa_ctx->indirect_ctx.obj); +} + /** * intel_gvt_scan_and_shadow_workload - audit the workload by scanning and * shadow it as well, include ringbuffer,wa_ctx and ctx. @@ -263,13 +272,13 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) ret = intel_gvt_scan_and_shadow_ringbuffer(workload); if (ret) - goto out; + goto err_scan; if ((workload->ring_id == RCS) && (workload->wa_ctx.indirect_ctx.size != 0)) { ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx); if (ret) - goto out; + goto err_scan; } /* pin shadow context by gvt even the shadow context will be pinned @@ -283,18 +292,18 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) if (IS_ERR(ring)) { ret = PTR_ERR(ring); gvt_vgpu_err("fail to pin shadow context\n"); - goto out; + goto err_shadow; } ret = populate_shadow_context(workload); if (ret) - goto out; + goto err_unpin; rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); if (IS_ERR(rq)) { gvt_vgpu_err("fail to allocate gem request\n"); ret = PTR_ERR(rq); - goto out; + goto err_unpin; } gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq); @@ -302,10 +311,15 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) workload->req = i915_gem_request_get(rq); ret = copy_workload_to_ring_buffer(workload); if (ret) - goto out; + goto err_unpin; workload->shadowed = true; + return 0; -out: +err_unpin: + engine->context_unpin(engine, shadow_ctx); +err_shadow: + release_shadow_wa_ctx(&workload->wa_ctx); +err_scan: return ret; } diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 0d431a968a32..f36b85fd6d01 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -140,4 +140,5 @@ int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu); void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu); +void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx); #endif -- cgit v1.2.3 From 0cce2823ed37b75555749c0969528d8c74887ada Mon Sep 17 00:00:00 2001 From: fred gao Date: Fri, 18 Aug 2017 15:41:08 +0800 Subject: drm/i915/gvt: Refine error handling for prepare_execlist_workload refine the error handling for prepare_execlist_workload to restore to the original states once error occurs. only release the shadowed batch buffer and wa ctx when the workload is completed successfully. v2: - split the mixed several error paths for better review. (Zhenyu) v3: - handle prepare batch buffer/wa ctx pin errors and - emulate_schedule_in null issue. (Zhenyu) v4: - no need to handle emulate_schedule_in null issue. (Zhenyu) v5: - release the shadowed batch buffer and wa ctx only for the successful workload. (Zhenyu) v6: - polish the return style. (Zhenyu) Signed-off-by: fred gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/execlist.c | 96 ++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index cbb2e8da1c7a..5ec07ecf33ad 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -368,7 +368,7 @@ static void free_workload(struct intel_vgpu_workload *workload) #define get_desc_from_elsp_dwords(ed, i) \ ((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2])) -static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) +static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) { const int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd; struct intel_shadow_bb_entry *entry_obj; @@ -379,7 +379,7 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, 4, 0); if (IS_ERR(vma)) { - return; + return PTR_ERR(vma); } /* FIXME: we are not tracking our pinned VMA leaving it @@ -392,6 +392,7 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) if (gmadr_bytes == 8) entry_obj->bb_start_cmd_va[2] = 0; } + return 0; } static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) @@ -420,7 +421,7 @@ static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) return 0; } -static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +static int prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) { struct i915_vma *vma; unsigned char *per_ctx_va = @@ -428,12 +429,12 @@ static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) wa_ctx->indirect_ctx.size; if (wa_ctx->indirect_ctx.size == 0) - return; + return 0; vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL, 0, CACHELINE_BYTES, 0); if (IS_ERR(vma)) { - return; + return PTR_ERR(vma); } /* FIXME: we are not tracking our pinned VMA leaving it @@ -447,26 +448,7 @@ static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) memset(per_ctx_va, 0, CACHELINE_BYTES); update_wa_ctx_2_shadow_ctx(wa_ctx); -} - -static int prepare_execlist_workload(struct intel_vgpu_workload *workload) -{ - struct intel_vgpu *vgpu = workload->vgpu; - struct execlist_ctx_descriptor_format ctx[2]; - int ring_id = workload->ring_id; - - intel_vgpu_pin_mm(workload->shadow_mm); - intel_vgpu_sync_oos_pages(workload->vgpu); - intel_vgpu_flush_post_shadow(workload->vgpu); - prepare_shadow_batch_buffer(workload); - prepare_shadow_wa_ctx(&workload->wa_ctx); - if (!workload->emulate_schedule_in) - return 0; - - ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1); - ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0); - - return emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx); + return 0; } static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) @@ -489,6 +471,64 @@ static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) } } +static int prepare_execlist_workload(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + struct execlist_ctx_descriptor_format ctx[2]; + int ring_id = workload->ring_id; + int ret; + + ret = intel_vgpu_pin_mm(workload->shadow_mm); + if (ret) { + gvt_vgpu_err("fail to vgpu pin mm\n"); + goto out; + } + + ret = intel_vgpu_sync_oos_pages(workload->vgpu); + if (ret) { + gvt_vgpu_err("fail to vgpu sync oos pages\n"); + goto err_unpin_mm; + } + + ret = intel_vgpu_flush_post_shadow(workload->vgpu); + if (ret) { + gvt_vgpu_err("fail to flush post shadow\n"); + goto err_unpin_mm; + } + + ret = prepare_shadow_batch_buffer(workload); + if (ret) { + gvt_vgpu_err("fail to prepare_shadow_batch_buffer\n"); + goto err_unpin_mm; + } + + ret = prepare_shadow_wa_ctx(&workload->wa_ctx); + if (ret) { + gvt_vgpu_err("fail to prepare_shadow_wa_ctx\n"); + goto err_shadow_batch; + } + + if (!workload->emulate_schedule_in) + return 0; + + ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1); + ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0); + + ret = emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx); + if (!ret) + goto out; + else + gvt_vgpu_err("fail to emulate execlist schedule in\n"); + + release_shadow_wa_ctx(&workload->wa_ctx); +err_shadow_batch: + release_shadow_batch_buffer(workload); +err_unpin_mm: + intel_vgpu_unpin_mm(workload->shadow_mm); +out: + return ret; +} + static int complete_execlist_workload(struct intel_vgpu_workload *workload) { struct intel_vgpu *vgpu = workload->vgpu; @@ -502,8 +542,10 @@ static int complete_execlist_workload(struct intel_vgpu_workload *workload) gvt_dbg_el("complete workload %p status %d\n", workload, workload->status); - release_shadow_batch_buffer(workload); - release_shadow_wa_ctx(&workload->wa_ctx); + if (!workload->status) { + release_shadow_batch_buffer(workload); + release_shadow_wa_ctx(&workload->wa_ctx); + } if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) { /* if workload->status is not successful means HW GPU -- cgit v1.2.3 From 46b441efa374cf1581c267a16089c205f2fc0ded Mon Sep 17 00:00:00 2001 From: fred gao Date: Fri, 18 Aug 2017 15:41:09 +0800 Subject: drm/i915/gvt: Refine error handling for intel_vgpu_pin_mm When it is failed in shadow_mm, the pin_count should rollback to the original states before return. v2: - split the mixed several error paths for better review. (Zhenyu) v3: increase the pincount after shadow success. (Zhenyu) Signed-off-by: fred gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/gtt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index e6dfc3331f4b..0bd028f8fef5 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1647,14 +1647,13 @@ int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm) if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT)) return 0; - atomic_inc(&mm->pincount); - if (!mm->shadowed) { ret = shadow_mm(mm); if (ret) return ret; } + atomic_inc(&mm->pincount); list_del_init(&mm->lru_list); list_add_tail(&mm->lru_list, &mm->vgpu->gvt->gtt.mm_lru_list_head); return 0; -- cgit v1.2.3 From 0f43702a334b2848ae2e942dbc0677ddc4566b57 Mon Sep 17 00:00:00 2001 From: fred gao Date: Fri, 18 Aug 2017 15:41:10 +0800 Subject: drm/i915/gvt: Refine error handling in dispatch_workload When an error occurs in dispatch_workload, this patch is to do the proper cleanup and rollback to the original states before the workload is abandoned. v2: - split the mixed several error paths for better review. (Zhenyu) v3: - original PTR_ERR(cs) is good and code cleanup. (Zhenyu) v4: - reuse the existing i915_add_request for error handling. (Zhenyu) v5: - remove the duplicate error handling release_shadow_wa_ctx and move the engine->context_unpin upper. (Zhenyu) v6: - keep the old label "out". (Zhenyu) Signed-off-by: fred gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/scheduler.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 29171961af5e..6fb9b589276d 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -342,8 +342,10 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) if (workload->prepare) { ret = workload->prepare(workload); - if (ret) + if (ret) { + engine->context_unpin(engine, shadow_ctx); goto out; + } } out: -- cgit v1.2.3 From 1e3197d6ad73ef34b71d96cfb37ddf0b7bddac0e Mon Sep 17 00:00:00 2001 From: fred gao Date: Fri, 18 Aug 2017 15:41:11 +0800 Subject: drm/i915/gvt: Refine error handling for perform_bb_shadow fix the wrong return type and return error once the unknown command is scanned. v2: - separate this error handle from healthy rating code. (Zhenyu) Signed-off-by: fred gao Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index e53efc0524f4..23a9bbbb6565 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1576,11 +1576,11 @@ static int batch_buffer_needs_scan(struct parser_exec_state *s) return 1; } -static uint32_t find_bb_size(struct parser_exec_state *s) +static int find_bb_size(struct parser_exec_state *s) { unsigned long gma = 0; struct cmd_info *info; - uint32_t bb_size = 0; + int bb_size = 0; uint32_t cmd_len = 0; bool met_bb_end = false; struct intel_vgpu *vgpu = s->vgpu; @@ -1637,6 +1637,8 @@ static int perform_bb_shadow(struct parser_exec_state *s) /* get the size of the batch buffer */ bb_size = find_bb_size(s); + if (bb_size < 0) + return -EINVAL; /* allocate shadow batch buffer */ entry_obj = kmalloc(sizeof(*entry_obj), GFP_KERNEL); -- cgit v1.2.3 From f1751362d6357a90bc6e53176cec715ff2dbed74 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Fri, 18 Aug 2017 17:49:58 +0800 Subject: drm/i915/gvt: Fix incorrect PCI BARs reporting Looking at our virtual PCI device, we can see surprising Region 4 and Region 5. 00:10.0 VGA compatible controller: Intel Corporation Sky Lake Integrated Graphics (rev 06) (prog-if 00 [VGA controller]) .... Region 0: Memory at 140000000 (64-bit, non-prefetchable) [size=16M] Region 2: Memory at 180000000 (64-bit, prefetchable) [size=1G] Region 4: Memory at (32-bit, non-prefetchable) Region 5: Memory at (32-bit, non-prefetchable) Expansion ROM at febd6000 [disabled] [size=2K] The fact is that we only implemented BAR0 and BAR2. Surprising Region 4 and Region 5 are shown because we report their size as 0xffffffff. They should report size 0 instead. BTW, the physical GPU has a PIO BAR. GVTg hasn't implemented PIO access, so we ignored this BAR for vGPU device. v2: fix BAR size value calculation. Link: https://bugzilla.redhat.com/show_bug.cgi?id=1458032 Signed-off-by: Changbin Du Cc: stable@vger.kernel.org Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cfg_space.c | 113 +++++++++++++++-------------------- 1 file changed, 48 insertions(+), 65 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index be0dd8534993..ce71b5878d65 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -211,78 +211,65 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu, static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { - unsigned int bar_index = - (rounddown(offset, 8) % PCI_BASE_ADDRESS_0) / 8; u32 new = *(u32 *)(p_data); bool lo = IS_ALIGNED(offset, 8); u64 size; int ret = 0; bool mmio_enabled = vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY; + struct intel_vgpu_pci_bar *bars = vgpu->cfg_space.bar; - if (WARN_ON(bar_index >= INTEL_GVT_PCI_BAR_MAX)) - return -EINVAL; - + /* + * Power-up software can determine how much address + * space the device requires by writing a value of + * all 1's to the register and then reading the value + * back. The device will return 0's in all don't-care + * address bits. + */ if (new == 0xffffffff) { - /* - * Power-up software can determine how much address - * space the device requires by writing a value of - * all 1's to the register and then reading the value - * back. The device will return 0's in all don't-care - * address bits. - */ - size = vgpu->cfg_space.bar[bar_index].size; - if (lo) { - new = rounddown(new, size); - } else { - u32 val = vgpu_cfg_space(vgpu)[rounddown(offset, 8)]; - /* for 32bit mode bar it returns all-0 in upper 32 - * bit, for 64bit mode bar it will calculate the - * size with lower 32bit and return the corresponding - * value + switch (offset) { + case PCI_BASE_ADDRESS_0: + case PCI_BASE_ADDRESS_1: + size = ~(bars[INTEL_GVT_PCI_BAR_GTTMMIO].size -1); + intel_vgpu_write_pci_bar(vgpu, offset, + size >> (lo ? 0 : 32), lo); + /* + * Untrap the BAR, since guest hasn't configured a + * valid GPA */ - if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) - new &= (~(size-1)) >> 32; - else - new = 0; - } - /* - * Unmapp & untrap the BAR, since guest hasn't configured a - * valid GPA - */ - switch (bar_index) { - case INTEL_GVT_PCI_BAR_GTTMMIO: ret = trap_gttmmio(vgpu, false); break; - case INTEL_GVT_PCI_BAR_APERTURE: + case PCI_BASE_ADDRESS_2: + case PCI_BASE_ADDRESS_3: + size = ~(bars[INTEL_GVT_PCI_BAR_APERTURE].size -1); + intel_vgpu_write_pci_bar(vgpu, offset, + size >> (lo ? 0 : 32), lo); ret = map_aperture(vgpu, false); break; + default: + /* Unimplemented BARs */ + intel_vgpu_write_pci_bar(vgpu, offset, 0x0, false); } - intel_vgpu_write_pci_bar(vgpu, offset, new, lo); } else { - /* - * Unmapp & untrap the old BAR first, since guest has - * re-configured the BAR - */ - switch (bar_index) { - case INTEL_GVT_PCI_BAR_GTTMMIO: - ret = trap_gttmmio(vgpu, false); + switch (offset) { + case PCI_BASE_ADDRESS_0: + case PCI_BASE_ADDRESS_1: + /* + * Untrap the old BAR first, since guest has + * re-configured the BAR + */ + trap_gttmmio(vgpu, false); + intel_vgpu_write_pci_bar(vgpu, offset, new, lo); + ret = trap_gttmmio(vgpu, mmio_enabled); break; - case INTEL_GVT_PCI_BAR_APERTURE: - ret = map_aperture(vgpu, false); + case PCI_BASE_ADDRESS_2: + case PCI_BASE_ADDRESS_3: + map_aperture(vgpu, false); + intel_vgpu_write_pci_bar(vgpu, offset, new, lo); + ret = map_aperture(vgpu, mmio_enabled); break; - } - intel_vgpu_write_pci_bar(vgpu, offset, new, lo); - /* Track the new BAR */ - if (mmio_enabled) { - switch (bar_index) { - case INTEL_GVT_PCI_BAR_GTTMMIO: - ret = trap_gttmmio(vgpu, true); - break; - case INTEL_GVT_PCI_BAR_APERTURE: - ret = map_aperture(vgpu, true); - break; - } + default: + intel_vgpu_write_pci_bar(vgpu, offset, new, lo); } } return ret; @@ -313,10 +300,7 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, } switch (rounddown(offset, 4)) { - case PCI_BASE_ADDRESS_0: - case PCI_BASE_ADDRESS_1: - case PCI_BASE_ADDRESS_2: - case PCI_BASE_ADDRESS_3: + case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5: if (WARN_ON(!IS_ALIGNED(offset, 4))) return -EINVAL; return emulate_pci_bar_write(vgpu, offset, p_data, bytes); @@ -358,7 +342,6 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, struct intel_gvt *gvt = vgpu->gvt; const struct intel_gvt_device_info *info = &gvt->device_info; u16 *gmch_ctl; - int i; memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space, info->cfg_space_size); @@ -385,13 +368,13 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, */ memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4); memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4); + memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_4, 0, 8); memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4); - for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) { - vgpu->cfg_space.bar[i].size = pci_resource_len( - gvt->dev_priv->drm.pdev, i * 2); - vgpu->cfg_space.bar[i].tracked = false; - } + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size = + pci_resource_len(gvt->dev_priv->drm.pdev, 0); + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size = + pci_resource_len(gvt->dev_priv->drm.pdev, 2); } /** -- cgit v1.2.3 From 02d578e5edd980eac3fbed15db4d9e5665f22089 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Wed, 23 Aug 2017 14:08:10 +0800 Subject: drm/i915/gvt: Add support for PCIe extended configuration space IGD is PCIe device and has extended configuration space. Checking the binary dump, we can see we have Caps located out of PCI compatible Configuration Space range. 0x000: 86 80 12 19 17 04 10 00 06 00 00 03 00 00 00 00 0x010: 04 00 00 10 08 00 00 00 0c 00 00 00 08 00 00 00 0x020: 00 00 00 00 00 00 00 00 00 00 00 00 28 10 b9 06 0x030: 00 f8 ff ff 40 00 00 00 00 00 00 00 0b 01 00 00 0x040: 09 70 0c 01 71 26 01 62 c8 00 04 84 00 00 00 00 0x050: c1 00 00 00 39 00 00 00 00 00 00 00 01 00 00 a2 0x060: 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 0x070: 10 ac 92 00 00 80 00 10 00 00 00 00 00 00 00 00 0x080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0a0: 00 00 00 00 00 00 00 00 00 00 00 00 05 d0 01 00 0x0b0: 18 00 e0 fe 00 00 00 00 00 00 00 00 00 00 00 00 0x0c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0d0: 01 00 22 00 00 80 00 00 00 00 00 00 00 00 00 00 0x0e0: 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 0x0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100: 1b 00 01 20 02 14 00 00 00 00 00 00 00 00 00 00 ... Currently, we only emulate the PCI compatible Configuration Space. This is okay if we attach vGPU to PCI bus. But when we attach to a PCI Express bus (when Qemu emulates a Intel Q35 chipset which has PCIe slot), it will not work. Extended Configuration Space is required for a PCIe device. This patch extended the virtual configuration space from 256 bytes to 4KB bytes. So we are to be a *real* PCIe device. And for the Extended CapList we keep same to physical GPU. Cc: Laszlo Ersek Tested-by: Laszlo Ersek Signed-off-by: Changbin Du Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/cfg_space.c | 4 ++-- drivers/gpu/drm/i915/gvt/gvt.c | 2 +- drivers/gpu/drm/i915/gvt/gvt.h | 3 +-- drivers/gpu/drm/i915/gvt/kvmgt.c | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index ce71b5878d65..ab19545d59a1 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -101,7 +101,7 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, if (WARN_ON(bytes > 4)) return -EINVAL; - if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ)) + if (WARN_ON(offset + bytes > vgpu->gvt->device_info.cfg_space_size)) return -EINVAL; memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes); @@ -289,7 +289,7 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, if (WARN_ON(bytes > 4)) return -EINVAL; - if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ)) + if (WARN_ON(offset + bytes > vgpu->gvt->device_info.cfg_space_size)) return -EINVAL; /* First check if it's PCI_COMMAND */ diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index c27c6838eaca..aaa347f8620c 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -111,7 +111,7 @@ static void init_device_info(struct intel_gvt *gvt) if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv) || IS_KABYLAKE(gvt->dev_priv)) { info->max_support_vgpus = 8; - info->cfg_space_size = 256; + info->cfg_space_size = PCI_CFG_SPACE_EXP_SIZE; info->mmio_size = 2 * 1024 * 1024; info->mmio_bar = 0; info->gtt_start_offset = 8 * 1024 * 1024; diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 031868f08e1c..9c2e7c0aa38f 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -100,7 +100,6 @@ struct intel_vgpu_mmio { bool disable_warn_untrack; }; -#define INTEL_GVT_MAX_CFG_SPACE_SZ 256 #define INTEL_GVT_MAX_BAR_NUM 4 struct intel_vgpu_pci_bar { @@ -109,7 +108,7 @@ struct intel_vgpu_pci_bar { }; struct intel_vgpu_cfg_space { - unsigned char virtual_cfg_space[INTEL_GVT_MAX_CFG_SPACE_SZ]; + unsigned char virtual_cfg_space[PCI_CFG_SPACE_EXP_SIZE]; struct intel_vgpu_pci_bar bar[INTEL_GVT_MAX_BAR_NUM]; }; diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index ae65268efce3..96060920a6fe 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -978,7 +978,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd, switch (info.index) { case VFIO_PCI_CONFIG_REGION_INDEX: info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); - info.size = INTEL_GVT_MAX_CFG_SPACE_SZ; + info.size = vgpu->gvt->device_info.cfg_space_size; info.flags = VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE; break; -- cgit v1.2.3 From a2d3d2655ea6d09edfcc6d9b11fb58729c8d5b95 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 30 Aug 2017 11:01:15 -0700 Subject: drm/i915: Add a default case in gen7 hwsp switch-case Gen7 won't get any new engines, and we already added VCS2 there to just silence gcc's not handled in switch warnings. Use a default case instead, otherwise we will need to keep adding extra cases if changes happen in the future. v2: Since reaching the default case is impossible, use GEM_BUG_ON (Chris). Cc: Chris Wilson Signed-off-by: Michel Thierry Link: https://patchwork.freedesktop.org/patch/msgid/20170830180115.907-1-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_ringbuffer.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index cdf084ef5aae..268342433a8e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -402,17 +402,18 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine) */ if (IS_GEN7(dev_priv)) { switch (engine->id) { + /* + * No more rings exist on Gen7. Default case is only to shut up + * gcc switch check warning. + */ + default: + GEM_BUG_ON(engine->id); case RCS: mmio = RENDER_HWS_PGA_GEN7; break; case BCS: mmio = BLT_HWS_PGA_GEN7; break; - /* - * VCS2 actually doesn't exist on Gen7. Only shut up - * gcc switch check warning - */ - case VCS2: case VCS: mmio = BSD_HWS_PGA_GEN7; break; -- cgit v1.2.3 From 1790625b1deaafb564def63a3a070602656134a1 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 8 Sep 2017 16:11:30 +0000 Subject: drm/i915: Make PAT macros more robust Macro params shall be wrapped into () to avoid unexpected results. Signed-off-by: Michal Wajdeczko Cc: Rodrigo Vivi Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170908161130.22424-1-michal.wajdeczko@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_gtt.h | 2 +- drivers/gpu/drm/i915/i915_reg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index b4e3aa7c0ce1..d9a076a2673a 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -132,7 +132,7 @@ typedef u64 gen8_ppgtt_pml4e_t; #define PPAT_DISPLAY_ELLC_INDEX _PAGE_PCD /* WT eLLC */ #define CHV_PPAT_SNOOP (1<<6) -#define GEN8_PPAT_AGE(x) (x<<4) +#define GEN8_PPAT_AGE(x) ((x)<<4) #define GEN8_PPAT_LLCeLLC (3<<2) #define GEN8_PPAT_LLCELLC (2<<2) #define GEN8_PPAT_LLC (1<<2) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9a73ea0a3293..0b03260a3967 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2336,7 +2336,7 @@ enum i915_power_well_id { #define DONE_REG _MMIO(0x40b0) #define GEN8_PRIVATE_PAT_LO _MMIO(0x40e0) #define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4) -#define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + index*4) +#define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + (index)*4) #define BSD_HWS_PGA_GEN7 _MMIO(0x04180) #define BLT_HWS_PGA_GEN7 _MMIO(0x04280) #define VEBOX_HWS_PGA_GEN7 _MMIO(0x04380) -- cgit v1.2.3 From 14826673247eaf36b16fd821fac27efa663f3fa6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 8 Sep 2017 19:16:22 +0100 Subject: drm/i915: Only initialize partially filled pagetables If we know that we will completely fill a pagetable (i.e. we are inserting a complete set of 512 pages), we can skip prefilling that PT with scratch entries. If we have to abort the insertion prior to writing the real entries, we will teardown the pagetable and remove it from the page directory (so that we will restart the allocation next time). We could do similar tricks for the PD and PDP, but the likelihood of a single insertion covering the entire 512 entries diminishes, as do the cycle savings. The saving are even greater (relatively) when we are preallocating page tables for huge pages, as then we never need to fill the page table. Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170908181622.17791-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_gem_gtt.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c33c2f97c814..33181d6eac3f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1168,19 +1168,22 @@ static int gen8_ppgtt_alloc_pd(struct i915_address_space *vm, unsigned int pde; gen8_for_each_pde(pt, pd, start, length, pde) { + int count = gen8_pte_count(start, length); + if (pt == vm->scratch_pt) { pt = alloc_pt(vm); if (IS_ERR(pt)) goto unwind; - gen8_initialize_pt(vm, pt); + if (count < GEN8_PTES) + gen8_initialize_pt(vm, pt); gen8_ppgtt_set_pde(vm, pd, pt, pde); pd->used_pdes++; GEM_BUG_ON(pd->used_pdes > I915_PDES); } - pt->used_ptes += gen8_pte_count(start, length); + pt->used_ptes += count; } return 0; -- cgit v1.2.3 From 37875d6b3af702425ce292de81b77faf94766616 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 10 Sep 2017 10:56:42 +0200 Subject: drm/i915: Fix an error handling in 'intel_framebuffer_init()' We should go through the error handling path to decrease the 'framebuffer_references' as done everywhere else in this function. Fixes: 2e2adb05736c ("drm/i915: Add render decompression support") Signed-off-by: Christophe JAILLET Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170910085642.13673-1-christophe.jaillet@wanadoo.fr --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 844efd45fed3..dbe7d8682c97 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14105,7 +14105,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, if (mode_cmd->handles[i] != mode_cmd->handles[0]) { DRM_DEBUG_KMS("bad plane %d handle\n", i); - return -EINVAL; + goto err; } stride_alignment = intel_fb_stride_alignment(fb, i); -- cgit v1.2.3 From 0f328da611953d078e86ea250eaeeb840dd7f5d0 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:31 -0700 Subject: drm/i915/psr: Avoid any PSR stuff on platforms without support. We really don't want to setup vfuncs and lock mutexes on platforms that has no support to PSR. Also we know what platforms they are so let's do it quietly. Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-2-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_psr.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index f62ab05d3d62..60a1ece6d4c9 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -496,10 +496,8 @@ void intel_psr_enable(struct intel_dp *intel_dp, enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 chicken; - if (!HAS_PSR(dev_priv)) { - DRM_DEBUG_KMS("PSR not supported on this platform\n"); + if (!HAS_PSR(dev_priv)) return; - } if (!is_edp_psr(intel_dp)) { DRM_DEBUG_KMS("PSR not supported by this panel\n"); @@ -678,6 +676,9 @@ void intel_psr_disable(struct intel_dp *intel_dp, struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + if (!HAS_PSR(dev_priv)) + return; + mutex_lock(&dev_priv->psr.lock); if (!dev_priv->psr.enabled) { mutex_unlock(&dev_priv->psr.lock); @@ -829,6 +830,9 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv, enum pipe pipe; u32 val; + if (!HAS_PSR(dev_priv)) + return; + /* * Single frame update is already supported on BDW+ but it requires * many W/A and it isn't really needed. @@ -875,6 +879,9 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; + if (!HAS_PSR(dev_priv)) + return; + mutex_lock(&dev_priv->psr.lock); if (!dev_priv->psr.enabled) { mutex_unlock(&dev_priv->psr.lock); @@ -912,6 +919,9 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; + if (!HAS_PSR(dev_priv)) + return; + mutex_lock(&dev_priv->psr.lock); if (!dev_priv->psr.enabled) { mutex_unlock(&dev_priv->psr.lock); @@ -944,6 +954,9 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, */ void intel_psr_init(struct drm_i915_private *dev_priv) { + if (!HAS_PSR(dev_priv)) + return; + dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ? HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE; -- cgit v1.2.3 From 424644c2504299e00b450328be9e3c5a12e9c9f9 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:32 -0700 Subject: drm/i915/psr: vfunc for disabling source. VLV/CHV has a total different PSR implementation than the other platforms, so let's start moving that to vfuncs. Let's start with disable_src one. v2: Rebased on top of commit d2419ffc10e4 ("drm/i915: Plumb crtc_state to PSR enable/disable") Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-3-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/intel_psr.c | 12 +++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 63ca2ffcafef..d24793cdf949 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1180,6 +1180,9 @@ struct i915_psr { bool y_cord_support; bool colorimetry_support; bool alpm; + + void (*disable_source)(struct intel_dp *, + const struct intel_crtc_state *); }; enum intel_pch { diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 60a1ece6d4c9..1d2b52e6a6d4 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -685,11 +685,7 @@ void intel_psr_disable(struct intel_dp *intel_dp, return; } - /* Disable PSR on Source */ - if (HAS_DDI(dev_priv)) - hsw_psr_disable(intel_dp, old_crtc_state); - else - vlv_psr_disable(intel_dp, old_crtc_state); + dev_priv->psr.disable_source(intel_dp, old_crtc_state); /* Disable PSR on Sink */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); @@ -987,4 +983,10 @@ void intel_psr_init(struct drm_i915_private *dev_priv) INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work); mutex_init(&dev_priv->psr.lock); + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + dev_priv->psr.disable_source = vlv_psr_disable; + } else { + dev_priv->psr.disable_source = hsw_psr_disable; + } } -- cgit v1.2.3 From ed63d24b4d19aee649fbec28b7c11e887eff6861 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:33 -0700 Subject: drm/i915/psr: hsw_psr_activate. On HSW+ the real activate of PSR is decided by the source after certain amount of configured idle frames. However for the driver perspective where we track psr.active variable this function here is the actual activate one. So let's rename it before moving to vfunc with that. v2: Fix typo on commit message (DK). Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-4-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_psr.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 1d2b52e6a6d4..92b3db3aa830 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -263,7 +263,7 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) VLV_EDP_PSR_ACTIVE_ENTRY); } -static void intel_enable_source_psr1(struct intel_dp *intel_dp) +static void hsw_activate_psr1(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; @@ -317,7 +317,7 @@ static void intel_enable_source_psr1(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR_CTL, val); } -static void intel_enable_source_psr2(struct intel_dp *intel_dp) +static void hsw_activate_psr2(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; @@ -353,17 +353,22 @@ static void intel_enable_source_psr2(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR2_CTL, val); } -static void hsw_psr_enable_source(struct intel_dp *intel_dp) +static void hsw_psr_activate(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + /* On HSW+ after we enable PSR on source it will activate it + * as soon as it match configure idle_frame count. So + * we just actually enable it here on activation time. + */ + /* psr1 and psr2 are mutually exclusive.*/ if (dev_priv->psr.psr2_support) - intel_enable_source_psr2(intel_dp); + hsw_activate_psr2(intel_dp); else - intel_enable_source_psr1(intel_dp); + hsw_activate_psr1(intel_dp); } static bool intel_psr_match_conditions(struct intel_dp *intel_dp) @@ -469,11 +474,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) /* Enable/Re-enable PSR on the host */ if (HAS_DDI(dev_priv)) - /* On HSW+ after we enable PSR on source it will activate it - * as soon as it match configure idle_frame count. So - * we just actually enable it here on activation time. - */ - hsw_psr_enable_source(intel_dp); + hsw_psr_activate(intel_dp); else vlv_psr_activate(intel_dp); -- cgit v1.2.3 From e3702ac9a2c128690b2219eb1282367584a3b7bb Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:34 -0700 Subject: drm/i915/psr: Add activate vfunc. Continue on VLV PSR split with vfunc, let's move activate function there. Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-5-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_psr.c | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d24793cdf949..fa279f3cc838 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1183,6 +1183,7 @@ struct i915_psr { void (*disable_source)(struct intel_dp *, const struct intel_crtc_state *); + void (*activate)(struct intel_dp *); }; enum intel_pch { diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 92b3db3aa830..b3c1e601a8b2 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -472,12 +472,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) WARN_ON(dev_priv->psr.active); lockdep_assert_held(&dev_priv->psr.lock); - /* Enable/Re-enable PSR on the host */ - if (HAS_DDI(dev_priv)) - hsw_psr_activate(intel_dp); - else - vlv_psr_activate(intel_dp); - + dev_priv->psr.activate(intel_dp); dev_priv->psr.active = true; } @@ -987,7 +982,9 @@ void intel_psr_init(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->psr.disable_source = vlv_psr_disable; + dev_priv->psr.activate = vlv_psr_activate; } else { dev_priv->psr.disable_source = hsw_psr_disable; + dev_priv->psr.activate = hsw_psr_activate; } } -- cgit v1.2.3 From 2ce4df87f133913dff26ae0f578d6b46f01fa6d3 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:35 -0700 Subject: drm/i915/psr: Unify VSC setup functions. VSC package is decided per eDP spec for psr1 or psr2, and not per platform, so let's unify it and kill "skl" func. v2: Rebased on top of commit d2419ffc10e4 ("drm/i915: Plumb crtc_state to PSR enable/disable") Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-6-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_psr.c | 61 ++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index b3c1e601a8b2..eca6170becdc 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -117,46 +117,41 @@ static void vlv_psr_setup_vsc(struct intel_dp *intel_dp, I915_WRITE(VLV_VSCSDP(crtc->pipe), val); } -static void skl_psr_setup_su_vsc(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) +static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); struct edp_vsc_psr psr_vsc; - /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ - memset(&psr_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - if (dev_priv->psr.colorimetry_support && - dev_priv->psr.y_cord_support) { - psr_vsc.sdp_header.HB2 = 0x5; - psr_vsc.sdp_header.HB3 = 0x13; - } else if (dev_priv->psr.y_cord_support) { - psr_vsc.sdp_header.HB2 = 0x4; - psr_vsc.sdp_header.HB3 = 0xe; + if (dev_priv->psr.psr2_support) { + /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + if (dev_priv->psr.colorimetry_support && + dev_priv->psr.y_cord_support) { + psr_vsc.sdp_header.HB2 = 0x5; + psr_vsc.sdp_header.HB3 = 0x13; + } else if (dev_priv->psr.y_cord_support) { + psr_vsc.sdp_header.HB2 = 0x4; + psr_vsc.sdp_header.HB3 = 0xe; + } else { + psr_vsc.sdp_header.HB2 = 0x3; + psr_vsc.sdp_header.HB3 = 0xc; + } } else { - psr_vsc.sdp_header.HB2 = 0x3; - psr_vsc.sdp_header.HB3 = 0xc; + /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; } intel_psr_write_vsc(intel_dp, &psr_vsc); } -static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct edp_vsc_psr psr_vsc; - - /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */ - memset(&psr_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - intel_psr_write_vsc(intel_dp, &psr_vsc); -} - static void vlv_psr_enable_sink(struct intel_dp *intel_dp) { drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, @@ -512,9 +507,10 @@ void intel_psr_enable(struct intel_dp *intel_dp, dev_priv->psr.busy_frontbuffer_bits = 0; if (HAS_DDI(dev_priv)) { - if (dev_priv->psr.psr2_support) { - skl_psr_setup_su_vsc(intel_dp, crtc_state); + hsw_psr_setup_vsc(intel_dp, crtc_state); + + if (dev_priv->psr.psr2_support) { chicken = PSR2_VSC_ENABLE_PROG_HEADER; if (dev_priv->psr.y_cord_support) chicken |= PSR2_ADD_VERTICAL_LINE_COUNT; @@ -527,9 +523,6 @@ void intel_psr_enable(struct intel_dp *intel_dp, EDP_PSR_DEBUG_MASK_MAX_SLEEP | EDP_PSR_DEBUG_MASK_DISP_REG_WRITE); } else { - /* set up vsc header for psr1 */ - hsw_psr_setup_vsc(intel_dp, crtc_state); - /* * Per Spec: Avoid continuous PSR exit by masking MEMUP * and HPD. also mask LPSP to avoid dependency on other -- cgit v1.2.3 From 4d1fa22f4372f27ebbf2376de79a665d23623c8c Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:36 -0700 Subject: drm/i915/psr: Re-create a hsw_psr_enable_source. This sequence is part of enable source anyways, but they only need to be executed once and not on every activation, So let's re-create hsw_enable_source. v2: Avoid changing order here to avoid changing behaviour as suggested by Jani. v3: Rebased on top of commit d2419ffc10e4 ("drm/i915: Plumb crtc_state to PSR enable/disable") Cc: Jani Nikula Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-7-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_psr.c | 70 +++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index eca6170becdc..575c8b93e96f 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -471,6 +471,42 @@ static void intel_psr_activate(struct intel_dp *intel_dp) dev_priv->psr.active = true; } +static void hsw_psr_enable_source(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u32 chicken; + + if (dev_priv->psr.psr2_support) { + chicken = PSR2_VSC_ENABLE_PROG_HEADER; + if (dev_priv->psr.y_cord_support) + chicken |= PSR2_ADD_VERTICAL_LINE_COUNT; + I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); + + I915_WRITE(EDP_PSR_DEBUG_CTL, + EDP_PSR_DEBUG_MASK_MEMUP | + EDP_PSR_DEBUG_MASK_HPD | + EDP_PSR_DEBUG_MASK_LPSP | + EDP_PSR_DEBUG_MASK_MAX_SLEEP | + EDP_PSR_DEBUG_MASK_DISP_REG_WRITE); + } else { + /* + * Per Spec: Avoid continuous PSR exit by masking MEMUP + * and HPD. also mask LPSP to avoid dependency on other + * drivers that might block runtime_pm besides + * preventing other hw tracking issues now we can rely + * on frontbuffer tracking. + */ + I915_WRITE(EDP_PSR_DEBUG_CTL, + EDP_PSR_DEBUG_MASK_MEMUP | + EDP_PSR_DEBUG_MASK_HPD | + EDP_PSR_DEBUG_MASK_LPSP); + } +} + /** * intel_psr_enable - Enable PSR * @intel_dp: Intel DP @@ -484,8 +520,6 @@ void intel_psr_enable(struct intel_dp *intel_dp, struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 chicken; if (!HAS_PSR(dev_priv)) return; @@ -510,31 +544,7 @@ void intel_psr_enable(struct intel_dp *intel_dp, hsw_psr_setup_vsc(intel_dp, crtc_state); - if (dev_priv->psr.psr2_support) { - chicken = PSR2_VSC_ENABLE_PROG_HEADER; - if (dev_priv->psr.y_cord_support) - chicken |= PSR2_ADD_VERTICAL_LINE_COUNT; - I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); - - I915_WRITE(EDP_PSR_DEBUG_CTL, - EDP_PSR_DEBUG_MASK_MEMUP | - EDP_PSR_DEBUG_MASK_HPD | - EDP_PSR_DEBUG_MASK_LPSP | - EDP_PSR_DEBUG_MASK_MAX_SLEEP | - EDP_PSR_DEBUG_MASK_DISP_REG_WRITE); - } else { - /* - * Per Spec: Avoid continuous PSR exit by masking MEMUP - * and HPD. also mask LPSP to avoid dependency on other - * drivers that might block runtime_pm besides - * preventing other hw tracking issues now we can rely - * on frontbuffer tracking. - */ - I915_WRITE(EDP_PSR_DEBUG_CTL, - EDP_PSR_DEBUG_MASK_MEMUP | - EDP_PSR_DEBUG_MASK_HPD | - EDP_PSR_DEBUG_MASK_LPSP); - } + hsw_psr_enable_source(intel_dp, crtc_state); /* Enable PSR on the panel */ hsw_psr_enable_sink(intel_dp); @@ -547,12 +557,6 @@ void intel_psr_enable(struct intel_dp *intel_dp, /* Enable PSR on the panel */ vlv_psr_enable_sink(intel_dp); - /* On HSW+ enable_source also means go to PSR entry/active - * state as soon as idle_frame achieved and here would be - * to soon. However on VLV enable_source just enable PSR - * but let it on inactive state. So we might do this prior - * to active transition, i.e. here. - */ vlv_psr_enable_source(intel_dp, crtc_state); } -- cgit v1.2.3 From 196cebddde80dd06b2de557ea393082bf5a06c3d Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:37 -0700 Subject: drm/i915/psr: Move hsw_enable_source after enabling sink. No functional change is expected here since at this point PSR is not allowed to go to any active state. In other words, not really enabled. However let's do in a separated patch so it gets clear on what is change and specially it can helps on bisect case if we figure something has caused changes in behaviour. But this needs to be done before we make the vfunc to enable source to be in parity with VLV implementation. Cc: Jani Nikula Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-8-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_psr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 575c8b93e96f..245cf3ee979f 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -544,11 +544,11 @@ void intel_psr_enable(struct intel_dp *intel_dp, hsw_psr_setup_vsc(intel_dp, crtc_state); - hsw_psr_enable_source(intel_dp, crtc_state); - /* Enable PSR on the panel */ hsw_psr_enable_sink(intel_dp); + hsw_psr_enable_source(intel_dp, crtc_state); + if (INTEL_GEN(dev_priv) >= 9) intel_psr_activate(intel_dp); } else { -- cgit v1.2.3 From 29d1efe070d3cb5c52d51d82af71790ffaf0a64f Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:38 -0700 Subject: drm/i915/psr: Re-org Activate after enable Let's move the activation calls together after enable is done. No real functional change should be expected here. Just an attempt to get it clear when we are really activating PSR after enabling it. v2: Add braces on if/else because commit message there is too long as suggested by Jani. v3: Rebased on top of commit d2419ffc10e4 ("drm/i915: Plumb crtc_state to PSR enable/disable") Cc: Jani Nikula Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-9-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_psr.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 245cf3ee979f..7031dfd50ae9 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -549,8 +549,6 @@ void intel_psr_enable(struct intel_dp *intel_dp, hsw_psr_enable_source(intel_dp, crtc_state); - if (INTEL_GEN(dev_priv) >= 9) - intel_psr_activate(intel_dp); } else { vlv_psr_setup_vsc(intel_dp, crtc_state); @@ -560,20 +558,25 @@ void intel_psr_enable(struct intel_dp *intel_dp, vlv_psr_enable_source(intel_dp, crtc_state); } - /* - * FIXME: Activation should happen immediately since this function - * is just called after pipe is fully trained and enabled. - * However on every platform we face issues when first activation - * follows a modeset so quickly. - * - On VLV/CHV we get bank screen on first activation - * - On HSW/BDW we get a recoverable frozen screen until next - * exit-activate sequence. - */ - if (INTEL_GEN(dev_priv) < 9) + dev_priv->psr.enabled = intel_dp; + + if (INTEL_GEN(dev_priv) >= 9) { + intel_psr_activate(intel_dp); + } else { + /* + * FIXME: Activation should happen immediately since this + * function is just called after pipe is fully trained and + * enabled. + * However on some platforms we face issues when first + * activation follows a modeset so quickly. + * - On VLV/CHV we get bank screen on first activation + * - On HSW/BDW we get a recoverable frozen screen until + * next exit-activate sequence. + */ schedule_delayed_work(&dev_priv->psr.work, msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5)); + } - dev_priv->psr.enabled = intel_dp; unlock: mutex_unlock(&dev_priv->psr.lock); } -- cgit v1.2.3 From 2a5db87f82cb6b2763d5e07cc4eef8cd94e56395 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:39 -0700 Subject: drm/i915/psr: Add setup VSC vfunc. Continue on VLV PSR split with vfunc, let's also create one for setting up VSC. v2: Rebased on top of commit d2419ffc10e4 ("drm/i915: Plumb crtc_state to PSR enable/disable") Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-10-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_psr.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fa279f3cc838..54786bc73263 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1184,6 +1184,7 @@ struct i915_psr { void (*disable_source)(struct intel_dp *, const struct intel_crtc_state *); void (*activate)(struct intel_dp *); + void (*setup_vsc)(struct intel_dp *, const struct intel_crtc_state *); }; enum intel_pch { diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 7031dfd50ae9..2516d2a50022 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -540,18 +540,15 @@ void intel_psr_enable(struct intel_dp *intel_dp, dev_priv->psr.busy_frontbuffer_bits = 0; - if (HAS_DDI(dev_priv)) { - - hsw_psr_setup_vsc(intel_dp, crtc_state); + dev_priv->psr.setup_vsc(intel_dp, crtc_state); + if (HAS_DDI(dev_priv)) { /* Enable PSR on the panel */ hsw_psr_enable_sink(intel_dp); hsw_psr_enable_source(intel_dp, crtc_state); } else { - vlv_psr_setup_vsc(intel_dp, crtc_state); - /* Enable PSR on the panel */ vlv_psr_enable_sink(intel_dp); @@ -983,8 +980,10 @@ void intel_psr_init(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->psr.disable_source = vlv_psr_disable; dev_priv->psr.activate = vlv_psr_activate; + dev_priv->psr.setup_vsc = vlv_psr_setup_vsc; } else { dev_priv->psr.disable_source = hsw_psr_disable; dev_priv->psr.activate = hsw_psr_activate; + dev_priv->psr.setup_vsc = hsw_psr_setup_vsc; } } -- cgit v1.2.3 From 49ad316f87f17b8eaf6985c7baac7bc069dccddc Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:40 -0700 Subject: drm/i915/psr: Add enable_sink vfunc. Continue on VLV PSR split with vfunc, let's also create one for enabling sink. v2: Fix typo on commit message (DK). Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-11-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_psr.c | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 54786bc73263..4efc2b591f6f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1183,6 +1183,7 @@ struct i915_psr { void (*disable_source)(struct intel_dp *, const struct intel_crtc_state *); + void (*enable_sink)(struct intel_dp *); void (*activate)(struct intel_dp *); void (*setup_vsc)(struct intel_dp *, const struct intel_crtc_state *); }; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 2516d2a50022..02c32cc38648 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -541,17 +541,12 @@ void intel_psr_enable(struct intel_dp *intel_dp, dev_priv->psr.busy_frontbuffer_bits = 0; dev_priv->psr.setup_vsc(intel_dp, crtc_state); + dev_priv->psr.enable_sink(intel_dp); if (HAS_DDI(dev_priv)) { - /* Enable PSR on the panel */ - hsw_psr_enable_sink(intel_dp); - hsw_psr_enable_source(intel_dp, crtc_state); } else { - /* Enable PSR on the panel */ - vlv_psr_enable_sink(intel_dp); - vlv_psr_enable_source(intel_dp, crtc_state); } @@ -979,10 +974,12 @@ void intel_psr_init(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->psr.disable_source = vlv_psr_disable; + dev_priv->psr.enable_sink = vlv_psr_enable_sink; dev_priv->psr.activate = vlv_psr_activate; dev_priv->psr.setup_vsc = vlv_psr_setup_vsc; } else { dev_priv->psr.disable_source = hsw_psr_disable; + dev_priv->psr.enable_sink = hsw_psr_enable_sink; dev_priv->psr.activate = hsw_psr_activate; dev_priv->psr.setup_vsc = hsw_psr_setup_vsc; } -- cgit v1.2.3 From d0d5e0d7b11359ccdc7276339ec29d98f4739453 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:00:41 -0700 Subject: drm/i915/psr: Add enable_source vfunc. Continue on VLV PSR split with vfunc, let's also create one for enabling source. Also since we are touching *_enable_source functions let's fix a comment with wrong name for vlv's one. v2: Fix typo on commit message (DK). Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Cc: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230041.22978-12-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_psr.c | 14 ++++---------- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4efc2b591f6f..ec70121410e4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1181,6 +1181,8 @@ struct i915_psr { bool colorimetry_support; bool alpm; + void (*enable_source)(struct intel_dp *, + const struct intel_crtc_state *); void (*disable_source)(struct intel_dp *, const struct intel_crtc_state *); void (*enable_sink)(struct intel_dp *); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 02c32cc38648..fdd9e3d95efb 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -542,14 +542,7 @@ void intel_psr_enable(struct intel_dp *intel_dp, dev_priv->psr.setup_vsc(intel_dp, crtc_state); dev_priv->psr.enable_sink(intel_dp); - - if (HAS_DDI(dev_priv)) { - hsw_psr_enable_source(intel_dp, crtc_state); - - } else { - vlv_psr_enable_source(intel_dp, crtc_state); - } - + dev_priv->psr.enable_source(intel_dp, crtc_state); dev_priv->psr.enabled = intel_dp; if (INTEL_GEN(dev_priv) >= 9) { @@ -777,8 +770,7 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv) * directly once PSR State 4 that is active with single frame * update can be skipped. PSR_state 5 that is PSR exit then * Hardware is responsible to transition back to PSR_state 1 - * that is PSR inactive. Same state after - * vlv_edp_psr_enable_source. + * that is PSR inactive. Same state after vlv_psr_enable_source. */ val &= ~VLV_EDP_PSR_ACTIVE_ENTRY; I915_WRITE(VLV_PSRCTL(pipe), val); @@ -973,11 +965,13 @@ void intel_psr_init(struct drm_i915_private *dev_priv) mutex_init(&dev_priv->psr.lock); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + dev_priv->psr.enable_source = vlv_psr_enable_source; dev_priv->psr.disable_source = vlv_psr_disable; dev_priv->psr.enable_sink = vlv_psr_enable_sink; dev_priv->psr.activate = vlv_psr_activate; dev_priv->psr.setup_vsc = vlv_psr_setup_vsc; } else { + dev_priv->psr.enable_source = hsw_psr_enable_source; dev_priv->psr.disable_source = hsw_psr_disable; dev_priv->psr.enable_sink = hsw_psr_enable_sink; dev_priv->psr.activate = hsw_psr_activate; -- cgit v1.2.3 From 3164888a40469c102b5d6d1b756c7646e7eb19e7 Mon Sep 17 00:00:00 2001 From: Marta Lofstedt Date: Fri, 8 Sep 2017 16:28:29 +0300 Subject: drm/i915: Increase poll time for BDW FCLK_DONE During IGT testing it has been shown that the specification defined polling time of 1 us for FCLK_DONE, is sometimes not enough. The issue is still reproducible while disabling C-states through the PM QoS framework and also while disabling preemtion. From this the most plausible explanation is that the issue is due to a firmware flaw. As a workaround, it is better to wait a little bit longer for the FCLK_DONE to come around, than to leave with an DRM_ERROR and having FCLK_DONE at a randome time after. While spinning a list of igt tests prone to reproduce the issue the FCLK_DONE poll failed at approximately 2% of the invocations of the bdw_set_cdclk function. The longest poll time during this testing was measured to ~7us. So, the suggested new poll time of 100us is on the safe side. v2: Added more documentation about investigations done. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102243 Signed-off-by: Marta Lofstedt Reviewed-by: Daniel Vetter Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20170908132829.6312-1-marta.lofstedt@intel.com --- drivers/gpu/drm/i915/intel_cdclk.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index d32911816fc2..87fc42b19336 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -669,8 +669,12 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv, val |= LCPLL_CD_SOURCE_FCLK; I915_WRITE(LCPLL_CTL, val); + /* + * According to the spec, it should be enough to poll for this 1 us. + * However, extensive testing shows that this can take longer. + */ if (wait_for_us(I915_READ(LCPLL_CTL) & - LCPLL_CD_SOURCE_FCLK_DONE, 1)) + LCPLL_CD_SOURCE_FCLK_DONE, 100)) DRM_ERROR("Switching to FCLK failed\n"); val = I915_READ(LCPLL_CTL); -- cgit v1.2.3 From c3881128cb672cf484a52fbb36b5daa9044d9168 Mon Sep 17 00:00:00 2001 From: "Lee, Shawn C" Date: Tue, 12 Sep 2017 11:36:30 +0800 Subject: drm/i915/bxt: set min brightness from VBT Min brightness value from vbt was missing for BXT platform. This setting have to refer backlight ic spec to restrict min backlight output. Without this restriction, driver would allow to configure lower brightness value and violate backlight ic requirement. Fixes: 0fb890c01349 ("drm/i915/bxt: BLC implementation") Cc: Jani Nikula Cc: Cooper Chiou Cc: Gary C Wang Signed-off-by: Shawn Lee Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/1505187390-7039-1-git-send-email-shawn.c.lee@intel.com --- drivers/gpu/drm/i915/intel_panel.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index a17b1de7d7e0..d4dd248ac9a8 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1699,6 +1699,8 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) if (!panel->backlight.max) return -ENODEV; + panel->backlight.min = get_backlight_min_vbt(connector); + val = bxt_get_backlight(connector); val = intel_panel_compute_brightness(connector, val); panel->backlight.level = clamp(val, panel->backlight.min, -- cgit v1.2.3 From 36e16c49dbfec806754862f63136de552d4de4ba Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Tue, 12 Sep 2017 15:42:24 +0800 Subject: drm/i915: Factor out setup_private_pat() Factor out setup_private_pat() for introducing the following patches. Signed-off-by: Zhi Wang Cc: Ben Widawsky Cc: Rodrigo Vivi Cc: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Chris Wilson Reviewed-by: Ben Widawsky Link: https://patchwork.freedesktop.org/patch/msgid/1505202148-22959-1-git-send-email-zhi.a.wang@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_gtt.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 33181d6eac3f..09e524dbc090 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2918,6 +2918,16 @@ static void gen6_gmch_remove(struct i915_address_space *vm) cleanup_scratch_page(vm); } +static void setup_private_pat(struct drm_i915_private *dev_priv) +{ + if (INTEL_GEN(dev_priv) >= 10) + cnl_setup_private_ppat(dev_priv); + else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) + chv_setup_private_ppat(dev_priv); + else + bdw_setup_private_ppat(dev_priv); +} + static int gen8_gmch_probe(struct i915_ggtt *ggtt) { struct drm_i915_private *dev_priv = ggtt->base.i915; @@ -2950,14 +2960,6 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) } ggtt->base.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT; - - if (INTEL_GEN(dev_priv) >= 10) - cnl_setup_private_ppat(dev_priv); - else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) - chv_setup_private_ppat(dev_priv); - else - bdw_setup_private_ppat(dev_priv); - ggtt->base.cleanup = gen6_gmch_remove; ggtt->base.bind_vma = ggtt_bind_vma; ggtt->base.unbind_vma = ggtt_unbind_vma; @@ -2978,6 +2980,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) ggtt->invalidate = gen6_ggtt_invalidate; + setup_private_pat(dev_priv); + return ggtt_probe_common(ggtt, size); } -- cgit v1.2.3 From 3e8ddd9e5071841827ec32a7a5ff11eaac5ad3d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 12 Sep 2017 18:34:10 +0300 Subject: drm/i915: Nuke some bogus tabs from the pcode defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170912153411.20171-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_reg.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0b03260a3967..f9f9fcc833c5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7954,8 +7954,8 @@ enum { #define GEN7_PCODE_TIMEOUT 0x2 #define GEN7_PCODE_ILLEGAL_DATA 0x3 #define GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE 0x10 -#define GEN6_PCODE_WRITE_RC6VIDS 0x4 -#define GEN6_PCODE_READ_RC6VIDS 0x5 +#define GEN6_PCODE_WRITE_RC6VIDS 0x4 +#define GEN6_PCODE_READ_RC6VIDS 0x5 #define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5) #define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245) #define BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ 0x18 @@ -7974,7 +7974,7 @@ enum { #define GEN6_PCODE_WRITE_D_COMP 0x11 #define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17 #define DISPLAY_IPS_CONTROL 0x19 -#define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A +#define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A #define GEN9_PCODE_SAGV_CONTROL 0x21 #define GEN9_SAGV_DISABLE 0x0 #define GEN9_SAGV_IS_DISABLED 0x1 -- cgit v1.2.3 From 61843f0e6212a8592cba26ff554af4af0dd93778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 12 Sep 2017 18:34:11 +0300 Subject: drm/i915: Name the IPS_PCODE_CONTROL bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Give a name to the bit which tells pcode to control IPS. v2: Note that IPS_CTL bits apply to DISPLAY_IPS_CONTROL as well (Chris) Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170912153411.20171-2-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_display.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f9f9fcc833c5..9f03cd063afe 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7974,6 +7974,8 @@ enum { #define GEN6_PCODE_WRITE_D_COMP 0x11 #define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17 #define DISPLAY_IPS_CONTROL 0x19 + /* See also IPS_CTL */ +#define IPS_PCODE_CONTROL (1 << 30) #define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A #define GEN9_PCODE_SAGV_CONTROL 0x21 #define GEN9_SAGV_DISABLE 0x0 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dbe7d8682c97..c4d8bb75686a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4956,7 +4956,8 @@ void hsw_enable_ips(struct intel_crtc *crtc) assert_plane_enabled(dev_priv, crtc->plane); if (IS_BROADWELL(dev_priv)) { mutex_lock(&dev_priv->rps.hw_lock); - WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000)); + WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, + IPS_ENABLE | IPS_PCODE_CONTROL)); mutex_unlock(&dev_priv->rps.hw_lock); /* Quoting Art Runyan: "its not safe to expect any particular * value in IPS_CTL bit 31 after enabling IPS through the -- cgit v1.2.3 From 4ebc65092ca3d9713d48ea43e7db5b3f07faf1bc Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 8 Sep 2017 17:42:55 -0700 Subject: drm/i915/spt+: Don't reset invalid AUX channel interrupt bits in SDEIMR The SDE interrupt bits 25, 26 and 27 are either reserved or meant for DDI E hotplug in SPT+. These bits are meant for AUX channels only in LPT and CPT, so add the appropriate checks. Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20170909004255.14827-1-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5d391e689070..91a2c5dbf2da 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3241,8 +3241,10 @@ static void ibx_irq_postinstall(struct drm_device *dev) if (HAS_PCH_IBX(dev_priv)) mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; - else + else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; + else + mask = SDE_GMBUS_CPT; gen5_assert_iir_is_zero(dev_priv, SDEIIR); I915_WRITE(SDEIMR, ~mask); -- cgit v1.2.3 From ac70ebe873f5161e46fbd3a5ed318f7c34d0d157 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Sep 2017 16:07:52 +0100 Subject: drm/i915: Cleanup error paths through eb_lookup_vma() Following the simplification to a single lookup loop in commit 170fa29b14fa ("drm/i915: Simplify eb_lookup_vmas()") and commit d1b48c1e7184 ("drm/i915: Replace execbuf vma ht with an idr"), we can go one step further and reorder the error paths so that the state of the local variable obj is always known to the compiler and doesn't need the uninitialized_var markup to squelch a compiler warning. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170912150752.20411-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7687483ff218..214a850b4b3c 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -679,7 +679,7 @@ static int eb_select_context(struct i915_execbuffer *eb) static int eb_lookup_vmas(struct i915_execbuffer *eb) { struct radix_tree_root *handles_vma = &eb->ctx->handles_vma; - struct drm_i915_gem_object *uninitialized_var(obj); + struct drm_i915_gem_object *obj; unsigned int i; int err; @@ -725,19 +725,17 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) goto err_obj; } + /* transfer ref to ctx */ vma->open_count++; list_add(&lut->obj_link, &obj->lut_list); list_add(&lut->ctx_link, &eb->ctx->handles_list); lut->ctx = eb->ctx; lut->handle = handle; - /* transfer ref to ctx */ - obj = NULL; - add_vma: err = eb_add_vma(eb, i, vma); if (unlikely(err)) - goto err_obj; + goto err_vma; GEM_BUG_ON(vma != eb->vma[i]); GEM_BUG_ON(vma->exec_flags != &eb->flags[i]); @@ -766,8 +764,7 @@ add_vma: return eb_reserve(eb); err_obj: - if (obj) - i915_gem_object_put(obj); + i915_gem_object_put(obj); err_vma: eb->vma[i] = NULL; return err; -- cgit v1.2.3 From 33c8d8870c67faf3161898a56af98ac3c1c71450 Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Tue, 5 Sep 2017 15:14:31 +0530 Subject: Revert "drm/i915/bxt: Disable device ready before shutdown command" This reverts commit bbdf0b2ff32a ("drm/i915/bxt: Disable device ready before shutdown command"). Disable device ready before shutdown command was added previously to avoid a split screen issue seen on dual link DSI panels. As of now, dual link is not supported and will need some rework in the upstream code. For single link DSI panels, the change is not required. This will cause failure in sending SHUTDOWN packet during disable. Hence reverting the change. Will handle the change as part of dual link enabling in upstream. Fixes: bbdf0b2ff32a ("drm/i915/bxt: Disable device ready before shutdown command") Cc: # v4.12+ Signed-off-by: Uma Shankar Signed-off-by: Vidya Srinivas Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/1504604671-17237-1-git-send-email-vidya.srinivas@intel.com --- drivers/gpu/drm/i915/intel_dsi.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 2a0f5d337bea..fc25d7d2d942 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -892,8 +892,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; @@ -902,15 +900,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder, intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_OFF); intel_panel_disable_backlight(old_conn_state); - /* - * Disable Device ready before the port shutdown in order - * to avoid split screen - */ - if (IS_BROXTON(dev_priv)) { - for_each_dsi_port(port, intel_dsi->ports) - I915_WRITE(MIPI_DEVICE_READY(port), 0); - } - /* * According to the spec we should send SHUTDOWN before * MIPI_SEQ_DISPLAY_OFF only for v3+ VBTs, but field testing -- cgit v1.2.3 From f44e354f857f207cd361269c5e38e1f96e0b616c Mon Sep 17 00:00:00 2001 From: "Lee, Shawn C" Date: Wed, 13 Sep 2017 13:19:20 +0800 Subject: drm/i915/cnp: set min brightness from VBT Min brightness value from vbt was missing for CNP platform. This setting have to refer backlight ic spec to restrict min backlight output. Without this restriction, driver would allow to configure lower brightness value and violate backlight ic requirement. Fixes: 4c9f7086ac6d ("drm/i915/cnp: Backlight support for CNP.") Cc: Jani Nikula Signed-off-by: Shawn Lee Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/1505279961-16140-1-git-send-email-shawn.c.lee@intel.com --- drivers/gpu/drm/i915/intel_panel.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index d4dd248ac9a8..3b1c5d783ee7 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1737,6 +1737,8 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) if (!panel->backlight.max) return -ENODEV; + panel->backlight.min = get_backlight_min_vbt(connector); + val = bxt_get_backlight(connector); val = intel_panel_compute_brightness(connector, val); panel->backlight.level = clamp(val, panel->backlight.min, -- cgit v1.2.3 From 5b60fc09806a9db0fb46e6821bc1ed3203b6740e Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 1 Sep 2017 10:51:01 +0300 Subject: drm/i915/dsi: Replace MIPI command error message with debug message Error message indicating that the same MIPI command is sent consecutively is perhaps too strongly said. Let's replace that as a debug message instead. Signed-off-by: Mika Kahola Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/1504252261-28964-3-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index fc25d7d2d942..578254ac799c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -263,7 +263,7 @@ static int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs, /* XXX: old code skips write if control unchanged */ if (cmd == I915_READ(MIPI_DPI_CONTROL(port))) - DRM_ERROR("Same special packet %02x twice in a row.\n", cmd); + DRM_DEBUG_KMS("Same special packet %02x twice in a row.\n", cmd); I915_WRITE(MIPI_DPI_CONTROL(port), cmd); -- cgit v1.2.3 From 2013ddebd2f4b5ef90625c8b82da216df0123134 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Sep 2017 22:49:05 +0100 Subject: drm/i915: Move the context descriptor to an inline helper The context descriptor is stored inside the per-engine context state, as we only need to compute it once and access it frequently. However, currently only intel_lrc.c has easy access, but i915_guc_submission.c would like to frequently read it as well, and more so only ever needs the lower 32bits. Make it an inline as the compiler should be able to retrieve the value in less instructions than it takes to do the function call: add/remove: 0/1 grow/shrink: 1/0 up/down: 8/-45 (-37) function old new delta i915_guc_submit 621 629 +8 intel_lr_context_descriptor 45 - -45 Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170912214905.21987-1-chris@chris-wilson.co.uk Reviewed-by: Oscar Mateo --- drivers/gpu/drm/i915/intel_lrc.c | 6 ------ drivers/gpu/drm/i915/intel_lrc.h | 11 +++++++++-- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d89e1b8e1cc5..9e4342b8e52b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -286,12 +286,6 @@ intel_lr_context_descriptor_update(struct i915_gem_context *ctx, ce->lrc_desc = desc; } -uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx, - struct intel_engine_cs *engine) -{ - return ctx->engine[engine->id].lrc_desc; -} - static inline void execlists_context_status_change(struct drm_i915_gem_request *rq, unsigned long status) diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 57ef5833c427..3b1de327e504 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -25,6 +25,7 @@ #define _INTEL_LRC_H_ #include "intel_ringbuffer.h" +#include "i915_gem_context.h" #define GEN8_LR_CONTEXT_ALIGN I915_GTT_MIN_ALIGNMENT @@ -78,8 +79,14 @@ struct drm_i915_private; struct i915_gem_context; void intel_lr_context_resume(struct drm_i915_private *dev_priv); -uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx, - struct intel_engine_cs *engine); + +static inline uint64_t +intel_lr_context_descriptor(struct i915_gem_context *ctx, + struct intel_engine_cs *engine) +{ + return ctx->engine[engine->id].lrc_desc; +} + /* Execlists */ int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv, -- cgit v1.2.3 From e9eb8039ba0cb902817fafb5a0217dba0544f165 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Tue, 12 Sep 2017 14:36:35 -0700 Subject: drm/i915/guc: Name the default GuC scheduling policy The default values for the default scheduling policy come from the GuC firmware itself. Transform the magic numbers into defines. Suggested-by: Joonas Lahtinen Signed-off-by: Oscar Mateo Link: https://patchwork.freedesktop.org/patch/msgid/1505252197-27696-1-git-send-email-oscar.mateo@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_guc_submission.c | 15 ++++++++++----- drivers/gpu/drm/i915/intel_guc_fwif.h | 6 +++++- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 48a1e9349a2c..0f1536edc1ea 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -996,22 +996,27 @@ static void guc_client_free(struct i915_guc_client *client) kfree(client); } +static void guc_policy_init(struct guc_policy *policy) +{ + policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US; + policy->preemption_time = POLICY_DEFAULT_PREEMPTION_TIME_US; + policy->fault_time = POLICY_DEFAULT_FAULT_TIME_US; + policy->policy_flags = 0; +} + static void guc_policies_init(struct guc_policies *policies) { struct guc_policy *policy; u32 p, i; - policies->dpc_promote_time = 500000; + policies->dpc_promote_time = POLICY_DEFAULT_DPC_PROMOTE_TIME_US; policies->max_num_work_items = POLICY_MAX_NUM_WI; for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) { for (i = GUC_RENDER_ENGINE; i < GUC_MAX_ENGINES_NUM; i++) { policy = &policies->policy[p][i]; - policy->execution_quantum = 1000000; - policy->preemption_time = 500000; - policy->fault_time = 250000; - policy->policy_flags = 0; + guc_policy_init(policy); } } diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 5fa286074811..83bd401196eb 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -388,7 +388,11 @@ struct guc_ct_buffer_desc { /* Preempt to idle on quantum expiry */ #define POLICY_PREEMPT_TO_IDLE (1<<1) -#define POLICY_MAX_NUM_WI 15 +#define POLICY_MAX_NUM_WI 15 +#define POLICY_DEFAULT_DPC_PROMOTE_TIME_US 500000 +#define POLICY_DEFAULT_EXECUTION_QUANTUM_US 1000000 +#define POLICY_DEFAULT_PREEMPTION_TIME_US 500000 +#define POLICY_DEFAULT_FAULT_TIME_US 250000 struct guc_policy { /* Time for one workload to execute. (in micro seconds) */ -- cgit v1.2.3 From 048d2847d76df2a7e801d77d411216910b0643c4 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Tue, 12 Sep 2017 14:36:36 -0700 Subject: drm/i915/guc: Remove WQ_WORKLOAD_SHIFT define We never used it in i915 and it's going to be removed in newer GuC firmwares anyway. Signed-off-by: Oscar Mateo Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/1505252197-27696-2-git-send-email-oscar.mateo@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_guc_fwif.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 83bd401196eb..7eb6b4fa1d6f 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -56,10 +56,6 @@ #define WQ_LEN_SHIFT 16 #define WQ_NO_WCFLUSH_WAIT (1 << 27) #define WQ_PRESENT_WORKLOAD (1 << 28) -#define WQ_WORKLOAD_SHIFT 29 -#define WQ_WORKLOAD_GENERAL (0 << WQ_WORKLOAD_SHIFT) -#define WQ_WORKLOAD_GPGPU (1 << WQ_WORKLOAD_SHIFT) -#define WQ_WORKLOAD_TOUCH (2 << WQ_WORKLOAD_SHIFT) #define WQ_RING_TAIL_SHIFT 20 #define WQ_RING_TAIL_MAX 0x7FF /* 2^11 QWords */ -- cgit v1.2.3 From ada8c4139fbad766fdf9e63b31c49874299fd60c Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Tue, 12 Sep 2017 14:36:37 -0700 Subject: drm/i915/guc: Small improvements to guc_wq_item_append Spare some comments and other small style changes. Suggested-by: Joonas Lahtinen Signed-off-by: Oscar Mateo Link: https://patchwork.freedesktop.org/patch/msgid/1505252197-27696-3-git-send-email-oscar.mateo@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_guc_submission.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 0f1536edc1ea..5c81d5f2353d 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -469,8 +469,9 @@ static void guc_wq_item_append(struct i915_guc_client *client, { /* wqi_len is in DWords, and does not include the one-word header */ const size_t wqi_size = sizeof(struct guc_wq_item); - const u32 wqi_len = wqi_size/sizeof(u32) - 1; + const u32 wqi_len = wqi_size / sizeof(u32) - 1; struct intel_engine_cs *engine = rq->engine; + struct i915_gem_context *ctx = rq->ctx; struct guc_process_desc *desc = __get_process_desc(client); struct guc_wq_item *wqi; u32 freespace, tail, wq_off; @@ -479,8 +480,7 @@ static void guc_wq_item_append(struct i915_guc_client *client, freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); GEM_BUG_ON(freespace < wqi_size); - /* The GuC firmware wants the tail index in QWords, not bytes */ - tail = intel_ring_set_tail(rq->ring, rq->tail) >> 3; + tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); GEM_BUG_ON(tail > WQ_RING_TAIL_MAX); /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we @@ -505,12 +505,11 @@ static void guc_wq_item_append(struct i915_guc_client *client, /* Now fill in the 4-word work queue item */ wqi->header = WQ_TYPE_INORDER | - (wqi_len << WQ_LEN_SHIFT) | - (engine->guc_id << WQ_TARGET_SHIFT) | - WQ_NO_WCFLUSH_WAIT; + (wqi_len << WQ_LEN_SHIFT) | + (engine->guc_id << WQ_TARGET_SHIFT) | + WQ_NO_WCFLUSH_WAIT; - /* The GuC wants only the low-order word of the context descriptor */ - wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, engine); + wqi->context_desc = lower_32_bits(intel_lr_context_descriptor(ctx, engine)); wqi->submit_element_info = tail << WQ_RING_TAIL_SHIFT; wqi->fence_id = rq->global_seqno; -- cgit v1.2.3 From e60b36f76c2ee0ba90b431daa534bc262798fb26 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Sep 2017 11:57:54 +0100 Subject: drm/i915: Squelch smatch warning for statement with no effect The sgt iterators cause an drivers/gpu/drm/i915/i915_gpu_error.c:846 i915_error_object_create() warn: statement has no effect 7 everywhere they are used. If we change the code slightly, we can achieve the same increment without altering the output or raising a warning. text data bss dec hex filename 1267906 20587 3168 1291661 13b58d before 1267906 20587 3168 1291661 13b58d after Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170913105754.4423-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ec70121410e4..9dba1b2e8019 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2835,8 +2835,8 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg) #define for_each_sgt_dma(__dmap, __iter, __sgt) \ for ((__iter) = __sgt_iter((__sgt)->sgl, true); \ ((__dmap) = (__iter).dma + (__iter).curr); \ - (((__iter).curr += PAGE_SIZE) < (__iter).max) || \ - ((__iter) = __sgt_iter(__sg_next((__iter).sgp), true), 0)) + (((__iter).curr += PAGE_SIZE) >= (__iter).max) ? \ + (__iter) = __sgt_iter(__sg_next((__iter).sgp), true), 0 : 0) /** * for_each_sgt_page - iterate over the pages of the given sg_table @@ -2848,8 +2848,8 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg) for ((__iter) = __sgt_iter((__sgt)->sgl, false); \ ((__pp) = (__iter).pfn == 0 ? NULL : \ pfn_to_page((__iter).pfn + ((__iter).curr >> PAGE_SHIFT))); \ - (((__iter).curr += PAGE_SIZE) < (__iter).max) || \ - ((__iter) = __sgt_iter(__sg_next((__iter).sgp), false), 0)) + (((__iter).curr += PAGE_SIZE) >= (__iter).max) ? \ + (__iter) = __sgt_iter(__sg_next((__iter).sgp), false), 0 : 0) static inline unsigned int i915_sg_segment_size(void) { -- cgit v1.2.3 From 3123698f50fe4ac9ddb775dcd2b34a1d9cdd603f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Sep 2017 11:51:53 +0100 Subject: drm/i915: Use mul_u32_u32() for 32b x 32b -> 64b result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As realised by commit 9e3d6223d209 ("math64, timers: Fix 32bit mul_u64_u32_shr() and friends"), GCC does not always generate ideal code for performing a 32b x 32b multiply returning a 64b result (i.e. where we idiomatically use u64 result = (u64)x * (u32)x). This catches a couple of instances in the display code using (u64)x * (u32)y. Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170913105154.2910-1-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_tv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c4d8bb75686a..3bfcf187a0a1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10224,7 +10224,7 @@ int intel_dotclock_calculate(int link_freq, if (!m_n->link_n) return 0; - return div_u64((u64)m_n->link_m * link_freq, m_n->link_n); + return div_u64(mul_u32_u32(m_n->link_m, link_freq), m_n->link_n); } static void ironlake_pch_clock_get(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 0cc999fa09c5..a79a7591b2cf 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1385,7 +1385,7 @@ intel_tv_get_modes(struct drm_connector *connector) mode_ptr->vsync_end = mode_ptr->vsync_start + 1; mode_ptr->vtotal = vactive_s + 33; - tmp = (u64) tv_mode->refresh * mode_ptr->vtotal; + tmp = mul_u32_u32(tv_mode->refresh, mode_ptr->vtotal); tmp *= mode_ptr->htotal; tmp = div_u64(tmp, 1000000); mode_ptr->clock = (int) tmp; -- cgit v1.2.3 From 7ce5b6850b47824a2b8d0a17b5fe75f9942e5cd1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Sep 2017 11:51:54 +0100 Subject: drm/i915/selftests: Use mul_u32_u32() for 32b x 32b -> 64b result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As realised by commit 9e3d6223d209 ("math64, timers: Fix 32bit mul_u64_u32_shr() and friends"), GCC does not always generate ideal code for performing a 32b x 32b multiply returning a 64b result (i.e. where we idiomatically use u64 result = (u64)x * (u32)x). Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170913105154.2910-2-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/selftests/i915_gem_timeline.c | 2 +- drivers/gpu/drm/i915/selftests/i915_random.c | 5 ----- drivers/gpu/drm/i915/selftests/i915_random.h | 5 +++++ 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c b/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c index 7a44dab631b8..4795877abe56 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c @@ -121,7 +121,7 @@ out: static unsigned int random_engine(struct rnd_state *rnd) { - return ((u64)prandom_u32_state(rnd) * I915_NUM_ENGINES) >> 32; + return i915_prandom_u32_max_state(I915_NUM_ENGINES, rnd); } static int bench_sync(void *arg) diff --git a/drivers/gpu/drm/i915/selftests/i915_random.c b/drivers/gpu/drm/i915/selftests/i915_random.c index d044bf9a6feb..ea0f5dbc0eb7 100644 --- a/drivers/gpu/drm/i915/selftests/i915_random.c +++ b/drivers/gpu/drm/i915/selftests/i915_random.c @@ -41,11 +41,6 @@ u64 i915_prandom_u64_state(struct rnd_state *rnd) return x; } -static inline u32 i915_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state) -{ - return upper_32_bits((u64)prandom_u32_state(state) * ep_ro); -} - void i915_random_reorder(unsigned int *order, unsigned int count, struct rnd_state *state) { diff --git a/drivers/gpu/drm/i915/selftests/i915_random.h b/drivers/gpu/drm/i915/selftests/i915_random.h index 6c9379871384..7dffedc501ca 100644 --- a/drivers/gpu/drm/i915/selftests/i915_random.h +++ b/drivers/gpu/drm/i915/selftests/i915_random.h @@ -43,6 +43,11 @@ u64 i915_prandom_u64_state(struct rnd_state *rnd); +static inline u32 i915_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state) +{ + return upper_32_bits(mul_u32_u32(prandom_u32_state(state), ep_ro)); +} + unsigned int *i915_random_order(unsigned int count, struct rnd_state *state); void i915_random_reorder(unsigned int *order, -- cgit v1.2.3 From 0b29c75a01e5413d9c1f368b8357b589c7b5a922 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 13 Sep 2017 09:56:00 +0100 Subject: drm/i915/lrc: Clarify the format of the context image Not only the context image consist of two parts (the PPHWSP, and the logical context state), but we also allocate a header at the start of for sharing data with GuC. Thus every lrc looks like this: | [guc] | [hwsp] [logical state] | |<- our header ->|<- context image ->| So far, we have oversimplified whenever we use each of these parts of the context, just because the GuC header happens to be in page 0, and the (PP)HWSP is in page 1. But this had led to using the same define for more than one meaning (as a page index in the lrc and as 1 page). This patch adds defines for the GuC shared page, the PPHWSP page and the start of the logical state. It also updated the places where the old define was being used. Since we are not changing the size (or format) of the context, there are no functional changes. v2: Use PPHWSP index for hws again. Suggested-by: Chris Wilson Signed-off-by: Michel Thierry Cc: Chris Wilson Cc: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: Oscar Mateo Cc: intel-gvt-dev@lists.freedesktop.org Link: http://patchwork.freedesktop.org/patch/msgid/20170712193032.27080-1-michel.thierry@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170913085605.18299-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gvt/scheduler.c | 4 ++-- drivers/gpu/drm/i915/i915_guc_submission.c | 4 ++-- drivers/gpu/drm/i915/intel_lrc.c | 9 ++++++--- drivers/gpu/drm/i915/intel_lrc.h | 25 ++++++++++++++++++++++--- 4 files changed, 32 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 6fb9b589276d..d5892d24f0b6 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -87,7 +87,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) return -EINVAL; } - page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i); + page = i915_gem_object_get_page(ctx_obj, LRC_HEADER_PAGES + i); dst = kmap(page); intel_gvt_hypervisor_read_gpa(vgpu, context_gpa, dst, GTT_PAGE_SIZE); @@ -454,7 +454,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload) return; } - page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i); + page = i915_gem_object_get_page(ctx_obj, LRC_HEADER_PAGES + i); src = kmap(page); intel_gvt_hypervisor_write_gpa(vgpu, context_gpa, src, GTT_PAGE_SIZE); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 5c81d5f2353d..226e5393d3c0 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1314,7 +1314,7 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv) /* any value greater than GUC_POWER_D0 */ data[1] = GUC_POWER_D1; /* first page is shared data with GuC */ - data[2] = guc_ggtt_offset(ctx->engine[RCS].state); + data[2] = guc_ggtt_offset(ctx->engine[RCS].state) + LRC_GUCSHR_PN * PAGE_SIZE; return intel_guc_send(guc, data, ARRAY_SIZE(data)); } @@ -1340,7 +1340,7 @@ int intel_guc_resume(struct drm_i915_private *dev_priv) data[0] = INTEL_GUC_ACTION_EXIT_S_STATE; data[1] = GUC_POWER_D0; /* first page is shared data with GuC */ - data[2] = guc_ggtt_offset(ctx->engine[RCS].state); + data[2] = guc_ggtt_offset(ctx->engine[RCS].state) + LRC_GUCSHR_PN * PAGE_SIZE; return intel_guc_send(guc, data, ARRAY_SIZE(data)); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 9e4342b8e52b..3b8f1a79d640 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -279,7 +279,7 @@ intel_lr_context_descriptor_update(struct i915_gem_context *ctx, BUILD_BUG_ON(MAX_CONTEXT_HW_ID > (1<desc_template; /* bits 0-11 */ - desc |= i915_ggtt_offset(ce->state) + LRC_PPHWSP_PN * PAGE_SIZE; + desc |= i915_ggtt_offset(ce->state) + LRC_HEADER_PAGES * PAGE_SIZE; /* bits 12-31 */ desc |= (u64)ctx->hw_id << GEN8_CTX_ID_SHIFT; /* bits 32-52 */ @@ -2048,8 +2048,11 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, context_size = round_up(engine->context_size, I915_GTT_PAGE_SIZE); - /* One extra page as the sharing data between driver and GuC */ - context_size += PAGE_SIZE * LRC_PPHWSP_PN; + /* + * Before the actual start of the context image, we insert a few pages + * for our own use and for sharing with the GuC. + */ + context_size += LRC_HEADER_PAGES * PAGE_SIZE; ctx_obj = i915_gem_object_create(ctx->i915, context_size); if (IS_ERR(ctx_obj)) { diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 3b1de327e504..314adee7127a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -70,10 +70,29 @@ int logical_xcs_ring_init(struct intel_engine_cs *engine); /* Logical Ring Contexts */ -/* One extra page is added before LRC for GuC as shared data */ +/* + * We allocate a header at the start of the context image for our own + * use, therefore the actual location of the logical state is offset + * from the start of the VMA. The layout is + * + * | [guc] | [hwsp] [logical state] | + * |<- our header ->|<- context image ->| + * + */ +/* The first page is used for sharing data with the GuC */ #define LRC_GUCSHR_PN (0) -#define LRC_PPHWSP_PN (LRC_GUCSHR_PN + 1) -#define LRC_STATE_PN (LRC_PPHWSP_PN + 1) +#define LRC_GUCSHR_SZ (1) +/* At the start of the context image is its per-process HWS page */ +#define LRC_PPHWSP_PN (LRC_GUCSHR_PN + LRC_GUCSHR_SZ) +#define LRC_PPHWSP_SZ (1) +/* Finally we have the logical state for the context */ +#define LRC_STATE_PN (LRC_PPHWSP_PN + LRC_PPHWSP_SZ) + +/* + * Currently we include the PPHWSP in __intel_engine_context_size() so + * the size of the header is synonymous with the start of the PPHWSP. + */ +#define LRC_HEADER_PAGES LRC_PPHWSP_PN struct drm_i915_private; struct i915_gem_context; -- cgit v1.2.3 From a922c0c7a6b7b84351c4051fc9defe1222185c16 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 13 Sep 2017 09:56:01 +0100 Subject: drm/i915/guc: Don't make assumptions while getting the lrca offset Using the HWSP ggtt_offset to get the lrca offset is only correct if the HWSP happens to be before it (when we reuse the PPHWSP of the kernel context as the engine HWSP). Instead of making this assumption, get the lrca offset from the kernel_context engine state. And while looking at this part of the GuC interaction, it was also noticed that the firmware expects the size of only the engine context (context minus the execlist part, i.e. don't include the first 80 dwords), so pass the right size. v2: Use the new macros to prevent abusive overuse of the old ones (Chris). Reported-by: Daniele Ceraolo Spurio Signed-off-by: Michel Thierry Cc: Chris Wilson Cc: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: Oscar Mateo Link: http://patchwork.freedesktop.org/patch/msgid/20170712193032.27080-2-michel.thierry@intel.com Reviewed-by: Chris Wilson Acked-by: Daniele Ceraolo Spurio Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170913085605.18299-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_guc_submission.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 226e5393d3c0..b28677e5a4f2 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1022,6 +1022,12 @@ static void guc_policies_init(struct guc_policies *policies) policies->is_valid = 1; } +/* + * The first 80 dwords of the register state context, containing the + * execlists and ppgtt registers. + */ +#define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) + static int guc_ads_create(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); @@ -1036,6 +1042,8 @@ static int guc_ads_create(struct intel_guc *guc) } __packed *blob; struct intel_engine_cs *engine; enum intel_engine_id id; + const u32 skipped_offset = LRC_HEADER_PAGES * PAGE_SIZE; + const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE; u32 base; GEM_BUG_ON(guc->ads_vma); @@ -1066,13 +1074,20 @@ static int guc_ads_create(struct intel_guc *guc) * engines after a reset. Here we use the Render ring default * context, which must already exist and be pinned in the GGTT, * so its address won't change after we've told the GuC where - * to find it. + * to find it. Note that we have to skip our header (1 page), + * because our GuC shared data is there. */ blob->ads.golden_context_lrca = - dev_priv->engine[RCS]->status_page.ggtt_offset; + guc_ggtt_offset(dev_priv->kernel_context->engine[RCS].state) + skipped_offset; + /* + * The GuC expects us to exclude the portion of the context image that + * it skips from the size it is to read. It starts reading from after + * the execlist context (so skipping the first page [PPHWSP] and 80 + * dwords). Weird guc is weird. + */ for_each_engine(engine, dev_priv, id) - blob->ads.eng_state_size[engine->guc_id] = engine->context_size; + blob->ads.eng_state_size[engine->guc_id] = engine->context_size - skipped_size; base = guc_ggtt_offset(vma); blob->ads.scheduler_policies = base + ptr_offset(blob, policies); -- cgit v1.2.3 From 486e93f72abd41559b740f017717c7f6b3f8bb1f Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 13 Sep 2017 09:56:02 +0100 Subject: drm/i915/lrc: allocate separate page for HWSP On gen8+ we're currently using the PPHWSP of the kernel ctx as the global HWSP. However, when the kernel ctx gets submitted (e.g. from __intel_autoenable_gt_powersave) the HW will use that page as both HWSP and PPHWSP. This causes a conflict in the register arena of the HWSP, i.e. dword indices below 0x30. We don't current utilize this arena, but in the following patches we will take advantage of the cached register state for handling execlist's context status interrupt. To avoid the conflict, instead of re-using the PPHWSP of the kernel ctx we can allocate a separate page for the HWSP like what happens for pre-execlists platform. v2: Add a use-case for the register arena of the HWSP. Signed-off-by: Daniele Ceraolo Spurio Cc: Michel Thierry Link: http://patchwork.freedesktop.org/patch/msgid/1499357440-34688-1-git-send-email-daniele.ceraolospurio@intel.com Signed-off-by: Chris Wilson Reviewed-by: Michel Thierry Link: https://patchwork.freedesktop.org/patch/msgid/20170913085605.18299-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_engine_cs.c | 126 +++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_lrc.c | 34 +-------- drivers/gpu/drm/i915/intel_ringbuffer.c | 125 +------------------------------ 3 files changed, 127 insertions(+), 158 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 3ae89a9d6241..8a5535ad6552 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -442,6 +442,114 @@ static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine) i915_vma_unpin_and_release(&engine->scratch); } +static void cleanup_phys_status_page(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + + if (!dev_priv->status_page_dmah) + return; + + drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); + engine->status_page.page_addr = NULL; +} + +static void cleanup_status_page(struct intel_engine_cs *engine) +{ + struct i915_vma *vma; + struct drm_i915_gem_object *obj; + + vma = fetch_and_zero(&engine->status_page.vma); + if (!vma) + return; + + obj = vma->obj; + + i915_vma_unpin(vma); + i915_vma_close(vma); + + i915_gem_object_unpin_map(obj); + __i915_gem_object_release_unless_active(obj); +} + +static int init_status_page(struct intel_engine_cs *engine) +{ + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + unsigned int flags; + void *vaddr; + int ret; + + obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); + if (IS_ERR(obj)) { + DRM_ERROR("Failed to allocate status page\n"); + return PTR_ERR(obj); + } + + ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); + if (ret) + goto err; + + vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err; + } + + flags = PIN_GLOBAL; + if (!HAS_LLC(engine->i915)) + /* On g33, we cannot place HWS above 256MiB, so + * restrict its pinning to the low mappable arena. + * Though this restriction is not documented for + * gen4, gen5, or byt, they also behave similarly + * and hang if the HWS is placed at the top of the + * GTT. To generalise, it appears that all !llc + * platforms have issues with us placing the HWS + * above the mappable region (even though we never + * actually map it). + */ + flags |= PIN_MAPPABLE; + ret = i915_vma_pin(vma, 0, 4096, flags); + if (ret) + goto err; + + vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + goto err_unpin; + } + + engine->status_page.vma = vma; + engine->status_page.ggtt_offset = i915_ggtt_offset(vma); + engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE); + + DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", + engine->name, i915_ggtt_offset(vma)); + return 0; + +err_unpin: + i915_vma_unpin(vma); +err: + i915_gem_object_put(obj); + return ret; +} + +static int init_phys_status_page(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + + GEM_BUG_ON(engine->id != RCS); + + dev_priv->status_page_dmah = + drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); + if (!dev_priv->status_page_dmah) + return -ENOMEM; + + engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; + memset(engine->status_page.page_addr, 0, PAGE_SIZE); + + return 0; +} + /** * intel_engines_init_common - initialize cengine state which might require hw access * @engine: Engine to initialize. @@ -477,10 +585,21 @@ int intel_engine_init_common(struct intel_engine_cs *engine) ret = i915_gem_render_state_init(engine); if (ret) - goto err_unpin; + goto err_breadcrumbs; + + if (HWS_NEEDS_PHYSICAL(engine->i915)) + ret = init_phys_status_page(engine); + else + ret = init_status_page(engine); + if (ret) + goto err_rs_fini; return 0; +err_rs_fini: + i915_gem_render_state_fini(engine); +err_breadcrumbs: + intel_engine_fini_breadcrumbs(engine); err_unpin: engine->context_unpin(engine, engine->i915->kernel_context); return ret; @@ -497,6 +616,11 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) { intel_engine_cleanup_scratch(engine); + if (HWS_NEEDS_PHYSICAL(engine->i915)) + cleanup_phys_status_page(engine); + else + cleanup_status_page(engine); + i915_gem_render_state_fini(engine); intel_engine_fini_breadcrumbs(engine); intel_engine_cleanup_cmd_parser(engine); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3b8f1a79d640..8886e3b60e82 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1674,11 +1674,6 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) if (engine->cleanup) engine->cleanup(engine); - if (engine->status_page.vma) { - i915_gem_object_unpin_map(engine->status_page.vma->obj); - engine->status_page.vma = NULL; - } - intel_engine_cleanup_common(engine); lrc_destroy_wa_ctx(engine); @@ -1725,24 +1720,6 @@ logical_ring_default_irqs(struct intel_engine_cs *engine) engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; } -static int -lrc_setup_hws(struct intel_engine_cs *engine, struct i915_vma *vma) -{ - const int hws_offset = LRC_PPHWSP_PN * PAGE_SIZE; - void *hws; - - /* The HWSP is part of the default context object in LRC mode. */ - hws = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); - if (IS_ERR(hws)) - return PTR_ERR(hws); - - engine->status_page.page_addr = hws + hws_offset; - engine->status_page.ggtt_offset = i915_ggtt_offset(vma) + hws_offset; - engine->status_page.vma = vma; - - return 0; -} - static void logical_ring_setup(struct intel_engine_cs *engine) { @@ -1775,23 +1752,14 @@ logical_ring_setup(struct intel_engine_cs *engine) logical_ring_default_irqs(engine); } -static int -logical_ring_init(struct intel_engine_cs *engine) +static int logical_ring_init(struct intel_engine_cs *engine) { - struct i915_gem_context *dctx = engine->i915->kernel_context; int ret; ret = intel_engine_init_common(engine); if (ret) goto error; - /* And setup the hardware status page. */ - ret = lrc_setup_hws(engine, dctx->engine[engine->id].state); - if (ret) { - DRM_ERROR("Failed to set up hws %s: %d\n", engine->name, ret); - goto error; - } - return 0; error: diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 268342433a8e..8af8871a8594 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1175,113 +1175,7 @@ i915_emit_bb_start(struct drm_i915_gem_request *req, return 0; } -static void cleanup_phys_status_page(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - - if (!dev_priv->status_page_dmah) - return; - - drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); - engine->status_page.page_addr = NULL; -} - -static void cleanup_status_page(struct intel_engine_cs *engine) -{ - struct i915_vma *vma; - struct drm_i915_gem_object *obj; - - vma = fetch_and_zero(&engine->status_page.vma); - if (!vma) - return; - - obj = vma->obj; - - i915_vma_unpin(vma); - i915_vma_close(vma); - - i915_gem_object_unpin_map(obj); - __i915_gem_object_release_unless_active(obj); -} -static int init_status_page(struct intel_engine_cs *engine) -{ - struct drm_i915_gem_object *obj; - struct i915_vma *vma; - unsigned int flags; - void *vaddr; - int ret; - - obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); - if (IS_ERR(obj)) { - DRM_ERROR("Failed to allocate status page\n"); - return PTR_ERR(obj); - } - - ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); - if (ret) - goto err; - - vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL); - if (IS_ERR(vma)) { - ret = PTR_ERR(vma); - goto err; - } - - flags = PIN_GLOBAL; - if (!HAS_LLC(engine->i915)) - /* On g33, we cannot place HWS above 256MiB, so - * restrict its pinning to the low mappable arena. - * Though this restriction is not documented for - * gen4, gen5, or byt, they also behave similarly - * and hang if the HWS is placed at the top of the - * GTT. To generalise, it appears that all !llc - * platforms have issues with us placing the HWS - * above the mappable region (even though we never - * actualy map it). - */ - flags |= PIN_MAPPABLE; - ret = i915_vma_pin(vma, 0, 4096, flags); - if (ret) - goto err; - - vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); - if (IS_ERR(vaddr)) { - ret = PTR_ERR(vaddr); - goto err_unpin; - } - - engine->status_page.vma = vma; - engine->status_page.ggtt_offset = i915_ggtt_offset(vma); - engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE); - - DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", - engine->name, i915_ggtt_offset(vma)); - return 0; - -err_unpin: - i915_vma_unpin(vma); -err: - i915_gem_object_put(obj); - return ret; -} - -static int init_phys_status_page(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - - GEM_BUG_ON(engine->id != RCS); - - dev_priv->status_page_dmah = - drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); - if (!dev_priv->status_page_dmah) - return -ENOMEM; - - engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; - memset(engine->status_page.page_addr, 0, PAGE_SIZE); - - return 0; -} int intel_ring_pin(struct intel_ring *ring, struct drm_i915_private *i915, @@ -1568,17 +1462,10 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine) if (err) goto err; - if (HWS_NEEDS_PHYSICAL(engine->i915)) - err = init_phys_status_page(engine); - else - err = init_status_page(engine); - if (err) - goto err; - ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); if (IS_ERR(ring)) { err = PTR_ERR(ring); - goto err_hws; + goto err; } /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ @@ -1593,11 +1480,6 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine) err_ring: intel_ring_free(ring); -err_hws: - if (HWS_NEEDS_PHYSICAL(engine->i915)) - cleanup_phys_status_page(engine); - else - cleanup_status_page(engine); err: intel_engine_cleanup_common(engine); return err; @@ -1616,11 +1498,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) if (engine->cleanup) engine->cleanup(engine); - if (HWS_NEEDS_PHYSICAL(dev_priv)) - cleanup_phys_status_page(engine); - else - cleanup_status_page(engine); - intel_engine_cleanup_common(engine); dev_priv->engine[engine->id] = NULL; -- cgit v1.2.3 From 34a04e5e46cb984a6bab336484fa856574db332f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Sep 2017 09:56:03 +0100 Subject: drm/i915: Allow HW status page to be bound high MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the time of commit 1f767e02d69f ("drm/i915: HWS must be in the mappable region for g33"), drm_mm insertion would often default to placing a new object high in the zone forcing us to specify that certain HWSP must be bound within the low mappable region. Since then, drm_mm has gained more finesse over its placement and exposes that to the caller, commit 4e64e5539d15 ("drm: Improve drm_mm search (and fix topdown allocation) with rbtrees"). As such where possible we want the HWSP to be outside of the mappable aperture and so need to specify that can be pinned high. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Ville Syrjälä Cc: Michel Thierry Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170913085605.18299-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_engine_cs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 8a5535ad6552..32d35f32d289 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -508,6 +508,8 @@ static int init_status_page(struct intel_engine_cs *engine) * actually map it). */ flags |= PIN_MAPPABLE; + else + flags |= PIN_HIGH; ret = i915_vma_pin(vma, 0, 4096, flags); if (ret) goto err; -- cgit v1.2.3 From 6d2cb5aa383bf020ee95e33d9d107975f340ae1c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Sep 2017 14:35:34 +0100 Subject: drm/i915/execlists: Read the context-status buffer from the HWSP The engine provides a mirror of the CSB in the HWSP. If we use the cacheable reads from the HWSP, we can shave off a few mmio reads per context-switch interrupt (which are quite frequent!). Just removing a couple of mmio is not enough to actually reduce any latency, but a small reduction in overall cpu usage. Much appreciation for Ben dropping the bombshell that the CSB was in the HWSP and for Michel in digging out the details. v2: Don't be lazy, add the defines for the indices. v3: Include the HWSP in debugfs/i915_engine_info v4: Check for GVT-g, it currently depends on intercepting CSB mmio v5: Fixup GVT-g mmio path v6: Disable HWSP if VT-d is active as the iommu adds unpredictable memory latency. (Mika) v7: Also markup the CSB read with READ_ONCE() as it may still be an mmio read and we want to stop the compiler from issuing a later (v.slow) reload. Suggested-by: Ben Widawsky Signed-off-by: Chris Wilson Cc: Michel Thierry Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Daniele Ceraolo Spurio Cc: Zhenyu Wang Cc: Zhi Wang Acked-by: Michel Thierry Link: https://patchwork.freedesktop.org/patch/msgid/20170913133534.26927-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_debugfs.c | 7 +++++-- drivers/gpu/drm/i915/intel_lrc.c | 35 ++++++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 3 files changed, 38 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6338018f655d..7062cde94a49 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3315,6 +3315,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) upper_32_bits(addr), lower_32_bits(addr)); if (i915.enable_execlists) { + const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX]; u32 ptr, read, write; unsigned int idx; @@ -3337,10 +3338,12 @@ static int i915_engine_info(struct seq_file *m, void *unused) write += GEN8_CSB_ENTRIES; while (read < write) { idx = ++read % GEN8_CSB_ENTRIES; - seq_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n", + seq_printf(m, "\tExeclist CSB[%d]: 0x%08x [0x%08x in hwsp], context: %d [%d in hwsp]\n", idx, I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)), - I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx))); + hws[idx * 2], + I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)), + hws[idx * 2 + 1]); } rcu_read_lock(); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8886e3b60e82..6d7bbb9e769a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -541,10 +541,17 @@ static void intel_lrc_irq_handler(unsigned long data) while (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) { u32 __iomem *csb_mmio = dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)); - u32 __iomem *buf = - dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0)); + /* The HWSP contains a (cacheable) mirror of the CSB */ + const u32 *buf = + &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX]; unsigned int head, tail; + /* However GVT emulation depends upon intercepting CSB mmio */ + if (unlikely(engine->csb_use_mmio)) { + buf = (u32 * __force) + (dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0))); + } + /* The write will be ordered by the uncached read (itself * a memory barrier), so we do not need another in the form * of a locked instruction. The race between the interrupt @@ -584,13 +591,12 @@ static void intel_lrc_irq_handler(unsigned long data) * status notifier. */ - status = readl(buf + 2 * head); + status = READ_ONCE(buf[2 * head]); /* maybe mmio! */ if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) continue; /* Check the context/desc id for this event matches */ - GEM_DEBUG_BUG_ON(readl(buf + 2 * head + 1) != - port->context_id); + GEM_DEBUG_BUG_ON(buf[2 * head + 1] != port->context_id); rq = port_unpack(port, &count); GEM_BUG_ON(count == 0); @@ -1720,6 +1726,23 @@ logical_ring_default_irqs(struct intel_engine_cs *engine) engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; } +static bool irq_handler_force_mmio(struct drm_i915_private *i915) +{ + /* GVT emulation depends upon intercepting CSB mmio */ + if (intel_vgpu_active(i915)) + return true; + + /* + * IOMMU adds unpredictable latency causing the CSB write (from the + * GPU into the HWSP) to only be visible some time after the interrupt + * (missed breadcrumb syndrome). + */ + if (intel_vtd_active()) + return true; + + return false; +} + static void logical_ring_setup(struct intel_engine_cs *engine) { @@ -1731,6 +1754,8 @@ logical_ring_setup(struct intel_engine_cs *engine) /* Intentionally left blank. */ engine->buffer = NULL; + engine->csb_use_mmio = irq_handler_force_mmio(dev_priv); + fw_domains = intel_uncore_forcewake_for_reg(dev_priv, RING_ELSP(engine), FW_REG_WRITE); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 79c0021f3700..5c055b62966d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -391,6 +391,7 @@ struct intel_engine_cs { struct rb_root execlist_queue; struct rb_node *execlist_first; unsigned int fw_domains; + bool csb_use_mmio; /* Contexts are pinned whilst they are active on the GPU. The last * context executed remains active whilst the GPU is idle - the @@ -496,6 +497,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) #define I915_GEM_HWS_SCRATCH_INDEX 0x40 #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT) +#define I915_HWS_CSB_BUF0_INDEX 0x10 + struct intel_ring * intel_engine_create_ring(struct intel_engine_cs *engine, int size); int intel_ring_pin(struct intel_ring *ring, -- cgit v1.2.3 From 767a983ab25564e8fcc84fa203d1c51d2e50c6ef Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Sep 2017 09:56:05 +0100 Subject: drm/i915/execlists: Read the context-status HEAD from the HWSP The engine also provides a mirror of the CSB write pointer in the HWSP, but not of our read pointer. To take advantage of this we need to remember where we read up to on the last interrupt and continue off from there. This poses a problem following a reset, as we don't know where the hw will start writing from, and due to the use of power contexts we cannot perform that query during the reset itself. So we continue the current modus operandi of delaying the first read of the context-status read/write pointers until after the first interrupt. With this we should now have eliminated all uncached mmio reads in handling the context-status interrupt, though we still have the uncached mmio writes for submitting new work, and many uncached mmio reads in the global interrupt handler itself. Still a step in the right direction towards reducing our resubmit latency, although it appears lost in the noise! v2: Cannonlake moved the CSB write index v3: Include the sw/hwsp state in debugfs/i915_engine_info v4: Also revert to using CSB mmio for GVT-g v5: Prevent the compiler reloading tail (Mika) Signed-off-by: Chris Wilson Cc: Michel Thierry Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Daniele Ceraolo Spurio Cc: Zhenyu Wang Cc: Zhi Wang Acked-by: Michel Thierry Link: https://patchwork.freedesktop.org/patch/msgid/20170913085605.18299-6-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_debugfs.c | 6 ++++-- drivers/gpu/drm/i915/i915_drv.h | 8 ++++++++ drivers/gpu/drm/i915/intel_lrc.c | 27 ++++++++++++++++++++------- drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 4 files changed, 35 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7062cde94a49..12381045ed6a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3326,8 +3326,10 @@ static int i915_engine_info(struct seq_file *m, void *unused) ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); read = GEN8_CSB_READ_PTR(ptr); write = GEN8_CSB_WRITE_PTR(ptr); - seq_printf(m, "\tExeclist CSB read %d, write %d, interrupt posted? %s\n", - read, write, + seq_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n", + read, engine->csb_head, + write, + intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)), yesno(test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted))); if (read >= GEN8_CSB_ENTRIES) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9dba1b2e8019..b657df74c92c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -4400,4 +4400,12 @@ int remap_io_mapping(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, struct io_mapping *iomap); +static inline int intel_hws_csb_write_index(struct drm_i915_private *i915) +{ + if (INTEL_GEN(i915) >= 10) + return CNL_HWS_CSB_WRITE_INDEX; + else + return I915_HWS_CSB_WRITE_INDEX; +} + #endif diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 6d7bbb9e769a..1960ba5ff9e4 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -539,8 +539,6 @@ static void intel_lrc_irq_handler(unsigned long data) * new request (outside of the context-switch interrupt). */ while (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) { - u32 __iomem *csb_mmio = - dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)); /* The HWSP contains a (cacheable) mirror of the CSB */ const u32 *buf = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX]; @@ -550,6 +548,7 @@ static void intel_lrc_irq_handler(unsigned long data) if (unlikely(engine->csb_use_mmio)) { buf = (u32 * __force) (dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0))); + engine->csb_head = -1; /* force mmio read of CSB ptrs */ } /* The write will be ordered by the uncached read (itself @@ -563,9 +562,19 @@ static void intel_lrc_irq_handler(unsigned long data) * is set and we do a new loop. */ __clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); - head = readl(csb_mmio); - tail = GEN8_CSB_WRITE_PTR(head); - head = GEN8_CSB_READ_PTR(head); + if (unlikely(engine->csb_head == -1)) { /* following a reset */ + head = readl(dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine))); + tail = GEN8_CSB_WRITE_PTR(head); + head = GEN8_CSB_READ_PTR(head); + engine->csb_head = head; + } else { + const int write_idx = + intel_hws_csb_write_index(dev_priv) - + I915_HWS_CSB_BUF0_INDEX; + + head = engine->csb_head; + tail = READ_ONCE(buf[write_idx]); + } while (head != tail) { struct drm_i915_gem_request *rq; unsigned int status; @@ -619,8 +628,11 @@ static void intel_lrc_irq_handler(unsigned long data) !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); } - writel(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, head << 8), - csb_mmio); + if (head != engine->csb_head) { + engine->csb_head = head; + writel(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, head << 8), + dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine))); + } } if (execlists_elsp_ready(engine)) @@ -1269,6 +1281,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) I915_WRITE(GEN8_GT_IIR(gtiir[engine->id]), GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift); clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); + engine->csb_head = -1; /* After a GPU reset, we may have requests to replay */ submit = false; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 5c055b62966d..abf171c3cb9c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -391,6 +391,7 @@ struct intel_engine_cs { struct rb_root execlist_queue; struct rb_node *execlist_first; unsigned int fw_domains; + unsigned int csb_head; bool csb_use_mmio; /* Contexts are pinned whilst they are active on the GPU. The last @@ -498,6 +499,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT) #define I915_HWS_CSB_BUF0_INDEX 0x10 +#define I915_HWS_CSB_WRITE_INDEX 0x1f +#define CNL_HWS_CSB_WRITE_INDEX 0x2f struct intel_ring * intel_engine_create_ring(struct intel_engine_cs *engine, int size); -- cgit v1.2.3 From 0d0c279405ec8eb1171c5de1bc4256bb803df77f Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 12 Sep 2017 11:30:59 -0700 Subject: drm/i915: Refresh VLV/CHV PSR comments on HW PSR_state machine. DK had pointed out a comment there was hard to understand, so I tried to read back again and I couldn't understand that as well. So let me re-phrase that in a way that anyone can understand later, even myself. Also fixed the comment block style. v2: Accept DK's suggestion on PSR_state 2 and PSR_state 3 named as spec. Cc: Dhinakaran Pandiyan Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170912183059.5086-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_psr.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index fdd9e3d95efb..55b4002bbe53 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -234,7 +234,7 @@ static void vlv_psr_enable_source(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - /* Transition from PSR_state 0 to PSR_state 1, i.e. PSR Inactive */ + /* Transition from PSR_state 0 (disabled) to PSR_state 1 (inactive) */ I915_WRITE(VLV_PSRCTL(crtc->pipe), VLV_EDP_PSR_MODE_SW_TIMER | VLV_EDP_PSR_SRC_TRANSMITTER_STATE | @@ -249,10 +249,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) struct drm_crtc *crtc = dig_port->base.base.crtc; enum pipe pipe = to_intel_crtc(crtc)->pipe; - /* Let's do the transition from PSR_state 1 to PSR_state 2 - * that is PSR transition to active - static frame transmission. - * Then Hardware is responsible for the transition to PSR_state 3 - * that is PSR active - no Remote Frame Buffer (RFB) update. + /* + * Let's do the transition from PSR_state 1 (inactive) to + * PSR_state 2 (transition to active - static frame transmission). + * Then Hardware is responsible for the transition to + * PSR_state 3 (active - no Remote Frame Buffer (RFB) update). */ I915_WRITE(VLV_PSRCTL(pipe), I915_READ(VLV_PSRCTL(pipe)) | VLV_EDP_PSR_ACTIVE_ENTRY); @@ -576,7 +577,7 @@ static void vlv_psr_disable(struct intel_dp *intel_dp, uint32_t val; if (dev_priv->psr.active) { - /* Put VLV PSR back to PSR_state 0 that is PSR Disabled. */ + /* Put VLV PSR back to PSR_state 0 (disabled). */ if (intel_wait_for_register(dev_priv, VLV_PSRSTAT(crtc->pipe), VLV_EDP_PSR_IN_TRANS, @@ -766,16 +767,20 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv) } else { val = I915_READ(VLV_PSRCTL(pipe)); - /* Here we do the transition from PSR_state 3 to PSR_state 5 - * directly once PSR State 4 that is active with single frame - * update can be skipped. PSR_state 5 that is PSR exit then - * Hardware is responsible to transition back to PSR_state 1 - * that is PSR inactive. Same state after vlv_psr_enable_source. + /* + * Here we do the transition drirectly from + * PSR_state 3 (active - no Remote Frame Buffer (RFB) update) to + * PSR_state 5 (exit). + * PSR State 4 (active with single frame update) can be skipped. + * On PSR_state 5 (exit) Hardware is responsible to transition + * back to PSR_state 1 (inactive). + * Now we are at Same state after vlv_psr_enable_source. */ val &= ~VLV_EDP_PSR_ACTIVE_ENTRY; I915_WRITE(VLV_PSRCTL(pipe), val); - /* Send AUX wake up - Spec says after transitioning to PSR + /* + * Send AUX wake up - Spec says after transitioning to PSR * active we have to send AUX wake up by writing 01h in DPCD * 600h of sink device. * XXX: This might slow down the transition, but without this -- cgit v1.2.3 From fe52e597fdbfd1098d47bdf314a1974dac003227 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 13 Sep 2017 14:52:54 +0300 Subject: drm/i915: Introduce INTEL_GEN_MASK Split INTEL_GEN_MASK out of IS_GEN macro, and make it usable within static declarations (unlike compound statements). v2: - s/combound/compound/ (Tvrtko) - Fix whitespace (yes, we need automatic checkpatch.pl) Signed-off-by: Joonas Lahtinen Cc: Jani Nikula Cc: Chris Wilson Reviewed-by: Jani Nikula Reviewed-by: Chris Wilson Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170913115255.13851-1-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b657df74c92c..2e1498cae893 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2881,23 +2881,21 @@ intel_info(const struct drm_i915_private *dev_priv) #define INTEL_REVID(dev_priv) ((dev_priv)->drm.pdev->revision) #define GEN_FOREVER (0) + +#define INTEL_GEN_MASK(s, e) ( \ + BUILD_BUG_ON_ZERO(!__builtin_constant_p(s)) + \ + BUILD_BUG_ON_ZERO(!__builtin_constant_p(e)) + \ + GENMASK((e) != GEN_FOREVER ? (e) - 1 : BITS_PER_LONG - 1, \ + (s) != GEN_FOREVER ? (s) - 1 : 0) \ +) + /* * Returns true if Gen is in inclusive range [Start, End]. * * Use GEN_FOREVER for unbound start and or end. */ -#define IS_GEN(dev_priv, s, e) ({ \ - unsigned int __s = (s), __e = (e); \ - BUILD_BUG_ON(!__builtin_constant_p(s)); \ - BUILD_BUG_ON(!__builtin_constant_p(e)); \ - if ((__s) != GEN_FOREVER) \ - __s = (s) - 1; \ - if ((__e) == GEN_FOREVER) \ - __e = BITS_PER_LONG - 1; \ - else \ - __e = (e) - 1; \ - !!((dev_priv)->info.gen_mask & GENMASK((__e), (__s))); \ -}) +#define IS_GEN(dev_priv, s, e) \ + (!!((dev_priv)->info.gen_mask & INTEL_GEN_MASK((s), (e)))) /* * Return true if revision is in range [since,until] inclusive. -- cgit v1.2.3 From 3fd3a6ffe279827543cbf4063e307ed18bad6763 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 13 Sep 2017 14:52:55 +0300 Subject: drm/i915: Simplify i915_reg_read_ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert to use the freshly available made INTEL_GEN_MASK for easier grepping and improve function readability and clarify the UABI documentation. No functional changes. v2: - Lift GEM_BUG_ONs and use is_power_of_2 (Chris) - Retain -EINVAL on bad flags behavior (Chris) v3: - Extract flags with 'entry->size - 1' (Chris) v4: - Add GEM_BUG_ON on for flags vs entry offset (Chris) v5: - Use 'u16' to match 'dev_priv' (Ville) v6: - Fix checkpatch.pl errors Signed-off-by: Joonas Lahtinen Cc: Tvrtko Ursulin Cc: Chris Wilson Cc: Ville Syrjälä Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170913115255.13851-2-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/intel_uncore.c | 95 +++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 51 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 1b38eb94d461..97525de2cee4 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1292,72 +1292,65 @@ void intel_uncore_fini(struct drm_i915_private *dev_priv) intel_uncore_forcewake_reset(dev_priv, false); } -#define GEN_RANGE(l, h) GENMASK((h) - 1, (l) - 1) - -static const struct register_whitelist { - i915_reg_t offset_ldw, offset_udw; - uint32_t size; - /* supported gens, 0x10 for 4, 0x30 for 4 and 5, etc. */ - uint32_t gen_bitmask; -} whitelist[] = { - { .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE), - .offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE), - .size = 8, .gen_bitmask = GEN_RANGE(4, 10) }, -}; +static const struct reg_whitelist { + i915_reg_t offset_ldw; + i915_reg_t offset_udw; + u16 gen_mask; + u8 size; +} reg_read_whitelist[] = { { + .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE), + .offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE), + .gen_mask = INTEL_GEN_MASK(4, 10), + .size = 8 +} }; int i915_reg_read_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_reg_read *reg = data; - struct register_whitelist const *entry = whitelist; - unsigned size; - i915_reg_t offset_ldw, offset_udw; - int i, ret = 0; - - for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) { - if (i915_mmio_reg_offset(entry->offset_ldw) == (reg->offset & -entry->size) && - (INTEL_INFO(dev_priv)->gen_mask & entry->gen_bitmask)) + struct reg_whitelist const *entry; + unsigned int flags; + int remain; + int ret = 0; + + entry = reg_read_whitelist; + remain = ARRAY_SIZE(reg_read_whitelist); + while (remain) { + u32 entry_offset = i915_mmio_reg_offset(entry->offset_ldw); + + GEM_BUG_ON(!is_power_of_2(entry->size)); + GEM_BUG_ON(entry->size > 8); + GEM_BUG_ON(entry_offset & (entry->size - 1)); + + if (INTEL_INFO(dev_priv)->gen_mask & entry->gen_mask && + entry_offset == (reg->offset & -entry->size)) break; + entry++; + remain--; } - if (i == ARRAY_SIZE(whitelist)) + if (!remain) return -EINVAL; - /* We use the low bits to encode extra flags as the register should - * be naturally aligned (and those that are not so aligned merely - * limit the available flags for that register). - */ - offset_ldw = entry->offset_ldw; - offset_udw = entry->offset_udw; - size = entry->size; - size |= reg->offset ^ i915_mmio_reg_offset(offset_ldw); + flags = reg->offset & (entry->size - 1); intel_runtime_pm_get(dev_priv); - - switch (size) { - case 8 | 1: - reg->val = I915_READ64_2x32(offset_ldw, offset_udw); - break; - case 8: - reg->val = I915_READ64(offset_ldw); - break; - case 4: - reg->val = I915_READ(offset_ldw); - break; - case 2: - reg->val = I915_READ16(offset_ldw); - break; - case 1: - reg->val = I915_READ8(offset_ldw); - break; - default: + if (entry->size == 8 && flags == I915_REG_READ_8B_WA) + reg->val = I915_READ64_2x32(entry->offset_ldw, + entry->offset_udw); + else if (entry->size == 8 && flags == 0) + reg->val = I915_READ64(entry->offset_ldw); + else if (entry->size == 4 && flags == 0) + reg->val = I915_READ(entry->offset_ldw); + else if (entry->size == 2 && flags == 0) + reg->val = I915_READ16(entry->offset_ldw); + else if (entry->size == 1 && flags == 0) + reg->val = I915_READ8(entry->offset_ldw); + else ret = -EINVAL; - goto out; - } - -out: intel_runtime_pm_put(dev_priv); + return ret; } -- cgit v1.2.3 From 93564044fb2c938e8ee4a91323157ded28072972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Aug 2017 22:10:51 +0300 Subject: drm/i915: Switch over to the LLC/eLLC hotspot avoidance hash mode for CCS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the LLC/eLLC hotspot avoidance mode for CCS on LLC machines. This is reported to give better performance. Testing has indicated that we don't need to enforce any massive 2 or 4 MiB alignment for all compressed resources even though there are still plenty of stale comments in the spec suggesting that we do. We do need to make sure every hardware unit that deals with the compressed data uses the same hash mode. Cc: Ben Widawsky Cc: Jason Ekstrand Cc: Daniel Stone Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170824191100.10949-4-ville.syrjala@linux.intel.com Reviewed-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_reg.h | 8 +++++++- drivers/gpu/drm/i915/intel_engine_cs.c | 13 +++++++++++++ drivers/gpu/drm/i915/intel_pm.c | 27 +++++++++++++-------------- 3 files changed, 33 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9f03cd063afe..0befefec7327 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6913,7 +6913,7 @@ enum { # define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2) #define CHICKEN_PAR1_1 _MMIO(0x42080) -#define SKL_RC_HASH_OUTSIDE (1 << 15) +#define SKL_DE_COMPRESSED_HASH_MODE (1 << 15) #define DPA_MASK_VBLANK_SRD (1 << 15) #define FORCE_ARB_IDLE_PLANES (1 << 14) #define SKL_EDP_PSR_FIX_RDWRAP (1 << 3) @@ -6991,6 +6991,7 @@ enum { # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26)) # define GEN9_RHWO_OPTIMIZATION_DISABLE (1<<14) #define COMMON_SLICE_CHICKEN2 _MMIO(0x7014) +# define GEN9_PBE_COMPRESSED_HASH_SELECTION (1<<13) # define GEN9_DISABLE_GATHER_AT_SET_SHADER_COMMON_SLICE (1<<12) # define GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION (1<<8) # define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE (1<<0) @@ -8085,6 +8086,7 @@ enum { #define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1) #define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194) +#define GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR (1<<8) #define GEN9_ENABLE_YV12_BUGFIX (1<<4) #define GEN9_ENABLE_GPGPU_PREEMPTION (1<<2) @@ -9385,4 +9387,8 @@ enum skl_power_gate { #define GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL 0x67F1427F /* " " */ #define GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT 0x5FF101FF /* " " */ +#define MMCD_MISC_CTRL _MMIO(0x4ddc) /* skl+ */ +#define MMCD_PCLA (1 << 31) +#define MMCD_HOTSPOT_EN (1 << 27) + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 32d35f32d289..3d135c3cd380 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -938,6 +938,19 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | ECOCHK_DIS_TLB); + if (HAS_LLC(dev_priv)) { + /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl + * + * Must match Display Engine. See + * WaCompressedResourceDisplayNewHashMode. + */ + WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, + GEN9_PBE_COMPRESSED_HASH_SELECTION); + WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, + GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR); + WA_SET_BIT(MMCD_MISC_CTRL, MMCD_PCLA | MMCD_HOTSPOT_EN); + } + /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk,cfl */ /* WaDisablePartialInstShootdown:skl,bxt,kbl,glk,cfl */ WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fa9055a4f790..94624ede3479 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -58,24 +58,23 @@ static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) { + if (HAS_LLC(dev_priv)) { + /* + * WaCompressedResourceDisplayNewHashMode:skl,kbl + * Display WA#0390: skl,kbl + * + * Must match Sampler, Pixel Back End, and Media. See + * WaCompressedResourceSamplerPbeMediaNewHashMode. + */ + I915_WRITE(CHICKEN_PAR1_1, + I915_READ(CHICKEN_PAR1_1) | + SKL_DE_COMPRESSED_HASH_MODE); + } + /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */ I915_WRITE(CHICKEN_PAR1_1, I915_READ(CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP); - /* - * Display WA#0390: skl,bxt,kbl,glk - * - * Must match Sampler, Pixel Back End, and Media - * (0xE194 bit 8, 0x7014 bit 13, 0x4DDC bits 27 and 31). - * - * Including bits outside the page in the hash would - * require 2 (or 4?) MiB alignment of resources. Just - * assume the defaul hashing mode which only uses bits - * within the page. - */ - I915_WRITE(CHICKEN_PAR1_1, - I915_READ(CHICKEN_PAR1_1) & ~SKL_RC_HASH_OUTSIDE); - I915_WRITE(GEN8_CONFIG0, I915_READ(GEN8_CONFIG0) | GEN9_DEFAULT_FIXES); -- cgit v1.2.3 From 4395890a48551982549d222d1923e2833dac47cf Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Thu, 14 Sep 2017 20:39:40 +0800 Subject: drm/i915: Introduce private PAT management The private PAT management is to support PPAT entry manipulation. Two APIs are introduced for dynamically managing PPAT entries: intel_ppat_get and intel_ppat_put. intel_ppat_get will search for an existing PPAT entry which perfectly matches the required PPAT value. If not, it will try to allocate a new entry if there is any available PPAT indexs, or return a partially matched PPAT entry if there is no available PPAT indexes. intel_ppat_put will put back the PPAT entry which comes from intel_ppat_get. If it's dynamically allocated, the reference count will be decreased. If the reference count turns into zero, the PPAT index is freed again. Besides, another two callbacks are introduced to support the private PAT management framework. One is ppat->update_hw(), which writes the PPAT configurations in ppat->entries into HW. Another one is ppat->match, which will return a score to show how two PPAT values match with each other. v17: - Refine the comparision of score of BDW. (Joonas) v16: - Fix a bug in PPAT match function of BDW. (Joonas) v15: - Refine some code flow. (Joonas) v12: - Fix a problem "not returning the entry of best score". (Zhenyu) v7: - Keep all the register writes unchanged in this patch. (Joonas) v6: - Address all comments from Chris: http://www.spinics.net/lists/intel-gfx/msg136850.html - Address all comments from Joonas: http://www.spinics.net/lists/intel-gfx/msg136845.html v5: - Add check and warnnings for those platforms which don't have PPAT. v3: - Introduce dirty bitmap for PPAT registers. (Chris) - Change the name of the pointer "dev_priv" to "i915". (Chris) - intel_ppat_{get, put} returns/takes a const intel_ppat_entry *. (Chris) v2: - API re-design. (Chris) Signed-off-by: Zhi Wang Cc: Ben Widawsky Cc: Rodrigo Vivi Cc: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Chris Wilson #v7 Reviewed-by: Joonas Lahtinen [Joonas: Use BIT() in the enum in bdw_private_pat_match] Signed-off-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/1505392783-4084-1-git-send-email-zhi.a.wang@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_gem_gtt.c | 285 +++++++++++++++++++++++++++++------- drivers/gpu/drm/i915/i915_gem_gtt.h | 36 +++++ 3 files changed, 274 insertions(+), 49 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2e1498cae893..5d379c89722c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2355,6 +2355,8 @@ struct drm_i915_private { DECLARE_HASHTABLE(mm_structs, 7); struct mutex mm_lock; + struct intel_ppat ppat; + /* Kernel Modesetting */ struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES]; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 09e524dbc090..c7ee7d8f1b43 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2819,41 +2819,209 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return 0; } -static void cnl_setup_private_ppat(struct drm_i915_private *dev_priv) +static struct intel_ppat_entry * +__alloc_ppat_entry(struct intel_ppat *ppat, unsigned int index, u8 value) { + struct intel_ppat_entry *entry = &ppat->entries[index]; + + GEM_BUG_ON(index >= ppat->max_entries); + GEM_BUG_ON(test_bit(index, ppat->used)); + + entry->ppat = ppat; + entry->value = value; + kref_init(&entry->ref); + set_bit(index, ppat->used); + set_bit(index, ppat->dirty); + + return entry; +} + +static void __free_ppat_entry(struct intel_ppat_entry *entry) +{ + struct intel_ppat *ppat = entry->ppat; + unsigned int index = entry - ppat->entries; + + GEM_BUG_ON(index >= ppat->max_entries); + GEM_BUG_ON(!test_bit(index, ppat->used)); + + entry->value = ppat->clear_value; + clear_bit(index, ppat->used); + set_bit(index, ppat->dirty); +} + +/** + * intel_ppat_get - get a usable PPAT entry + * @i915: i915 device instance + * @value: the PPAT value required by the caller + * + * The function tries to search if there is an existing PPAT entry which + * matches with the required value. If perfectly matched, the existing PPAT + * entry will be used. If only partially matched, it will try to check if + * there is any available PPAT index. If yes, it will allocate a new PPAT + * index for the required entry and update the HW. If not, the partially + * matched entry will be used. + */ +const struct intel_ppat_entry * +intel_ppat_get(struct drm_i915_private *i915, u8 value) +{ + struct intel_ppat *ppat = &i915->ppat; + struct intel_ppat_entry *entry; + unsigned int scanned, best_score; + int i; + + GEM_BUG_ON(!ppat->max_entries); + + scanned = best_score = 0; + for_each_set_bit(i, ppat->used, ppat->max_entries) { + unsigned int score; + + score = ppat->match(ppat->entries[i].value, value); + if (score > best_score) { + entry = &ppat->entries[i]; + if (score == INTEL_PPAT_PERFECT_MATCH) { + kref_get(&entry->ref); + return entry; + } + best_score = score; + } + scanned++; + } + + if (scanned == ppat->max_entries) { + if (!best_score) + return ERR_PTR(-ENOSPC); + + kref_get(&entry->ref); + return entry; + } + + i = find_first_zero_bit(ppat->used, ppat->max_entries); + entry = __alloc_ppat_entry(ppat, i, value); + ppat->update_hw(i915); + return entry; +} + +static void release_ppat(struct kref *kref) +{ + struct intel_ppat_entry *entry = + container_of(kref, struct intel_ppat_entry, ref); + struct drm_i915_private *i915 = entry->ppat->i915; + + __free_ppat_entry(entry); + entry->ppat->update_hw(i915); +} + +/** + * intel_ppat_put - put back the PPAT entry got from intel_ppat_get() + * @entry: an intel PPAT entry + * + * Put back the PPAT entry got from intel_ppat_get(). If the PPAT index of the + * entry is dynamically allocated, its reference count will be decreased. Once + * the reference count becomes into zero, the PPAT index becomes free again. + */ +void intel_ppat_put(const struct intel_ppat_entry *entry) +{ + struct intel_ppat *ppat = entry->ppat; + unsigned int index = entry - ppat->entries; + + GEM_BUG_ON(!ppat->max_entries); + + kref_put(&ppat->entries[index].ref, release_ppat); +} + +static void cnl_private_pat_update_hw(struct drm_i915_private *dev_priv) +{ + struct intel_ppat *ppat = &dev_priv->ppat; + int i; + + for_each_set_bit(i, ppat->dirty, ppat->max_entries) { + I915_WRITE(GEN10_PAT_INDEX(i), ppat->entries[i].value); + clear_bit(i, ppat->dirty); + } +} + +static void bdw_private_pat_update_hw(struct drm_i915_private *dev_priv) +{ + struct intel_ppat *ppat = &dev_priv->ppat; + u64 pat = 0; + int i; + + for (i = 0; i < ppat->max_entries; i++) + pat |= GEN8_PPAT(i, ppat->entries[i].value); + + bitmap_clear(ppat->dirty, 0, ppat->max_entries); + + I915_WRITE(GEN8_PRIVATE_PAT_LO, lower_32_bits(pat)); + I915_WRITE(GEN8_PRIVATE_PAT_HI, upper_32_bits(pat)); +} + +static unsigned int bdw_private_pat_match(u8 src, u8 dst) +{ + unsigned int score = 0; + enum { + AGE_MATCH = BIT(0), + TC_MATCH = BIT(1), + CA_MATCH = BIT(2), + }; + + /* Cache attribute has to be matched. */ + if (GEN8_PPAT_GET_CA(src) == GEN8_PPAT_GET_CA(dst)) + return 0; + + score |= CA_MATCH; + + if (GEN8_PPAT_GET_TC(src) == GEN8_PPAT_GET_TC(dst)) + score |= TC_MATCH; + + if (GEN8_PPAT_GET_AGE(src) == GEN8_PPAT_GET_AGE(dst)) + score |= AGE_MATCH; + + if (score == (AGE_MATCH | TC_MATCH | CA_MATCH)) + return INTEL_PPAT_PERFECT_MATCH; + + return score; +} + +static unsigned int chv_private_pat_match(u8 src, u8 dst) +{ + return (CHV_PPAT_GET_SNOOP(src) == CHV_PPAT_GET_SNOOP(dst)) ? + INTEL_PPAT_PERFECT_MATCH : 0; +} + +static void cnl_setup_private_ppat(struct intel_ppat *ppat) +{ + ppat->max_entries = 8; + ppat->update_hw = cnl_private_pat_update_hw; + ppat->match = bdw_private_pat_match; + ppat->clear_value = GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3); + /* XXX: spec is unclear if this is still needed for CNL+ */ - if (!USES_PPGTT(dev_priv)) { - I915_WRITE(GEN10_PAT_INDEX(0), GEN8_PPAT_UC); + if (!USES_PPGTT(ppat->i915)) { + __alloc_ppat_entry(ppat, 0, GEN8_PPAT_UC); return; } - I915_WRITE(GEN10_PAT_INDEX(0), GEN8_PPAT_WB | GEN8_PPAT_LLC); - I915_WRITE(GEN10_PAT_INDEX(1), GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); - I915_WRITE(GEN10_PAT_INDEX(2), GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); - I915_WRITE(GEN10_PAT_INDEX(3), GEN8_PPAT_UC); - I915_WRITE(GEN10_PAT_INDEX(4), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)); - I915_WRITE(GEN10_PAT_INDEX(5), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)); - I915_WRITE(GEN10_PAT_INDEX(6), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)); - I915_WRITE(GEN10_PAT_INDEX(7), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); + __alloc_ppat_entry(ppat, 0, GEN8_PPAT_WB | GEN8_PPAT_LLC); + __alloc_ppat_entry(ppat, 1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); + __alloc_ppat_entry(ppat, 2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); + __alloc_ppat_entry(ppat, 3, GEN8_PPAT_UC); + __alloc_ppat_entry(ppat, 4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)); + __alloc_ppat_entry(ppat, 5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)); + __alloc_ppat_entry(ppat, 6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)); + __alloc_ppat_entry(ppat, 7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); } /* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability * bits. When using advanced contexts each context stores its own PAT, but * writing this data shouldn't be harmful even in those cases. */ -static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv) +static void bdw_setup_private_ppat(struct intel_ppat *ppat) { - u64 pat; + ppat->max_entries = 8; + ppat->update_hw = bdw_private_pat_update_hw; + ppat->match = bdw_private_pat_match; + ppat->clear_value = GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3); - pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC) | /* for normal objects, no eLLC */ - GEN8_PPAT(1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC) | /* for something pointing to ptes? */ - GEN8_PPAT(2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC) | /* for scanout with eLLC */ - GEN8_PPAT(3, GEN8_PPAT_UC) | /* Uncached objects, mostly for scanout */ - GEN8_PPAT(4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)) | - GEN8_PPAT(5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)) | - GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) | - GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); - - if (!USES_PPGTT(dev_priv)) + if (!USES_PPGTT(ppat->i915)) { /* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry, * so RTL will always use the value corresponding to * pat_sel = 000". @@ -2867,17 +3035,26 @@ static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv) * So we can still hold onto all our assumptions wrt cpu * clflushing on LLC machines. */ - pat = GEN8_PPAT(0, GEN8_PPAT_UC); + __alloc_ppat_entry(ppat, 0, GEN8_PPAT_UC); + return; + } - /* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b - * write would work. */ - I915_WRITE(GEN8_PRIVATE_PAT_LO, pat); - I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32); + __alloc_ppat_entry(ppat, 0, GEN8_PPAT_WB | GEN8_PPAT_LLC); /* for normal objects, no eLLC */ + __alloc_ppat_entry(ppat, 1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); /* for something pointing to ptes? */ + __alloc_ppat_entry(ppat, 2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); /* for scanout with eLLC */ + __alloc_ppat_entry(ppat, 3, GEN8_PPAT_UC); /* Uncached objects, mostly for scanout */ + __alloc_ppat_entry(ppat, 4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)); + __alloc_ppat_entry(ppat, 5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)); + __alloc_ppat_entry(ppat, 6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)); + __alloc_ppat_entry(ppat, 7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); } -static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) +static void chv_setup_private_ppat(struct intel_ppat *ppat) { - u64 pat; + ppat->max_entries = 8; + ppat->update_hw = bdw_private_pat_update_hw; + ppat->match = chv_private_pat_match; + ppat->clear_value = CHV_PPAT_SNOOP; /* * Map WB on BDW to snooped on CHV. @@ -2897,17 +3074,15 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) * Which means we must set the snoop bit in PAT entry 0 * in order to keep the global status page working. */ - pat = GEN8_PPAT(0, CHV_PPAT_SNOOP) | - GEN8_PPAT(1, 0) | - GEN8_PPAT(2, 0) | - GEN8_PPAT(3, 0) | - GEN8_PPAT(4, CHV_PPAT_SNOOP) | - GEN8_PPAT(5, CHV_PPAT_SNOOP) | - GEN8_PPAT(6, CHV_PPAT_SNOOP) | - GEN8_PPAT(7, CHV_PPAT_SNOOP); - I915_WRITE(GEN8_PRIVATE_PAT_LO, pat); - I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32); + __alloc_ppat_entry(ppat, 0, CHV_PPAT_SNOOP); + __alloc_ppat_entry(ppat, 1, 0); + __alloc_ppat_entry(ppat, 2, 0); + __alloc_ppat_entry(ppat, 3, 0); + __alloc_ppat_entry(ppat, 4, CHV_PPAT_SNOOP); + __alloc_ppat_entry(ppat, 5, CHV_PPAT_SNOOP); + __alloc_ppat_entry(ppat, 6, CHV_PPAT_SNOOP); + __alloc_ppat_entry(ppat, 7, CHV_PPAT_SNOOP); } static void gen6_gmch_remove(struct i915_address_space *vm) @@ -2920,12 +3095,27 @@ static void gen6_gmch_remove(struct i915_address_space *vm) static void setup_private_pat(struct drm_i915_private *dev_priv) { + struct intel_ppat *ppat = &dev_priv->ppat; + int i; + + ppat->i915 = dev_priv; + if (INTEL_GEN(dev_priv) >= 10) - cnl_setup_private_ppat(dev_priv); + cnl_setup_private_ppat(ppat); else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) - chv_setup_private_ppat(dev_priv); + chv_setup_private_ppat(ppat); else - bdw_setup_private_ppat(dev_priv); + bdw_setup_private_ppat(ppat); + + GEM_BUG_ON(ppat->max_entries > INTEL_MAX_PPAT_ENTRIES); + + for_each_clear_bit(i, ppat->used, ppat->max_entries) { + ppat->entries[i].value = ppat->clear_value; + ppat->entries[i].ppat = ppat; + set_bit(i, ppat->dirty); + } + + ppat->update_hw(dev_priv); } static int gen8_gmch_probe(struct i915_ggtt *ggtt) @@ -3239,13 +3429,10 @@ void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv) ggtt->base.closed = false; if (INTEL_GEN(dev_priv) >= 8) { - if (INTEL_GEN(dev_priv) >= 10) - cnl_setup_private_ppat(dev_priv); - else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) - chv_setup_private_ppat(dev_priv); - else - bdw_setup_private_ppat(dev_priv); + struct intel_ppat *ppat = &dev_priv->ppat; + bitmap_set(ppat->dirty, 0, ppat->max_entries); + dev_priv->ppat.update_hw(dev_priv); return; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index d9a076a2673a..f3943b6ab30c 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -143,6 +143,11 @@ typedef u64 gen8_ppgtt_pml4e_t; #define GEN8_PPAT_ELLC_OVERRIDE (0<<2) #define GEN8_PPAT(i, x) ((u64)(x) << ((i) * 8)) +#define GEN8_PPAT_GET_CA(x) ((x) & 3) +#define GEN8_PPAT_GET_TC(x) ((x) & (3 << 2)) +#define GEN8_PPAT_GET_AGE(x) ((x) & (3 << 4)) +#define CHV_PPAT_GET_SNOOP(x) ((x) & (1 << 6)) + struct sg_table; struct intel_rotation_info { @@ -536,6 +541,37 @@ i915_vm_to_ggtt(struct i915_address_space *vm) return container_of(vm, struct i915_ggtt, base); } +#define INTEL_MAX_PPAT_ENTRIES 8 +#define INTEL_PPAT_PERFECT_MATCH (~0U) + +struct intel_ppat; + +struct intel_ppat_entry { + struct intel_ppat *ppat; + struct kref ref; + u8 value; +}; + +struct intel_ppat { + struct intel_ppat_entry entries[INTEL_MAX_PPAT_ENTRIES]; + DECLARE_BITMAP(used, INTEL_MAX_PPAT_ENTRIES); + DECLARE_BITMAP(dirty, INTEL_MAX_PPAT_ENTRIES); + unsigned int max_entries; + u8 clear_value; + /* + * Return a score to show how two PPAT values match, + * a INTEL_PPAT_PERFECT_MATCH indicates a perfect match + */ + unsigned int (*match)(u8 src, u8 dst); + void (*update_hw)(struct drm_i915_private *i915); + + struct drm_i915_private *i915; +}; + +const struct intel_ppat_entry * +intel_ppat_get(struct drm_i915_private *i915, u8 value); +void intel_ppat_put(const struct intel_ppat_entry *entry); + int i915_gem_init_aliasing_ppgtt(struct drm_i915_private *i915); void i915_gem_fini_aliasing_ppgtt(struct drm_i915_private *i915); -- cgit v1.2.3 From c095b97c1e972d67d08bb90de99118a95a6390cd Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Thu, 14 Sep 2017 20:39:41 +0800 Subject: drm/i915: Remove the "INDEX" suffix from PPAT marcos Remove the "INDEX" suffix from PPAT marcos as they are bits actually, not indexes. Suggested-by: Chris Wilson Signed-off-by: Zhi Wang Cc: Ben Widawsky Cc: Rodrigo Vivi Cc: Joonas Lahtinen Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/1505392783-4084-2-git-send-email-zhi.a.wang@intel.com --- drivers/gpu/drm/i915/gvt/gtt.c | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 10 +++++----- drivers/gpu/drm/i915/i915_gem_gtt.h | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 0bd028f8fef5..2801d70579d8 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1971,7 +1971,7 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu, */ se.val64 |= _PAGE_PRESENT | _PAGE_RW; if (type == GTT_TYPE_PPGTT_PDE_PT) - se.val64 |= PPAT_CACHED_INDEX; + se.val64 |= PPAT_CACHED; for (i = 0; i < page_entry_num; i++) ops->set_entry(scratch_pt, &se, i, false, 0, vgpu); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c7ee7d8f1b43..729ebaf29b71 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -230,13 +230,13 @@ static gen8_pte_t gen8_pte_encode(dma_addr_t addr, switch (level) { case I915_CACHE_NONE: - pte |= PPAT_UNCACHED_INDEX; + pte |= PPAT_UNCACHED; break; case I915_CACHE_WT: - pte |= PPAT_DISPLAY_ELLC_INDEX; + pte |= PPAT_DISPLAY_ELLC; break; default: - pte |= PPAT_CACHED_INDEX; + pte |= PPAT_CACHED; break; } @@ -249,9 +249,9 @@ static gen8_pde_t gen8_pde_encode(const dma_addr_t addr, gen8_pde_t pde = _PAGE_PRESENT | _PAGE_RW; pde |= addr; if (level != I915_CACHE_NONE) - pde |= PPAT_CACHED_PDE_INDEX; + pde |= PPAT_CACHED_PDE; else - pde |= PPAT_UNCACHED_INDEX; + pde |= PPAT_UNCACHED; return pde; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index f3943b6ab30c..f62fb903dc24 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -126,10 +126,10 @@ typedef u64 gen8_ppgtt_pml4e_t; * tables */ #define GEN8_PDPE_MASK 0x1ff -#define PPAT_UNCACHED_INDEX (_PAGE_PWT | _PAGE_PCD) -#define PPAT_CACHED_PDE_INDEX 0 /* WB LLC */ -#define PPAT_CACHED_INDEX _PAGE_PAT /* WB LLCeLLC */ -#define PPAT_DISPLAY_ELLC_INDEX _PAGE_PCD /* WT eLLC */ +#define PPAT_UNCACHED (_PAGE_PWT | _PAGE_PCD) +#define PPAT_CACHED_PDE 0 /* WB LLC */ +#define PPAT_CACHED _PAGE_PAT /* WB LLCeLLC */ +#define PPAT_DISPLAY_ELLC _PAGE_PCD /* WT eLLC */ #define CHV_PPAT_SNOOP (1<<6) #define GEN8_PPAT_AGE(x) ((x)<<4) -- cgit v1.2.3 From 842ebf7aeb1d6d5d679491d33d8c3f113de7964e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:50 +0300 Subject: drm/i915: Don't enable/unmask flip interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit fd3a40242e87 ("drm/i915: Rip out legacy page_flip completion/irq handling") removed the code to hande the flip done/pending interrupts, but it failed to actually disable/mask those interrupts. Let's do that now. Also remove a stale comment that was left behind. Cc: Daniel Vetter Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-2-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/i915_irq.c | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 91a2c5dbf2da..9b5be5c4bef7 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2925,8 +2925,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) u32 enable_mask; enum pipe pipe; - pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV | - PIPE_CRC_DONE_INTERRUPT_STATUS; + pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); for_each_pipe(dev_priv, pipe) @@ -3301,18 +3300,14 @@ static int ironlake_irq_postinstall(struct drm_device *dev) if (INTEL_GEN(dev_priv) >= 7) { display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | - DE_PCH_EVENT_IVB | DE_PLANEC_FLIP_DONE_IVB | - DE_PLANEB_FLIP_DONE_IVB | - DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB); + DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | DE_DP_A_HOTPLUG_IVB); } else { display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | - DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE | - DE_AUX_CHANNEL_A | - DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE | - DE_POISON); + DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | + DE_PIPEA_CRC_DONE | DE_POISON); extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT | DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | DE_DP_A_HOTPLUG); @@ -3434,15 +3429,13 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) enum pipe pipe; if (INTEL_GEN(dev_priv) >= 9) { - de_pipe_masked |= GEN9_PIPE_PLANE1_FLIP_DONE | - GEN9_DE_PIPE_IRQ_FAULT_ERRORS; + de_pipe_masked |= GEN9_DE_PIPE_IRQ_FAULT_ERRORS; de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | GEN9_AUX_CHANNEL_D; if (IS_GEN9_LP(dev_priv)) de_port_masked |= BXT_DE_PORT_GMBUS; } else { - de_pipe_masked |= GEN8_PIPE_PRIMARY_FLIP_DONE | - GEN8_DE_PIPE_IRQ_FAULT_ERRORS; + de_pipe_masked |= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; } de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | @@ -3592,9 +3585,7 @@ static int i8xx_irq_postinstall(struct drm_device *dev) /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | - I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT); + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); I915_WRITE16(IMR, dev_priv->irq_mask); I915_WRITE16(IER, @@ -3613,9 +3604,6 @@ static int i8xx_irq_postinstall(struct drm_device *dev) return 0; } -/* - * Returns true when a page flip has completed. - */ static irqreturn_t i8xx_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; @@ -3734,9 +3722,7 @@ static int i915_irq_postinstall(struct drm_device *dev) dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | - I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT); + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); enable_mask = I915_ASLE_INTERRUPT | @@ -3921,13 +3907,9 @@ static int i965_irq_postinstall(struct drm_device *dev) I915_DISPLAY_PORT_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | - I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT | I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); enable_mask = ~dev_priv->irq_mask; - enable_mask &= ~(I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | - I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT); enable_mask |= I915_USER_INTERRUPT; if (IS_G4X(dev_priv)) -- cgit v1.2.3 From 44d9241e3e62a6938b5ae2ec6b3b4cd5abfdb717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:51 +0300 Subject: drm/i915: Clear pipestat consistently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a lot of different ways of clearing the PIPESTAT registers. Let's unify it all into one function. There's no magic in PIPESTAT that would require any of the double clearing and whatnot that some of the code tries to do. All we can really do is clear the status bits and disable the enable bits. There is no way to mask anything so as soon as another event happens the status bit will become set again, and trying to clear them twice or something can't protect against that. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-3-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/i915_irq.c | 67 ++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 37 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 9b5be5c4bef7..12c5af965833 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1709,6 +1709,19 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) } } +static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) +{ + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + I915_WRITE(PIPESTAT(pipe), + PIPESTAT_INT_STATUS_MASK | + PIPE_FIFO_UNDERRUN_STATUS); + + dev_priv->pipestat_irq_mask[pipe] = 0; + } +} + static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv, u32 iir, u32 pipe_stats[I915_MAX_PIPES]) { @@ -2898,8 +2911,6 @@ static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv) static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) { - enum pipe pipe; - if (IS_CHERRYVIEW(dev_priv)) I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV); else @@ -2908,12 +2919,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - for_each_pipe(dev_priv, pipe) { - I915_WRITE(PIPESTAT(pipe), - PIPE_FIFO_UNDERRUN_STATUS | - PIPESTAT_INT_STATUS_MASK); - dev_priv->pipestat_irq_mask[pipe] = 0; - } + i9xx_pipestat_irq_reset(dev_priv); GEN5_IRQ_RESET(VLV_); dev_priv->irq_mask = ~0; @@ -3566,10 +3572,9 @@ static void ironlake_irq_uninstall(struct drm_device *dev) static void i8xx_irq_preinstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), 0); + i9xx_pipestat_irq_reset(dev_priv); + I915_WRITE16(IMR, 0xffff); I915_WRITE16(IER, 0x0); POSTING_READ16(IER); @@ -3681,13 +3686,9 @@ out: static void i8xx_irq_uninstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; - for_each_pipe(dev_priv, pipe) { - /* Clear enable bits; then clear status bits */ - I915_WRITE(PIPESTAT(pipe), 0); - I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); - } + i9xx_pipestat_irq_reset(dev_priv); + I915_WRITE16(IMR, 0xffff); I915_WRITE16(IER, 0x0); I915_WRITE16(IIR, I915_READ16(IIR)); @@ -3696,16 +3697,16 @@ static void i8xx_irq_uninstall(struct drm_device * dev) static void i915_irq_preinstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; if (I915_HAS_HOTPLUG(dev_priv)) { i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } + i9xx_pipestat_irq_reset(dev_priv); + I915_WRITE16(HWSTAM, 0xeffe); - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), 0); + I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); POSTING_READ(IER); @@ -3861,36 +3862,32 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) static void i915_irq_uninstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; if (I915_HAS_HOTPLUG(dev_priv)) { i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } + i9xx_pipestat_irq_reset(dev_priv); + I915_WRITE16(HWSTAM, 0xffff); - for_each_pipe(dev_priv, pipe) { - /* Clear enable bits; then clear status bits */ - I915_WRITE(PIPESTAT(pipe), 0); - I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); - } + I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); - I915_WRITE(IIR, I915_READ(IIR)); } static void i965_irq_preinstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); + i9xx_pipestat_irq_reset(dev_priv); + I915_WRITE(HWSTAM, 0xeffe); - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), 0); + I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); POSTING_READ(IER); @@ -4084,7 +4081,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) static void i965_irq_uninstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; if (!dev_priv) return; @@ -4092,15 +4088,12 @@ static void i965_irq_uninstall(struct drm_device * dev) i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); + i9xx_pipestat_irq_reset(dev_priv); + I915_WRITE(HWSTAM, 0xffffffff); - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), 0); + I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); - - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), - I915_READ(PIPESTAT(pipe)) & 0x8000ffff); I915_WRITE(IIR, I915_READ(IIR)); } -- cgit v1.2.3 From 3488d4eb43aaf63bc4db7d878b106f73de547d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:52 +0300 Subject: drm/i915: s/GEN5/GEN3/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GEN5_IRQ_RESET/INIT macros are perfectly suitable even for gen3/4 hardware as those have 32 bit interrupt registers. Let's rename the macros to reflect that fact. Gen2 on the other hand has 16 bit interrupt registers so these macros aren't really appropriate there. v2: Fix patch subject (Maarten) Reviewed-by: Chris Wilson Acked-by: Maarten Lankhorst Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 12c5af965833..6dba97e28347 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -126,7 +126,7 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { POSTING_READ(GEN8_##type##_IIR(which)); \ } while (0) -#define GEN5_IRQ_RESET(type) do { \ +#define GEN3_IRQ_RESET(type) do { \ I915_WRITE(type##IMR, 0xffffffff); \ POSTING_READ(type##IMR); \ I915_WRITE(type##IER, 0); \ @@ -139,7 +139,7 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { /* * We should clear IMR at preinstall/uninstall, and just check at postinstall. */ -static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, +static void gen3_assert_iir_is_zero(struct drm_i915_private *dev_priv, i915_reg_t reg) { u32 val = I915_READ(reg); @@ -156,14 +156,14 @@ static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, } #define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \ - gen5_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \ + gen3_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \ I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \ I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \ POSTING_READ(GEN8_##type##_IMR(which)); \ } while (0) -#define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \ - gen5_assert_iir_is_zero(dev_priv, type##IIR); \ +#define GEN3_IRQ_INIT(type, imr_val, ier_val) do { \ + gen3_assert_iir_is_zero(dev_priv, type##IIR); \ I915_WRITE(type##IER, (ier_val)); \ I915_WRITE(type##IMR, (imr_val)); \ POSTING_READ(type##IMR); \ @@ -2876,7 +2876,7 @@ static void ibx_irq_reset(struct drm_i915_private *dev_priv) if (HAS_PCH_NOP(dev_priv)) return; - GEN5_IRQ_RESET(SDE); + GEN3_IRQ_RESET(SDE); if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) I915_WRITE(SERR_INT, 0xffffffff); @@ -2904,9 +2904,9 @@ static void ibx_irq_pre_postinstall(struct drm_device *dev) static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv) { - GEN5_IRQ_RESET(GT); + GEN3_IRQ_RESET(GT); if (INTEL_GEN(dev_priv) >= 6) - GEN5_IRQ_RESET(GEN6_PM); + GEN3_IRQ_RESET(GEN6_PM); } static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) @@ -2921,7 +2921,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) i9xx_pipestat_irq_reset(dev_priv); - GEN5_IRQ_RESET(VLV_); + GEN3_IRQ_RESET(VLV_); dev_priv->irq_mask = ~0; } @@ -2951,7 +2951,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->irq_mask = ~enable_mask; - GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); + GEN3_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); } /* drm_dma.h hooks @@ -2962,7 +2962,7 @@ static void ironlake_irq_reset(struct drm_device *dev) I915_WRITE(HWSTAM, 0xffffffff); - GEN5_IRQ_RESET(DE); + GEN3_IRQ_RESET(DE); if (IS_GEN7(dev_priv)) I915_WRITE(GEN7_ERR_INT, 0xffffffff); @@ -3009,9 +3009,9 @@ static void gen8_irq_reset(struct drm_device *dev) POWER_DOMAIN_PIPE(pipe))) GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); - GEN5_IRQ_RESET(GEN8_DE_PORT_); - GEN5_IRQ_RESET(GEN8_DE_MISC_); - GEN5_IRQ_RESET(GEN8_PCU_); + GEN3_IRQ_RESET(GEN8_DE_PORT_); + GEN3_IRQ_RESET(GEN8_DE_MISC_); + GEN3_IRQ_RESET(GEN8_PCU_); if (HAS_PCH_SPLIT(dev_priv)) ibx_irq_reset(dev_priv); @@ -3054,7 +3054,7 @@ static void cherryview_irq_preinstall(struct drm_device *dev) gen8_gt_irq_reset(dev_priv); - GEN5_IRQ_RESET(GEN8_PCU_); + GEN3_IRQ_RESET(GEN8_PCU_); spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->display_irqs_enabled) @@ -3251,7 +3251,7 @@ static void ibx_irq_postinstall(struct drm_device *dev) else mask = SDE_GMBUS_CPT; - gen5_assert_iir_is_zero(dev_priv, SDEIIR); + gen3_assert_iir_is_zero(dev_priv, SDEIIR); I915_WRITE(SDEIMR, ~mask); if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || @@ -3282,7 +3282,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; } - GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); + GEN3_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); if (INTEL_GEN(dev_priv) >= 6) { /* @@ -3295,7 +3295,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) } dev_priv->pm_imr = 0xffffffff; - GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs); + GEN3_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs); } } @@ -3325,7 +3325,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) ibx_irq_pre_postinstall(dev); - GEN5_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask); + GEN3_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask); gen5_gt_irq_postinstall(dev); @@ -3464,8 +3464,8 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->de_irq_mask[pipe], de_pipe_enables); - GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables); - GEN5_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); + GEN3_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables); + GEN3_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); if (IS_GEN9_LP(dev_priv)) bxt_hpd_detection_setup(dev_priv); @@ -3551,7 +3551,7 @@ static void cherryview_irq_uninstall(struct drm_device *dev) gen8_gt_irq_reset(dev_priv); - GEN5_IRQ_RESET(GEN8_PCU_); + GEN3_IRQ_RESET(GEN8_PCU_); spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->display_irqs_enabled) -- cgit v1.2.3 From ba7eb78932173ce6e315a754b7b32eb0a4f155ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:53 +0300 Subject: drm/i915: Use GEN3_IRQ_RESET/INIT on gen3/4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the manual IMR+IER+IIR write sequences with the appropriate GEN3_IRQ_RESET/INIT macro invocations in gen3/4. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-5-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_irq.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6dba97e28347..788d37166872 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3707,9 +3707,7 @@ static void i915_irq_preinstall(struct drm_device * dev) I915_WRITE16(HWSTAM, 0xeffe); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - POSTING_READ(IER); + GEN3_IRQ_RESET(); } static int i915_irq_postinstall(struct drm_device *dev) @@ -3741,9 +3739,7 @@ static int i915_irq_postinstall(struct drm_device *dev) dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; } - I915_WRITE(IMR, dev_priv->irq_mask); - I915_WRITE(IER, enable_mask); - POSTING_READ(IER); + GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); i915_enable_asle_pipestat(dev_priv); @@ -3872,9 +3868,7 @@ static void i915_irq_uninstall(struct drm_device * dev) I915_WRITE16(HWSTAM, 0xffff); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - I915_WRITE(IIR, I915_READ(IIR)); + GEN3_IRQ_RESET(); } static void i965_irq_preinstall(struct drm_device * dev) @@ -3888,9 +3882,7 @@ static void i965_irq_preinstall(struct drm_device * dev) I915_WRITE(HWSTAM, 0xeffe); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - POSTING_READ(IER); + GEN3_IRQ_RESET(); } static int i965_irq_postinstall(struct drm_device *dev) @@ -3935,9 +3927,7 @@ static int i965_irq_postinstall(struct drm_device *dev) } I915_WRITE(EMR, error_mask); - I915_WRITE(IMR, dev_priv->irq_mask); - I915_WRITE(IER, enable_mask); - POSTING_READ(IER); + GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); POSTING_READ(PORT_HOTPLUG_EN); @@ -4092,9 +4082,7 @@ static void i965_irq_uninstall(struct drm_device * dev) I915_WRITE(HWSTAM, 0xffffffff); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - I915_WRITE(IIR, I915_READ(IIR)); + GEN3_IRQ_RESET(); } /** -- cgit v1.2.3 From e9e9848a6bcfb635c94e1d5f0b3f60799cfe8955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:54 +0300 Subject: drm/i915: Introduce GEN2_IRQ_RESET/INIT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify the appearance of the gen2 irq code with the gen3+ code by introducing the GEN2_IRQ_RESET/INIT macros. Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 54 ++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 788d37166872..daf8ea719f6f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -136,6 +136,16 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { POSTING_READ(type##IIR); \ } while (0) +#define GEN2_IRQ_RESET(type) do { \ + I915_WRITE16(type##IMR, 0xffff); \ + POSTING_READ16(type##IMR); \ + I915_WRITE16(type##IER, 0); \ + I915_WRITE16(type##IIR, 0xffff); \ + POSTING_READ16(type##IIR); \ + I915_WRITE16(type##IIR, 0xffff); \ + POSTING_READ16(type##IIR); \ +} while (0) + /* * We should clear IMR at preinstall/uninstall, and just check at postinstall. */ @@ -155,6 +165,22 @@ static void gen3_assert_iir_is_zero(struct drm_i915_private *dev_priv, POSTING_READ(reg); } +static void gen2_assert_iir_is_zero(struct drm_i915_private *dev_priv, + i915_reg_t reg) +{ + u16 val = I915_READ16(reg); + + if (val == 0) + return; + + WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", + i915_mmio_reg_offset(reg), val); + I915_WRITE16(reg, 0xffff); + POSTING_READ16(reg); + I915_WRITE16(reg, 0xffff); + POSTING_READ16(reg); +} + #define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \ gen3_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \ I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \ @@ -169,6 +195,13 @@ static void gen3_assert_iir_is_zero(struct drm_i915_private *dev_priv, POSTING_READ(type##IMR); \ } while (0) +#define GEN2_IRQ_INIT(type, imr_val, ier_val) do { \ + gen2_assert_iir_is_zero(dev_priv, type##IIR); \ + I915_WRITE16(type##IER, (ier_val)); \ + I915_WRITE16(type##IMR, (imr_val)); \ + POSTING_READ16(type##IMR); \ +} while (0) + static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); @@ -3575,14 +3608,13 @@ static void i8xx_irq_preinstall(struct drm_device * dev) i9xx_pipestat_irq_reset(dev_priv); - I915_WRITE16(IMR, 0xffff); - I915_WRITE16(IER, 0x0); - POSTING_READ16(IER); + GEN2_IRQ_RESET(); } static int i8xx_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + u16 enable_mask; I915_WRITE16(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); @@ -3591,13 +3623,13 @@ static int i8xx_irq_postinstall(struct drm_device *dev) dev_priv->irq_mask = ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); - I915_WRITE16(IMR, dev_priv->irq_mask); - I915_WRITE16(IER, - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_USER_INTERRUPT); - POSTING_READ16(IER); + enable_mask = + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | + I915_USER_INTERRUPT; + + GEN2_IRQ_INIT(, dev_priv->irq_mask, enable_mask); /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ @@ -3689,9 +3721,7 @@ static void i8xx_irq_uninstall(struct drm_device * dev) i9xx_pipestat_irq_reset(dev_priv); - I915_WRITE16(IMR, 0xffff); - I915_WRITE16(IER, 0x0); - I915_WRITE16(IIR, I915_READ16(IIR)); + GEN2_IRQ_RESET(); } static void i915_irq_preinstall(struct drm_device * dev) -- cgit v1.2.3 From 045cebd2e4c29c55e46a1044fa1d0dd38b790392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:55 +0300 Subject: drm/i915: Setup EMR first on all gen2-4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify the appaerance of the gen2-4 irq postinstall hooks a little bit by doing the EMR setup first on all the platforms. Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index daf8ea719f6f..ebaac9cf8823 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3616,8 +3616,8 @@ static int i8xx_irq_postinstall(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); u16 enable_mask; - I915_WRITE16(EMR, - ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); + I915_WRITE16(EMR, ~(I915_ERROR_PAGE_TABLE | + I915_ERROR_MEMORY_REFRESH)); /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = @@ -3745,7 +3745,8 @@ static int i915_irq_postinstall(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); u32 enable_mask; - I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); + I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | + I915_ERROR_MEMORY_REFRESH)); /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = @@ -3921,6 +3922,21 @@ static int i965_irq_postinstall(struct drm_device *dev) u32 enable_mask; u32 error_mask; + /* + * Enable some error detection, note the instruction error mask + * bit is reserved, so we leave it masked. + */ + if (IS_G4X(dev_priv)) { + error_mask = ~(GM45_ERROR_PAGE_TABLE | + GM45_ERROR_MEM_PRIV | + GM45_ERROR_CP_PRIV | + I915_ERROR_MEMORY_REFRESH); + } else { + error_mask = ~(I915_ERROR_PAGE_TABLE | + I915_ERROR_MEMORY_REFRESH); + } + I915_WRITE(EMR, error_mask); + /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | I915_DISPLAY_PORT_INTERRUPT | @@ -3942,21 +3958,6 @@ static int i965_irq_postinstall(struct drm_device *dev) i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); spin_unlock_irq(&dev_priv->irq_lock); - /* - * Enable some error detection, note the instruction error mask - * bit is reserved, so we leave it masked. - */ - if (IS_G4X(dev_priv)) { - error_mask = ~(GM45_ERROR_PAGE_TABLE | - GM45_ERROR_MEM_PRIV | - GM45_ERROR_CP_PRIV | - I915_ERROR_MEMORY_REFRESH); - } else { - error_mask = ~(I915_ERROR_PAGE_TABLE | - I915_ERROR_MEMORY_REFRESH); - } - I915_WRITE(EMR, error_mask); - GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); -- cgit v1.2.3 From e13924a8c2d32dc86d25771acc484e5f63426bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:56 +0300 Subject: drm/i915: Eliminate PORT_HOTPLUG_EN setup from gen3/4 irq_postinstall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We've already cleared PORT_HOTPLUG_EN in the .irq_preinstall hook so doing it again in the .irq_postinstall is pointless. Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ebaac9cf8823..6431f4ebb726 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3761,9 +3761,6 @@ static int i915_irq_postinstall(struct drm_device *dev) I915_USER_INTERRUPT; if (I915_HAS_HOTPLUG(dev_priv)) { - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - POSTING_READ(PORT_HOTPLUG_EN); - /* Enable in IER... */ enable_mask |= I915_DISPLAY_PORT_INTERRUPT; /* and unmask in IMR */ @@ -3960,9 +3957,6 @@ static int i965_irq_postinstall(struct drm_device *dev) GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - POSTING_READ(PORT_HOTPLUG_EN); - i915_enable_asle_pipestat(dev_priv); return 0; -- cgit v1.2.3 From c30bb1fd384c459bf70d4780a3ad2dec7211ee9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:57 +0300 Subject: drm/i915: Unify the appearance of gen3/4 irq_postistall hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do the irq_mask/enable_mask setup in the same way on gen3/4, and also reorder the steps to make the code more uniform. Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6431f4ebb726..b51aeed59e71 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3769,8 +3769,6 @@ static int i915_irq_postinstall(struct drm_device *dev) GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); - i915_enable_asle_pipestat(dev_priv); - /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ spin_lock_irq(&dev_priv->irq_lock); @@ -3778,6 +3776,8 @@ static int i915_irq_postinstall(struct drm_device *dev) i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); spin_unlock_irq(&dev_priv->irq_lock); + i915_enable_asle_pipestat(dev_priv); + return 0; } @@ -3935,18 +3935,26 @@ static int i965_irq_postinstall(struct drm_device *dev) I915_WRITE(EMR, error_mask); /* Unmask the interrupts that we always want on. */ - dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | - I915_DISPLAY_PORT_INTERRUPT | - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); + dev_priv->irq_mask = + ~(I915_ASLE_INTERRUPT | + I915_DISPLAY_PORT_INTERRUPT | + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | + I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); - enable_mask = ~dev_priv->irq_mask; - enable_mask |= I915_USER_INTERRUPT; + enable_mask = + I915_ASLE_INTERRUPT | + I915_DISPLAY_PORT_INTERRUPT | + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | + I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT | + I915_USER_INTERRUPT; if (IS_G4X(dev_priv)) enable_mask |= I915_BSD_USER_INTERRUPT; + GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); + /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ spin_lock_irq(&dev_priv->irq_lock); @@ -3955,8 +3963,6 @@ static int i965_irq_postinstall(struct drm_device *dev) i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); spin_unlock_irq(&dev_priv->irq_lock); - GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); - i915_enable_asle_pipestat(dev_priv); return 0; -- cgit v1.2.3 From 9515d7b8eb0bff20f9a2fa973331674e8abe06c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:58 +0300 Subject: drm/i915: Remove NULL dev_priv checks from irq_uninstall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There should be no way to land in irq_uninstall without a valid dev_priv. Let's kill off the remaining checks, which are probably some kind of UMS leftovers. Not all the irq_uninstall hooks even had them anymore. Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b51aeed59e71..93cba2de32bc 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3544,11 +3544,6 @@ static int cherryview_irq_postinstall(struct drm_device *dev) static void gen8_irq_uninstall(struct drm_device *dev) { - struct drm_i915_private *dev_priv = to_i915(dev); - - if (!dev_priv) - return; - gen8_irq_reset(dev); } @@ -3556,9 +3551,6 @@ static void valleyview_irq_uninstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (!dev_priv) - return; - I915_WRITE(VLV_MASTER_IER, 0); POSTING_READ(VLV_MASTER_IER); @@ -3576,9 +3568,6 @@ static void cherryview_irq_uninstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (!dev_priv) - return; - I915_WRITE(GEN8_MASTER_IRQ, 0); POSTING_READ(GEN8_MASTER_IRQ); @@ -3594,11 +3583,6 @@ static void cherryview_irq_uninstall(struct drm_device *dev) static void ironlake_irq_uninstall(struct drm_device *dev) { - struct drm_i915_private *dev_priv = to_i915(dev); - - if (!dev_priv) - return; - ironlake_irq_reset(dev); } @@ -4103,9 +4087,6 @@ static void i965_irq_uninstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (!dev_priv) - return; - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); -- cgit v1.2.3 From eb64343ca6dd03241579400e037f0e15e6831b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:36:59 +0300 Subject: drm/i915: Extract PIPESTAT irq handling into separate functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the gen2-4 PIPESTAT irq handling into separate functions just like we already do on VLV/CHV. We can share valleyview_pipestat_irq_ack() on all gmch platforms to actually read and clear the PIPESTAT status bits, so let's rename it to i9xx_pipestat_irq_ack(). Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-11-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 215 +++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 122 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 93cba2de32bc..27fd8e91084d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1755,8 +1755,8 @@ static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) } } -static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv, - u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, + u32 iir, u32 pipe_stats[I915_MAX_PIPES]) { int pipe; @@ -1813,6 +1813,74 @@ static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv, spin_unlock(&dev_priv->irq_lock); } +static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, + u16 iir, u32 pipe_stats[I915_MAX_PIPES]) +{ + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) + drm_handle_vblank(&dev_priv->drm, pipe); + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_irq_handler(dev_priv, pipe); + + if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) + intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + } +} + +static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, + u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +{ + bool blc_event = false; + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) + drm_handle_vblank(&dev_priv->drm, pipe); + + if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) + blc_event = true; + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_irq_handler(dev_priv, pipe); + + if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) + intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + } + + if (blc_event || (iir & I915_ASLE_INTERRUPT)) + intel_opregion_asle_intr(dev_priv); +} + +static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, + u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +{ + bool blc_event = false; + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) + drm_handle_vblank(&dev_priv->drm, pipe); + + if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) + blc_event = true; + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_irq_handler(dev_priv, pipe); + + if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) + intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + } + + if (blc_event || (iir & I915_ASLE_INTERRUPT)) + intel_opregion_asle_intr(dev_priv); + + if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) + gmbus_irq_handler(dev_priv); +} + static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, u32 pipe_stats[I915_MAX_PIPES]) { @@ -1928,7 +1996,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) /* Call regardless, as some status bits might not be * signalled in iir */ - valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats); + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); if (iir & (I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT)) @@ -2012,7 +2080,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) /* Call regardless, as some status bits might not be * signalled in iir */ - valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats); + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); if (iir & (I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT | @@ -3630,8 +3698,6 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); u16 iir, new_iir; - u32 pipe_stats[2]; - int pipe; irqreturn_t ret; if (!intel_irqs_enabled(dev_priv)) @@ -3646,26 +3712,14 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) goto out; while (iir) { - /* Can't rely on pipestat interrupt bit in iir as it might - * have been cleared after the pipestat interrupt was received. - * It doesn't set the bit in iir again, but it still produces - * interrupts (for non-MSI). - */ - spin_lock(&dev_priv->irq_lock); + u32 pipe_stats[I915_MAX_PIPES] = {}; + if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - for_each_pipe(dev_priv, pipe) { - i915_reg_t reg = PIPESTAT(pipe); - pipe_stats[pipe] = I915_READ(reg); - - /* - * Clear the PIPE*STAT regs before the IIR - */ - if (pipe_stats[pipe] & 0x8000ffff) - I915_WRITE(reg, pipe_stats[pipe]); - } - spin_unlock(&dev_priv->irq_lock); + /* Call regardless, as some status bits might not be + * signalled in iir */ + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); I915_WRITE16(IIR, iir); new_iir = I915_READ16(IIR); /* Flush posted writes */ @@ -3673,21 +3727,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev_priv->engine[RCS]); - for_each_pipe(dev_priv, pipe) { - int plane = pipe; - if (HAS_FBC(dev_priv)) - plane = !plane; - - if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) - drm_handle_vblank(&dev_priv->drm, pipe); - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev_priv, pipe); - - if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, - pipe); - } + i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); iir = new_iir; } @@ -3769,8 +3809,8 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); - u32 iir, new_iir, pipe_stats[I915_MAX_PIPES]; - int pipe, ret = IRQ_NONE; + u32 iir, new_iir; + int ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -3780,29 +3820,15 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) iir = I915_READ(IIR); do { - bool irq_received = (iir) != 0; - bool blc_event = false; + u32 pipe_stats[I915_MAX_PIPES] = {}; + bool irq_received = iir != 0; - /* Can't rely on pipestat interrupt bit in iir as it might - * have been cleared after the pipestat interrupt was received. - * It doesn't set the bit in iir again, but it still produces - * interrupts (for non-MSI). - */ - spin_lock(&dev_priv->irq_lock); if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - for_each_pipe(dev_priv, pipe) { - i915_reg_t reg = PIPESTAT(pipe); - pipe_stats[pipe] = I915_READ(reg); - - /* Clear the PIPE*STAT regs before the IIR */ - if (pipe_stats[pipe] & 0x8000ffff) { - I915_WRITE(reg, pipe_stats[pipe]); - irq_received = true; - } - } - spin_unlock(&dev_priv->irq_lock); + /* Call regardless, as some status bits might not be + * signalled in iir */ + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); if (!irq_received) break; @@ -3821,27 +3847,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev_priv->engine[RCS]); - for_each_pipe(dev_priv, pipe) { - int plane = pipe; - if (HAS_FBC(dev_priv)) - plane = !plane; - - if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) - drm_handle_vblank(&dev_priv->drm, pipe); - - if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) - blc_event = true; - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev_priv, pipe); - - if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, - pipe); - } - - if (blc_event || (iir & I915_ASLE_INTERRUPT)) - intel_opregion_asle_intr(dev_priv); + i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); /* With MSI, interrupts are only generated when iir * transitions from zero to nonzero. If another bit got @@ -3982,8 +3988,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); u32 iir, new_iir; - u32 pipe_stats[I915_MAX_PIPES]; - int ret = IRQ_NONE, pipe; + int ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -3994,31 +3999,15 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) iir = I915_READ(IIR); for (;;) { - bool irq_received = (iir) != 0; - bool blc_event = false; + u32 pipe_stats[I915_MAX_PIPES] = {}; + bool irq_received = iir != 0; - /* Can't rely on pipestat interrupt bit in iir as it might - * have been cleared after the pipestat interrupt was received. - * It doesn't set the bit in iir again, but it still produces - * interrupts (for non-MSI). - */ - spin_lock(&dev_priv->irq_lock); if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - for_each_pipe(dev_priv, pipe) { - i915_reg_t reg = PIPESTAT(pipe); - pipe_stats[pipe] = I915_READ(reg); - - /* - * Clear the PIPE*STAT regs before the IIR - */ - if (pipe_stats[pipe] & 0x8000ffff) { - I915_WRITE(reg, pipe_stats[pipe]); - irq_received = true; - } - } - spin_unlock(&dev_priv->irq_lock); + /* Call regardless, as some status bits might not be + * signalled in iir */ + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); if (!irq_received) break; @@ -4040,25 +4029,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) if (iir & I915_BSD_USER_INTERRUPT) notify_ring(dev_priv->engine[VCS]); - for_each_pipe(dev_priv, pipe) { - if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) - drm_handle_vblank(&dev_priv->drm, pipe); - - if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) - blc_event = true; - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev_priv, pipe); - - if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); - } - - if (blc_event || (iir & I915_ASLE_INTERRUPT)) - intel_opregion_asle_intr(dev_priv); - - if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) - gmbus_irq_handler(dev_priv); + i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); /* With MSI, interrupts are only generated when iir * transitions from zero to nonzero. If another bit got -- cgit v1.2.3 From af722d280e8551e918b22e96f487824935470c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:37:00 +0300 Subject: drm/i915: Rewrite GMCH irq handlers to avoid loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate the loops from the gen2-3 irq handlers. Since we don't use MSI anymore on these platforms, and thus the CPU interrupt will be level triggered, we shouldn't need to play any tricks with IER to induce edges from IIR. IIR itself still detects only edges from PIPESTAT & co. on gen4 but since IIR is double buffered and we only clear one bit per irq handler invocation we can use the normal "clear PIPESTAT & co. -> clear IIR" approach to ack the interrupts. On gen2 everything is level triggered, and gen3 presumably follows either the gen2 or gen4 approach since nothing else would really make sense. v2: Drop the IER tricks since we no longer use MSI Cc: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-12-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_irq.c | 143 ++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 92 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 27fd8e91084d..26569a00b40c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3697,8 +3697,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); - u16 iir, new_iir; - irqreturn_t ret; + irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -3706,34 +3705,31 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - ret = IRQ_NONE; - iir = I915_READ16(IIR); - if (iir == 0) - goto out; - - while (iir) { + do { u32 pipe_stats[I915_MAX_PIPES] = {}; + u16 iir; - if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) - DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); + iir = I915_READ16(IIR); + if (iir == 0) + break; + + ret = IRQ_HANDLED; /* Call regardless, as some status bits might not be * signalled in iir */ i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); I915_WRITE16(IIR, iir); - new_iir = I915_READ16(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) notify_ring(dev_priv->engine[RCS]); - i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); + if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) + DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - iir = new_iir; - } - ret = IRQ_HANDLED; + i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); + } while (0); -out: enable_rpm_wakeref_asserts(dev_priv); return ret; @@ -3809,8 +3805,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); - u32 iir, new_iir; - int ret = IRQ_NONE; + irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -3818,55 +3813,38 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - iir = I915_READ(IIR); do { u32 pipe_stats[I915_MAX_PIPES] = {}; - bool irq_received = iir != 0; + u32 hotplug_status = 0; + u32 iir; - if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) - DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); + iir = I915_READ(IIR); + if (iir == 0) + break; + + ret = IRQ_HANDLED; + + if (I915_HAS_HOTPLUG(dev_priv) && + iir & I915_DISPLAY_PORT_INTERRUPT) + hotplug_status = i9xx_hpd_irq_ack(dev_priv); /* Call regardless, as some status bits might not be * signalled in iir */ i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); - if (!irq_received) - break; - - /* Consume port. Then clear IIR or we'll miss events */ - if (I915_HAS_HOTPLUG(dev_priv) && - iir & I915_DISPLAY_PORT_INTERRUPT) { - u32 hotplug_status = i9xx_hpd_irq_ack(dev_priv); - if (hotplug_status) - i9xx_hpd_irq_handler(dev_priv, hotplug_status); - } - I915_WRITE(IIR, iir); - new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) notify_ring(dev_priv->engine[RCS]); - i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); + if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) + DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - /* With MSI, interrupts are only generated when iir - * transitions from zero to nonzero. If another bit got - * set while we were handling the existing iir bits, then - * we would never get another interrupt. - * - * This is fine on non-MSI as well, as if we hit this path - * we avoid exiting the interrupt handler only to generate - * another one. - * - * Note that for MSI this could cause a stray interrupt report - * if an interrupt landed in the time between writing IIR and - * the posting read. This should be rare enough to never - * trigger the 99% of 100,000 interrupts test for disabling - * stray interrupts. - */ - ret = IRQ_HANDLED; - iir = new_iir; - } while (iir); + if (hotplug_status) + i9xx_hpd_irq_handler(dev_priv, hotplug_status); + + i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); + } while (0); enable_rpm_wakeref_asserts(dev_priv); @@ -3987,8 +3965,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); - u32 iir, new_iir; - int ret = IRQ_NONE; + irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -3996,58 +3973,40 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - iir = I915_READ(IIR); - - for (;;) { + do { u32 pipe_stats[I915_MAX_PIPES] = {}; - bool irq_received = iir != 0; - - if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) - DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - - /* Call regardless, as some status bits might not be - * signalled in iir */ - i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); + u32 hotplug_status = 0; + u32 iir; - if (!irq_received) + iir = I915_READ(IIR); + if (iir == 0) break; ret = IRQ_HANDLED; - /* Consume port. Then clear IIR or we'll miss events */ - if (iir & I915_DISPLAY_PORT_INTERRUPT) { - u32 hotplug_status = i9xx_hpd_irq_ack(dev_priv); - if (hotplug_status) - i9xx_hpd_irq_handler(dev_priv, hotplug_status); - } + if (iir & I915_DISPLAY_PORT_INTERRUPT) + hotplug_status = i9xx_hpd_irq_ack(dev_priv); + + /* Call regardless, as some status bits might not be + * signalled in iir */ + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); I915_WRITE(IIR, iir); - new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) notify_ring(dev_priv->engine[RCS]); + if (iir & I915_BSD_USER_INTERRUPT) notify_ring(dev_priv->engine[VCS]); - i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); + if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) + DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - /* With MSI, interrupts are only generated when iir - * transitions from zero to nonzero. If another bit got - * set while we were handling the existing iir bits, then - * we would never get another interrupt. - * - * This is fine on non-MSI as well, as if we hit this path - * we avoid exiting the interrupt handler only to generate - * another one. - * - * Note that for MSI this could cause a stray interrupt report - * if an interrupt landed in the time between writing IIR and - * the posting read. This should be rare enough to never - * trigger the 99% of 100,000 interrupts test for disabling - * stray interrupts. - */ - iir = new_iir; - } + if (hotplug_status) + i9xx_hpd_irq_handler(dev_priv, hotplug_status); + + i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); + } while (0); enable_rpm_wakeref_asserts(dev_priv); -- cgit v1.2.3 From 5190707e7a4fc701e94cd7e152d15dbba90b63ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:37:02 +0300 Subject: drm/i915: Gen3 HWSTAM is actually 32 bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bspec claims that HWSTAM is only 16 bits on gen3, but the other interrupts registers are 32 bits and there are 18 valid interrupt bits. Hence a 16 bit HWSTAM wouldn't be able to contain all the bits, so it seems the spec is incorrect about the size of the register. And indeed I can clear bits 16 and 17 just fine with a 32 bit write. So let's adjust the code to treat the register as 32 bits. Acked-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-14-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 26569a00b40c..003a92857102 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3755,7 +3755,7 @@ static void i915_irq_preinstall(struct drm_device * dev) i9xx_pipestat_irq_reset(dev_priv); - I915_WRITE16(HWSTAM, 0xeffe); + I915_WRITE(HWSTAM, 0xffffeffe); GEN3_IRQ_RESET(); } @@ -3862,7 +3862,7 @@ static void i915_irq_uninstall(struct drm_device * dev) i9xx_pipestat_irq_reset(dev_priv); - I915_WRITE16(HWSTAM, 0xffff); + I915_WRITE(HWSTAM, 0xffffffff); GEN3_IRQ_RESET(); } -- cgit v1.2.3 From 442aa277c066cec6cfe8508b3edbdda022b10568 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Thu, 14 Sep 2017 11:31:39 -0700 Subject: drm/i915/cnl: Change the macro name to DPLL_CFGCR0_DCO_FRACTION_SHIFT No functional changes. Only change the macro from "DPLL_CFGCR0_DC0_FRAC_SHIFT to DPLL_CFGCR0_DCO_FRACTION_SHIFT to be consistent with DPLL_CFGCR0_DCO_FRACTION_MASK and DPLL_CFGCR0_DCO_FRACTION Cc: Rodrigo Vivi Signed-off-by: Manasi Navare Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/1505413899-30876-1-git-send-email-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_ddi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0befefec7327..94b40a469afd 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8599,7 +8599,7 @@ enum skl_power_gate { #define DPLL_CFGCR0_LINK_RATE_3240 (6 << 25) #define DPLL_CFGCR0_LINK_RATE_4050 (7 << 25) #define DPLL_CFGCR0_DCO_FRACTION_MASK (0x7fff << 10) -#define DPLL_CFGCR0_DCO_FRAC_SHIFT (10) +#define DPLL_CFGCR0_DCO_FRACTION_SHIFT (10) #define DPLL_CFGCR0_DCO_FRACTION(x) ((x) << 10) #define DPLL_CFGCR0_DCO_INTEGER_MASK (0x3ff) #define CNL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR0, _CNL_DPLL1_CFGCR0) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 1da3bb2cc4b4..31d14587ad86 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1212,7 +1212,7 @@ static int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv, dco_freq = (cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * ref_clock; dco_freq += (((cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >> - DPLL_CFGCR0_DCO_FRAC_SHIFT) * ref_clock) / 0x8000; + DPLL_CFGCR0_DCO_FRACTION_SHIFT) * ref_clock) / 0x8000; return dco_freq / (p0 * p1 * p2 * 5); } -- cgit v1.2.3 From e01e71fc49d4c95090a04f898a3fe788c652a04b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 14 Sep 2017 17:42:13 +0100 Subject: drm/i915: Remove unused 'in_vbl' from i915_get_crtc_scanoutpos() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 1bf6ad622b9b ("drm/vblank: drop the mode argument from drm_calc_vbltimestamp_from_scanoutpos") removed the use of in_vbl, but did not remove the local variable. Do so now. Fixes: 1bf6ad622b9b ("drm/vblank: drop the mode argument from drm_calc_vbltimestamp_from_scanoutpos") Signed-off-by: Chris Wilson Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170914164213.18461-1-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_irq.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 003a92857102..e8bb6c644fa4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -872,7 +872,6 @@ static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, pipe); int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; - bool in_vbl = true; unsigned long irqflags; if (WARN_ON(!mode->crtc_clock)) { @@ -955,8 +954,6 @@ static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - in_vbl = position >= vbl_start && position < vbl_end; - /* * While in vblank, position will be negative * counting up towards 0 at vbl_end. And outside -- cgit v1.2.3 From 21cc6431e0c2d7c3a2e2fd4dd002400be73cb270 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Sep 2017 09:41:25 +0100 Subject: drm/i915: Mark the userptr invalidate workqueue as WQ_MEM_RECLAIM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To silence the critcs: [56532.161115] workqueue: PF_MEMALLOC task 36(khugepaged) is flushing !WQ_MEM_RECLAIM i915-userptr-release: (null) [56532.161138] ------------[ cut here ]------------ [56532.161144] WARNING: CPU: 1 PID: 36 at kernel/workqueue.c:2418 check_flush_dependency+0xe8/0xf0 [56532.161145] Modules linked in: wmi_bmof [56532.161148] CPU: 1 PID: 36 Comm: khugepaged Not tainted 4.13.0-krejzi #1 [56532.161149] Hardware name: HP HP ProBook 470 G3/8102, BIOS N78 Ver. 01.17 06/08/2017 [56532.161150] task: ffff8802371ee200 task.stack: ffffc90000174000 [56532.161152] RIP: 0010:check_flush_dependency+0xe8/0xf0 [56532.161152] RSP: 0018:ffffc900001777b8 EFLAGS: 00010286 [56532.161153] RAX: 000000000000006c RBX: ffff88022fc5a000 RCX: 0000000000000001 [56532.161154] RDX: 0000000000000000 RSI: 0000000000000086 RDI: 00000000ffffffff [56532.161155] RBP: 0000000000000000 R08: 14f038bb55f6dae0 R09: 0000000000000516 [56532.161155] R10: ffffc900001778a0 R11: 000000006c756e28 R12: ffff8802371ee200 [56532.161156] R13: 0000000000000000 R14: 000000000000000b R15: ffffc90000177810 [56532.161157] FS: 0000000000000000(0000) GS:ffff880240480000(0000) knlGS:0000000000000000 [56532.161158] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [56532.161158] CR2: 0000000004795ff8 CR3: 000000000220a000 CR4: 00000000003406e0 [56532.161159] Call Trace: [56532.161161] ? flush_workqueue+0x136/0x3e0 [56532.161178] ? _raw_spin_unlock_irqrestore+0xf/0x30 [56532.161179] ? try_to_wake_up+0x1ce/0x3b0 [56532.161183] ? i915_gem_userptr_mn_invalidate_range_start+0x13f/0x150 [56532.161184] ? _raw_spin_unlock+0xd/0x20 [56532.161186] ? i915_gem_userptr_mn_invalidate_range_start+0x13f/0x150 [56532.161189] ? __mmu_notifier_invalidate_range_start+0x4a/0x70 [56532.161191] ? try_to_unmap_one+0x5e5/0x660 [56532.161193] ? rmap_walk_file+0xe4/0x240 [56532.161195] ? __ClearPageMovable+0x10/0x10 [56532.161196] ? try_to_unmap+0x8c/0xe0 [56532.161197] ? page_remove_rmap+0x280/0x280 [56532.161199] ? page_not_mapped+0x10/0x10 [56532.161200] ? page_get_anon_vma+0x90/0x90 [56532.161202] ? migrate_pages+0x6a5/0x940 [56532.161203] ? isolate_freepages_block+0x330/0x330 [56532.161205] ? compact_zone+0x593/0x6a0 [56532.161206] ? enqueue_task_fair+0xc3/0x1180 [56532.161208] ? compact_zone_order+0x9b/0xc0 [56532.161210] ? get_page_from_freelist+0x24a/0x900 [56532.161212] ? try_to_compact_pages+0xc8/0x240 [56532.161213] ? try_to_compact_pages+0xc8/0x240 [56532.161215] ? __alloc_pages_direct_compact+0x45/0xe0 [56532.161216] ? __alloc_pages_slowpath+0x845/0xb90 [56532.161218] ? __alloc_pages_nodemask+0x176/0x1f0 [56532.161220] ? wait_woken+0x80/0x80 [56532.161222] ? khugepaged+0x29e/0x17d0 [56532.161223] ? wait_woken+0x80/0x80 [56532.161225] ? collapse_shmem.isra.39+0xa60/0xa60 [56532.161226] ? kthread+0x10d/0x130 [56532.161227] ? kthread_create_on_node+0x60/0x60 [56532.161228] ? ret_from_fork+0x22/0x30 [56532.161229] Code: 00 8b b0 10 05 00 00 48 8d 8b b0 00 00 00 48 8d 90 b8 06 00 00 49 89 e8 48 c7 c7 38 55 09 82 c6 05 f9 c6 1d 01 01 e8 0e a1 03 00 <0f> ff e9 6b ff ff ff 90 48 8b 37 40 f6 c6 04 75 1b 48 c1 ee 05 [56532.161251] ---[ end trace 2ce2b4f5f69b803b ]--- Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170911084135.22903-2-chris@chris-wilson.co.uk Reviewed-by: Michał Winiarski --- drivers/gpu/drm/i915/i915_gem_userptr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 2ce078e8c763..15547c8f7d3f 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -813,7 +813,9 @@ int i915_gem_init_userptr(struct drm_i915_private *dev_priv) hash_init(dev_priv->mm_structs); dev_priv->mm.userptr_wq = - alloc_workqueue("i915-userptr-acquire", WQ_HIGHPRI, 0); + alloc_workqueue("i915-userptr-acquire", + WQ_HIGHPRI | WQ_MEM_RECLAIM, + 0); if (!dev_priv->mm.userptr_wq) return -ENOMEM; -- cgit v1.2.3 From 17533bf95719466c524e07a5880d47a8d7aaa0cd Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 14 Sep 2017 15:08:01 +0000 Subject: drm/i915: Rename lvds_use_ssc modparam to panel_use_ssc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This modparam affects not only LVDS but also eDP panels. Additionally with this rename we will keep modparam and i915_params field name in sync. This patch will unblock us with further improvements around params defs. Suggested-by: Ville Syrjala Signed-off-by: Michal Wajdeczko Cc: Ville Syrjala Cc: Chris Wilson Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170914150805.28376-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/i915_params.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 8ab003dca113..221f7d4caae6 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -105,8 +105,8 @@ MODULE_PARM_DESC(lvds_channel_mode, "Specify LVDS channel mode " "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)"); -module_param_named_unsafe(lvds_use_ssc, i915.panel_use_ssc, int, 0600); -MODULE_PARM_DESC(lvds_use_ssc, +module_param_named_unsafe(panel_use_ssc, i915.panel_use_ssc, int, 0600); +MODULE_PARM_DESC(panel_use_ssc, "Use Spread Spectrum Clock with panels [LVDS/eDP] " "(default: auto from VBT)"); -- cgit v1.2.3 From c95469324518f3ab216d7e3a820b5f0609569681 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 14 Sep 2017 15:08:02 +0000 Subject: drm/i915: Introduce custom variant of module_param_named macro As we now use same name for public module param and its local representation we can simplify param definition macro. Changes done with Coccinelle: @@ declarer name module_param_named; declarer name module_param_named_unsafe; declarer name i915_param_named; declarer name i915_param_named_unsafe; identifier n; @@ ( -module_param_named(n, i915.n, +i915_module_param_named(n, ...); | -module_param_named_unsafe(n, i915.n, +i915_module_param_named_unsafe(n, ...); ) Suggested-by: Chris Wilson Signed-off-by: Michal Wajdeczko Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170914150805.28376-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/i915_params.c | 85 ++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 40 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 221f7d4caae6..891e0a5e9336 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -25,6 +25,11 @@ #include "i915_params.h" #include "i915_drv.h" +#define i915_param_named(name, T, perm) \ + module_param_named(name, i915.name, T, perm) +#define i915_param_named_unsafe(name, T, perm) \ + module_param_named_unsafe(name, i915.name, T, perm) + struct i915_params i915 __read_mostly = { .modeset = -1, .panel_ignore_lid = 1, @@ -67,22 +72,22 @@ struct i915_params i915 __read_mostly = { .enable_gvt = false, }; -module_param_named(modeset, i915.modeset, int, 0400); +i915_param_named(modeset, int, 0400); MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (0=disable, " "1=on, -1=force vga console preference [default])"); -module_param_named_unsafe(panel_ignore_lid, i915.panel_ignore_lid, int, 0600); +i915_param_named_unsafe(panel_ignore_lid, int, 0600); MODULE_PARM_DESC(panel_ignore_lid, "Override lid status (0=autodetect, 1=autodetect disabled [default], " "-1=force lid closed, -2=force lid open)"); -module_param_named_unsafe(semaphores, i915.semaphores, int, 0400); +i915_param_named_unsafe(semaphores, int, 0400); MODULE_PARM_DESC(semaphores, "Use semaphores for inter-ring sync " "(default: -1 (use per-chip defaults))"); -module_param_named_unsafe(enable_rc6, i915.enable_rc6, int, 0400); +i915_param_named_unsafe(enable_rc6, int, 0400); MODULE_PARM_DESC(enable_rc6, "Enable power-saving render C-state 6. " "Different stages can be selected via bitmask values " @@ -90,100 +95,100 @@ MODULE_PARM_DESC(enable_rc6, "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. " "default: -1 (use per-chip default)"); -module_param_named_unsafe(enable_dc, i915.enable_dc, int, 0400); +i915_param_named_unsafe(enable_dc, int, 0400); MODULE_PARM_DESC(enable_dc, "Enable power-saving display C-states. " "(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6)"); -module_param_named_unsafe(enable_fbc, i915.enable_fbc, int, 0600); +i915_param_named_unsafe(enable_fbc, int, 0600); MODULE_PARM_DESC(enable_fbc, "Enable frame buffer compression for power savings " "(default: -1 (use per-chip default))"); -module_param_named_unsafe(lvds_channel_mode, i915.lvds_channel_mode, int, 0400); +i915_param_named_unsafe(lvds_channel_mode, int, 0400); MODULE_PARM_DESC(lvds_channel_mode, "Specify LVDS channel mode " "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)"); -module_param_named_unsafe(panel_use_ssc, i915.panel_use_ssc, int, 0600); +i915_param_named_unsafe(panel_use_ssc, int, 0600); MODULE_PARM_DESC(panel_use_ssc, "Use Spread Spectrum Clock with panels [LVDS/eDP] " "(default: auto from VBT)"); -module_param_named_unsafe(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0400); +i915_param_named_unsafe(vbt_sdvo_panel_type, int, 0400); MODULE_PARM_DESC(vbt_sdvo_panel_type, "Override/Ignore selection of SDVO panel mode in the VBT " "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); -module_param_named_unsafe(reset, i915.reset, int, 0600); +i915_param_named_unsafe(reset, int, 0600); MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset, 2=engine reset [default])"); -module_param_named_unsafe(vbt_firmware, i915.vbt_firmware, charp, 0400); +i915_param_named_unsafe(vbt_firmware, charp, 0400); MODULE_PARM_DESC(vbt_firmware, "Load VBT from specified file under /lib/firmware"); #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) -module_param_named(error_capture, i915.error_capture, bool, 0600); +i915_param_named(error_capture, bool, 0600); MODULE_PARM_DESC(error_capture, "Record the GPU state following a hang. " "This information in /sys/class/drm/card/error is vital for " "triaging and debugging hangs."); #endif -module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644); +i915_param_named_unsafe(enable_hangcheck, bool, 0644); MODULE_PARM_DESC(enable_hangcheck, "Periodically check GPU activity for detecting hangs. " "WARNING: Disabling this can cause system wide hangs. " "(default: true)"); -module_param_named_unsafe(enable_ppgtt, i915.enable_ppgtt, int, 0400); +i915_param_named_unsafe(enable_ppgtt, int, 0400); MODULE_PARM_DESC(enable_ppgtt, "Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)"); -module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400); +i915_param_named_unsafe(enable_execlists, int, 0400); MODULE_PARM_DESC(enable_execlists, "Override execlists usage. " "(-1=auto [default], 0=disabled, 1=enabled)"); -module_param_named_unsafe(enable_psr, i915.enable_psr, int, 0600); +i915_param_named_unsafe(enable_psr, int, 0600); MODULE_PARM_DESC(enable_psr, "Enable PSR " "(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) " "Default: -1 (use per-chip default)"); -module_param_named_unsafe(alpha_support, i915.alpha_support, bool, 0400); +i915_param_named_unsafe(alpha_support, bool, 0400); MODULE_PARM_DESC(alpha_support, "Enable alpha quality driver support for latest hardware. " "See also CONFIG_DRM_I915_ALPHA_SUPPORT."); -module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0400); +i915_param_named_unsafe(disable_power_well, int, 0400); MODULE_PARM_DESC(disable_power_well, "Disable display power wells when possible " "(-1=auto [default], 0=power wells always on, 1=power wells disabled when possible)"); -module_param_named_unsafe(enable_ips, i915.enable_ips, int, 0600); +i915_param_named_unsafe(enable_ips, int, 0600); MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)"); -module_param_named(fastboot, i915.fastboot, bool, 0600); +i915_param_named(fastboot, bool, 0600); MODULE_PARM_DESC(fastboot, "Try to skip unnecessary mode sets at boot time (default: false)"); -module_param_named_unsafe(prefault_disable, i915.prefault_disable, bool, 0600); +i915_param_named_unsafe(prefault_disable, bool, 0600); MODULE_PARM_DESC(prefault_disable, "Disable page prefaulting for pread/pwrite/reloc (default:false). " "For developers only."); -module_param_named_unsafe(load_detect_test, i915.load_detect_test, bool, 0600); +i915_param_named_unsafe(load_detect_test, bool, 0600); MODULE_PARM_DESC(load_detect_test, "Force-enable the VGA load detect code for testing (default:false). " "For developers only."); -module_param_named_unsafe(force_reset_modeset_test, i915.force_reset_modeset_test, bool, 0600); +i915_param_named_unsafe(force_reset_modeset_test, bool, 0600); MODULE_PARM_DESC(force_reset_modeset_test, "Force a modeset during gpu reset for testing (default:false). " "For developers only."); -module_param_named_unsafe(invert_brightness, i915.invert_brightness, int, 0600); +i915_param_named_unsafe(invert_brightness, int, 0600); MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " "(-1 force normal, 0 machine defaults, 1 force inversion), please " @@ -191,69 +196,69 @@ MODULE_PARM_DESC(invert_brightness, "to dri-devel@lists.freedesktop.org, if your machine needs it. " "It will then be included in an upcoming module version."); -module_param_named(disable_display, i915.disable_display, bool, 0400); +i915_param_named(disable_display, bool, 0400); MODULE_PARM_DESC(disable_display, "Disable display (default: false)"); -module_param_named_unsafe(enable_cmd_parser, i915.enable_cmd_parser, bool, 0400); +i915_param_named_unsafe(enable_cmd_parser, bool, 0400); MODULE_PARM_DESC(enable_cmd_parser, "Enable command parsing (true=enabled [default], false=disabled)"); -module_param_named_unsafe(use_mmio_flip, i915.use_mmio_flip, int, 0600); +i915_param_named_unsafe(use_mmio_flip, int, 0600); MODULE_PARM_DESC(use_mmio_flip, "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)"); -module_param_named(mmio_debug, i915.mmio_debug, int, 0600); +i915_param_named(mmio_debug, int, 0600); MODULE_PARM_DESC(mmio_debug, "Enable the MMIO debug code for the first N failures (default: off). " "This may negatively affect performance."); -module_param_named(verbose_state_checks, i915.verbose_state_checks, bool, 0600); +i915_param_named(verbose_state_checks, bool, 0600); MODULE_PARM_DESC(verbose_state_checks, "Enable verbose logs (ie. WARN_ON()) in case of unexpected hw state conditions."); -module_param_named_unsafe(nuclear_pageflip, i915.nuclear_pageflip, bool, 0400); +i915_param_named_unsafe(nuclear_pageflip, bool, 0400); MODULE_PARM_DESC(nuclear_pageflip, "Force enable atomic functionality on platforms that don't have full support yet."); /* WA to get away with the default setting in VBT for early platforms.Will be removed */ -module_param_named_unsafe(edp_vswing, i915.edp_vswing, int, 0400); +i915_param_named_unsafe(edp_vswing, int, 0400); MODULE_PARM_DESC(edp_vswing, "Ignore/Override vswing pre-emph table selection from VBT " "(0=use value from vbt [default], 1=low power swing(200mV)," "2=default swing(400mV))"); -module_param_named_unsafe(enable_guc_loading, i915.enable_guc_loading, int, 0400); +i915_param_named_unsafe(enable_guc_loading, int, 0400); MODULE_PARM_DESC(enable_guc_loading, "Enable GuC firmware loading " "(-1=auto, 0=never [default], 1=if available, 2=required)"); -module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, int, 0400); +i915_param_named_unsafe(enable_guc_submission, int, 0400); MODULE_PARM_DESC(enable_guc_submission, "Enable GuC submission " "(-1=auto, 0=never [default], 1=if available, 2=required)"); -module_param_named(guc_log_level, i915.guc_log_level, int, 0400); +i915_param_named(guc_log_level, int, 0400); MODULE_PARM_DESC(guc_log_level, "GuC firmware logging level (-1:disabled (default), 0-3:enabled)"); -module_param_named_unsafe(guc_firmware_path, i915.guc_firmware_path, charp, 0400); +i915_param_named_unsafe(guc_firmware_path, charp, 0400); MODULE_PARM_DESC(guc_firmware_path, "GuC firmware path to use instead of the default one"); -module_param_named_unsafe(huc_firmware_path, i915.huc_firmware_path, charp, 0400); +i915_param_named_unsafe(huc_firmware_path, charp, 0400); MODULE_PARM_DESC(huc_firmware_path, "HuC firmware path to use instead of the default one"); -module_param_named_unsafe(enable_dp_mst, i915.enable_dp_mst, bool, 0600); +i915_param_named_unsafe(enable_dp_mst, bool, 0600); MODULE_PARM_DESC(enable_dp_mst, "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)"); -module_param_named_unsafe(inject_load_failure, i915.inject_load_failure, uint, 0400); +i915_param_named_unsafe(inject_load_failure, uint, 0400); MODULE_PARM_DESC(inject_load_failure, "Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)"); -module_param_named(enable_dpcd_backlight, i915.enable_dpcd_backlight, bool, 0600); +i915_param_named(enable_dpcd_backlight, bool, 0600); MODULE_PARM_DESC(enable_dpcd_backlight, "Enable support for DPCD backlight control (default:false)"); -module_param_named(enable_gvt, i915.enable_gvt, bool, 0400); +i915_param_named(enable_gvt, bool, 0400); MODULE_PARM_DESC(enable_gvt, "Enable support for Intel GVT-g graphics virtualization host support(default:false)"); -- cgit v1.2.3 From 3dcf4f207e8e0703cc00d5384e46ed6eb6902613 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 14 Sep 2017 15:08:03 +0000 Subject: drm/i915: Extend private i915_param_named macro with description We're always specifying description of each module param in separate macro. Let's combine description into our main macro. Started with Coccinelle, followed by minor cleanup. @match1@ declarer name MODULE_PARM_DESC; identifier n; constant c; @@ ( - MODULE_PARM_DESC(n, c); ) @fix1 depends on match1@ declarer name i915_param_named; declarer name i915_param_named_unsafe; identifier match1.n; constant match1.c; @@ ( i915_param_named(n, ... + , c ); | i915_param_named_unsafe(n, ... + , c ); ) Suggested-by: Jani Nikula Signed-off-by: Michal Wajdeczko Cc: Jani Nikula Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170914150805.28376-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/i915_params.c | 167 +++++++++++++++---------------------- 1 file changed, 67 insertions(+), 100 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 891e0a5e9336..ddda513cc7f4 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -25,10 +25,12 @@ #include "i915_params.h" #include "i915_drv.h" -#define i915_param_named(name, T, perm) \ - module_param_named(name, i915.name, T, perm) -#define i915_param_named_unsafe(name, T, perm) \ - module_param_named_unsafe(name, i915.name, T, perm) +#define i915_param_named(name, T, perm, desc) \ + module_param_named(name, i915.name, T, perm); \ + MODULE_PARM_DESC(name, desc) +#define i915_param_named_unsafe(name, T, perm, desc) \ + module_param_named_unsafe(name, i915.name, T, perm); \ + MODULE_PARM_DESC(name, desc) struct i915_params i915 __read_mostly = { .modeset = -1, @@ -72,193 +74,158 @@ struct i915_params i915 __read_mostly = { .enable_gvt = false, }; -i915_param_named(modeset, int, 0400); -MODULE_PARM_DESC(modeset, +i915_param_named(modeset, int, 0400, "Use kernel modesetting [KMS] (0=disable, " "1=on, -1=force vga console preference [default])"); -i915_param_named_unsafe(panel_ignore_lid, int, 0600); -MODULE_PARM_DESC(panel_ignore_lid, +i915_param_named_unsafe(panel_ignore_lid, int, 0600, "Override lid status (0=autodetect, 1=autodetect disabled [default], " "-1=force lid closed, -2=force lid open)"); -i915_param_named_unsafe(semaphores, int, 0400); -MODULE_PARM_DESC(semaphores, +i915_param_named_unsafe(semaphores, int, 0400, "Use semaphores for inter-ring sync " "(default: -1 (use per-chip defaults))"); -i915_param_named_unsafe(enable_rc6, int, 0400); -MODULE_PARM_DESC(enable_rc6, +i915_param_named_unsafe(enable_rc6, int, 0400, "Enable power-saving render C-state 6. " "Different stages can be selected via bitmask values " "(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). " "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. " "default: -1 (use per-chip default)"); -i915_param_named_unsafe(enable_dc, int, 0400); -MODULE_PARM_DESC(enable_dc, +i915_param_named_unsafe(enable_dc, int, 0400, "Enable power-saving display C-states. " "(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6)"); -i915_param_named_unsafe(enable_fbc, int, 0600); -MODULE_PARM_DESC(enable_fbc, +i915_param_named_unsafe(enable_fbc, int, 0600, "Enable frame buffer compression for power savings " "(default: -1 (use per-chip default))"); -i915_param_named_unsafe(lvds_channel_mode, int, 0400); -MODULE_PARM_DESC(lvds_channel_mode, +i915_param_named_unsafe(lvds_channel_mode, int, 0400, "Specify LVDS channel mode " "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)"); -i915_param_named_unsafe(panel_use_ssc, int, 0600); -MODULE_PARM_DESC(panel_use_ssc, +i915_param_named_unsafe(panel_use_ssc, int, 0600, "Use Spread Spectrum Clock with panels [LVDS/eDP] " "(default: auto from VBT)"); -i915_param_named_unsafe(vbt_sdvo_panel_type, int, 0400); -MODULE_PARM_DESC(vbt_sdvo_panel_type, +i915_param_named_unsafe(vbt_sdvo_panel_type, int, 0400, "Override/Ignore selection of SDVO panel mode in the VBT " "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); -i915_param_named_unsafe(reset, int, 0600); -MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset, 2=engine reset [default])"); +i915_param_named_unsafe(reset, int, 0600, + "Attempt GPU resets (0=disabled, 1=full gpu reset, 2=engine reset [default])"); -i915_param_named_unsafe(vbt_firmware, charp, 0400); -MODULE_PARM_DESC(vbt_firmware, - "Load VBT from specified file under /lib/firmware"); +i915_param_named_unsafe(vbt_firmware, charp, 0400, + "Load VBT from specified file under /lib/firmware"); #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) -i915_param_named(error_capture, bool, 0600); -MODULE_PARM_DESC(error_capture, +i915_param_named(error_capture, bool, 0600, "Record the GPU state following a hang. " "This information in /sys/class/drm/card/error is vital for " "triaging and debugging hangs."); #endif -i915_param_named_unsafe(enable_hangcheck, bool, 0644); -MODULE_PARM_DESC(enable_hangcheck, +i915_param_named_unsafe(enable_hangcheck, bool, 0644, "Periodically check GPU activity for detecting hangs. " "WARNING: Disabling this can cause system wide hangs. " "(default: true)"); -i915_param_named_unsafe(enable_ppgtt, int, 0400); -MODULE_PARM_DESC(enable_ppgtt, +i915_param_named_unsafe(enable_ppgtt, int, 0400, "Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)"); -i915_param_named_unsafe(enable_execlists, int, 0400); -MODULE_PARM_DESC(enable_execlists, +i915_param_named_unsafe(enable_execlists, int, 0400, "Override execlists usage. " "(-1=auto [default], 0=disabled, 1=enabled)"); -i915_param_named_unsafe(enable_psr, int, 0600); -MODULE_PARM_DESC(enable_psr, "Enable PSR " - "(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) " - "Default: -1 (use per-chip default)"); +i915_param_named_unsafe(enable_psr, int, 0600, + "Enable PSR " + "(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) " + "Default: -1 (use per-chip default)"); -i915_param_named_unsafe(alpha_support, bool, 0400); -MODULE_PARM_DESC(alpha_support, +i915_param_named_unsafe(alpha_support, bool, 0400, "Enable alpha quality driver support for latest hardware. " "See also CONFIG_DRM_I915_ALPHA_SUPPORT."); -i915_param_named_unsafe(disable_power_well, int, 0400); -MODULE_PARM_DESC(disable_power_well, +i915_param_named_unsafe(disable_power_well, int, 0400, "Disable display power wells when possible " "(-1=auto [default], 0=power wells always on, 1=power wells disabled when possible)"); -i915_param_named_unsafe(enable_ips, int, 0600); -MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)"); +i915_param_named_unsafe(enable_ips, int, 0600, "Enable IPS (default: true)"); -i915_param_named(fastboot, bool, 0600); -MODULE_PARM_DESC(fastboot, +i915_param_named(fastboot, bool, 0600, "Try to skip unnecessary mode sets at boot time (default: false)"); -i915_param_named_unsafe(prefault_disable, bool, 0600); -MODULE_PARM_DESC(prefault_disable, +i915_param_named_unsafe(prefault_disable, bool, 0600, "Disable page prefaulting for pread/pwrite/reloc (default:false). " "For developers only."); -i915_param_named_unsafe(load_detect_test, bool, 0600); -MODULE_PARM_DESC(load_detect_test, +i915_param_named_unsafe(load_detect_test, bool, 0600, "Force-enable the VGA load detect code for testing (default:false). " "For developers only."); -i915_param_named_unsafe(force_reset_modeset_test, bool, 0600); -MODULE_PARM_DESC(force_reset_modeset_test, +i915_param_named_unsafe(force_reset_modeset_test, bool, 0600, "Force a modeset during gpu reset for testing (default:false). " "For developers only."); -i915_param_named_unsafe(invert_brightness, int, 0600); -MODULE_PARM_DESC(invert_brightness, +i915_param_named_unsafe(invert_brightness, int, 0600, "Invert backlight brightness " "(-1 force normal, 0 machine defaults, 1 force inversion), please " "report PCI device ID, subsystem vendor and subsystem device ID " "to dri-devel@lists.freedesktop.org, if your machine needs it. " "It will then be included in an upcoming module version."); -i915_param_named(disable_display, bool, 0400); -MODULE_PARM_DESC(disable_display, "Disable display (default: false)"); +i915_param_named(disable_display, bool, 0400, + "Disable display (default: false)"); -i915_param_named_unsafe(enable_cmd_parser, bool, 0400); -MODULE_PARM_DESC(enable_cmd_parser, - "Enable command parsing (true=enabled [default], false=disabled)"); +i915_param_named_unsafe(enable_cmd_parser, bool, 0400, + "Enable command parsing (true=enabled [default], false=disabled)"); -i915_param_named_unsafe(use_mmio_flip, int, 0600); -MODULE_PARM_DESC(use_mmio_flip, - "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)"); +i915_param_named_unsafe(use_mmio_flip, int, 0600, + "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)"); -i915_param_named(mmio_debug, int, 0600); -MODULE_PARM_DESC(mmio_debug, +i915_param_named(mmio_debug, int, 0600, "Enable the MMIO debug code for the first N failures (default: off). " "This may negatively affect performance."); -i915_param_named(verbose_state_checks, bool, 0600); -MODULE_PARM_DESC(verbose_state_checks, +i915_param_named(verbose_state_checks, bool, 0600, "Enable verbose logs (ie. WARN_ON()) in case of unexpected hw state conditions."); -i915_param_named_unsafe(nuclear_pageflip, bool, 0400); -MODULE_PARM_DESC(nuclear_pageflip, - "Force enable atomic functionality on platforms that don't have full support yet."); +i915_param_named_unsafe(nuclear_pageflip, bool, 0400, + "Force enable atomic functionality on platforms that don't have full support yet."); /* WA to get away with the default setting in VBT for early platforms.Will be removed */ -i915_param_named_unsafe(edp_vswing, int, 0400); -MODULE_PARM_DESC(edp_vswing, - "Ignore/Override vswing pre-emph table selection from VBT " - "(0=use value from vbt [default], 1=low power swing(200mV)," - "2=default swing(400mV))"); - -i915_param_named_unsafe(enable_guc_loading, int, 0400); -MODULE_PARM_DESC(enable_guc_loading, - "Enable GuC firmware loading " - "(-1=auto, 0=never [default], 1=if available, 2=required)"); - -i915_param_named_unsafe(enable_guc_submission, int, 0400); -MODULE_PARM_DESC(enable_guc_submission, - "Enable GuC submission " - "(-1=auto, 0=never [default], 1=if available, 2=required)"); - -i915_param_named(guc_log_level, int, 0400); -MODULE_PARM_DESC(guc_log_level, +i915_param_named_unsafe(edp_vswing, int, 0400, + "Ignore/Override vswing pre-emph table selection from VBT " + "(0=use value from vbt [default], 1=low power swing(200mV)," + "2=default swing(400mV))"); + +i915_param_named_unsafe(enable_guc_loading, int, 0400, + "Enable GuC firmware loading " + "(-1=auto, 0=never [default], 1=if available, 2=required)"); + +i915_param_named_unsafe(enable_guc_submission, int, 0400, + "Enable GuC submission " + "(-1=auto, 0=never [default], 1=if available, 2=required)"); + +i915_param_named(guc_log_level, int, 0400, "GuC firmware logging level (-1:disabled (default), 0-3:enabled)"); -i915_param_named_unsafe(guc_firmware_path, charp, 0400); -MODULE_PARM_DESC(guc_firmware_path, +i915_param_named_unsafe(guc_firmware_path, charp, 0400, "GuC firmware path to use instead of the default one"); -i915_param_named_unsafe(huc_firmware_path, charp, 0400); -MODULE_PARM_DESC(huc_firmware_path, +i915_param_named_unsafe(huc_firmware_path, charp, 0400, "HuC firmware path to use instead of the default one"); -i915_param_named_unsafe(enable_dp_mst, bool, 0600); -MODULE_PARM_DESC(enable_dp_mst, +i915_param_named_unsafe(enable_dp_mst, bool, 0600, "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)"); -i915_param_named_unsafe(inject_load_failure, uint, 0400); -MODULE_PARM_DESC(inject_load_failure, + +i915_param_named_unsafe(inject_load_failure, uint, 0400, "Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)"); -i915_param_named(enable_dpcd_backlight, bool, 0600); -MODULE_PARM_DESC(enable_dpcd_backlight, + +i915_param_named(enable_dpcd_backlight, bool, 0600, "Enable support for DPCD backlight control (default:false)"); -i915_param_named(enable_gvt, bool, 0400); -MODULE_PARM_DESC(enable_gvt, +i915_param_named(enable_gvt, bool, 0400, "Enable support for Intel GVT-g graphics virtualization host support(default:false)"); -- cgit v1.2.3 From c5498089463b94690085158eba7dd29835c8c9b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:37:01 +0300 Subject: drm/i915: Mask everything in ring HWSTAM on gen6+ in ringbuffer mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The execlist code already masks everything in the ring HWSTAM, but the ringbuffer code doesn't. Let's go ahead and do that. Pre-gen6 platforms setup HWSTAM during irq setup already since there's just the one register, and it also contains bits for non-ring interrupts. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-13-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_ringbuffer.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8af8871a8594..22e5ea8516b6 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -428,6 +428,9 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine) mmio = RING_HWS_PGA(engine->mmio_base); } + if (INTEL_GEN(dev_priv) >= 6) + I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff); + I915_WRITE(mmio, engine->status_page.ggtt_offset); POSTING_READ(mmio); -- cgit v1.2.3 From d420a50c21efa4ec9e43494547de4f2b1826e167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:37:03 +0300 Subject: drm/i915: Clean up the HWSTAM mess MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we're unmasking some random looking bits in HWSTAM on gen3/4/5. The two bits we apparently unmask are 0 and 12, and also bits 16-31 on gen4/5. What those bits do depends on the gen as follows: bit 0: Breakpoint (gen2), ASLE (gen3), reserved (gen4), render user interrupt (gen5) bit 12: Sync flush statusa (gen2-4), reserved (gen5) bit 16-31: The ones that can unmasked seem to be mostly some display stuff on gen4. Bit 18 is the PIPE_CONTROL notify, which might be the only intresting one. On gen5 all the bits are reserved. So I don't know whether we actually depend on that status page write somehow. Extra seqno coherency by accident perhaps? Except we don't even unmask the user interrupt bit in HWSTAM except on gen5, and sync flush isn't something we use normally, so seems unlikely. So let's just assume we don't need any of this and mask everything in HWSTAM. From gen6 onwards there's a separate HWSTAM for each engine, and so we deal with them during the engine setup. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-15-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_irq.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e8bb6c644fa4..2b3a84de9460 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3058,7 +3058,8 @@ static void ironlake_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - I915_WRITE(HWSTAM, 0xffffffff); + if (IS_GEN5(dev_priv)) + I915_WRITE(HWSTAM, 0xffffffff); GEN3_IRQ_RESET(DE); if (IS_GEN7(dev_priv)) @@ -3419,8 +3420,6 @@ static int ironlake_irq_postinstall(struct drm_device *dev) dev_priv->irq_mask = ~display_mask; - I915_WRITE(HWSTAM, 0xeffe); - ibx_irq_pre_postinstall(dev); GEN3_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask); @@ -3621,8 +3620,6 @@ static void valleyview_irq_uninstall(struct drm_device *dev) gen5_gt_irq_reset(dev_priv); - I915_WRITE(HWSTAM, 0xffffffff); - spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->display_irqs_enabled) vlv_display_irq_reset(dev_priv); @@ -3657,6 +3654,8 @@ static void i8xx_irq_preinstall(struct drm_device * dev) i9xx_pipestat_irq_reset(dev_priv); + I915_WRITE16(HWSTAM, 0xffff); + GEN2_IRQ_RESET(); } @@ -3738,6 +3737,8 @@ static void i8xx_irq_uninstall(struct drm_device * dev) i9xx_pipestat_irq_reset(dev_priv); + I915_WRITE16(HWSTAM, 0xffff); + GEN2_IRQ_RESET(); } @@ -3752,7 +3753,7 @@ static void i915_irq_preinstall(struct drm_device * dev) i9xx_pipestat_irq_reset(dev_priv); - I915_WRITE(HWSTAM, 0xffffeffe); + I915_WRITE(HWSTAM, 0xffffffff); GEN3_IRQ_RESET(); } @@ -3873,7 +3874,7 @@ static void i965_irq_preinstall(struct drm_device * dev) i9xx_pipestat_irq_reset(dev_priv); - I915_WRITE(HWSTAM, 0xeffe); + I915_WRITE(HWSTAM, 0xffffffff); GEN3_IRQ_RESET(); } -- cgit v1.2.3 From 6bcdb1c839b5d75270d4a492221a7af891d8a484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:37:04 +0300 Subject: drm/i915: Remove duplicated irq_preinstall/uninstall hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the irq_preinstall and irq_uninstall hooks are now identical. Let's just rename them all the irq_reset and remove the pointless duplicates. Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-16-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/i915_irq.c | 117 ++++++---------------------------------- 1 file changed, 17 insertions(+), 100 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2b3a84de9460..4d0e8f76ed1a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3070,7 +3070,7 @@ static void ironlake_irq_reset(struct drm_device *dev) ibx_irq_reset(dev_priv); } -static void valleyview_irq_preinstall(struct drm_device *dev) +static void valleyview_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -3144,7 +3144,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, synchronize_irq(dev_priv->drm.irq); } -static void cherryview_irq_preinstall(struct drm_device *dev) +static void cherryview_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -3606,49 +3606,7 @@ static int cherryview_irq_postinstall(struct drm_device *dev) return 0; } -static void gen8_irq_uninstall(struct drm_device *dev) -{ - gen8_irq_reset(dev); -} - -static void valleyview_irq_uninstall(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - I915_WRITE(VLV_MASTER_IER, 0); - POSTING_READ(VLV_MASTER_IER); - - gen5_gt_irq_reset(dev_priv); - - spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) - vlv_display_irq_reset(dev_priv); - spin_unlock_irq(&dev_priv->irq_lock); -} - -static void cherryview_irq_uninstall(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - I915_WRITE(GEN8_MASTER_IRQ, 0); - POSTING_READ(GEN8_MASTER_IRQ); - - gen8_gt_irq_reset(dev_priv); - - GEN3_IRQ_RESET(GEN8_PCU_); - - spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) - vlv_display_irq_reset(dev_priv); - spin_unlock_irq(&dev_priv->irq_lock); -} - -static void ironlake_irq_uninstall(struct drm_device *dev) -{ - ironlake_irq_reset(dev); -} - -static void i8xx_irq_preinstall(struct drm_device * dev) +static void i8xx_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -3731,18 +3689,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) return ret; } -static void i8xx_irq_uninstall(struct drm_device * dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - i9xx_pipestat_irq_reset(dev_priv); - - I915_WRITE16(HWSTAM, 0xffff); - - GEN2_IRQ_RESET(); -} - -static void i915_irq_preinstall(struct drm_device * dev) +static void i915_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -3849,23 +3796,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) return ret; } -static void i915_irq_uninstall(struct drm_device * dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - if (I915_HAS_HOTPLUG(dev_priv)) { - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - } - - i9xx_pipestat_irq_reset(dev_priv); - - I915_WRITE(HWSTAM, 0xffffffff); - - GEN3_IRQ_RESET(); -} - -static void i965_irq_preinstall(struct drm_device * dev) +static void i965_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -4011,20 +3942,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) return ret; } -static void i965_irq_uninstall(struct drm_device * dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - - i9xx_pipestat_irq_reset(dev_priv); - - I915_WRITE(HWSTAM, 0xffffffff); - - GEN3_IRQ_RESET(); -} - /** * intel_irq_init - initializes irq support * @dev_priv: i915 device instance @@ -4105,17 +4022,17 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (IS_CHERRYVIEW(dev_priv)) { dev->driver->irq_handler = cherryview_irq_handler; - dev->driver->irq_preinstall = cherryview_irq_preinstall; + dev->driver->irq_preinstall = cherryview_irq_reset; dev->driver->irq_postinstall = cherryview_irq_postinstall; - dev->driver->irq_uninstall = cherryview_irq_uninstall; + dev->driver->irq_uninstall = cherryview_irq_reset; dev->driver->enable_vblank = i965_enable_vblank; dev->driver->disable_vblank = i965_disable_vblank; dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; } else if (IS_VALLEYVIEW(dev_priv)) { dev->driver->irq_handler = valleyview_irq_handler; - dev->driver->irq_preinstall = valleyview_irq_preinstall; + dev->driver->irq_preinstall = valleyview_irq_reset; dev->driver->irq_postinstall = valleyview_irq_postinstall; - dev->driver->irq_uninstall = valleyview_irq_uninstall; + dev->driver->irq_uninstall = valleyview_irq_reset; dev->driver->enable_vblank = i965_enable_vblank; dev->driver->disable_vblank = i965_disable_vblank; dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; @@ -4123,7 +4040,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_handler = gen8_irq_handler; dev->driver->irq_preinstall = gen8_irq_reset; dev->driver->irq_postinstall = gen8_irq_postinstall; - dev->driver->irq_uninstall = gen8_irq_uninstall; + dev->driver->irq_uninstall = gen8_irq_reset; dev->driver->enable_vblank = gen8_enable_vblank; dev->driver->disable_vblank = gen8_disable_vblank; if (IS_GEN9_LP(dev_priv)) @@ -4137,29 +4054,29 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_handler = ironlake_irq_handler; dev->driver->irq_preinstall = ironlake_irq_reset; dev->driver->irq_postinstall = ironlake_irq_postinstall; - dev->driver->irq_uninstall = ironlake_irq_uninstall; + dev->driver->irq_uninstall = ironlake_irq_reset; dev->driver->enable_vblank = ironlake_enable_vblank; dev->driver->disable_vblank = ironlake_disable_vblank; dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; } else { if (IS_GEN2(dev_priv)) { - dev->driver->irq_preinstall = i8xx_irq_preinstall; + dev->driver->irq_preinstall = i8xx_irq_reset; dev->driver->irq_postinstall = i8xx_irq_postinstall; dev->driver->irq_handler = i8xx_irq_handler; - dev->driver->irq_uninstall = i8xx_irq_uninstall; + dev->driver->irq_uninstall = i8xx_irq_reset; dev->driver->enable_vblank = i8xx_enable_vblank; dev->driver->disable_vblank = i8xx_disable_vblank; } else if (IS_GEN3(dev_priv)) { - dev->driver->irq_preinstall = i915_irq_preinstall; + dev->driver->irq_preinstall = i915_irq_reset; dev->driver->irq_postinstall = i915_irq_postinstall; - dev->driver->irq_uninstall = i915_irq_uninstall; + dev->driver->irq_uninstall = i915_irq_reset; dev->driver->irq_handler = i915_irq_handler; dev->driver->enable_vblank = i8xx_enable_vblank; dev->driver->disable_vblank = i8xx_disable_vblank; } else { - dev->driver->irq_preinstall = i965_irq_preinstall; + dev->driver->irq_preinstall = i965_irq_reset; dev->driver->irq_postinstall = i965_irq_postinstall; - dev->driver->irq_uninstall = i965_irq_uninstall; + dev->driver->irq_uninstall = i965_irq_reset; dev->driver->irq_handler = i965_irq_handler; dev->driver->enable_vblank = i965_enable_vblank; dev->driver->disable_vblank = i965_disable_vblank; -- cgit v1.2.3 From 309bd8ed464fc08f79152e4a18b1da2b11410842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Aug 2017 21:37:05 +0300 Subject: drm/i915: Reinstate GMBUS and AUX interrupts on gen4/g4x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we're not using MSI anymore on gen4 we can start using GMBUS and AUX interrupts again. These were disabled on account of them causing the hardware to somehow generate legacy interrupts even when MSI was enabled. See commit c12aba5aa0e6 ("drm/i915: stop using GMBUS IRQs on Gen4 chips") and commit 4e6b788c3f23 ("drm/i915: Disable dp aux irq on g4x") for more details. Cc: Daniel Vetter Cc: Chris Wilson Cc: Jiri Kosina Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-17-ville.syrjala@linux.intel.com Acked-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 8 +++++--- drivers/gpu/drm/i915/i915_pci.c | 6 ------ 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5d379c89722c..a24659b5e6b5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -777,7 +777,6 @@ struct intel_csr { func(has_fpga_dbg); \ func(has_full_ppgtt); \ func(has_full_48bit_ppgtt); \ - func(has_gmbus_irq); \ func(has_gmch_display); \ func(has_guc); \ func(has_guc_ct); \ @@ -3095,9 +3094,12 @@ intel_info(const struct drm_i915_private *dev_priv) * even when in MSI mode. This results in spurious interrupt warnings if the * legacy irq no. is shared with another device. The kernel then disables that * interrupt source and so prevents the other device from working properly. + * + * Since we don't enable MSI anymore on gen4, we can always use GMBUS/AUX + * interrupts. */ -#define HAS_AUX_IRQ(dev_priv) ((dev_priv)->info.gen >= 5) -#define HAS_GMBUS_IRQ(dev_priv) ((dev_priv)->info.has_gmbus_irq) +#define HAS_AUX_IRQ(dev_priv) true +#define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte * rows, which changed the alignment requirements and fence programming. diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 129877b94c20..853002fb0371 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -200,7 +200,6 @@ static const struct intel_device_info intel_gm45_info __initconst = { #define GEN5_FEATURES \ .gen = 5, .num_pipes = 2, \ .has_hotplug = 1, \ - .has_gmbus_irq = 1, \ .ring_mask = RENDER_RING | BSD_RING, \ .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ @@ -225,7 +224,6 @@ static const struct intel_device_info intel_ironlake_m_info __initconst = { .has_llc = 1, \ .has_rc6 = 1, \ .has_rc6p = 1, \ - .has_gmbus_irq = 1, \ .has_aliasing_ppgtt = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -268,7 +266,6 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info __initconst = .has_llc = 1, \ .has_rc6 = 1, \ .has_rc6p = 1, \ - .has_gmbus_irq = 1, \ .has_aliasing_ppgtt = 1, \ .has_full_ppgtt = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ @@ -321,7 +318,6 @@ static const struct intel_device_info intel_valleyview_info __initconst = { .has_psr = 1, .has_runtime_pm = 1, .has_rc6 = 1, - .has_gmbus_irq = 1, .has_gmch_display = 1, .has_hotplug = 1, .has_aliasing_ppgtt = 1, @@ -412,7 +408,6 @@ static const struct intel_device_info intel_cherryview_info __initconst = { .has_runtime_pm = 1, .has_resource_streamer = 1, .has_rc6 = 1, - .has_gmbus_irq = 1, .has_logical_ring_contexts = 1, .has_gmch_display = 1, .has_aliasing_ppgtt = 1, @@ -474,7 +469,6 @@ static const struct intel_device_info intel_skylake_gt4_info __initconst = { .has_resource_streamer = 1, \ .has_rc6 = 1, \ .has_dp_mst = 1, \ - .has_gmbus_irq = 1, \ .has_logical_ring_contexts = 1, \ .has_guc = 1, \ .has_aliasing_ppgtt = 1, \ -- cgit v1.2.3 From 27a5f61b377bb62e4813af57fd91636f91ea5755 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Sep 2017 18:31:00 +0100 Subject: drm/i915: Cancel all ready but queued requests when wedging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When wedging the hw, we want to mark all in-flight requests as -EIO. This is made slightly more complex by execlists who store the ready but not yet submitted-to-hw requests on a private queue (an rbtree priolist). Call into execlists to cancel not only the ELSP tracking for the submitted requests, but also the queue of unsubmitted requests. v2: Move the majority of engine_set_wedged to the backends (both legacy ringbuffer and execlists handling their own lists). Reported-by: Michał Winiarski Testcase: igt/gem_eio/in-flight-contexts Signed-off-by: Chris Wilson Cc: Michał Winiarski Cc: Mika Kuoppala Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170915173100.26470-1-chris@chris-wilson.co.uk Reviewed-by: Michał Winiarski --- drivers/gpu/drm/i915/i915_gem.c | 38 +-------------------- drivers/gpu/drm/i915/intel_lrc.c | 60 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 20 +++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 8 +++++ 4 files changed, 89 insertions(+), 37 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f445587c1a4b..b0bbf8729dae 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3022,9 +3022,6 @@ static void nop_submit_request(struct drm_i915_gem_request *request) static void engine_set_wedged(struct intel_engine_cs *engine) { - struct drm_i915_gem_request *request; - unsigned long flags; - /* We need to be sure that no thread is running the old callback as * we install the nop handler (otherwise we would submit a request * to hardware that will never complete). In order to prevent this @@ -3034,40 +3031,7 @@ static void engine_set_wedged(struct intel_engine_cs *engine) engine->submit_request = nop_submit_request; /* Mark all executing requests as skipped */ - spin_lock_irqsave(&engine->timeline->lock, flags); - list_for_each_entry(request, &engine->timeline->requests, link) - if (!i915_gem_request_completed(request)) - dma_fence_set_error(&request->fence, -EIO); - spin_unlock_irqrestore(&engine->timeline->lock, flags); - - /* - * Clear the execlists queue up before freeing the requests, as those - * are the ones that keep the context and ringbuffer backing objects - * pinned in place. - */ - - if (i915.enable_execlists) { - struct execlist_port *port = engine->execlist_port; - unsigned long flags; - unsigned int n; - - spin_lock_irqsave(&engine->timeline->lock, flags); - - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) - i915_gem_request_put(port_request(&port[n])); - memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); - engine->execlist_queue = RB_ROOT; - engine->execlist_first = NULL; - - spin_unlock_irqrestore(&engine->timeline->lock, flags); - - /* The port is checked prior to scheduling a tasklet, but - * just in case we have suspended the tasklet to do the - * wedging make sure that when it wakes, it decides there - * is no work to do by clearing the irq_posted bit. - */ - clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); - } + engine->cancel_requests(engine); /* Mark all pending requests as complete so that any concurrent * (lockless) lookup doesn't try and wait upon the request as we diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 1960ba5ff9e4..8e5caa5d3973 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -506,6 +506,65 @@ done: execlists_submit_ports(engine); } +static void execlists_cancel_requests(struct intel_engine_cs *engine) +{ + struct execlist_port *port = engine->execlist_port; + struct drm_i915_gem_request *rq, *rn; + struct rb_node *rb; + unsigned long flags; + unsigned long n; + + spin_lock_irqsave(&engine->timeline->lock, flags); + + /* Cancel the requests on the HW and clear the ELSP tracker. */ + for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) + i915_gem_request_put(port_request(&port[n])); + memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); + + /* Mark all executing requests as skipped. */ + list_for_each_entry(rq, &engine->timeline->requests, link) { + GEM_BUG_ON(!rq->global_seqno); + if (!i915_gem_request_completed(rq)) + dma_fence_set_error(&rq->fence, -EIO); + } + + /* Flush the queued requests to the timeline list (for retiring). */ + rb = engine->execlist_first; + while (rb) { + struct i915_priolist *p = rb_entry(rb, typeof(*p), node); + + list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { + INIT_LIST_HEAD(&rq->priotree.link); + rq->priotree.priority = INT_MAX; + + dma_fence_set_error(&rq->fence, -EIO); + __i915_gem_request_submit(rq); + } + + rb = rb_next(rb); + rb_erase(&p->node, &engine->execlist_queue); + INIT_LIST_HEAD(&p->requests); + if (p->priority != I915_PRIORITY_NORMAL) + kmem_cache_free(engine->i915->priorities, p); + } + + /* Remaining _unready_ requests will be nop'ed when submitted */ + + engine->execlist_queue = RB_ROOT; + engine->execlist_first = NULL; + GEM_BUG_ON(port_isset(&port[0])); + + /* + * The port is checked prior to scheduling a tasklet, but + * just in case we have suspended the tasklet to do the + * wedging make sure that when it wakes, it decides there + * is no work to do by clearing the irq_posted bit. + */ + clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); + + spin_unlock_irqrestore(&engine->timeline->lock, flags); +} + static bool execlists_elsp_ready(const struct intel_engine_cs *engine) { const struct execlist_port *port = engine->execlist_port; @@ -1704,6 +1763,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) static void execlists_set_default_submission(struct intel_engine_cs *engine) { engine->submit_request = execlists_submit_request; + engine->cancel_requests = execlists_cancel_requests; engine->schedule = execlists_schedule; engine->irq_tasklet.func = intel_lrc_irq_handler; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 22e5ea8516b6..85e64a45d0bf 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -782,6 +782,24 @@ static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *cs) return cs; } +static void cancel_requests(struct intel_engine_cs *engine) +{ + struct drm_i915_gem_request *request; + unsigned long flags; + + spin_lock_irqsave(&engine->timeline->lock, flags); + + /* Mark all submitted requests as skipped. */ + list_for_each_entry(request, &engine->timeline->requests, link) { + GEM_BUG_ON(!request->global_seqno); + if (!i915_gem_request_completed(request)) + dma_fence_set_error(&request->fence, -EIO); + } + /* Remaining _unready_ requests will be nop'ed when submitted */ + + spin_unlock_irqrestore(&engine->timeline->lock, flags); +} + static void i9xx_submit_request(struct drm_i915_gem_request *request) { struct drm_i915_private *dev_priv = request->i915; @@ -1996,11 +2014,13 @@ static void intel_ring_init_irq(struct drm_i915_private *dev_priv, static void i9xx_set_default_submission(struct intel_engine_cs *engine) { engine->submit_request = i9xx_submit_request; + engine->cancel_requests = cancel_requests; } static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine) { engine->submit_request = gen6_bsd_submit_request; + engine->cancel_requests = cancel_requests; } static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index abf171c3cb9c..138116a3b537 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -306,6 +306,14 @@ struct intel_engine_cs { void (*schedule)(struct drm_i915_gem_request *request, int priority); + /* + * Cancel all requests on the hardware, or queued for execution. + * This should only cancel the ready requests that have been + * submitted to the engine (via the engine->submit_request callback). + * This is called when marking the device as wedged. + */ + void (*cancel_requests)(struct intel_engine_cs *engine); + /* Some chipsets are not quite as coherent as advertised and need * an expensive kick to force a true read of the up-to-date seqno. * However, the up-to-date seqno is not always required and the last -- cgit v1.2.3 From 523e7c9278f0a2ca6174319e33f255161e74d16c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 16 Sep 2017 21:44:11 +0100 Subject: drm/i915/execlists: Kick start request processing after a reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During a reset, we may skip over completed requests and lost context-switch interrupts. Following the reset, we may then may end up with no active requests in the ELSP (and so do not resubmit to restart the engine), but have a queue of requests ready for execution. This is unlikely, it requires the last request to complete after the hang is detected, but not impossible. The outcome of this is that the engine stalls, possibly leading to full ring and indefinite wait under struct_mutex, eventually leading to a full driver hang. Alternatively, we can solve this by unsubmitting the incomplete requests and just kickstarting the tasklet. Michał has patches for that, which I initially disliked due to the extra complexity, but the complexity of this "simple" restart is growing... Signed-off-by: Chris Wilson Cc: Michał Winiarski Cc: Mika Kuoppala Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170916204414.32762-1-chris@chris-wilson.co.uk Reviewed-by: Michał Winiarski --- drivers/gpu/drm/i915/intel_lrc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8e5caa5d3973..0f578f76f79f 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1357,8 +1357,12 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) submit = true; } - if (submit && !i915.enable_guc_submission) - execlists_submit_ports(engine); + if (!i915.enable_guc_submission) { + if (submit) + execlists_submit_ports(engine); + else if (engine->execlist_first) + tasklet_schedule(&engine->irq_tasklet); + } return 0; } -- cgit v1.2.3 From 08dd3e1acc169100ee35df322e2146e39b43a827 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 16 Sep 2017 21:44:12 +0100 Subject: drm/i915/execlists: Move insert_request() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move insert_request() earlier to avoid a forward declaration in a later patch. Signed-off-by: Chris Wilson Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20170916204414.32762-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 128 +++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 64 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 0f578f76f79f..7c709530b422 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -286,6 +286,70 @@ intel_lr_context_descriptor_update(struct i915_gem_context *ctx, ce->lrc_desc = desc; } +static bool +insert_request(struct intel_engine_cs *engine, + struct i915_priotree *pt, + int prio) +{ + struct i915_priolist *p; + struct rb_node **parent, *rb; + bool first = true; + + if (unlikely(engine->no_priolist)) + prio = I915_PRIORITY_NORMAL; + +find_priolist: + /* most positive priority is scheduled first, equal priorities fifo */ + rb = NULL; + parent = &engine->execlist_queue.rb_node; + while (*parent) { + rb = *parent; + p = rb_entry(rb, typeof(*p), node); + if (prio > p->priority) { + parent = &rb->rb_left; + } else if (prio < p->priority) { + parent = &rb->rb_right; + first = false; + } else { + list_add_tail(&pt->link, &p->requests); + return false; + } + } + + if (prio == I915_PRIORITY_NORMAL) { + p = &engine->default_priolist; + } else { + p = kmem_cache_alloc(engine->i915->priorities, GFP_ATOMIC); + /* Convert an allocation failure to a priority bump */ + if (unlikely(!p)) { + prio = I915_PRIORITY_NORMAL; /* recurses just once */ + + /* To maintain ordering with all rendering, after an + * allocation failure we have to disable all scheduling. + * Requests will then be executed in fifo, and schedule + * will ensure that dependencies are emitted in fifo. + * There will be still some reordering with existing + * requests, so if userspace lied about their + * dependencies that reordering may be visible. + */ + engine->no_priolist = true; + goto find_priolist; + } + } + + p->priority = prio; + rb_link_node(&p->node, rb, parent); + rb_insert_color(&p->node, &engine->execlist_queue); + + INIT_LIST_HEAD(&p->requests); + list_add_tail(&pt->link, &p->requests); + + if (first) + engine->execlist_first = &p->node; + + return first; +} + static inline void execlists_context_status_change(struct drm_i915_gem_request *rq, unsigned long status) @@ -700,70 +764,6 @@ static void intel_lrc_irq_handler(unsigned long data) intel_uncore_forcewake_put(dev_priv, engine->fw_domains); } -static bool -insert_request(struct intel_engine_cs *engine, - struct i915_priotree *pt, - int prio) -{ - struct i915_priolist *p; - struct rb_node **parent, *rb; - bool first = true; - - if (unlikely(engine->no_priolist)) - prio = I915_PRIORITY_NORMAL; - -find_priolist: - /* most positive priority is scheduled first, equal priorities fifo */ - rb = NULL; - parent = &engine->execlist_queue.rb_node; - while (*parent) { - rb = *parent; - p = rb_entry(rb, typeof(*p), node); - if (prio > p->priority) { - parent = &rb->rb_left; - } else if (prio < p->priority) { - parent = &rb->rb_right; - first = false; - } else { - list_add_tail(&pt->link, &p->requests); - return false; - } - } - - if (prio == I915_PRIORITY_NORMAL) { - p = &engine->default_priolist; - } else { - p = kmem_cache_alloc(engine->i915->priorities, GFP_ATOMIC); - /* Convert an allocation failure to a priority bump */ - if (unlikely(!p)) { - prio = I915_PRIORITY_NORMAL; /* recurses just once */ - - /* To maintain ordering with all rendering, after an - * allocation failure we have to disable all scheduling. - * Requests will then be executed in fifo, and schedule - * will ensure that dependencies are emitted in fifo. - * There will be still some reordering with existing - * requests, so if userspace lied about their - * dependencies that reordering may be visible. - */ - engine->no_priolist = true; - goto find_priolist; - } - } - - p->priority = prio; - rb_link_node(&p->node, rb, parent); - rb_insert_color(&p->node, &engine->execlist_queue); - - INIT_LIST_HEAD(&p->requests); - list_add_tail(&pt->link, &p->requests); - - if (first) - engine->execlist_first = &p->node; - - return first; -} - static void execlists_submit_request(struct drm_i915_gem_request *request) { struct intel_engine_cs *engine = request->engine; -- cgit v1.2.3 From 27606fd87895c3b45072a796caead8055a2f4b94 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 16 Sep 2017 21:44:13 +0100 Subject: drm/i915/execlists: Split insert_request() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the next patch we will want to reinsert a request not at the end of the priority queue, but at the front. Here we split insert_request() into two, the first function retrieves the priority list (for reuse for unsubmit later) and a wrapper function to insert at the end of that list and to schedule the tasklet if we were first. Signed-off-by: Chris Wilson Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20170916204414.32762-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7c709530b422..be2cba6b36d1 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -286,10 +286,10 @@ intel_lr_context_descriptor_update(struct i915_gem_context *ctx, ce->lrc_desc = desc; } -static bool -insert_request(struct intel_engine_cs *engine, - struct i915_priotree *pt, - int prio) +static struct i915_priolist * +lookup_priolist(struct intel_engine_cs *engine, + struct i915_priotree *pt, + int prio) { struct i915_priolist *p; struct rb_node **parent, *rb; @@ -311,8 +311,7 @@ find_priolist: parent = &rb->rb_right; first = false; } else { - list_add_tail(&pt->link, &p->requests); - return false; + return p; } } @@ -338,16 +337,14 @@ find_priolist: } p->priority = prio; + INIT_LIST_HEAD(&p->requests); rb_link_node(&p->node, rb, parent); rb_insert_color(&p->node, &engine->execlist_queue); - INIT_LIST_HEAD(&p->requests); - list_add_tail(&pt->link, &p->requests); - if (first) engine->execlist_first = &p->node; - return first; + return ptr_pack_bits(p, first, 1); } static inline void @@ -764,6 +761,17 @@ static void intel_lrc_irq_handler(unsigned long data) intel_uncore_forcewake_put(dev_priv, engine->fw_domains); } +static void insert_request(struct intel_engine_cs *engine, + struct i915_priotree *pt, + int prio) +{ + struct i915_priolist *p = lookup_priolist(engine, pt, prio); + + list_add_tail(&pt->link, &ptr_mask_bits(p, 1)->requests); + if (ptr_unmask_bits(p, 1) && execlists_elsp_ready(engine)) + tasklet_hi_schedule(&engine->irq_tasklet); +} + static void execlists_submit_request(struct drm_i915_gem_request *request) { struct intel_engine_cs *engine = request->engine; @@ -772,12 +780,7 @@ static void execlists_submit_request(struct drm_i915_gem_request *request) /* Will be called from irq-context when using foreign fences. */ spin_lock_irqsave(&engine->timeline->lock, flags); - if (insert_request(engine, - &request->priotree, - request->priotree.priority)) { - if (execlists_elsp_ready(engine)) - tasklet_hi_schedule(&engine->irq_tasklet); - } + insert_request(engine, &request->priotree, request->priotree.priority); GEM_BUG_ON(!engine->execlist_first); GEM_BUG_ON(list_empty(&request->priotree.link)); -- cgit v1.2.3 From 221ab9719bf33ad2984928d2afb20988d652a289 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 16 Sep 2017 21:44:14 +0100 Subject: drm/i915/execlists: Unwind incomplete requests on resets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given the mechanism to unwind and replay requests (designed to support preemption), we have an alternative to the current method of resubmitting the ELSP upon reset. Resubmitting ELSP turns out to be more complicated than expected, due to having to handle lost context-switch interrupts and so guessing what ELSP we need to resubmit later. Instead, by unwinding the requests and clearing the ELSP tracking entirely, we can then just dequeue the first pair of ready requests after resetting, using the normal submission procedure. Currently, the unwound requests have maximum priority and so are guaranteed to be resubmitted upon resume. If we are lucky, we may be able to coalesce a new request on top! Suggested-by: Michał Winiarski Signed-off-by: Chris Wilson Cc: Michał Winiarski Cc: Mika Kuoppala Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170916204414.32762-4-chris@chris-wilson.co.uk Reviewed-by: Michał Winiarski --- drivers/gpu/drm/i915/intel_lrc.c | 61 +++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 35 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index be2cba6b36d1..94a89eff4dbd 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1308,9 +1308,6 @@ static u8 gtiir[] = { static int gen8_init_common_ring(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; - struct execlist_port *port = engine->execlist_port; - unsigned int n; - bool submit; int ret; ret = intel_mocs_init_engine(engine); @@ -1346,26 +1343,8 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) engine->csb_head = -1; /* After a GPU reset, we may have requests to replay */ - submit = false; - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) { - if (!port_isset(&port[n])) - break; - - DRM_DEBUG_DRIVER("Restarting %s:%d from 0x%x\n", - engine->name, n, - port_request(&port[n])->global_seqno); - - /* Discard the current inflight count */ - port_set(&port[n], port_request(&port[n])); - submit = true; - } - - if (!i915.enable_guc_submission) { - if (submit) - execlists_submit_ports(engine); - else if (engine->execlist_first) - tasklet_schedule(&engine->irq_tasklet); - } + if (!i915.enable_guc_submission && engine->execlist_first) + tasklet_schedule(&engine->irq_tasklet); return 0; } @@ -1407,9 +1386,13 @@ static void reset_common_ring(struct intel_engine_cs *engine, struct drm_i915_gem_request *request) { struct execlist_port *port = engine->execlist_port; + struct drm_i915_gem_request *rq, *rn; struct intel_context *ce; + unsigned long flags; unsigned int n; + spin_lock_irqsave(&engine->timeline->lock, flags); + /* * Catch up with any missed context-switch interrupts. * @@ -1419,20 +1402,28 @@ static void reset_common_ring(struct intel_engine_cs *engine, * guessing the missed context-switch events by looking at what * requests were completed. */ - if (!request) { - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) - i915_gem_request_put(port_request(&port[n])); - memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); - return; - } + for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) + i915_gem_request_put(port_request(&port[n])); + memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); - if (request->ctx != port_request(port)->ctx) { - i915_gem_request_put(port_request(port)); - port[0] = port[1]; - memset(&port[1], 0, sizeof(port[1])); + /* Push back any incomplete requests for replay after the reset. */ + list_for_each_entry_safe_reverse(rq, rn, + &engine->timeline->requests, link) { + struct i915_priolist *p; + + if (i915_gem_request_completed(rq)) + break; + + __i915_gem_request_unsubmit(rq); + + p = lookup_priolist(engine, + &rq->priotree, + rq->priotree.priority); + list_add(&rq->priotree.link, + &ptr_mask_bits(p, 1)->requests); } - GEM_BUG_ON(request->ctx != port_request(port)->ctx); + spin_unlock_irqrestore(&engine->timeline->lock, flags); /* If the request was innocent, we leave the request in the ELSP * and will try to replay it on restarting. The context image may @@ -1444,7 +1435,7 @@ static void reset_common_ring(struct intel_engine_cs *engine, * and have to at least restore the RING register in the context * image back to the expected values to skip over the guilty request. */ - if (request->fence.error != -EIO) + if (!request || request->fence.error != -EIO) return; /* We want a simple context + ring to execute the breadcrumb update. -- cgit v1.2.3 From 45ec5bc8774b1a03213de072f240bad01c7ff09d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Thu, 14 Sep 2017 10:32:12 +0200 Subject: drm/i915/guc: Remove obsolete comments and remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Originally removed in: c1adab970348 ("drm/i915/guc: Remove failed doorbell stat from debugfs") f1448a62a103 ("drm/i915/guc: Remove last submission result from debugfs") Were accidentally restored in: 925344ccc91d ("BackMerge tag 'v4.12-rc5' into drm-next") We can also remove unused variable and replace it with a WARN. Cc: Chris Wilson Cc: Michal Wajdeczko Signed-off-by: Michał Winiarski Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170914083216.10192-1-michal.winiarski@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_guc_submission.c | 3 +-- drivers/gpu/drm/i915/intel_uc.h | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index b28677e5a4f2..c180ff1423fd 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -601,7 +601,6 @@ static void __i915_guc_submit(struct drm_i915_gem_request *rq) struct intel_guc *guc = &rq->i915->guc; struct i915_guc_client *client = guc->execbuf_client; unsigned long flags; - int b_ret; /* WA to flush out the pending GMADR writes to ring buffer. */ if (i915_vma_is_map_and_fenceable(rq->ring->vma)) @@ -610,7 +609,7 @@ static void __i915_guc_submit(struct drm_i915_gem_request *rq) spin_lock_irqsave(&client->wq_lock, flags); guc_wq_item_append(client, rq); - b_ret = guc_ring_doorbell(client); + WARN_ON(guc_ring_doorbell(client)); client->submissions[engine_id] += 1; diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index 22ae52b17b0f..69daf4c01cd0 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -59,10 +59,6 @@ struct drm_i915_gem_request; * available in the work queue (note, the queue is shared, * not per-engine). It is OK for this to be nonzero, but * it should not be huge! - * b_fail: failed to ring the doorbell. This should never happen, unless - * somehow the hardware misbehaves, or maybe if the GuC firmware - * crashes? We probably need to reset the GPU to recover. - * retcode: errno from last guc_submit() */ struct i915_guc_client { struct i915_vma *vma; -- cgit v1.2.3 From 85e2fe679e053326191f92b923f22a834f82cb53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Thu, 14 Sep 2017 10:32:13 +0200 Subject: drm/i915/guc: Submit GuC workitems containing coalesced requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To create an upper bound on number of GuC workitems, we need to change the way that requests are being submitted. Rather than submitting each request as an individual workitem, we can do coalescing in a similar way we're handlig execlist submission ports. We also need to stop pretending that we're doing "lite-restore" in GuC submission (we would create a workitem each time we hit this condition). This allows us to completely remove the reservation, replacing it with a compile time check. v2: Also coalesce when replaying on reset (Daniele) v3: Consistent wq_resv - per-request (Daniele) v4: Squash removing wq_resv v5: Reflect i915_guc_submit argument changes in doc v6: Rebase on top of execlists reset/restart fix (Chris,Michał) References: https://bugs.freedesktop.org/show_bug.cgi?id=101873 Cc: Chris Wilson Cc: Daniele Ceraolo Spurio Cc: Jeff McGee Cc: Michal Wajdeczko Cc: Oscar Mateo Signed-off-by: Michał Winiarski Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170914083216.10192-2-michal.winiarski@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 2 - drivers/gpu/drm/i915/i915_guc_submission.c | 182 ++++++++++------------------- drivers/gpu/drm/i915/intel_lrc.c | 25 +--- drivers/gpu/drm/i915/intel_uc.h | 11 -- 4 files changed, 63 insertions(+), 157 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 12381045ed6a..a4c2d0718a70 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2450,8 +2450,6 @@ static void i915_guc_client_info(struct seq_file *m, seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", client->wq_size, client->wq_offset, client->wq_tail); - seq_printf(m, "\tWork queue full: %u\n", client->no_wq_space); - for_each_engine(engine, dev_priv, id) { u64 submissions = client->submissions[id]; tot += submissions; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index c180ff1423fd..a30cff294b30 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -406,63 +406,6 @@ static void guc_stage_desc_fini(struct intel_guc *guc, memset(desc, 0, sizeof(*desc)); } -/** - * i915_guc_wq_reserve() - reserve space in the GuC's workqueue - * @request: request associated with the commands - * - * Return: 0 if space is available - * -EAGAIN if space is not currently available - * - * This function must be called (and must return 0) before a request - * is submitted to the GuC via i915_guc_submit() below. Once a result - * of 0 has been returned, it must be balanced by a corresponding - * call to submit(). - * - * Reservation allows the caller to determine in advance that space - * will be available for the next submission before committing resources - * to it, and helps avoid late failures with complicated recovery paths. - */ -int i915_guc_wq_reserve(struct drm_i915_gem_request *request) -{ - const size_t wqi_size = sizeof(struct guc_wq_item); - struct i915_guc_client *client = request->i915->guc.execbuf_client; - struct guc_process_desc *desc = __get_process_desc(client); - u32 freespace; - int ret; - - spin_lock_irq(&client->wq_lock); - freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); - freespace -= client->wq_rsvd; - if (likely(freespace >= wqi_size)) { - client->wq_rsvd += wqi_size; - ret = 0; - } else { - client->no_wq_space++; - ret = -EAGAIN; - } - spin_unlock_irq(&client->wq_lock); - - return ret; -} - -static void guc_client_update_wq_rsvd(struct i915_guc_client *client, int size) -{ - unsigned long flags; - - spin_lock_irqsave(&client->wq_lock, flags); - client->wq_rsvd += size; - spin_unlock_irqrestore(&client->wq_lock, flags); -} - -void i915_guc_wq_unreserve(struct drm_i915_gem_request *request) -{ - const int wqi_size = sizeof(struct guc_wq_item); - struct i915_guc_client *client = request->i915->guc.execbuf_client; - - GEM_BUG_ON(READ_ONCE(client->wq_rsvd) < wqi_size); - guc_client_update_wq_rsvd(client, -wqi_size); -} - /* Construct a Work Item and append it to the GuC's Work Queue */ static void guc_wq_item_append(struct i915_guc_client *client, struct drm_i915_gem_request *rq) @@ -476,7 +419,7 @@ static void guc_wq_item_append(struct i915_guc_client *client, struct guc_wq_item *wqi; u32 freespace, tail, wq_off; - /* Free space is guaranteed, see i915_guc_wq_reserve() above */ + /* Free space is guaranteed */ freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); GEM_BUG_ON(freespace < wqi_size); @@ -491,14 +434,12 @@ static void guc_wq_item_append(struct i915_guc_client *client, * workqueue buffer dw by dw. */ BUILD_BUG_ON(wqi_size != 16); - GEM_BUG_ON(client->wq_rsvd < wqi_size); /* postincrement WQ tail for next time */ wq_off = client->wq_tail; GEM_BUG_ON(wq_off & (wqi_size - 1)); client->wq_tail += wqi_size; client->wq_tail &= client->wq_size - 1; - client->wq_rsvd -= wqi_size; /* WQ starts from the page after doorbell / process_desc */ wqi = client->vaddr + wq_off + GUC_DB_SIZE; @@ -579,47 +520,42 @@ static int guc_ring_doorbell(struct i915_guc_client *client) } /** - * __i915_guc_submit() - Submit commands through GuC - * @rq: request associated with the commands - * - * The caller must have already called i915_guc_wq_reserve() above with - * a result of 0 (success), guaranteeing that there is space in the work - * queue for the new request, so enqueuing the item cannot fail. - * - * Bad Things Will Happen if the caller violates this protocol e.g. calls - * submit() when _reserve() says there's no space, or calls _submit() - * a different number of times from (successful) calls to _reserve(). + * i915_guc_submit() - Submit commands through GuC + * @engine: engine associated with the commands * * The only error here arises if the doorbell hardware isn't functioning * as expected, which really shouln't happen. */ -static void __i915_guc_submit(struct drm_i915_gem_request *rq) +static void i915_guc_submit(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = rq->i915; - struct intel_engine_cs *engine = rq->engine; - unsigned int engine_id = engine->id; - struct intel_guc *guc = &rq->i915->guc; + struct drm_i915_private *dev_priv = engine->i915; + struct intel_guc *guc = &dev_priv->guc; struct i915_guc_client *client = guc->execbuf_client; - unsigned long flags; + struct execlist_port *port = engine->execlist_port; + unsigned int engine_id = engine->id; + unsigned int n; - /* WA to flush out the pending GMADR writes to ring buffer. */ - if (i915_vma_is_map_and_fenceable(rq->ring->vma)) - POSTING_READ_FW(GUC_STATUS); + for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) { + struct drm_i915_gem_request *rq; + unsigned int count; - spin_lock_irqsave(&client->wq_lock, flags); + rq = port_unpack(&port[n], &count); + if (rq && count == 0) { + port_set(&port[n], port_pack(rq, ++count)); - guc_wq_item_append(client, rq); - WARN_ON(guc_ring_doorbell(client)); + if (i915_vma_is_map_and_fenceable(rq->ring->vma)) + POSTING_READ_FW(GUC_STATUS); - client->submissions[engine_id] += 1; + spin_lock(&client->wq_lock); - spin_unlock_irqrestore(&client->wq_lock, flags); -} + guc_wq_item_append(client, rq); + WARN_ON(guc_ring_doorbell(client)); -static void i915_guc_submit(struct drm_i915_gem_request *rq) -{ - __i915_gem_request_submit(rq); - __i915_guc_submit(rq); + client->submissions[engine_id] += 1; + + spin_unlock(&client->wq_lock); + } + } } static void nested_enable_signaling(struct drm_i915_gem_request *rq) @@ -653,16 +589,19 @@ static void port_assign(struct execlist_port *port, if (port_isset(port)) i915_gem_request_put(port_request(port)); - port_set(port, i915_gem_request_get(rq)); + port_set(port, port_pack(i915_gem_request_get(rq), port_count(port))); nested_enable_signaling(rq); } -static bool i915_guc_dequeue(struct intel_engine_cs *engine) +static void i915_guc_dequeue(struct intel_engine_cs *engine) { struct execlist_port *port = engine->execlist_port; - struct drm_i915_gem_request *last = port_request(port); - struct rb_node *rb; + struct drm_i915_gem_request *last = NULL; bool submit = false; + struct rb_node *rb; + + if (port_isset(port)) + port++; spin_lock_irq(&engine->timeline->lock); rb = engine->execlist_first; @@ -687,7 +626,7 @@ static bool i915_guc_dequeue(struct intel_engine_cs *engine) INIT_LIST_HEAD(&rq->priotree.link); rq->priotree.priority = INT_MAX; - i915_guc_submit(rq); + __i915_gem_request_submit(rq); trace_i915_gem_request_in(rq, port_index(port, engine)); last = rq; submit = true; @@ -701,11 +640,11 @@ static bool i915_guc_dequeue(struct intel_engine_cs *engine) } done: engine->execlist_first = rb; - if (submit) + if (submit) { port_assign(port, last); + i915_guc_submit(engine); + } spin_unlock_irq(&engine->timeline->lock); - - return submit; } static void i915_guc_irq_handler(unsigned long data) @@ -713,24 +652,20 @@ static void i915_guc_irq_handler(unsigned long data) struct intel_engine_cs *engine = (struct intel_engine_cs *)data; struct execlist_port *port = engine->execlist_port; struct drm_i915_gem_request *rq; - bool submit; - do { - rq = port_request(&port[0]); - while (rq && i915_gem_request_completed(rq)) { - trace_i915_gem_request_out(rq); - i915_gem_request_put(rq); + rq = port_request(&port[0]); + while (rq && i915_gem_request_completed(rq)) { + trace_i915_gem_request_out(rq); + i915_gem_request_put(rq); - port[0] = port[1]; - memset(&port[1], 0, sizeof(port[1])); + port[0] = port[1]; + memset(&port[1], 0, sizeof(port[1])); - rq = port_request(&port[0]); - } + rq = port_request(&port[0]); + } - submit = false; - if (!port_count(&port[1])) - submit = i915_guc_dequeue(engine); - } while (submit); + if (!port_isset(&port[1])) + i915_guc_dequeue(engine); } /* @@ -1239,6 +1174,19 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) enum intel_engine_id id; int err; + /* + * We're using GuC work items for submitting work through GuC. Since + * we're coalescing multiple requests from a single context into a + * single work item prior to assigning it to execlist_port, we can + * never have more work items than the total number of ports (for all + * engines). The GuC firmware is controlling the HEAD of work queue, + * and it is guaranteed that it will remove the work item from the + * queue before our request is completed. + */ + BUILD_BUG_ON(ARRAY_SIZE(engine->execlist_port) * + sizeof(struct guc_wq_item) * + I915_NUM_ENGINES > GUC_WQ_SIZE); + if (!client) { client = guc_client_alloc(dev_priv, INTEL_INFO(dev_priv)->ring_mask, @@ -1266,9 +1214,6 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) guc_interrupts_capture(dev_priv); for_each_engine(engine, dev_priv, id) { - const int wqi_size = sizeof(struct guc_wq_item); - struct drm_i915_gem_request *rq; - /* The tasklet was initialised by execlists, and may be in * a state of flux (across a reset) and so we just want to * take over the callback without changing any other state @@ -1276,14 +1221,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) */ engine->irq_tasklet.func = i915_guc_irq_handler; clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); - - /* Replay the current set of previously submitted requests */ - spin_lock_irq(&engine->timeline->lock); - list_for_each_entry(rq, &engine->timeline->requests, link) { - guc_client_update_wq_rsvd(client, wqi_size); - __i915_guc_submit(rq); - } - spin_unlock_irq(&engine->timeline->lock); + tasklet_schedule(&engine->irq_tasklet); } return 0; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 94a89eff4dbd..86fed9f1f1ae 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -988,27 +988,14 @@ static int execlists_request_alloc(struct drm_i915_gem_request *request) */ request->reserved_space += EXECLISTS_REQUEST_SIZE; - if (i915.enable_guc_submission) { - /* - * Check that the GuC has space for the request before - * going any further, as the i915_add_request() call - * later on mustn't fail ... - */ - ret = i915_guc_wq_reserve(request); - if (ret) - goto err; - } - cs = intel_ring_begin(request, 0); - if (IS_ERR(cs)) { - ret = PTR_ERR(cs); - goto err_unreserve; - } + if (IS_ERR(cs)) + return PTR_ERR(cs); if (!ce->initialised) { ret = engine->init_context(request); if (ret) - goto err_unreserve; + return ret; ce->initialised = true; } @@ -1022,12 +1009,6 @@ static int execlists_request_alloc(struct drm_i915_gem_request *request) request->reserved_space -= EXECLISTS_REQUEST_SIZE; return 0; - -err_unreserve: - if (i915.enable_guc_submission) - i915_guc_wq_unreserve(request); -err: - return ret; } /* diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index 69daf4c01cd0..d41051688221 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -52,13 +52,6 @@ struct drm_i915_gem_request; * GuC). The subsequent pages of the client object constitute the work * queue (a circular array of work items), again described in the process * descriptor. Work queue pages are mapped momentarily as required. - * - * We also keep a few statistics on failures. Ideally, these should all - * be zero! - * no_wq_space: times that the submission pre-check found no space was - * available in the work queue (note, the queue is shared, - * not per-engine). It is OK for this to be nonzero, but - * it should not be huge! */ struct i915_guc_client { struct i915_vma *vma; @@ -79,8 +72,6 @@ struct i915_guc_client { uint32_t wq_offset; uint32_t wq_size; uint32_t wq_tail; - uint32_t wq_rsvd; - uint32_t no_wq_space; /* Per-engine counts of GuC submissions */ uint64_t submissions[I915_NUM_ENGINES]; @@ -246,8 +237,6 @@ u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv); /* i915_guc_submission.c */ int i915_guc_submission_init(struct drm_i915_private *dev_priv); int i915_guc_submission_enable(struct drm_i915_private *dev_priv); -int i915_guc_wq_reserve(struct drm_i915_gem_request *rq); -void i915_guc_wq_unreserve(struct drm_i915_gem_request *request); void i915_guc_submission_disable(struct drm_i915_private *dev_priv); void i915_guc_submission_fini(struct drm_i915_private *dev_priv); struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); -- cgit v1.2.3 From 59db36cf4d67b74f5b8cb001493847464240d136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Thu, 14 Sep 2017 12:51:23 +0200 Subject: drm/i915/guc: Simplify GuC doorbell logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All we're really doing is incrementing a simple counter in a doorbell_info struct. We can do without extra variables and a separate counter kept in guc_client. Since it's gone, we're also removing its debugfs. The only functional change here, is that we're no longer treating 0 as a special value. GuC doesn't seem to care, why should we? v2: Restore desc->tail update. v3: Drop the retry loop, assert that doorbell cookie doesn't change behind our back. v4: WARN rather than BUG, use xchg. (Chris) Cc: Chris Wilson Cc: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: Oscar Mateo Suggested-by: Chris Wilson Signed-off-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20170914105125.3031-1-michal.winiarski@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_guc_submission.c | 60 +++++++----------------------- drivers/gpu/drm/i915/intel_uc.h | 1 - 3 files changed, 15 insertions(+), 50 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a4c2d0718a70..46ac6091772e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2445,8 +2445,8 @@ static void i915_guc_client_info(struct seq_file *m, seq_printf(m, "\tPriority %d, GuC stage index: %u, PD offset 0x%x\n", client->priority, client->stage_id, client->proc_desc_offset); - seq_printf(m, "\tDoorbell id %d, offset: 0x%lx, cookie 0x%x\n", - client->doorbell_id, client->doorbell_offset, client->doorbell_cookie); + seq_printf(m, "\tDoorbell id %d, offset: 0x%lx\n", + client->doorbell_id, client->doorbell_offset); seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", client->wq_size, client->wq_offset, client->wq_tail); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index a30cff294b30..2231214597b9 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -192,13 +192,12 @@ static int __create_doorbell(struct i915_guc_client *client) doorbell = __get_doorbell(client); doorbell->db_status = GUC_DOORBELL_ENABLED; - doorbell->cookie = client->doorbell_cookie; + doorbell->cookie = 0; err = __guc_allocate_doorbell(client->guc, client->stage_id); - if (err) { + if (err) doorbell->db_status = GUC_DOORBELL_DISABLED; - doorbell->cookie = 0; - } + return err; } @@ -466,57 +465,24 @@ static void guc_reset_wq(struct i915_guc_client *client) client->wq_tail = 0; } -static int guc_ring_doorbell(struct i915_guc_client *client) +static void guc_ring_doorbell(struct i915_guc_client *client) { struct guc_process_desc *desc = __get_process_desc(client); - union guc_doorbell_qw db_cmp, db_exc, db_ret; - union guc_doorbell_qw *db; - int attempt = 2, ret = -EAGAIN; + struct guc_doorbell_info *db; + u32 cookie; /* Update the tail so it is visible to GuC */ desc->tail = client->wq_tail; - /* current cookie */ - db_cmp.db_status = GUC_DOORBELL_ENABLED; - db_cmp.cookie = client->doorbell_cookie; - - /* cookie to be updated */ - db_exc.db_status = GUC_DOORBELL_ENABLED; - db_exc.cookie = client->doorbell_cookie + 1; - if (db_exc.cookie == 0) - db_exc.cookie = 1; - /* pointer of current doorbell cacheline */ - db = (union guc_doorbell_qw *)__get_doorbell(client); - - while (attempt--) { - /* lets ring the doorbell */ - db_ret.value_qw = atomic64_cmpxchg((atomic64_t *)db, - db_cmp.value_qw, db_exc.value_qw); - - /* if the exchange was successfully executed */ - if (db_ret.value_qw == db_cmp.value_qw) { - /* db was successfully rung */ - client->doorbell_cookie = db_exc.cookie; - ret = 0; - break; - } - - /* XXX: doorbell was lost and need to acquire it again */ - if (db_ret.db_status == GUC_DOORBELL_DISABLED) - break; + db = __get_doorbell(client); - DRM_WARN("Cookie mismatch. Expected %d, found %d\n", - db_cmp.cookie, db_ret.cookie); + /* we're not expecting the doorbell cookie to change behind our back */ + cookie = READ_ONCE(db->cookie); + WARN_ON_ONCE(xchg(&db->cookie, cookie + 1) != cookie); - /* update the cookie to newly read cookie from GuC */ - db_cmp.cookie = db_ret.cookie; - db_exc.cookie = db_ret.cookie + 1; - if (db_exc.cookie == 0) - db_exc.cookie = 1; - } - - return ret; + /* XXX: doorbell was lost and need to acquire it again */ + GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED); } /** @@ -549,7 +515,7 @@ static void i915_guc_submit(struct intel_engine_cs *engine) spin_lock(&client->wq_lock); guc_wq_item_append(client, rq); - WARN_ON(guc_ring_doorbell(client)); + guc_ring_doorbell(client); client->submissions[engine_id] += 1; diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index d41051688221..f505dcccd613 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -66,7 +66,6 @@ struct i915_guc_client { u16 doorbell_id; unsigned long doorbell_offset; - u32 doorbell_cookie; spinlock_t wq_lock; uint32_t wq_offset; -- cgit v1.2.3 From a529a1c9db931a5d4fd6683199d73a8363bc7e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Mon, 18 Sep 2017 11:25:35 +0200 Subject: drm/i915/guc: Cleanup adding GuC work items MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can just operate on the wq_tail directly (in the process descriptor). This allows us to remove the duplicated tail from the client. While I'm here let's also remove the constants kept in the client and document our locking requirements. This causes a small change in one of GuC debugfs files. We're no longer reporting constant values (which I don't think is a problem), but we're also no longer reporting the tail (does anyone care?). v2: Update tail after wqi contents. (Chris) v3: Really update tail after wqi contents. Cc: Chris Wilson Cc: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: Oscar Mateo Signed-off-by: Michał Winiarski Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170918092536.12287-1-michal.winiarski@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 2 -- drivers/gpu/drm/i915/i915_guc_submission.c | 37 +++++++++++++----------------- drivers/gpu/drm/i915/intel_uc.h | 4 ---- 3 files changed, 16 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 46ac6091772e..2518bdf95eef 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2447,8 +2447,6 @@ static void i915_guc_client_info(struct seq_file *m, client->priority, client->stage_id, client->proc_desc_offset); seq_printf(m, "\tDoorbell id %d, offset: 0x%lx\n", client->doorbell_id, client->doorbell_offset); - seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", - client->wq_size, client->wq_offset, client->wq_tail); for_each_engine(engine, dev_priv, id) { u64 submissions = client->submissions[id]; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 2231214597b9..e191d56fc990 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -305,7 +305,7 @@ static void guc_proc_desc_init(struct intel_guc *guc, desc->db_base_addr = 0; desc->stage_id = client->stage_id; - desc->wq_size_bytes = client->wq_size; + desc->wq_size_bytes = GUC_WQ_SIZE; desc->wq_status = WQ_STATUS_ACTIVE; desc->priority = client->priority; } @@ -390,8 +390,8 @@ static void guc_stage_desc_init(struct intel_guc *guc, desc->db_trigger_cpu = (uintptr_t)__get_doorbell(client); desc->db_trigger_uk = gfx_addr + client->doorbell_offset; desc->process_desc = gfx_addr + client->proc_desc_offset; - desc->wq_addr = gfx_addr + client->wq_offset; - desc->wq_size = client->wq_size; + desc->wq_addr = gfx_addr + GUC_DB_SIZE; + desc->wq_size = GUC_WQ_SIZE; desc->desc_private = (uintptr_t)client; } @@ -416,14 +416,12 @@ static void guc_wq_item_append(struct i915_guc_client *client, struct i915_gem_context *ctx = rq->ctx; struct guc_process_desc *desc = __get_process_desc(client); struct guc_wq_item *wqi; - u32 freespace, tail, wq_off; + u32 ring_tail, wq_off; - /* Free space is guaranteed */ - freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); - GEM_BUG_ON(freespace < wqi_size); + lockdep_assert_held(&client->wq_lock); - tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); - GEM_BUG_ON(tail > WQ_RING_TAIL_MAX); + ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); + GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX); /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we * should not have the case where structure wqi is across page, neither @@ -434,11 +432,11 @@ static void guc_wq_item_append(struct i915_guc_client *client, */ BUILD_BUG_ON(wqi_size != 16); - /* postincrement WQ tail for next time */ - wq_off = client->wq_tail; + /* Free space is guaranteed. */ + wq_off = READ_ONCE(desc->tail); + GEM_BUG_ON(CIRC_SPACE(wq_off, READ_ONCE(desc->head), + GUC_WQ_SIZE) < wqi_size); GEM_BUG_ON(wq_off & (wqi_size - 1)); - client->wq_tail += wqi_size; - client->wq_tail &= client->wq_size - 1; /* WQ starts from the page after doorbell / process_desc */ wqi = client->vaddr + wq_off + GUC_DB_SIZE; @@ -451,8 +449,11 @@ static void guc_wq_item_append(struct i915_guc_client *client, wqi->context_desc = lower_32_bits(intel_lr_context_descriptor(ctx, engine)); - wqi->submit_element_info = tail << WQ_RING_TAIL_SHIFT; + wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT; wqi->fence_id = rq->global_seqno; + + /* Postincrement WQ tail for next time. */ + WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1)); } static void guc_reset_wq(struct i915_guc_client *client) @@ -461,18 +462,14 @@ static void guc_reset_wq(struct i915_guc_client *client) desc->head = 0; desc->tail = 0; - - client->wq_tail = 0; } static void guc_ring_doorbell(struct i915_guc_client *client) { - struct guc_process_desc *desc = __get_process_desc(client); struct guc_doorbell_info *db; u32 cookie; - /* Update the tail so it is visible to GuC */ - desc->tail = client->wq_tail; + lockdep_assert_held(&client->wq_lock); /* pointer of current doorbell cacheline */ db = __get_doorbell(client); @@ -812,8 +809,6 @@ guc_client_alloc(struct drm_i915_private *dev_priv, client->engines = engines; client->priority = priority; client->doorbell_id = GUC_DOORBELL_INVALID; - client->wq_offset = GUC_DB_SIZE; - client->wq_size = GUC_WQ_SIZE; spin_lock_init(&client->wq_lock); ret = ida_simple_get(&guc->stage_ids, 0, GUC_MAX_STAGE_DESCRIPTORS, diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index f505dcccd613..7703c9ad6511 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -68,10 +68,6 @@ struct i915_guc_client { unsigned long doorbell_offset; spinlock_t wq_lock; - uint32_t wq_offset; - uint32_t wq_size; - uint32_t wq_tail; - /* Per-engine counts of GuC submissions */ uint64_t submissions[I915_NUM_ENGINES]; }; -- cgit v1.2.3 From 1298d51c44fddcb609ea6c9fa37b76028593963b Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Mon, 18 Sep 2017 21:36:34 +0800 Subject: drm/i915: Return the correct score in i915_ppat_get() The cache attribute of the required entry has to be the same with the existing value. After this requirement is met, the futher comparison should be performed. After this fix, the refined test case can pass. v2: - Refine the tittle and comments. (Rodrigo) Fixes: 4395890a4855 ("drm/i915: Introduce private PAT management") Cc: Chris Wilson Cc: Ben Widawsky Cc: Rodrigo Vivi Cc: Joonas Lahtinen Signed-off-by: Zhi Wang Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/1505741794-10593-1-git-send-email-zhi.a.wang@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 729ebaf29b71..37cd0860fc29 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2965,7 +2965,7 @@ static unsigned int bdw_private_pat_match(u8 src, u8 dst) }; /* Cache attribute has to be matched. */ - if (GEN8_PPAT_GET_CA(src) == GEN8_PPAT_GET_CA(dst)) + if (GEN8_PPAT_GET_CA(src) != GEN8_PPAT_GET_CA(dst)) return 0; score |= CA_MATCH; -- cgit v1.2.3 From b5891fb520f742ce48b097c6b8a0b2db1e2bb979 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 14 Sep 2017 17:22:40 +0100 Subject: drm/i915/selftests: Disable iommu for the mock device On some machines, the iommu cannot allocate a domain for the mock device causing the dma_map_sg() to fail, and the selftest to fail with -ENOMEM. For the mock selftests, we are using a fake device and do not care about iommu; so convince intel_iommu to treat us as a dummy device with an identity mapping (and no iommu domain). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101080 Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170914162240.18310-1-chris@chris-wilson.co.uk Tested-by: Elizabeth De La Torre Mena Reviewed-by: Matthew Auld dev, "mock"); dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + /* hack to disable iommu for the fake device; force identity mapping */ + pdev->dev.archdata.iommu = (void *)-1; + dev_pm_domain_set(&pdev->dev, &pm_domain); pm_runtime_enable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); -- cgit v1.2.3 From 342a2c840ed0cb99509e99e082b1f8aa784b5e59 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Mon, 18 Sep 2017 12:21:23 +0100 Subject: drm/i915/perf: disable clk ratio reports on gen9 We're doing this on all Gen9 based platforms, let's just check the gen rather than listing every single platforms. Signed-off-by: Lionel Landwerlin Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20170918112124.29541-2-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 94185d610673..1b40ac6d1400 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1850,8 +1850,7 @@ static int gen8_enable_metric_set(struct drm_i915_private *dev_priv, * be read back from automatically triggered reports, as part of the * RPT_ID field. */ - if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) || - IS_KABYLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) { + if (IS_GEN9(dev_priv)) { I915_WRITE(GEN8_OA_DEBUG, _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS | GEN9_OA_DEBUG_INCLUDE_CLK_RATIO)); -- cgit v1.2.3 From 22ea4f3528efaa0523d1643264372d0bdfbd49bd Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Mon, 18 Sep 2017 12:21:24 +0100 Subject: drm/i915/perf: add support for Coffeelake GT2 Add the test configuration & timestamp frequency for Coffeelake GT2. Signed-off-by: Lionel Landwerlin Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20170918112124.29541-3-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/i915/Makefile | 3 +- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_oa_cflgt2.c | 109 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_oa_cflgt2.h | 34 +++++++++++ drivers/gpu/drm/i915/i915_perf.c | 5 ++ 5 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/i915_oa_cflgt2.c create mode 100644 drivers/gpu/drm/i915/i915_oa_cflgt2.h (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 1cb8059a3a16..5182e3d5557d 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -139,7 +139,8 @@ i915-y += i915_perf.o \ i915_oa_bxt.o \ i915_oa_kblgt2.o \ i915_oa_kblgt3.o \ - i915_oa_glk.o + i915_oa_glk.o \ + i915_oa_cflgt2.o ifeq ($(CONFIG_DRM_I915_GVT),y) i915-y += intel_gvt.o diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a24659b5e6b5..08e3ae15b52e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2984,6 +2984,8 @@ intel_info(const struct drm_i915_private *dev_priv) (dev_priv)->info.gt == 3) #define IS_CFL_ULT(dev_priv) (IS_COFFEELAKE(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0x00F0) == 0x00A0) +#define IS_CFL_GT2(dev_priv) (IS_COFFEELAKE(dev_priv) && \ + (dev_priv)->info.gt == 2) #define IS_ALPHA_SUPPORT(intel_info) ((intel_info)->is_alpha_support) diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt2.c b/drivers/gpu/drm/i915/i915_oa_cflgt2.c new file mode 100644 index 000000000000..368c87d7ee9a --- /dev/null +++ b/drivers/gpu/drm/i915/i915_oa_cflgt2.c @@ -0,0 +1,109 @@ +/* + * Autogenerated file by GPU Top : https://github.com/rib/gputop + * DO NOT EDIT manually! + * + * + * Copyright (c) 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include + +#include "i915_drv.h" +#include "i915_oa_cflgt2.h" + +static const struct i915_oa_reg b_counter_config_test_oa[] = { + { _MMIO(0x2740), 0x00000000 }, + { _MMIO(0x2744), 0x00800000 }, + { _MMIO(0x2714), 0xf0800000 }, + { _MMIO(0x2710), 0x00000000 }, + { _MMIO(0x2724), 0xf0800000 }, + { _MMIO(0x2720), 0x00000000 }, + { _MMIO(0x2770), 0x00000004 }, + { _MMIO(0x2774), 0x00000000 }, + { _MMIO(0x2778), 0x00000003 }, + { _MMIO(0x277c), 0x00000000 }, + { _MMIO(0x2780), 0x00000007 }, + { _MMIO(0x2784), 0x00000000 }, + { _MMIO(0x2788), 0x00100002 }, + { _MMIO(0x278c), 0x0000fff7 }, + { _MMIO(0x2790), 0x00100002 }, + { _MMIO(0x2794), 0x0000ffcf }, + { _MMIO(0x2798), 0x00100082 }, + { _MMIO(0x279c), 0x0000ffef }, + { _MMIO(0x27a0), 0x001000c2 }, + { _MMIO(0x27a4), 0x0000ffe7 }, + { _MMIO(0x27a8), 0x00100001 }, + { _MMIO(0x27ac), 0x0000ffe7 }, +}; + +static const struct i915_oa_reg flex_eu_config_test_oa[] = { +}; + +static const struct i915_oa_reg mux_config_test_oa[] = { + { _MMIO(0x9840), 0x00000080 }, + { _MMIO(0x9888), 0x11810000 }, + { _MMIO(0x9888), 0x07810013 }, + { _MMIO(0x9888), 0x1f810000 }, + { _MMIO(0x9888), 0x1d810000 }, + { _MMIO(0x9888), 0x1b930040 }, + { _MMIO(0x9888), 0x07e54000 }, + { _MMIO(0x9888), 0x1f908000 }, + { _MMIO(0x9888), 0x11900000 }, + { _MMIO(0x9888), 0x37900000 }, + { _MMIO(0x9888), 0x53900000 }, + { _MMIO(0x9888), 0x45900000 }, + { _MMIO(0x9888), 0x33900000 }, +}; + +static ssize_t +show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "1\n"); +} + +void +i915_perf_load_test_config_cflgt2(struct drm_i915_private *dev_priv) +{ + strncpy(dev_priv->perf.oa.test_config.uuid, + "74fb4902-d3d3-4237-9e90-cbdc68d0a446", + UUID_STRING_LEN); + dev_priv->perf.oa.test_config.id = 1; + + dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; + dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa); + + dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa; + dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa); + + dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa; + dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa); + + dev_priv->perf.oa.test_config.sysfs_metric.name = "74fb4902-d3d3-4237-9e90-cbdc68d0a446"; + dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs; + + dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr; + + dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id"; + dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444; + dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id; +} diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt2.h b/drivers/gpu/drm/i915/i915_oa_cflgt2.h new file mode 100644 index 000000000000..1f3268ef2ea2 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_oa_cflgt2.h @@ -0,0 +1,34 @@ +/* + * Autogenerated file by GPU Top : https://github.com/rib/gputop + * DO NOT EDIT manually! + * + * + * Copyright (c) 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef __I915_OA_CFLGT2_H__ +#define __I915_OA_CFLGT2_H__ + +extern void i915_perf_load_test_config_cflgt2(struct drm_i915_private *dev_priv); + +#endif diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 1b40ac6d1400..902722ab84c9 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -206,6 +206,7 @@ #include "i915_oa_kblgt2.h" #include "i915_oa_kblgt3.h" #include "i915_oa_glk.h" +#include "i915_oa_cflgt2.h" /* HW requires this to be a power of two, between 128k and 16M, though driver * is currently generally designed assuming the largest 16M size is used such @@ -2926,6 +2927,9 @@ void i915_perf_register(struct drm_i915_private *dev_priv) i915_perf_load_test_config_kblgt3(dev_priv); } else if (IS_GEMINILAKE(dev_priv)) { i915_perf_load_test_config_glk(dev_priv); + } else if (IS_COFFEELAKE(dev_priv)) { + if (IS_CFL_GT2(dev_priv)) + i915_perf_load_test_config_cflgt2(dev_priv); } if (dev_priv->perf.oa.test_config.id == 0) @@ -3452,6 +3456,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv) break; case INTEL_SKYLAKE: case INTEL_KABYLAKE: + case INTEL_COFFEELAKE: dev_priv->perf.oa.timestamp_frequency = 12000000; break; default: -- cgit v1.2.3 From da83ef85f5356b4bdf534add20fb34dcc6b53fc1 Mon Sep 17 00:00:00 2001 From: Radhakrishna Sripada Date: Thu, 14 Sep 2017 11:16:41 -0700 Subject: drm/i915: Do not enable DRRS when PSR is enabled Some platforms do not support PSR and DRRS simultaneously. Visual artifacts and flickering were reported on BDW HP Spectre x360 Convertible. Deferring to PSR when both PSR and DRRS are supported by the panel. V2: Minor code-style changes suggested by Rodrigo V3: Add a WARN_ON during PSR init suggested by Dhinakaran Correct debug message,title suggested by Jani Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101111 Cc: Nicholas Stommel Cc: Dhinakaran Pandiyan Cc: Jani Nikula Cc: Clinton Taylor Cc: Rodrigo Vivi Signed-off-by: Radhakrishna Sripada Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20170914181641.24393-1-radhakrishna.sripada@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 10 +++++----- drivers/gpu/drm/i915/intel_psr.c | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 887953c0f495..8db6b11f103f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5467,11 +5467,6 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, return; } - /* - * FIXME: This needs proper synchronization with psr state for some - * platforms that cannot have PSR and DRRS enabled at the same time. - */ - dig_port = dp_to_dig_port(intel_dp); encoder = &dig_port->base; intel_crtc = to_intel_crtc(encoder->base.crtc); @@ -5555,6 +5550,11 @@ void intel_edp_drrs_enable(struct intel_dp *intel_dp, return; } + if (dev_priv->psr.enabled) { + DRM_DEBUG_KMS("PSR enabled. Not enabling DRRS.\n"); + return; + } + mutex_lock(&dev_priv->drrs.mutex); if (WARN_ON(dev_priv->drrs.dp)) { DRM_ERROR("DRRS already enabled\n"); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 55b4002bbe53..acb50945bfa8 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -530,6 +530,7 @@ void intel_psr_enable(struct intel_dp *intel_dp, return; } + WARN_ON(dev_priv->drrs.dp); mutex_lock(&dev_priv->psr.lock); if (dev_priv->psr.enabled) { DRM_DEBUG_KMS("PSR already in use\n"); -- cgit v1.2.3 From 4cc6feb715c223d59c8cad0dc71bce1a574a2c67 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 8 Sep 2017 16:45:33 -0700 Subject: drm/i915/cnp: Don't touch other PCH clock gating bits. Don't touch other bits. My bad. I haven't seen any case where those other bits appeard to be set before we touch it, but it is safe to avoid touching other bits we weren't told to touch. Fixes: 0a46ddd57c9e ("drm/i915/cnp: Wa 1181: Fix Backlight issue") Cc: Dhinakaran Pandiyan Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170908234534.17986-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 94624ede3479..adfeb7bb8874 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -8369,7 +8369,8 @@ static void cnp_init_clock_gating(struct drm_i915_private *dev_priv) return; /* Wa #1181 */ - I915_WRITE(SOUTH_DSPCLK_GATE_D, CNP_PWM_CGE_GATING_DISABLE); + I915_WRITE(SOUTH_DSPCLK_GATE_D, I915_READ(SOUTH_DSPCLK_GATE_D) | + CNP_PWM_CGE_GATING_DISABLE); } static void cnl_init_clock_gating(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From f46f156ea7704a40577800c3df63b599121a87ec Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Sep 2017 17:46:52 +0100 Subject: drm/i915/selftests: Only touch archdata.iommu when it exists archdata.iommu only exists when CONFIG_IOMMU_API is enabled (and only applies to intel-iommu in our case) so conditionally compile it out when it doesn't exist. Fixes: b5891fb520f7 ("drm/i915/selftests: Disable iommu for the mock device") Signed-off-by: Chris Wilson Cc: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20170918164652.14200-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 38ed006be5be..2388424a14da 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -146,8 +146,10 @@ struct drm_i915_private *mock_gem_device(void) dev_set_name(&pdev->dev, "mock"); dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); +#if IS_ENABLED(CONFIG_IOMMU_API) /* hack to disable iommu for the fake device; force identity mapping */ pdev->dev.archdata.iommu = (void *)-1; +#endif dev_pm_domain_set(&pdev->dev, &pm_domain); pm_runtime_enable(&pdev->dev); -- cgit v1.2.3 From 81c0ed21aa91230ab6c0de945155aa5c0626d001 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Sep 2017 09:41:26 +0100 Subject: drm/i915/fence: Avoid del_timer_sync() from inside a timer A fence may be signaled from any context, including from inside a timer. One example is timer_i915_sw_fence_wake() which is used to provide a safety-net when waiting on an external fence. If the external fence is not signaled within a timely fashion, we signal our fence on its behalf, and so we then may process subsequent fences in the chain from within that timer context. Given that dma_i915_sw_fence_wake() may be from inside a timer, we cannot then use del_timer_sync() as that requires the timer lock for itself. To circumvent this, while trying to keep the signal propagation as low latency as possible, move the completion into a worker and use a bit of atomic switheroo to serialise the timer-callback and the dma-callback. Testcase: igt/gem_eio/in-flight-external Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170911084135.22903-3-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/Kconfig | 1 + drivers/gpu/drm/i915/i915_sw_fence.c | 27 +++++++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index e9e64e8e9765..dfd95889f4b7 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -12,6 +12,7 @@ config DRM_I915 select DRM_PANEL select DRM_MIPI_DSI select RELAY + select IRQ_WORK # i915 depends on ACPI_VIDEO when ACPI is enabled # but for select to work, need to select ACPI_VIDEO's dependencies, ick select BACKLIGHT_LCD_SUPPORT if ACPI diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index f29540f922af..808ea4d5b962 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -9,6 +9,7 @@ #include #include +#include #include #include "i915_sw_fence.h" @@ -356,31 +357,44 @@ struct i915_sw_dma_fence_cb { struct i915_sw_fence *fence; struct dma_fence *dma; struct timer_list timer; + struct irq_work work; }; static void timer_i915_sw_fence_wake(unsigned long data) { struct i915_sw_dma_fence_cb *cb = (struct i915_sw_dma_fence_cb *)data; + struct i915_sw_fence *fence; + + fence = xchg(&cb->fence, NULL); + if (!fence) + return; pr_warn("asynchronous wait on fence %s:%s:%x timed out\n", cb->dma->ops->get_driver_name(cb->dma), cb->dma->ops->get_timeline_name(cb->dma), cb->dma->seqno); - dma_fence_put(cb->dma); - cb->dma = NULL; - i915_sw_fence_complete(cb->fence); - cb->timer.function = NULL; + i915_sw_fence_complete(fence); } static void dma_i915_sw_fence_wake(struct dma_fence *dma, struct dma_fence_cb *data) { struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base); + struct i915_sw_fence *fence; + + fence = xchg(&cb->fence, NULL); + if (fence) + i915_sw_fence_complete(fence); + + irq_work_queue(&cb->work); +} + +static void irq_i915_sw_fence_work(struct irq_work *wrk) +{ + struct i915_sw_dma_fence_cb *cb = container_of(wrk, typeof(*cb), work); del_timer_sync(&cb->timer); - if (cb->timer.function) - i915_sw_fence_complete(cb->fence); dma_fence_put(cb->dma); kfree(cb); @@ -414,6 +428,7 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, __setup_timer(&cb->timer, timer_i915_sw_fence_wake, (unsigned long)cb, TIMER_IRQSAFE); + init_irq_work(&cb->work, irq_i915_sw_fence_work); if (timeout) { cb->dma = dma_fence_get(dma); mod_timer(&cb->timer, round_jiffies_up(jiffies + timeout)); -- cgit v1.2.3 From 20303eb4e09e196f33e1a558c2ac8bb699df0a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Sep 2017 21:25:36 +0300 Subject: drm/i915: Replace some spaces with tabs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some comments in intel_ddi.c are indented with spaces instead of tabs. Fix that up. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170918182604.9519-2-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 31d14587ad86..797008033089 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1939,7 +1939,7 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, val |= RCOMP_SCALAR(0x98); I915_WRITE(CNL_PORT_TX_DW2_GRP(port), val); - /* Program PORT_TX_DW4 */ + /* Program PORT_TX_DW4 */ /* We cannot write to GRP. It would overrite individual loadgen */ for (ln = 0; ln < 4; ln++) { val = I915_READ(CNL_PORT_TX_DW4_LN(port, ln)); @@ -1951,7 +1951,7 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, I915_WRITE(CNL_PORT_TX_DW4_LN(port, ln), val); } - /* Program PORT_TX_DW5 */ + /* Program PORT_TX_DW5 */ /* All DW5 values are fixed for every table entry */ val = I915_READ(CNL_PORT_TX_DW5_LN0(port)); val &= ~RTERM_SELECT_MASK; @@ -1959,7 +1959,7 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, val |= TAP3_DISABLE; I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val); - /* Program PORT_TX_DW7 */ + /* Program PORT_TX_DW7 */ val = I915_READ(CNL_PORT_TX_DW7_LN0(port)); val &= ~N_SCALAR_MASK; val |= N_SCALAR(ddi_translations[level].dw7_n_scalar); -- cgit v1.2.3 From ac3ad6c66998ee90ff83e70e9eb9dbe08a402ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Sep 2017 21:25:37 +0300 Subject: drm/i915: Shrink bxt_ddi_buf_trans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the values we put into the BXT buf_trans tables fit into 8 bits. So switch over to u8 from the u32 we use currently. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170918182604.9519-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_ddi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 797008033089..5c709985904e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -301,10 +301,10 @@ static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = { }; struct bxt_ddi_buf_trans { - u32 margin; /* swing value */ - u32 scale; /* scale value */ - u32 enable; /* scale enable */ - u32 deemphasis; + u8 margin; /* swing value */ + u8 scale; /* scale value */ + u8 enable; /* scale enable */ + u8 deemphasis; bool default_index; /* true if the entry represents default value */ }; -- cgit v1.2.3 From fb5f4e96fdf9cb7ec5e6a590e1c3fdc3b6fd1e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 18 Sep 2017 21:25:38 +0300 Subject: drm/i915: Shrink cnl_ddi_buf_trans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the values we put into the CNL buf_trans tables fit into 8 bits. So switch over to u8 from the u32 we use currently. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170918182604.9519-4-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson Acked-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 5c709985904e..93cbbcbbc193 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -354,11 +354,11 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { }; struct cnl_ddi_buf_trans { - u32 dw2_swing_sel; - u32 dw7_n_scalar; - u32 dw4_cursor_coeff; - u32 dw4_post_cursor_2; - u32 dw4_post_cursor_1; + u8 dw2_swing_sel; + u8 dw7_n_scalar; + u8 dw4_cursor_coeff; + u8 dw4_post_cursor_2; + u8 dw4_post_cursor_1; }; /* Voltage Swing Programming for VccIO 0.85V for DP */ -- cgit v1.2.3 From 3b92e263dd4a38fa168d12a55ea4c8193483b884 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 19 Sep 2017 14:57:03 -0700 Subject: drm/i915/cnp: Display Wa #1179: WaHardHangonHotPlug "CNL PCH chance of hang when software accesses south display registers after hotplug is enabled. Workaround: Program 0xC2000 bits 11:8 = 0xF before enabling south display hotplug detection." "Workaround only needs to be applied to pre-production steppings used in graphics capable SKUs, but it is easier to apply to everything, and does not hurt." v2: Moving from clock gating to right before enabling SHOTPLUG_CTL as it should be. v3: Align with SOUTH_CHICKEN1 (DK) and consequently use proper spaces on bits definition since other bits around already use new style. And now that checkpatch is not noise anymore I also fixed the reg read mask to avoid going over 80 chars. Suggested-by: Ben Widawsky Cc: Ben Widawsky Cc: Dhinakaran Pandiyan Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170919215703.25947-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 10 +++++++++- drivers/gpu/drm/i915/i915_reg.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4d0e8f76ed1a..c23efc4394ce 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3218,7 +3218,15 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; + u32 val, hotplug; + + /* Display WA #1179 WaHardHangonHotPlug: cnp */ + if (HAS_PCH_CNP(dev_priv)) { + val = I915_READ(SOUTH_CHICKEN1); + val &= ~CHASSIS_CLK_REQ_DURATION_MASK; + val |= CHASSIS_CLK_REQ_DURATION(0xf); + I915_WRITE(SOUTH_CHICKEN1, val); + } /* Enable digital hotplug on the PCH */ hotplug = I915_READ(PCH_PORT_HOTPLUG); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 94b40a469afd..82f36dd0cd94 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7471,6 +7471,8 @@ enum { #define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2))) #define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2))) #define FDI_BC_BIFURCATION_SELECT (1 << 12) +#define CHASSIS_CLK_REQ_DURATION_MASK (0xf << 8) +#define CHASSIS_CLK_REQ_DURATION(x) ((x) << 8) #define SPT_PWM_GRANULARITY (1<<0) #define SOUTH_CHICKEN2 _MMIO(0xc2004) #define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13) -- cgit v1.2.3 From e6b20bf1b77c24465393b5b1e12781110cedc12c Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 7 Sep 2017 16:06:32 -0700 Subject: drm/i915/cfl: Remove alpha support protection. We now have Coffee Lake on our CI systems. Coffee Lake is at this point in same stage as Kaby Lake. And it seems that we don't have any risk of bad blank screens or anything like that. So let's remove the protection. Cc: Daniel Vetter Cc: Dhinakaran Pandiyan Signed-off-by: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Link: https://patchwork.freedesktop.org/patch/msgid/20170907230632.25650-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 853002fb0371..ce2c08eb9890 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -520,7 +520,6 @@ static const struct intel_device_info intel_kabylake_gt3_info __initconst = { }; #define CFL_PLATFORM \ - .is_alpha_support = 1, \ BDW_FEATURES, \ .gen = 9, \ .platform = INTEL_COFFEELAKE, \ -- cgit v1.2.3 From d81fb7fd9436e81fda67e5bc8ed0713aa28d3db2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 19 Sep 2017 18:38:13 +0300 Subject: drm/i915: always update ELD connector type after get modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_edid_to_eld() initializes the connector ELD to zero, overwriting the ELD connector type initialized in intel_audio_codec_enable(). If userspace does getconnector and thus get_modes after modeset, a subsequent audio component i915_audio_component_get_eld() call will receive an ELD without the connector type properly set. It's fine for HDMI, but screws up audio for DP. Always set the ELD connector type at intel_connector_update_modes() based on the connector type. We can drop the connector type update from intel_audio_codec_enable(). Credits to Joseph Nuzman for figuring this out. Cc: Ville Syrjälä Cc: Joseph Nuzman Reported-by: Joseph Nuzman Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101583 Reviewed-by: Ville Syrjälä Tested-by: Joseph Nuzman Cc: stable@vger.kernel.org # v4.10+, maybe earlier Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170919153813.29808-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 5 ----- drivers/gpu/drm/i915/intel_modes.c | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index d805b6e6fe71..27743be5b768 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -606,11 +606,6 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder, connector->encoder->base.id, connector->encoder->name); - /* ELD Conn_Type */ - connector->eld[5] &= ~(3 << 2); - if (intel_crtc_has_dp_encoder(crtc_state)) - connector->eld[5] |= (1 << 2); - connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; if (dev_priv->display.audio_codec_enable) diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index 951e834dd274..28a778b785ac 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -30,6 +30,21 @@ #include "intel_drv.h" #include "i915_drv.h" +static void intel_connector_update_eld_conn_type(struct drm_connector *connector) +{ + u8 conn_type; + + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + conn_type = DRM_ELD_CONN_TYPE_DP; + } else { + conn_type = DRM_ELD_CONN_TYPE_HDMI; + } + + connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] &= ~DRM_ELD_CONN_TYPE_MASK; + connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= conn_type; +} + /** * intel_connector_update_modes - update connector from edid * @connector: DRM connector device to use @@ -44,6 +59,8 @@ int intel_connector_update_modes(struct drm_connector *connector, ret = drm_add_edid_modes(connector, edid); drm_edid_to_eld(connector, edid); + intel_connector_update_eld_conn_type(connector); + return ret; } -- cgit v1.2.3 From 87de8d5613a7221abcce0b680b0da3c98b0871c8 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Tue, 19 Sep 2017 17:41:28 +0300 Subject: drm/i915: Stop engines before reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On kbl evidence indicates that even if the hardware happily tells us to proceed with reset, it really isn't ready. Resetting a freely running batchbuffer after we have ack for readiness, still can cause a system hang. We also have similar experiences on older gens. So now attempt to stop engines before proceeding for reset, on all gens where we have a gpu reset. This has shown to improve reset reliability and reduce the risk of losing the machine. v2: Add fixme for wa (Joonas) Testcase: igt/prime_busy/hang-* # kbl Cc: Joonas Lahtinen Cc: Chris Wilson Cc: Ville Syrjälä Signed-off-by: Mika Kuoppala Acked-by: Chris Wilson Acked-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170919144128.25506-1-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/intel_uncore.c | 75 +++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 32 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 97525de2cee4..fdd7f93acb4f 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1354,33 +1354,39 @@ int i915_reg_read_ioctl(struct drm_device *dev, return ret; } -static void gen3_stop_rings(struct drm_i915_private *dev_priv) +static void gen3_stop_engine(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + const u32 base = engine->mmio_base; + const i915_reg_t mode = RING_MI_MODE(base); + + I915_WRITE_FW(mode, _MASKED_BIT_ENABLE(STOP_RING)); + if (intel_wait_for_register_fw(dev_priv, + mode, + MODE_IDLE, + MODE_IDLE, + 500)) + DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", + engine->name); + + I915_WRITE_FW(RING_CTL(base), 0); + I915_WRITE_FW(RING_HEAD(base), 0); + I915_WRITE_FW(RING_TAIL(base), 0); + + /* Check acts as a post */ + if (I915_READ_FW(RING_HEAD(base)) != 0) + DRM_DEBUG_DRIVER("%s: ring head not parked\n", + engine->name); +} + +static void i915_stop_engines(struct drm_i915_private *dev_priv, + unsigned engine_mask) { struct intel_engine_cs *engine; enum intel_engine_id id; - for_each_engine(engine, dev_priv, id) { - const u32 base = engine->mmio_base; - const i915_reg_t mode = RING_MI_MODE(base); - - I915_WRITE_FW(mode, _MASKED_BIT_ENABLE(STOP_RING)); - if (intel_wait_for_register_fw(dev_priv, - mode, - MODE_IDLE, - MODE_IDLE, - 500)) - DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", - engine->name); - - I915_WRITE_FW(RING_CTL(base), 0); - I915_WRITE_FW(RING_HEAD(base), 0); - I915_WRITE_FW(RING_TAIL(base), 0); - - /* Check acts as a post */ - if (I915_READ_FW(RING_HEAD(base)) != 0) - DRM_DEBUG_DRIVER("%s: ring head not parked\n", - engine->name); - } + for_each_engine_masked(engine, dev_priv, engine_mask, id) + gen3_stop_engine(engine); } static bool i915_reset_complete(struct pci_dev *pdev) @@ -1415,9 +1421,6 @@ static int g33_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) { struct pci_dev *pdev = dev_priv->drm.pdev; - /* Stop engines before we reset; see g4x_do_reset() below for why. */ - gen3_stop_rings(dev_priv); - pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE); return wait_for(g4x_reset_complete(pdev), 500); } @@ -1432,12 +1435,6 @@ static int g4x_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) I915_READ(VDECCLK_GATE_D) | VCP_UNIT_CLOCK_GATE_DISABLE); POSTING_READ(VDECCLK_GATE_D); - /* We stop engines, otherwise we might get failed reset and a - * dead gpu (on elk). - * WaMediaResetMainRingCleanup:ctg,elk (presumably) - */ - gen3_stop_rings(dev_priv); - pci_write_config_byte(pdev, I915_GDRST, GRDOM_MEDIA | GRDOM_RESET_ENABLE); ret = wait_for(g4x_reset_complete(pdev), 500); @@ -1742,6 +1739,20 @@ int intel_gpu_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) */ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); for (retry = 0; retry < 3; retry++) { + + /* We stop engines, otherwise we might get failed reset and a + * dead gpu (on elk). Also as modern gpu as kbl can suffer + * from system hang if batchbuffer is progressing when + * the reset is issued, regardless of READY_TO_RESET ack. + * Thus assume it is best to stop engines on all gens + * where we have a gpu reset. + * + * WaMediaResetMainRingCleanup:ctg,elk (presumably) + * + * FIXME: Wa for more modern gens needs to be validated + */ + i915_stop_engines(dev_priv, engine_mask); + ret = reset(dev_priv, engine_mask); if (ret != -ETIMEDOUT) break; -- cgit v1.2.3 From 76a4b41d654c0eaaf3b4ebc65fc0728d205f028a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 20 Sep 2017 18:12:36 +0300 Subject: drm/i915: Drop useless HAS_PSR() check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is safe to call intel_psr_disable() on a platform without PSR. We don't have such a check when calling intel_psr_enable() either. v2: Don't drop the HAS_DDI check quite yet (Rodrigo) Reviewed-by: Rodrigo Vivi Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170920151236.5864-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8db6b11f103f..e536f5942d7f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2697,7 +2697,7 @@ static void intel_disable_dp(struct intel_encoder *encoder, if (old_crtc_state->has_audio) intel_audio_codec_disable(encoder); - if (HAS_PSR(dev_priv) && !HAS_DDI(dev_priv)) + if (!HAS_DDI(dev_priv)) intel_psr_disable(intel_dp, old_crtc_state); /* Make sure the panel is off before trying to change the mode. But also -- cgit v1.2.3 From 1a8ff6076e8f3e197831455e4bba8fa2f5f1d0f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 20 Sep 2017 18:12:51 +0300 Subject: drm/i915: Reorganize .disable hooks for pre-DDI DP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of our DP encoder hooks are split into per-platform variants. .disable() an exception, and thus it's a bit messy. Let's split it up as well. We'll leave the common parts in a helper called by each platform specific hook. Now each platform has mostly its own hooks. Some hooks are still shared between vlv and chv, and between g4x and ilk. None of the remaining shared hooks have any platform checks in them however so duplicating them doesn't seem particularly useful. There is a subtle change on VLV/CHV where we now disable PSR before audio, whereas before we disabled PSR after audio. That should be totally fine, and PSR is disabled by default anyway. Jani also pointed out to me that PSR + audio doesn't seem like a particularly realistic combination. v2: Drop the PSR HAS_DDI check here (Rodrigo) Pimp up the commit message a bit based on a chat with Jani Cc: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170920151251.5961-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_dp.c | 45 ++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e536f5942d7f..1e0bfbe6b4f3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2692,24 +2692,46 @@ static void intel_disable_dp(struct intel_encoder *encoder, const struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); if (old_crtc_state->has_audio) intel_audio_codec_disable(encoder); - if (!HAS_DDI(dev_priv)) - intel_psr_disable(intel_dp, old_crtc_state); - /* Make sure the panel is off before trying to change the mode. But also * ensure that we have vdd while we switch off the panel. */ intel_edp_panel_vdd_on(intel_dp); intel_edp_backlight_off(old_conn_state); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); intel_edp_panel_off(intel_dp); +} + +static void g4x_disable_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + + intel_disable_dp(encoder, old_crtc_state, old_conn_state); /* disable the port before the pipe on g4x */ - if (INTEL_GEN(dev_priv) < 5) - intel_dp_link_down(intel_dp); + intel_dp_link_down(intel_dp); +} + +static void ilk_disable_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + intel_disable_dp(encoder, old_crtc_state, old_conn_state); +} + +static void vlv_disable_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + + intel_psr_disable(intel_dp, old_crtc_state); + + intel_disable_dp(encoder, old_crtc_state, old_conn_state); } static void ilk_post_disable_dp(struct intel_encoder *encoder, @@ -6145,7 +6167,6 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, goto err_encoder_init; intel_encoder->compute_config = intel_dp_compute_config; - intel_encoder->disable = intel_disable_dp; intel_encoder->get_hw_state = intel_dp_get_hw_state; intel_encoder->get_config = intel_dp_get_config; intel_encoder->suspend = intel_dp_encoder_suspend; @@ -6153,18 +6174,24 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; intel_encoder->pre_enable = chv_pre_enable_dp; intel_encoder->enable = vlv_enable_dp; + intel_encoder->disable = vlv_disable_dp; intel_encoder->post_disable = chv_post_disable_dp; intel_encoder->post_pll_disable = chv_dp_post_pll_disable; } else if (IS_VALLEYVIEW(dev_priv)) { intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable; intel_encoder->pre_enable = vlv_pre_enable_dp; intel_encoder->enable = vlv_enable_dp; + intel_encoder->disable = vlv_disable_dp; intel_encoder->post_disable = vlv_post_disable_dp; + } else if (INTEL_GEN(dev_priv) >= 5) { + intel_encoder->pre_enable = g4x_pre_enable_dp; + intel_encoder->enable = g4x_enable_dp; + intel_encoder->disable = ilk_disable_dp; + intel_encoder->post_disable = ilk_post_disable_dp; } else { intel_encoder->pre_enable = g4x_pre_enable_dp; intel_encoder->enable = g4x_enable_dp; - if (INTEL_GEN(dev_priv) >= 5) - intel_encoder->post_disable = ilk_post_disable_dp; + intel_encoder->disable = g4x_disable_dp; } intel_dig_port->port = port; -- cgit v1.2.3 From 4babc5e27cfda59e2e257d28628b8d853aea5206 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 14 Sep 2017 17:21:54 +0100 Subject: drm/i915: remove redundant variable hw_check hw_check is being assigned and updated but is no longer being read, hence it is redundant and can be removed. Detected by clang scan-build: "warning: Value stored to 'hw_check' during its initialization is never read" Fixes: f6d1973db2d2 ("drm/i915: Move modeset state verifier calls") Signed-off-by: Colin Ian King Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20170914162154.11304-1-colin.king@canonical.com --- drivers/gpu/drm/i915/intel_display.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3bfcf187a0a1..2e407dc49c19 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12367,7 +12367,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; struct intel_crtc_state *intel_cstate; - bool hw_check = intel_state->modeset; u64 put_domains[I915_MAX_PIPES] = {}; unsigned crtc_vblank_mask = 0; int i; @@ -12384,7 +12383,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) if (needs_modeset(new_crtc_state) || to_intel_crtc_state(new_crtc_state)->update_pipe) { - hw_check = true; put_domains[to_intel_crtc(crtc)->pipe] = modeset_get_crtc_power_domains(crtc, -- cgit v1.2.3 From 74c1c694a2deab0561c1f502de9d32fdc7eb7b32 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Sep 2017 12:01:35 +0100 Subject: drm/i915: Document the split in internal and public execbuf flags Since we reuse the same field for the user passing in their control flags, and for the kernel to track a couple of bits of state, document and check that those do not overlap. Suggested-by: Tvrtko Ursulin Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170921110135.15990-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 214a850b4b3c..61b9b079c8c8 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -58,6 +58,7 @@ enum { #define __EXEC_HAS_RELOC BIT(31) #define __EXEC_VALIDATED BIT(30) +#define __EXEC_INTERNAL_FLAGS (~0u << 30) #define UPDATE PIN_OFFSET_FIXED #define BATCH_OFFSET_BIAS (256*1024) @@ -2185,6 +2186,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, int out_fence_fd = -1; int err; + BUILD_BUG_ON(__EXEC_INTERNAL_FLAGS & ~__I915_EXEC_ILLEGAL_FLAGS); BUILD_BUG_ON(__EXEC_OBJECT_INTERNAL_FLAGS & ~__EXEC_OBJECT_UNKNOWN_FLAGS); -- cgit v1.2.3 From 17b51ad8e5c051032d8e1d698e7dfd01d9133a92 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Sep 2017 17:27:33 +0100 Subject: drm/i915: Only wake the waiter from the interrupt if passed As we now check if the seqno is complete in order to signal the fence, we can also decide not to wake up the first_waiter until it is ready (since it is waiting on the same seqno). The only caveat is that if we need the engine->irq_seqno_barrier to enforce some coherency between an interrupt and the seqno read, we have to always wake the waiter in order to perform that heavyweight barrier. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170918162734.21294-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_irq.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c23efc4394ce..2190e42ba310 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1038,6 +1038,8 @@ static void notify_ring(struct intel_engine_cs *engine) spin_lock(&engine->breadcrumbs.irq_lock); wait = engine->breadcrumbs.irq_wait; if (wait) { + bool wakeup = engine->irq_seqno_barrier; + /* We use a callback from the dma-fence to submit * requests after waiting on our own requests. To * ensure minimum delay in queuing the next request to @@ -1050,12 +1052,15 @@ static void notify_ring(struct intel_engine_cs *engine) * and many waiters. */ if (i915_seqno_passed(intel_engine_get_seqno(engine), - wait->seqno) && - !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, - &wait->request->fence.flags)) - rq = i915_gem_request_get(wait->request); + wait->seqno)) { + wakeup = true; + if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, + &wait->request->fence.flags)) + rq = i915_gem_request_get(wait->request); + } - wake_up_process(wait->tsk); + if (wakeup) + wake_up_process(wait->tsk); } else { __intel_engine_disarm_breadcrumbs(engine); } -- cgit v1.2.3 From de4d2106f88ad7d98bf3adc602885d1d9071b644 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Sep 2017 17:27:34 +0100 Subject: drm/i915: Check waiter->seqno carefully in case of preemption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If preemption occurs at precisely the right moment, we may decide that the wait is complete even though the wait's request is no longer executing (having been preempted). We handle this situation by double checking that request following deciding whether the wait is complete. Reported-by: Michał Winiarski Signed-off-by: Chris Wilson Cc: Michał Winiarski Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170918162734.21294-2-chris@chris-wilson.co.uk Reviewed-by: Michał Winiarski --- drivers/gpu/drm/i915/i915_irq.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2190e42ba310..bd38c6983eec 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1053,10 +1053,13 @@ static void notify_ring(struct intel_engine_cs *engine) */ if (i915_seqno_passed(intel_engine_get_seqno(engine), wait->seqno)) { + struct drm_i915_gem_request *waiter = wait->request; + wakeup = true; if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, - &wait->request->fence.flags)) - rq = i915_gem_request_get(wait->request); + &waiter->fence.flags) && + intel_wait_check_request(wait, waiter)) + rq = i915_gem_request_get(waiter); } if (wakeup) -- cgit v1.2.3 From a3df2c857c103b1103c9d578d68193a6fbe63c61 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Sep 2017 22:09:03 +0100 Subject: drm/i915: Confirm request->global_seqno after spin completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After we see our target seqno has been completed by the hw, we need to confirm that it still matches the request (as it may have been preempted before the spin completes). If the request no longer matches the target seqno, we need to restart the wait to reacquire that seqno. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Michal Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20170921210903.18337-1-chris@chris-wilson.co.uk Reviewed-by: Michał Winiarski --- drivers/gpu/drm/i915/i915_gem_request.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 813a3b546d6e..289fb08acaf5 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -1040,12 +1040,9 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, irq = atomic_read(&engine->irq_count); timeout_us += local_clock_us(&cpu); do { - if (seqno != i915_gem_request_global_seqno(req)) - break; - if (i915_seqno_passed(intel_engine_get_seqno(req->engine), seqno)) - return true; + return seqno == i915_gem_request_global_seqno(req); /* Seqno are meant to be ordered *before* the interrupt. If * we see an interrupt without a corresponding seqno advance, -- cgit v1.2.3 From 4f044a88a86adb4c8cc6cb1a7303bb9c61ea2caa Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Tue, 19 Sep 2017 19:38:44 +0000 Subject: drm/i915: Rename global i915 to i915_modparams Our global struct with params is named exactly the same way as new preferred name for the drm_i915_private function parameter. To avoid such name reuse lets use different name for the global. v5: pure rename v6: fix Credits-to: Coccinelle @@ identifier n; @@ ( - i915.n + i915_modparams.n ) Signed-off-by: Michal Wajdeczko Cc: Jani Nikula Cc: Chris Wilson Cc: Tvrtko Ursulin Cc: Ville Syrjala Cc: Joonas Lahtinen Acked-by: Joonas Lahtinen Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170919193846.38060-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/gvt/render.c | 2 +- drivers/gpu/drm/i915/i915_debugfs.c | 14 ++++---- drivers/gpu/drm/i915/i915_drv.c | 34 ++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 10 +++--- drivers/gpu/drm/i915/i915_gem.c | 4 +-- drivers/gpu/drm/i915/i915_gem_context.c | 12 +++---- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++-- drivers/gpu/drm/i915/i915_gpu_error.c | 6 ++-- drivers/gpu/drm/i915/i915_guc_submission.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/i915_params.c | 6 ++-- drivers/gpu/drm/i915/i915_params.h | 2 +- drivers/gpu/drm/i915/i915_pci.c | 6 ++-- drivers/gpu/drm/i915/i915_perf.c | 6 ++-- drivers/gpu/drm/i915/intel_bios.c | 7 ++-- drivers/gpu/drm/i915/intel_crt.c | 4 +-- drivers/gpu/drm/i915/intel_device_info.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 12 +++---- drivers/gpu/drm/i915/intel_dp.c | 4 +-- drivers/gpu/drm/i915/intel_dp_aux_backlight.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_engine_cs.c | 4 +-- drivers/gpu/drm/i915/intel_fbc.c | 11 +++--- drivers/gpu/drm/i915/intel_guc_loader.c | 13 +++---- drivers/gpu/drm/i915/intel_guc_log.c | 26 +++++++------- drivers/gpu/drm/i915/intel_gvt.c | 12 +++---- drivers/gpu/drm/i915/intel_hangcheck.c | 2 +- drivers/gpu/drm/i915/intel_huc.c | 4 +-- drivers/gpu/drm/i915/intel_lrc.c | 4 +-- drivers/gpu/drm/i915/intel_lvds.c | 4 +-- drivers/gpu/drm/i915/intel_opregion.c | 2 +- drivers/gpu/drm/i915/intel_panel.c | 8 ++--- drivers/gpu/drm/i915/intel_pm.c | 6 ++-- drivers/gpu/drm/i915/intel_psr.c | 10 +++--- drivers/gpu/drm/i915/intel_ringbuffer.c | 8 ++--- drivers/gpu/drm/i915/intel_runtime_pm.c | 17 ++++----- drivers/gpu/drm/i915/intel_uc.c | 51 ++++++++++++++------------- drivers/gpu/drm/i915/intel_uncore.c | 22 ++++++------ 39 files changed, 182 insertions(+), 169 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index 2ea542257f03..6d066cf35478 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -293,7 +293,7 @@ static void switch_mmio_to_vgpu(struct intel_vgpu *vgpu, int ring_id) */ if (mmio->in_context && ((ctx_ctrl & inhibit_mask) != inhibit_mask) && - i915.enable_execlists) + i915_modparams.enable_execlists) continue; if (mmio->mask) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 2518bdf95eef..b08ebed4e700 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -66,7 +66,7 @@ static int i915_capabilities(struct seq_file *m, void *data) #undef PRINT_FLAG kernel_param_lock(THIS_MODULE); -#define PRINT_PARAM(T, x) seq_print_param(m, #x, #T, &i915.x); +#define PRINT_PARAM(T, x) seq_print_param(m, #x, #T, &i915_modparams.x); I915_PARAMS_FOR_EACH(PRINT_PARAM); #undef PRINT_PARAM kernel_param_unlock(THIS_MODULE); @@ -1266,7 +1266,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) if (waitqueue_active(&dev_priv->gpu_error.reset_queue)) seq_puts(m, "struct_mutex blocked for reset\n"); - if (!i915.enable_hangcheck) { + if (!i915_modparams.enable_hangcheck) { seq_puts(m, "Hangcheck disabled\n"); return 0; } @@ -1701,7 +1701,7 @@ static int i915_ips_status(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); seq_printf(m, "Enabled by kernel parameter: %s\n", - yesno(i915.enable_ips)); + yesno(i915_modparams.enable_ips)); if (INTEL_GEN(dev_priv) >= 8) { seq_puts(m, "Currently: unknown\n"); @@ -2016,7 +2016,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) enum intel_engine_id id; int ret; - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { seq_printf(m, "Logical Ring Contexts are disabled\n"); return 0; } @@ -2592,7 +2592,7 @@ static int i915_guc_log_control_get(void *data, u64 *val) if (!dev_priv->guc.log.vma) return -EINVAL; - *val = i915.guc_log_level; + *val = i915_modparams.guc_log_level; return 0; } @@ -3310,7 +3310,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) seq_printf(m, "\tBBADDR: 0x%08x_%08x\n", upper_32_bits(addr), lower_32_bits(addr)); - if (i915.enable_execlists) { + if (i915_modparams.enable_execlists) { const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX]; u32 ptr, read, write; unsigned int idx; @@ -3406,7 +3406,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) enum intel_engine_id id; int j, ret; - if (!i915.semaphores) { + if (!i915_modparams.semaphores) { seq_puts(m, "Semaphores are disabled\n"); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5c111ea96e80..7056bb299dc6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -58,12 +58,12 @@ static unsigned int i915_load_fail_count; bool __i915_inject_load_failure(const char *func, int line) { - if (i915_load_fail_count >= i915.inject_load_failure) + if (i915_load_fail_count >= i915_modparams.inject_load_failure) return false; - if (++i915_load_fail_count == i915.inject_load_failure) { + if (++i915_load_fail_count == i915_modparams.inject_load_failure) { DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n", - i915.inject_load_failure, func, line); + i915_modparams.inject_load_failure, func, line); return true; } @@ -106,8 +106,8 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, static bool i915_error_injected(struct drm_i915_private *dev_priv) { - return i915.inject_load_failure && - i915_load_fail_count == i915.inject_load_failure; + return i915_modparams.inject_load_failure && + i915_load_fail_count == i915_modparams.inject_load_failure; } #define i915_load_error(dev_priv, fmt, ...) \ @@ -321,7 +321,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = USES_PPGTT(dev_priv); break; case I915_PARAM_HAS_SEMAPHORES: - value = i915.semaphores; + value = i915_modparams.semaphores; break; case I915_PARAM_HAS_SECURE_BATCHES: value = capable(CAP_SYS_ADMIN); @@ -340,7 +340,8 @@ static int i915_getparam(struct drm_device *dev, void *data, return -ENODEV; break; case I915_PARAM_HAS_GPU_RESET: - value = i915.enable_hangcheck && intel_has_gpu_reset(dev_priv); + value = i915_modparams.enable_hangcheck && + intel_has_gpu_reset(dev_priv); if (value && intel_has_reset_engine(dev_priv)) value = 2; break; @@ -1031,9 +1032,9 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv) static void intel_sanitize_options(struct drm_i915_private *dev_priv) { - i915.enable_execlists = + i915_modparams.enable_execlists = intel_sanitize_enable_execlists(dev_priv, - i915.enable_execlists); + i915_modparams.enable_execlists); /* * i915.enable_ppgtt is read-only, so do an early pass to validate the @@ -1041,12 +1042,15 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) * do this now so that we can print out any log messages once rather * than every time we check intel_enable_ppgtt(). */ - i915.enable_ppgtt = - intel_sanitize_enable_ppgtt(dev_priv, i915.enable_ppgtt); - DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt); + i915_modparams.enable_ppgtt = + intel_sanitize_enable_ppgtt(dev_priv, + i915_modparams.enable_ppgtt); + DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915_modparams.enable_ppgtt); - i915.semaphores = intel_sanitize_semaphores(dev_priv, i915.semaphores); - DRM_DEBUG_DRIVER("use GPU semaphores? %s\n", yesno(i915.semaphores)); + i915_modparams.semaphores = + intel_sanitize_semaphores(dev_priv, i915_modparams.semaphores); + DRM_DEBUG_DRIVER("use GPU semaphores? %s\n", + yesno(i915_modparams.semaphores)); intel_uc_sanitize_options(dev_priv); @@ -1277,7 +1281,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) int ret; /* Enable nuclear pageflip on ILK+ */ - if (!i915.nuclear_pageflip && match_info->gen < 5) + if (!i915_modparams.nuclear_pageflip && match_info->gen < 5) driver.driver_features &= ~DRIVER_ATOMIC; ret = -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 08e3ae15b52e..d6babe7d362d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -93,7 +93,7 @@ #define I915_STATE_WARN(condition, format...) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ - if (!WARN(i915.verbose_state_checks, format)) \ + if (!WARN(i915_modparams.verbose_state_checks, format)) \ DRM_ERROR(format); \ unlikely(__ret_warn_on); \ }) @@ -3076,9 +3076,9 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_LOGICAL_RING_CONTEXTS(dev_priv) \ ((dev_priv)->info.has_logical_ring_contexts) -#define USES_PPGTT(dev_priv) (i915.enable_ppgtt) -#define USES_FULL_PPGTT(dev_priv) (i915.enable_ppgtt >= 2) -#define USES_FULL_48BIT_PPGTT(dev_priv) (i915.enable_ppgtt == 3) +#define USES_PPGTT(dev_priv) (i915_modparams.enable_ppgtt) +#define USES_FULL_PPGTT(dev_priv) (i915_modparams.enable_ppgtt >= 2) +#define USES_FULL_48BIT_PPGTT(dev_priv) (i915_modparams.enable_ppgtt == 3) #define HAS_OVERLAY(dev_priv) ((dev_priv)->info.has_overlay) #define OVERLAY_NEEDS_PHYSICAL(dev_priv) \ @@ -3279,7 +3279,7 @@ static inline void i915_queue_hangcheck(struct drm_i915_private *dev_priv) { unsigned long delay; - if (unlikely(!i915.enable_hangcheck)) + if (unlikely(!i915_modparams.enable_hangcheck)) return; /* Don't continually defer the hangcheck so that it is always run at diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b0bbf8729dae..12ce97d47afb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4738,7 +4738,7 @@ bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value) return false; /* TODO: make semaphores and Execlists play nicely together */ - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) return false; if (value >= 0) @@ -4759,7 +4759,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv) dev_priv->mm.unordered_timeline = dma_fence_context_alloc(1); - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { dev_priv->gt.resume = intel_legacy_submission_resume; dev_priv->gt.cleanup_engine = intel_engine_cleanup; } else { diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 58a2a44f88bd..921ee369c74d 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -314,7 +314,7 @@ __create_hw_context(struct drm_i915_private *dev_priv, * present or not in use we still need a small bias as ring wraparound * at offset 0 sometimes hangs. No idea why. */ - if (HAS_GUC(dev_priv) && i915.enable_guc_loading) + if (HAS_GUC(dev_priv) && i915_modparams.enable_guc_loading) ctx->ggtt_offset_bias = GUC_WOPCM_TOP; else ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE; @@ -407,7 +407,7 @@ i915_gem_context_create_gvt(struct drm_device *dev) i915_gem_context_set_closed(ctx); /* not user accessible */ i915_gem_context_clear_bannable(ctx); i915_gem_context_set_force_single_submission(ctx); - if (!i915.enable_guc_submission) + if (!i915_modparams.enable_guc_submission) ctx->ring_size = 512 * PAGE_SIZE; /* Max ring buffer size */ GEM_BUG_ON(i915_gem_context_is_kernel(ctx)); @@ -431,7 +431,7 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) if (intel_vgpu_active(dev_priv) && HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { DRM_INFO("Only EXECLIST mode is supported in vgpu.\n"); return -EINVAL; } @@ -483,7 +483,7 @@ void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) } /* Force the GPU state to be restored on enabling */ - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { struct i915_gem_context *ctx; list_for_each_entry(ctx, &dev_priv->contexts.list, link) { @@ -568,7 +568,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 flags) enum intel_engine_id id; const int num_rings = /* Use an extended w/a on gen7 if signalling from other rings */ - (i915.semaphores && INTEL_GEN(dev_priv) == 7) ? + (i915_modparams.semaphores && INTEL_GEN(dev_priv) == 7) ? INTEL_INFO(dev_priv)->num_rings - 1 : 0; int len; @@ -837,7 +837,7 @@ int i915_switch_context(struct drm_i915_gem_request *req) struct intel_engine_cs *engine = req->engine; lockdep_assert_held(&req->i915->drm.struct_mutex); - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) return 0; if (!req->ctx->engine[engine->id].state) { diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 61b9b079c8c8..fa18677cdb54 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1585,7 +1585,7 @@ static int eb_prefault_relocations(const struct i915_execbuffer *eb) const unsigned int count = eb->buffer_count; unsigned int i; - if (unlikely(i915.prefault_disable)) + if (unlikely(i915_modparams.prefault_disable)) return 0; for (i = 0; i < count; i++) { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 37cd0860fc29..ecb5e8cd37ba 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -180,7 +180,7 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, return 0; } - if (INTEL_GEN(dev_priv) >= 8 && i915.enable_execlists) { + if (INTEL_GEN(dev_priv) >= 8 && i915_modparams.enable_execlists) { if (has_full_48bit_ppgtt) return 3; @@ -1972,7 +1972,7 @@ int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv) /* In the case of execlists, PPGTT is enabled by the context descriptor * and the PDPs are contained within the context itself. We don't * need to do anything here. */ - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) return 0; if (!USES_PPGTT(dev_priv)) @@ -3292,7 +3292,7 @@ int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv) * currently don't have any bits spare to pass in this upper * restriction! */ - if (HAS_GUC(dev_priv) && i915.enable_guc_loading) { + if (HAS_GUC(dev_priv) && i915_modparams.enable_guc_loading) { ggtt->base.total = min_t(u64, ggtt->base.total, GUC_GGTT_TOP); ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total); } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index ed5a1eb839ad..6cd5eba643e8 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1554,7 +1554,7 @@ static void i915_gem_capture_guc_log_buffer(struct drm_i915_private *dev_priv, struct i915_gpu_state *error) { /* Capturing log buf contents won't be useful if logging was disabled */ - if (!dev_priv->guc.log.vma || (i915.guc_log_level < 0)) + if (!dev_priv->guc.log.vma || (i915_modparams.guc_log_level < 0)) return; error->guc_log = i915_error_object_create(dev_priv, @@ -1696,7 +1696,7 @@ static int capture(void *data) ktime_to_timeval(ktime_sub(ktime_get(), error->i915->gt.last_init_time)); - error->params = i915; + error->params = i915_modparams; #define DUP(T, x) dup_param(#T, &error->params.x); I915_PARAMS_FOR_EACH(DUP); #undef DUP @@ -1751,7 +1751,7 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, struct i915_gpu_state *error; unsigned long flags; - if (!i915.error_capture) + if (!i915_modparams.error_capture) return; if (READ_ONCE(dev_priv->gpu_error.first_error)) diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index e191d56fc990..06a26c610806 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1245,7 +1245,7 @@ int intel_guc_resume(struct drm_i915_private *dev_priv) if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) return 0; - if (i915.guc_log_level >= 0) + if (i915_modparams.guc_log_level >= 0) gen9_enable_guc_interrupts(dev_priv); ctx = dev_priv->kernel_context; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index bd38c6983eec..b1bab7605db9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1357,7 +1357,7 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) { notify_ring(engine); - tasklet |= i915.enable_guc_submission; + tasklet |= i915_modparams.enable_guc_submission; } if (tasklet) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index ddda513cc7f4..ec6534180d54 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -26,13 +26,13 @@ #include "i915_drv.h" #define i915_param_named(name, T, perm, desc) \ - module_param_named(name, i915.name, T, perm); \ + module_param_named(name, i915_modparams.name, T, perm); \ MODULE_PARM_DESC(name, desc) #define i915_param_named_unsafe(name, T, perm, desc) \ - module_param_named_unsafe(name, i915.name, T, perm); \ + module_param_named_unsafe(name, i915_modparams.name, T, perm); \ MODULE_PARM_DESC(name, desc) -struct i915_params i915 __read_mostly = { +struct i915_params i915_modparams __read_mostly = { .modeset = -1, .panel_ignore_lid = 1, .semaphores = -1, diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index ac844709c97e..a2cbb4782fcd 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -76,7 +76,7 @@ struct i915_params { }; #undef MEMBER -extern struct i915_params i915 __read_mostly; +extern struct i915_params i915_modparams __read_mostly; #endif diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index ce2c08eb9890..da60866b6628 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -631,7 +631,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (struct intel_device_info *) ent->driver_data; int err; - if (IS_ALPHA_SUPPORT(intel_info) && !i915.alpha_support) { + if (IS_ALPHA_SUPPORT(intel_info) && !i915_modparams.alpha_support) { DRM_INFO("The driver support for your hardware in this kernel version is alpha quality\n" "See CONFIG_DRM_I915_ALPHA_SUPPORT or i915.alpha_support module parameter\n" "to enable support in this kernel version, or check for kernel updates.\n"); @@ -689,10 +689,10 @@ static int __init i915_init(void) * vga_text_mode_force boot option. */ - if (i915.modeset == 0) + if (i915_modparams.modeset == 0) use_kms = false; - if (vgacon_text_force() && i915.modeset == -1) + if (vgacon_text_force() && i915_modparams.modeset == -1) use_kms = false; if (!use_kms) { diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 902722ab84c9..1383a2995a69 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1214,7 +1214,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream) { struct drm_i915_private *dev_priv = stream->dev_priv; - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) dev_priv->perf.oa.specific_ctx_id = stream->ctx->hw_id; else { struct intel_engine_cs *engine = dev_priv->engine[RCS]; @@ -1260,7 +1260,7 @@ static void oa_put_render_ctx_id(struct i915_perf_stream *stream) { struct drm_i915_private *dev_priv = stream->dev_priv; - if (i915.enable_execlists) { + if (i915_modparams.enable_execlists) { dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; } else { struct intel_engine_cs *engine = dev_priv->engine[RCS]; @@ -3408,7 +3408,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv) dev_priv->perf.oa.timestamp_frequency = 12500000; dev_priv->perf.oa.oa_formats = hsw_oa_formats; - } else if (i915.enable_execlists) { + } else if (i915_modparams.enable_execlists) { /* Note: that although we could theoretically also support the * legacy ringbuffer mode on BDW (and earlier iterations of * this driver, before upstreaming did this) it didn't seem diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 5949750a35ee..8526da90168c 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -356,7 +356,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, struct drm_display_mode *panel_fixed_mode; int index; - index = i915.vbt_sdvo_panel_type; + index = i915_modparams.vbt_sdvo_panel_type; if (index == -2) { DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n"); return; @@ -675,8 +675,9 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) uint8_t vswing; /* Don't read from VBT if module parameter has valid value*/ - if (i915.edp_vswing) { - dev_priv->vbt.edp.low_vswing = i915.edp_vswing == 1; + if (i915_modparams.edp_vswing) { + dev_priv->vbt.edp.low_vswing = + i915_modparams.edp_vswing == 1; } else { vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF; dev_priv->vbt.edp.low_vswing = vswing == 0; diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index a77dd80a97f2..954070255b4d 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -712,7 +712,7 @@ intel_crt_detect(struct drm_connector *connector, * broken monitor (without edid) to work behind a broken kvm (that fails * to have the right resistors for HP detection) needs to fix this up. * For now just bail out. */ - if (I915_HAS_HOTPLUG(dev_priv) && !i915.load_detect_test) { + if (I915_HAS_HOTPLUG(dev_priv) && !i915_modparams.load_detect_test) { status = connector_status_disconnected; goto out; } @@ -730,7 +730,7 @@ intel_crt_detect(struct drm_connector *connector, else if (INTEL_GEN(dev_priv) < 4) status = intel_crt_load_detect(crt, to_intel_crtc(connector->state->crtc)->pipe); - else if (i915.load_detect_test) + else if (i915_modparams.load_detect_test) status = connector_status_disconnected; else status = connector_status_unknown; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 43831b09b47a..fdf9b54b71e9 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -343,7 +343,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) info->num_sprites[pipe] = 1; } - if (i915.disable_display) { + if (i915_modparams.disable_display) { DRM_INFO("Display disabled (module parameter)\n"); info->num_pipes = 0; } else if (info->num_pipes > 0 && diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2e407dc49c19..8a185971798b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3701,7 +3701,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv) /* reset doesn't touch the display */ - if (!i915.force_reset_modeset_test && + if (!i915_modparams.force_reset_modeset_test && !gpu_reset_clobbers_display(dev_priv)) return; @@ -3757,7 +3757,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) int ret; /* reset doesn't touch the display */ - if (!i915.force_reset_modeset_test && + if (!i915_modparams.force_reset_modeset_test && !gpu_reset_clobbers_display(dev_priv)) return; @@ -6313,7 +6313,7 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - pipe_config->ips_enabled = i915.enable_ips && + pipe_config->ips_enabled = i915_modparams.enable_ips && hsw_crtc_supports_ips(crtc) && pipe_config_supports_ips(dev_priv, pipe_config); } @@ -6494,8 +6494,8 @@ intel_link_compute_m_n(int bits_per_pixel, int nlanes, static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) { - if (i915.panel_use_ssc >= 0) - return i915.panel_use_ssc != 0; + if (i915_modparams.panel_use_ssc >= 0) + return i915_modparams.panel_use_ssc != 0; return dev_priv->vbt.lvds_use_ssc && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); } @@ -12084,7 +12084,7 @@ static int intel_atomic_check(struct drm_device *dev, return ret; } - if (i915.fastboot && + if (i915_modparams.fastboot && intel_pipe_config_compare(dev_priv, to_intel_crtc_state(old_crtc_state), pipe_config, true)) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1e0bfbe6b4f3..48ed6c1b5a76 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3848,7 +3848,7 @@ intel_dp_can_mst(struct intel_dp *intel_dp) { u8 mstm_cap; - if (!i915.enable_dp_mst) + if (!i915_modparams.enable_dp_mst) return false; if (!intel_dp->can_mst) @@ -3866,7 +3866,7 @@ intel_dp_can_mst(struct intel_dp *intel_dp) static void intel_dp_configure_mst(struct intel_dp *intel_dp) { - if (!i915.enable_dp_mst) + if (!i915_modparams.enable_dp_mst) return; if (!intel_dp->can_mst) diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c index d2830ba3162e..2bb2ceb9d463 100644 --- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c @@ -264,7 +264,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) { struct intel_panel *panel = &intel_connector->panel; - if (!i915.enable_dpcd_backlight) + if (!i915_modparams.enable_dpcd_backlight) return -ENODEV; if (!intel_dp_aux_display_control_capable(intel_connector)) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 307807672896..64358d2f2422 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1902,7 +1902,7 @@ void intel_init_ipc(struct drm_i915_private *dev_priv); void intel_enable_ipc(struct drm_i915_private *dev_priv); static inline int intel_enable_rc6(void) { - return i915.enable_rc6; + return i915_modparams.enable_rc6; } /* intel_sdvo.c */ diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 3d135c3cd380..d755a2ae4223 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -153,7 +153,7 @@ __intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) case 9: return GEN9_LR_CONTEXT_RENDER_SIZE; case 8: - return i915.enable_execlists ? + return i915_modparams.enable_execlists ? GEN8_LR_CONTEXT_RENDER_SIZE : GEN8_CXT_TOTAL_SIZE; case 7: @@ -301,7 +301,7 @@ int intel_engines_init(struct drm_i915_private *dev_priv) &intel_engine_classes[engine->class]; int (*init)(struct intel_engine_cs *engine); - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) init = class_info->init_execlists; else init = class_info->init_legacy; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 58a772de6672..8e3a05505f49 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -859,7 +859,7 @@ static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv) return false; } - if (!i915.enable_fbc) { + if (!i915_modparams.enable_fbc) { fbc->no_fbc_reason = "disabled per module param or by default"; return false; } @@ -1310,8 +1310,8 @@ void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv) */ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) { - if (i915.enable_fbc >= 0) - return !!i915.enable_fbc; + if (i915_modparams.enable_fbc >= 0) + return !!i915_modparams.enable_fbc; if (!HAS_FBC(dev_priv)) return 0; @@ -1355,8 +1355,9 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) if (need_fbc_vtd_wa(dev_priv)) mkwrite_device_info(dev_priv)->has_fbc = false; - i915.enable_fbc = intel_sanitize_fbc_option(dev_priv); - DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", i915.enable_fbc); + i915_modparams.enable_fbc = intel_sanitize_fbc_option(dev_priv); + DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", + i915_modparams.enable_fbc); if (!HAS_FBC(dev_priv)) { fbc->no_fbc_reason = "unsupported by this chipset"; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 8b0ae7fce7f2..c9e25be4db40 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -131,14 +131,14 @@ static void guc_params_init(struct drm_i915_private *dev_priv) params[GUC_CTL_LOG_PARAMS] = guc->log.flags; - if (i915.guc_log_level >= 0) { + if (i915_modparams.guc_log_level >= 0) { params[GUC_CTL_DEBUG] = - i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT; + i915_modparams.guc_log_level << GUC_LOG_VERBOSITY_SHIFT; } else params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED; /* If GuC submission is enabled, set up additional parameters here */ - if (i915.enable_guc_submission) { + if (i915_modparams.enable_guc_submission) { u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool); u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16; @@ -368,7 +368,8 @@ int intel_guc_init_hw(struct intel_guc *guc) guc->fw.load_status = INTEL_UC_FIRMWARE_SUCCESS; DRM_INFO("GuC %s (firmware %s [version %u.%u])\n", - i915.enable_guc_submission ? "submission enabled" : "loaded", + i915_modparams.enable_guc_submission ? "submission enabled" : + "loaded", guc->fw.path, guc->fw.major_ver_found, guc->fw.minor_ver_found); @@ -390,8 +391,8 @@ int intel_guc_select_fw(struct intel_guc *guc) guc->fw.load_status = INTEL_UC_FIRMWARE_NONE; guc->fw.type = INTEL_UC_FW_TYPE_GUC; - if (i915.guc_firmware_path) { - guc->fw.path = i915.guc_firmware_path; + if (i915_modparams.guc_firmware_path) { + guc->fw.path = i915_modparams.guc_firmware_path; guc->fw.major_ver_wanted = 0; guc->fw.minor_ver_wanted = 0; } else if (IS_SKYLAKE(dev_priv)) { diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c index 16d3b8719cab..6571d96704ad 100644 --- a/drivers/gpu/drm/i915/intel_guc_log.c +++ b/drivers/gpu/drm/i915/intel_guc_log.c @@ -144,7 +144,7 @@ static int guc_log_relay_file_create(struct intel_guc *guc) struct dentry *log_dir; int ret; - if (i915.guc_log_level < 0) + if (i915_modparams.guc_log_level < 0) return 0; /* For now create the log file in /sys/kernel/debug/dri/0 dir */ @@ -480,7 +480,7 @@ err_runtime: guc_log_runtime_destroy(guc); err: /* logging will remain off */ - i915.guc_log_level = -1; + i915_modparams.guc_log_level = -1; return ret; } @@ -502,7 +502,8 @@ static void guc_flush_logs(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); - if (!i915.enable_guc_submission || (i915.guc_log_level < 0)) + if (!i915_modparams.enable_guc_submission || + (i915_modparams.guc_log_level < 0)) return; /* First disable the interrupts, will be renabled afterwards */ @@ -529,8 +530,8 @@ int intel_guc_log_create(struct intel_guc *guc) GEM_BUG_ON(guc->log.vma); - if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX) - i915.guc_log_level = GUC_LOG_VERBOSITY_MAX; + if (i915_modparams.guc_log_level > GUC_LOG_VERBOSITY_MAX) + i915_modparams.guc_log_level = GUC_LOG_VERBOSITY_MAX; /* The first page is to save log buffer state. Allocate one * extra page for others in case for overlap */ @@ -555,7 +556,7 @@ int intel_guc_log_create(struct intel_guc *guc) guc->log.vma = vma; - if (i915.guc_log_level >= 0) { + if (i915_modparams.guc_log_level >= 0) { ret = guc_log_runtime_create(guc); if (ret < 0) goto err_vma; @@ -576,7 +577,7 @@ err_vma: i915_vma_unpin_and_release(&guc->log.vma); err: /* logging will be off */ - i915.guc_log_level = -1; + i915_modparams.guc_log_level = -1; return ret; } @@ -600,7 +601,7 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) return -EINVAL; /* This combination doesn't make sense & won't have any effect */ - if (!log_param.logging_enabled && (i915.guc_log_level < 0)) + if (!log_param.logging_enabled && (i915_modparams.guc_log_level < 0)) return 0; ret = guc_log_control(guc, log_param.value); @@ -610,7 +611,7 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) } if (log_param.logging_enabled) { - i915.guc_log_level = log_param.verbosity; + i915_modparams.guc_log_level = log_param.verbosity; /* If log_level was set as -1 at boot time, then the relay channel file * wouldn't have been created by now and interrupts also would not have @@ -633,7 +634,7 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) guc_flush_logs(guc); /* As logging is disabled, update log level to reflect that */ - i915.guc_log_level = -1; + i915_modparams.guc_log_level = -1; } return ret; @@ -641,7 +642,8 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) void i915_guc_log_register(struct drm_i915_private *dev_priv) { - if (!i915.enable_guc_submission || i915.guc_log_level < 0) + if (!i915_modparams.enable_guc_submission || + (i915_modparams.guc_log_level < 0)) return; mutex_lock(&dev_priv->drm.struct_mutex); @@ -651,7 +653,7 @@ void i915_guc_log_register(struct drm_i915_private *dev_priv) void i915_guc_log_unregister(struct drm_i915_private *dev_priv) { - if (!i915.enable_guc_submission) + if (!i915_modparams.enable_guc_submission) return; mutex_lock(&dev_priv->drm.struct_mutex); diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index c17ed0e62b67..b4a7f31f0214 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -58,7 +58,7 @@ static bool is_supported_device(struct drm_i915_private *dev_priv) */ void intel_gvt_sanitize_options(struct drm_i915_private *dev_priv) { - if (!i915.enable_gvt) + if (!i915_modparams.enable_gvt) return; if (intel_vgpu_active(dev_priv)) { @@ -73,7 +73,7 @@ void intel_gvt_sanitize_options(struct drm_i915_private *dev_priv) return; bail: - i915.enable_gvt = 0; + i915_modparams.enable_gvt = 0; } /** @@ -90,17 +90,17 @@ int intel_gvt_init(struct drm_i915_private *dev_priv) { int ret; - if (!i915.enable_gvt) { + if (!i915_modparams.enable_gvt) { DRM_DEBUG_DRIVER("GVT-g is disabled by kernel params\n"); return 0; } - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { DRM_ERROR("i915 GVT-g loading failed due to disabled execlists mode\n"); return -EIO; } - if (i915.enable_guc_submission) { + if (i915_modparams.enable_guc_submission) { DRM_ERROR("i915 GVT-g loading failed due to Graphics virtualization is not yet supported with GuC submission\n"); return -EIO; } @@ -123,7 +123,7 @@ int intel_gvt_init(struct drm_i915_private *dev_priv) return 0; bail: - i915.enable_gvt = 0; + i915_modparams.enable_gvt = 0; return 0; } diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index d9d87d96fb69..12ac270a5f93 100644 --- a/drivers/gpu/drm/i915/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/intel_hangcheck.c @@ -428,7 +428,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) unsigned int hung = 0, stuck = 0; int busy_count = 0; - if (!i915.enable_hangcheck) + if (!i915_modparams.enable_hangcheck) return; if (!READ_ONCE(dev_priv->gt.awake)) diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 6145fa0d6773..6e1779ba87a9 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c @@ -155,8 +155,8 @@ void intel_huc_select_fw(struct intel_huc *huc) huc->fw.load_status = INTEL_UC_FIRMWARE_NONE; huc->fw.type = INTEL_UC_FW_TYPE_HUC; - if (i915.huc_firmware_path) { - huc->fw.path = i915.huc_firmware_path; + if (i915_modparams.huc_firmware_path) { + huc->fw.path = i915_modparams.huc_firmware_path; huc->fw.major_ver_wanted = 0; huc->fw.minor_ver_wanted = 0; } else if (IS_SKYLAKE(dev_priv)) { diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 86fed9f1f1ae..955c87999280 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -244,7 +244,7 @@ int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv, int enabl if (HAS_LOGICAL_RING_CONTEXTS(dev_priv) && USES_PPGTT(dev_priv) && - i915.use_mmio_flip >= 0) + i915_modparams.use_mmio_flip >= 0) return 1; return 0; @@ -1324,7 +1324,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) engine->csb_head = -1; /* After a GPU reset, we may have requests to replay */ - if (!i915.enable_guc_submission && engine->execlist_first) + if (!i915_modparams.enable_guc_submission && engine->execlist_first) tasklet_schedule(&engine->irq_tasklet); return 0; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index a9813aea89d8..a55954a89148 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -880,8 +880,8 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) struct drm_i915_private *dev_priv = to_i915(dev); /* use the module option value if specified */ - if (i915.lvds_channel_mode > 0) - return i915.lvds_channel_mode == 2; + if (i915_modparams.lvds_channel_mode > 0) + return i915_modparams.lvds_channel_mode == 2; /* single channel LVDS is limited to 112 MHz */ if (lvds_encoder->attached_connector->base.panel.fixed_mode->clock diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 98154efcb2f4..1d946240e55f 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -921,7 +921,7 @@ static int intel_load_vbt_firmware(struct drm_i915_private *dev_priv) { struct intel_opregion *opregion = &dev_priv->opregion; const struct firmware *fw = NULL; - const char *name = i915.vbt_firmware; + const char *name = i915_modparams.vbt_firmware; int ret; if (!name || !*name) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 3b1c5d783ee7..adc51e452e3e 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -379,13 +379,13 @@ enum drm_connector_status intel_panel_detect(struct drm_i915_private *dev_priv) { /* Assume that the BIOS does not lie through the OpRegion... */ - if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) { + if (!i915_modparams.panel_ignore_lid && dev_priv->opregion.lid_state) { return *dev_priv->opregion.lid_state & 0x1 ? connector_status_connected : connector_status_disconnected; } - switch (i915.panel_ignore_lid) { + switch (i915_modparams.panel_ignore_lid) { case -2: return connector_status_connected; case -1: @@ -465,10 +465,10 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector, WARN_ON(panel->backlight.max == 0); - if (i915.invert_brightness < 0) + if (i915_modparams.invert_brightness < 0) return val; - if (i915.invert_brightness > 0 || + if (i915_modparams.invert_brightness > 0 || dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { return panel->backlight.max - val + panel->backlight.min; } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index adfeb7bb8874..c66af09e27a7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7825,7 +7825,7 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv) * RPM depends on RC6 to save restore the GT HW context, so make RC6 a * requirement. */ - if (!i915.enable_rc6) { + if (!i915_modparams.enable_rc6) { DRM_INFO("RC6 disabled, disabling runtime PM support\n"); intel_runtime_pm_get(dev_priv); } @@ -7882,7 +7882,7 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv)) valleyview_cleanup_gt_powersave(dev_priv); - if (!i915.enable_rc6) + if (!i915_modparams.enable_rc6) intel_runtime_pm_put(dev_priv); } @@ -8004,7 +8004,7 @@ static void __intel_autoenable_gt_powersave(struct work_struct *work) if (IS_ERR(req)) goto unlock; - if (!i915.enable_execlists && i915_switch_context(req) == 0) + if (!i915_modparams.enable_execlists && i915_switch_context(req) == 0) rcs->init_context(req); /* Mark the device busy, calling intel_enable_gt_powersave() */ diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index acb50945bfa8..0a17d1f3ca77 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -396,7 +396,7 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) return false; } - if (!i915.enable_psr) { + if (!i915_modparams.enable_psr) { DRM_DEBUG_KMS("PSR disable by flag\n"); return false; } @@ -943,8 +943,8 @@ void intel_psr_init(struct drm_i915_private *dev_priv) HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE; /* Per platform default: all disabled. */ - if (i915.enable_psr == -1) - i915.enable_psr = 0; + if (i915_modparams.enable_psr == -1) + i915_modparams.enable_psr = 0; /* Set link_standby x link_off defaults */ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) @@ -958,11 +958,11 @@ void intel_psr_init(struct drm_i915_private *dev_priv) dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link; /* Override link_standby x link_off defaults */ - if (i915.enable_psr == 2 && !dev_priv->psr.link_standby) { + if (i915_modparams.enable_psr == 2 && !dev_priv->psr.link_standby) { DRM_DEBUG_KMS("PSR: Forcing link standby\n"); dev_priv->psr.link_standby = true; } - if (i915.enable_psr == 3 && dev_priv->psr.link_standby) { + if (i915_modparams.enable_psr == 3 && dev_priv->psr.link_standby) { DRM_DEBUG_KMS("PSR: Forcing main link off\n"); dev_priv->psr.link_standby = false; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 85e64a45d0bf..05c08b0bc172 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1882,7 +1882,7 @@ static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, struct drm_i915_gem_object *obj; int ret, i; - if (!i915.semaphores) + if (!i915_modparams.semaphores) return; if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) { @@ -1982,7 +1982,7 @@ err_obj: i915_gem_object_put(obj); err: DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n"); - i915.semaphores = 0; + i915_modparams.semaphores = 0; } static void intel_ring_init_irq(struct drm_i915_private *dev_priv, @@ -2039,7 +2039,7 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, engine->emit_breadcrumb = i9xx_emit_breadcrumb; engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz; - if (i915.semaphores) { + if (i915_modparams.semaphores) { int num_rings; engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; @@ -2083,7 +2083,7 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) engine->emit_breadcrumb = gen8_render_emit_breadcrumb; engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz; engine->emit_flush = gen8_render_ring_flush; - if (i915.semaphores) { + if (i915_modparams.semaphores) { int num_rings; engine->semaphore.signal = gen8_rcs_signal; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index a3bfb9f27e7a..7933d1bc6a1c 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2413,7 +2413,7 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv, mask = 0; } - if (!i915.disable_power_well) + if (!i915_modparams.disable_power_well) max_dc = 0; if (enable_dc >= 0 && enable_dc <= max_dc) { @@ -2471,10 +2471,11 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) { struct i915_power_domains *power_domains = &dev_priv->power_domains; - i915.disable_power_well = sanitize_disable_power_well_option(dev_priv, - i915.disable_power_well); - dev_priv->csr.allowed_dc_mask = get_allowed_dc_mask(dev_priv, - i915.enable_dc); + i915_modparams.disable_power_well = + sanitize_disable_power_well_option(dev_priv, + i915_modparams.disable_power_well); + dev_priv->csr.allowed_dc_mask = + get_allowed_dc_mask(dev_priv, i915_modparams.enable_dc); BUILD_BUG_ON(POWER_DOMAIN_NUM > 64); @@ -2535,7 +2536,7 @@ void intel_power_domains_fini(struct drm_i915_private *dev_priv) intel_display_set_init_power(dev_priv, true); /* Remove the refcount we took to keep power well support disabled. */ - if (!i915.disable_power_well) + if (!i915_modparams.disable_power_well) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); /* @@ -2995,7 +2996,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) /* For now, we need the power well to be always enabled. */ intel_display_set_init_power(dev_priv, true); /* Disable power support if the user asked so. */ - if (!i915.disable_power_well) + if (!i915_modparams.disable_power_well) intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); intel_power_domains_sync_hw(dev_priv); power_domains->initializing = false; @@ -3014,7 +3015,7 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv) * Even if power well support was disabled we still want to disable * power wells while we are system suspended. */ - if (!i915.disable_power_well) + if (!i915_modparams.disable_power_well) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); if (IS_CANNONLAKE(dev_priv)) diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 0178ba42a0e5..901854007664 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c @@ -63,35 +63,35 @@ static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv) void intel_uc_sanitize_options(struct drm_i915_private *dev_priv) { if (!HAS_GUC(dev_priv)) { - if (i915.enable_guc_loading > 0 || - i915.enable_guc_submission > 0) + if (i915_modparams.enable_guc_loading > 0 || + i915_modparams.enable_guc_submission > 0) DRM_INFO("Ignoring GuC options, no hardware\n"); - i915.enable_guc_loading = 0; - i915.enable_guc_submission = 0; + i915_modparams.enable_guc_loading = 0; + i915_modparams.enable_guc_submission = 0; return; } /* A negative value means "use platform default" */ - if (i915.enable_guc_loading < 0) - i915.enable_guc_loading = HAS_GUC_UCODE(dev_priv); + if (i915_modparams.enable_guc_loading < 0) + i915_modparams.enable_guc_loading = HAS_GUC_UCODE(dev_priv); /* Verify firmware version */ - if (i915.enable_guc_loading) { + if (i915_modparams.enable_guc_loading) { if (HAS_HUC_UCODE(dev_priv)) intel_huc_select_fw(&dev_priv->huc); if (intel_guc_select_fw(&dev_priv->guc)) - i915.enable_guc_loading = 0; + i915_modparams.enable_guc_loading = 0; } /* Can't enable guc submission without guc loaded */ - if (!i915.enable_guc_loading) - i915.enable_guc_submission = 0; + if (!i915_modparams.enable_guc_loading) + i915_modparams.enable_guc_submission = 0; /* A negative value means "use platform default" */ - if (i915.enable_guc_submission < 0) - i915.enable_guc_submission = HAS_GUC_SCHED(dev_priv); + if (i915_modparams.enable_guc_submission < 0) + i915_modparams.enable_guc_submission = HAS_GUC_SCHED(dev_priv); } static void gen8_guc_raise_irq(struct intel_guc *guc) @@ -290,7 +290,7 @@ static void guc_init_send_regs(struct intel_guc *guc) static void guc_capture_load_err_log(struct intel_guc *guc) { - if (!guc->log.vma || i915.guc_log_level < 0) + if (!guc->log.vma || i915_modparams.guc_log_level < 0) return; if (!guc->load_err_log) @@ -333,7 +333,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) struct intel_guc *guc = &dev_priv->guc; int ret, attempts; - if (!i915.enable_guc_loading) + if (!i915_modparams.enable_guc_loading) return 0; guc_disable_communication(guc); @@ -342,7 +342,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) /* We need to notify the guc whenever we change the GGTT */ i915_ggtt_enable_guc(dev_priv); - if (i915.enable_guc_submission) { + if (i915_modparams.enable_guc_submission) { /* * This is stuff we need to have available at fw load time * if we are planning to enable submission later @@ -391,8 +391,8 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) goto err_log_capture; intel_guc_auth_huc(dev_priv); - if (i915.enable_guc_submission) { - if (i915.guc_log_level >= 0) + if (i915_modparams.enable_guc_submission) { + if (i915_modparams.guc_log_level >= 0) gen9_enable_guc_interrupts(dev_priv); ret = i915_guc_submission_enable(dev_priv); @@ -417,23 +417,24 @@ err_interrupts: err_log_capture: guc_capture_load_err_log(guc); err_submission: - if (i915.enable_guc_submission) + if (i915_modparams.enable_guc_submission) i915_guc_submission_fini(dev_priv); err_guc: i915_ggtt_disable_guc(dev_priv); DRM_ERROR("GuC init failed\n"); - if (i915.enable_guc_loading > 1 || i915.enable_guc_submission > 1) + if (i915_modparams.enable_guc_loading > 1 || + i915_modparams.enable_guc_submission > 1) ret = -EIO; else ret = 0; - if (i915.enable_guc_submission) { - i915.enable_guc_submission = 0; + if (i915_modparams.enable_guc_submission) { + i915_modparams.enable_guc_submission = 0; DRM_NOTE("Falling back from GuC submission to execlist mode\n"); } - i915.enable_guc_loading = 0; + i915_modparams.enable_guc_loading = 0; DRM_NOTE("GuC firmware loading disabled\n"); return ret; @@ -443,15 +444,15 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv) { guc_free_load_err_log(&dev_priv->guc); - if (!i915.enable_guc_loading) + if (!i915_modparams.enable_guc_loading) return; - if (i915.enable_guc_submission) + if (i915_modparams.enable_guc_submission) i915_guc_submission_disable(dev_priv); guc_disable_communication(&dev_priv->guc); - if (i915.enable_guc_submission) { + if (i915_modparams.enable_guc_submission) { gen9_disable_guc_interrupts(dev_priv); i915_guc_submission_fini(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index fdd7f93acb4f..b3c3f94fc7e4 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -436,7 +436,8 @@ void intel_uncore_resume_early(struct drm_i915_private *dev_priv) void intel_uncore_sanitize(struct drm_i915_private *dev_priv) { - i915.enable_rc6 = sanitize_rc6_option(dev_priv, i915.enable_rc6); + i915_modparams.enable_rc6 = + sanitize_rc6_option(dev_priv, i915_modparams.enable_rc6); /* BIOS often leaves RC6 enabled, but disable it for hw init */ intel_sanitize_gt_powersave(dev_priv); @@ -507,10 +508,10 @@ void intel_uncore_forcewake_user_get(struct drm_i915_private *dev_priv) dev_priv->uncore.user_forcewake.saved_mmio_check = dev_priv->uncore.unclaimed_mmio_check; dev_priv->uncore.user_forcewake.saved_mmio_debug = - i915.mmio_debug; + i915_modparams.mmio_debug; dev_priv->uncore.unclaimed_mmio_check = 0; - i915.mmio_debug = 0; + i915_modparams.mmio_debug = 0; } spin_unlock_irq(&dev_priv->uncore.lock); } @@ -532,7 +533,7 @@ void intel_uncore_forcewake_user_put(struct drm_i915_private *dev_priv) dev_priv->uncore.unclaimed_mmio_check = dev_priv->uncore.user_forcewake.saved_mmio_check; - i915.mmio_debug = + i915_modparams.mmio_debug = dev_priv->uncore.user_forcewake.saved_mmio_debug; intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); @@ -841,7 +842,8 @@ __unclaimed_reg_debug(struct drm_i915_private *dev_priv, "Unclaimed %s register 0x%x\n", read ? "read from" : "write to", i915_mmio_reg_offset(reg))) - i915.mmio_debug--; /* Only report the first N failures */ + /* Only report the first N failures */ + i915_modparams.mmio_debug--; } static inline void @@ -850,7 +852,7 @@ unclaimed_reg_debug(struct drm_i915_private *dev_priv, const bool read, const bool before) { - if (likely(!i915.mmio_debug)) + if (likely(!i915_modparams.mmio_debug)) return; __unclaimed_reg_debug(dev_priv, reg, read, before); @@ -1703,7 +1705,7 @@ typedef int (*reset_func)(struct drm_i915_private *, unsigned engine_mask); static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv) { - if (!i915.reset) + if (!i915_modparams.reset) return NULL; if (INTEL_INFO(dev_priv)->gen >= 8) @@ -1777,7 +1779,7 @@ bool intel_has_reset_engine(struct drm_i915_private *dev_priv) { return (dev_priv->info.has_reset_engine && !dev_priv->guc.execbuf_client && - i915.reset >= 2); + i915_modparams.reset >= 2); } int intel_guc_reset(struct drm_i915_private *dev_priv) @@ -1802,7 +1804,7 @@ bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv) bool intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) { - if (unlikely(i915.mmio_debug || + if (unlikely(i915_modparams.mmio_debug || dev_priv->uncore.unclaimed_mmio_check <= 0)) return false; @@ -1810,7 +1812,7 @@ intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) DRM_DEBUG("Unclaimed register detected, " "enabling oneshot unclaimed register reporting. " "Please use i915.mmio_debug=N for more information.\n"); - i915.mmio_debug++; + i915_modparams.mmio_debug++; dev_priv->uncore.unclaimed_mmio_check--; return true; } -- cgit v1.2.3 From 7fd0b1a2593647aba4538196dd80314fd134877b Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Thu, 21 Sep 2017 16:19:49 -0700 Subject: drm/i915/cnl: Add Gen10 LRC size The total size of the context has decreased with the removal of the URB_ATOMIC section. BSpec indicates 16750 DWORDs (17 pages), plus one page for PPHWSP, and I'm throwing an extra page for precaution. Signed-off-by: Oscar Mateo Cc: Rodrigo Vivi Cc: Daniele Ceraolo Spurio Cc: Ben Widawsky Acked-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/1506035989-14295-1-git-send-email-oscar.mateo@intel.com --- drivers/gpu/drm/i915/intel_engine_cs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index d755a2ae4223..020e4c6c0192 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -39,6 +39,7 @@ #define GEN8_LR_CONTEXT_RENDER_SIZE (20 * PAGE_SIZE) #define GEN9_LR_CONTEXT_RENDER_SIZE (22 * PAGE_SIZE) +#define GEN10_LR_CONTEXT_RENDER_SIZE (19 * PAGE_SIZE) #define GEN8_LR_CONTEXT_OTHER_SIZE ( 2 * PAGE_SIZE) @@ -150,6 +151,7 @@ __intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) default: MISSING_CASE(INTEL_GEN(dev_priv)); case 10: + return GEN10_LR_CONTEXT_RENDER_SIZE; case 9: return GEN9_LR_CONTEXT_RENDER_SIZE; case 8: -- cgit v1.2.3 From b2f2f0fc69056a495391cab792394965973aabf8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 22 Sep 2017 13:03:33 +0100 Subject: drm/i915: Make i915_spin_request() static No users now outside of i915_wait_request(), so we can make it private to i915_gem_request.c, and assume the caller knows the seqno. In the process, also remove i915_gem_request_started() as that was only ever used by i915_spin_request(). Signed-off-by: Chris Wilson Cc: Michal Winiarski Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170922120333.25535-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem_request.c | 27 +++++++++++++++++++------ drivers/gpu/drm/i915/i915_gem_request.h | 35 --------------------------------- 2 files changed, 21 insertions(+), 41 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 289fb08acaf5..4eb1a76731b2 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -1021,12 +1021,28 @@ static bool busywait_stop(unsigned long timeout, unsigned int cpu) return this_cpu != cpu; } -bool __i915_spin_request(const struct drm_i915_gem_request *req, - u32 seqno, int state, unsigned long timeout_us) +static bool __i915_spin_request(const struct drm_i915_gem_request *req, + u32 seqno, int state, unsigned long timeout_us) { struct intel_engine_cs *engine = req->engine; unsigned int irq, cpu; + GEM_BUG_ON(!seqno); + + /* + * Only wait for the request if we know it is likely to complete. + * + * We don't track the timestamps around requests, nor the average + * request length, so we do not have a good indicator that this + * request will complete within the timeout. What we do know is the + * order in which requests are executed by the engine and so we can + * tell if the request has started. If the request hasn't started yet, + * it is a fair assumption that it will not complete within our + * relatively short timeout. + */ + if (!i915_seqno_passed(intel_engine_get_seqno(engine), seqno - 1)) + return false; + /* When waiting for high frequency requests, e.g. during synchronous * rendering split between the CPU and GPU, the finite amount of time * required to set up the irq and wait upon it limits the response @@ -1040,8 +1056,7 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, irq = atomic_read(&engine->irq_count); timeout_us += local_clock_us(&cpu); do { - if (i915_seqno_passed(intel_engine_get_seqno(req->engine), - seqno)) + if (i915_seqno_passed(intel_engine_get_seqno(engine), seqno)) return seqno == i915_gem_request_global_seqno(req); /* Seqno are meant to be ordered *before* the interrupt. If @@ -1153,7 +1168,7 @@ restart: GEM_BUG_ON(!i915_sw_fence_signaled(&req->submit)); /* Optimistic short spin before touching IRQs */ - if (i915_spin_request(req, state, 5)) + if (__i915_spin_request(req, wait.seqno, state, 5)) goto complete; set_current_state(state); @@ -1210,7 +1225,7 @@ wakeup: continue; /* Only spin if we know the GPU is processing this request */ - if (i915_spin_request(req, state, 2)) + if (__i915_spin_request(req, wait.seqno, state, 2)) break; if (!intel_wait_check_request(&wait, req)) { diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 49a4c8994ff0..96eb52471dad 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -312,26 +312,6 @@ static inline bool i915_seqno_passed(u32 seq1, u32 seq2) return (s32)(seq1 - seq2) >= 0; } -static inline bool -__i915_gem_request_started(const struct drm_i915_gem_request *req, u32 seqno) -{ - GEM_BUG_ON(!seqno); - return i915_seqno_passed(intel_engine_get_seqno(req->engine), - seqno - 1); -} - -static inline bool -i915_gem_request_started(const struct drm_i915_gem_request *req) -{ - u32 seqno; - - seqno = i915_gem_request_global_seqno(req); - if (!seqno) - return false; - - return __i915_gem_request_started(req, seqno); -} - static inline bool __i915_gem_request_completed(const struct drm_i915_gem_request *req, u32 seqno) { @@ -352,21 +332,6 @@ i915_gem_request_completed(const struct drm_i915_gem_request *req) return __i915_gem_request_completed(req, seqno); } -bool __i915_spin_request(const struct drm_i915_gem_request *request, - u32 seqno, int state, unsigned long timeout_us); -static inline bool i915_spin_request(const struct drm_i915_gem_request *request, - int state, unsigned long timeout_us) -{ - u32 seqno; - - seqno = i915_gem_request_global_seqno(request); - if (!seqno) - return 0; - - return (__i915_gem_request_started(request, seqno) && - __i915_spin_request(request, seqno, state, timeout_us)); -} - /* We treat requests as fences. This is not be to confused with our * "fence registers" but pipeline synchronisation objects ala GL_ARB_sync. * We use the fences to synchronize access from the CPU with activity on the -- cgit v1.2.3 From d27ffc1d00327c29b3aa97f941b42f0949f9e99f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 21 Sep 2017 17:19:20 +0300 Subject: drm/i915/bios: ignore HDMI on port A MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware state readout oopses after several warnings when trying to use HDMI on port A, if such a combination is configured in VBT. Filter the combo out already at the VBT parsing phase. v2: also ignore DVI (Ville) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102889 Cc: stable@vger.kernel.org Cc: Imre Deak Reviewed-by: Ville Syrjälä Tested-by: Daniel Drake Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170921141920.18172-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 8526da90168c..b881ce8596ee 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1163,6 +1163,13 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, is_hdmi = is_dvi && (child->device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; is_edp = is_dp && (child->device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); + if (port == PORT_A && is_dvi) { + DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n", + is_hdmi ? "/HDMI" : ""); + is_dvi = false; + is_hdmi = false; + } + info->supports_dvi = is_dvi; info->supports_hdmi = is_hdmi; info->supports_dp = is_dp; -- cgit v1.2.3 From b620e870218ebe75b8221c7596b46e36d8329c85 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 22 Sep 2017 15:43:03 +0300 Subject: drm/i915: Make own struct for execlist items MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Engine's execlist related items have been increasing to a point where a separate struct is warranted. Carve execlist specific items to a dedicated struct to add clarity. v2: add kerneldoc and fix whitespace (Joonas, Chris) v3: csb_mmio changes, rebase v4: s/\b(el|execlist)\b/execlists/ (Joonas) Suggested-by: Chris Wilson Cc: Chris Wilson Cc: Joonas Lahtinen Signed-off-by: Mika Kuoppala Acked-by: Joonas Lahtinen Reviewed-by: Michał Winiarski (v3) Reviewed-by: Chris Wilson (v3) Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170922124307.10914-1-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 8 +-- drivers/gpu/drm/i915/i915_gem.c | 6 +- drivers/gpu/drm/i915/i915_gpu_error.c | 4 +- drivers/gpu/drm/i915/i915_guc_submission.c | 31 +++++---- drivers/gpu/drm/i915/i915_irq.c | 5 +- drivers/gpu/drm/i915/intel_engine_cs.c | 12 ++-- drivers/gpu/drm/i915/intel_lrc.c | 100 +++++++++++++++-------------- drivers/gpu/drm/i915/intel_ringbuffer.h | 100 +++++++++++++++++++++++------ 8 files changed, 167 insertions(+), 99 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b08ebed4e700..87e06da55a69 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3323,7 +3323,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) read = GEN8_CSB_READ_PTR(ptr); write = GEN8_CSB_WRITE_PTR(ptr); seq_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n", - read, engine->csb_head, + read, engine->execlists.csb_head, write, intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)), yesno(test_bit(ENGINE_IRQ_EXECLIST, @@ -3345,10 +3345,10 @@ static int i915_engine_info(struct seq_file *m, void *unused) } rcu_read_lock(); - for (idx = 0; idx < ARRAY_SIZE(engine->execlist_port); idx++) { + for (idx = 0; idx < ARRAY_SIZE(engine->execlists.port); idx++) { unsigned int count; - rq = port_unpack(&engine->execlist_port[idx], + rq = port_unpack(&engine->execlists.port[idx], &count); if (rq) { seq_printf(m, "\t\tELSP[%d] count=%d, ", @@ -3362,7 +3362,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) rcu_read_unlock(); spin_lock_irq(&engine->timeline->lock); - for (rb = engine->execlist_first; rb; rb = rb_next(rb)){ + for (rb = engine->execlists.first; rb; rb = rb_next(rb)) { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 12ce97d47afb..49bf5ddfa7fd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2815,8 +2815,8 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine) * Turning off the engine->irq_tasklet until the reset is over * prevents the race. */ - tasklet_kill(&engine->irq_tasklet); - tasklet_disable(&engine->irq_tasklet); + tasklet_kill(&engine->execlists.irq_tasklet); + tasklet_disable(&engine->execlists.irq_tasklet); if (engine->irq_seqno_barrier) engine->irq_seqno_barrier(engine); @@ -2995,7 +2995,7 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) void i915_gem_reset_finish_engine(struct intel_engine_cs *engine) { - tasklet_enable(&engine->irq_tasklet); + tasklet_enable(&engine->execlists.irq_tasklet); kthread_unpark(engine->breadcrumbs.signaler); } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 6cd5eba643e8..20a1f034bf95 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1327,10 +1327,10 @@ static void engine_record_requests(struct intel_engine_cs *engine, static void error_record_engine_execlists(struct intel_engine_cs *engine, struct drm_i915_error_engine *ee) { - const struct execlist_port *port = engine->execlist_port; + const struct execlist_port *port = engine->execlists.port; unsigned int n; - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) { + for (n = 0; n < ARRAY_SIZE(engine->execlists.port); n++) { struct drm_i915_gem_request *rq = port_request(&port[n]); if (!rq) diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 06a26c610806..bce3f1b5892b 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -494,11 +494,12 @@ static void i915_guc_submit(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->i915; struct intel_guc *guc = &dev_priv->guc; struct i915_guc_client *client = guc->execbuf_client; - struct execlist_port *port = engine->execlist_port; - unsigned int engine_id = engine->id; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; + const unsigned int engine_id = engine->id; unsigned int n; - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) { + for (n = 0; n < ARRAY_SIZE(execlists->port); n++) { struct drm_i915_gem_request *rq; unsigned int count; @@ -558,7 +559,8 @@ static void port_assign(struct execlist_port *port, static void i915_guc_dequeue(struct intel_engine_cs *engine) { - struct execlist_port *port = engine->execlist_port; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; struct drm_i915_gem_request *last = NULL; bool submit = false; struct rb_node *rb; @@ -567,15 +569,15 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine) port++; spin_lock_irq(&engine->timeline->lock); - rb = engine->execlist_first; - GEM_BUG_ON(rb_first(&engine->execlist_queue) != rb); + rb = execlists->first; + GEM_BUG_ON(rb_first(&execlists->queue) != rb); while (rb) { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); struct drm_i915_gem_request *rq, *rn; list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { if (last && rq->ctx != last->ctx) { - if (port != engine->execlist_port) { + if (port != execlists->port) { __list_del_many(&p->requests, &rq->priotree.link); goto done; @@ -596,13 +598,13 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine) } rb = rb_next(rb); - rb_erase(&p->node, &engine->execlist_queue); + rb_erase(&p->node, &execlists->queue); INIT_LIST_HEAD(&p->requests); if (p->priority != I915_PRIORITY_NORMAL) kmem_cache_free(engine->i915->priorities, p); } done: - engine->execlist_first = rb; + execlists->first = rb; if (submit) { port_assign(port, last); i915_guc_submit(engine); @@ -612,8 +614,8 @@ done: static void i915_guc_irq_handler(unsigned long data) { - struct intel_engine_cs *engine = (struct intel_engine_cs *)data; - struct execlist_port *port = engine->execlist_port; + struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; + struct execlist_port *port = engine->execlists.port; struct drm_i915_gem_request *rq; rq = port_request(&port[0]); @@ -1144,7 +1146,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) * and it is guaranteed that it will remove the work item from the * queue before our request is completed. */ - BUILD_BUG_ON(ARRAY_SIZE(engine->execlist_port) * + BUILD_BUG_ON(ARRAY_SIZE(engine->execlists.port) * sizeof(struct guc_wq_item) * I915_NUM_ENGINES > GUC_WQ_SIZE); @@ -1175,14 +1177,15 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) guc_interrupts_capture(dev_priv); for_each_engine(engine, dev_priv, id) { + struct intel_engine_execlists * const execlists = &engine->execlists; /* The tasklet was initialised by execlists, and may be in * a state of flux (across a reset) and so we just want to * take over the callback without changing any other state * in the tasklet. */ - engine->irq_tasklet.func = i915_guc_irq_handler; + execlists->irq_tasklet.func = i915_guc_irq_handler; clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); - tasklet_schedule(&engine->irq_tasklet); + tasklet_schedule(&execlists->irq_tasklet); } return 0; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b1bab7605db9..af82bd721dbc 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1346,10 +1346,11 @@ static void snb_gt_irq_handler(struct drm_i915_private *dev_priv, static void gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) { + struct intel_engine_execlists * const execlists = &engine->execlists; bool tasklet = false; if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) { - if (port_count(&engine->execlist_port[0])) { + if (port_count(&execlists->port[0])) { __set_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); tasklet = true; } @@ -1361,7 +1362,7 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) } if (tasklet) - tasklet_hi_schedule(&engine->irq_tasklet); + tasklet_hi_schedule(&execlists->irq_tasklet); } static irqreturn_t gen8_gt_irq_ack(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 020e4c6c0192..bf132266a007 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -393,8 +393,8 @@ static void intel_engine_init_timeline(struct intel_engine_cs *engine) */ void intel_engine_setup_common(struct intel_engine_cs *engine) { - engine->execlist_queue = RB_ROOT; - engine->execlist_first = NULL; + engine->execlists.queue = RB_ROOT; + engine->execlists.first = NULL; intel_engine_init_timeline(engine); intel_engine_init_hangcheck(engine); @@ -1475,11 +1475,11 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine) return false; /* Both ports drained, no more ELSP submission? */ - if (port_request(&engine->execlist_port[0])) + if (port_request(&engine->execlists.port[0])) return false; /* ELSP is empty, but there are ready requests? */ - if (READ_ONCE(engine->execlist_first)) + if (READ_ONCE(engine->execlists.first)) return false; /* Ring stopped? */ @@ -1528,8 +1528,8 @@ void intel_engines_mark_idle(struct drm_i915_private *i915) for_each_engine(engine, i915, id) { intel_engine_disarm_breadcrumbs(engine); i915_gem_batch_pool_fini(&engine->batch_pool); - tasklet_kill(&engine->irq_tasklet); - engine->no_priolist = false; + tasklet_kill(&engine->execlists.irq_tasklet); + engine->execlists.no_priolist = false; } } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 955c87999280..4f202b840e3d 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -291,17 +291,18 @@ lookup_priolist(struct intel_engine_cs *engine, struct i915_priotree *pt, int prio) { + struct intel_engine_execlists * const execlists = &engine->execlists; struct i915_priolist *p; struct rb_node **parent, *rb; bool first = true; - if (unlikely(engine->no_priolist)) + if (unlikely(execlists->no_priolist)) prio = I915_PRIORITY_NORMAL; find_priolist: /* most positive priority is scheduled first, equal priorities fifo */ rb = NULL; - parent = &engine->execlist_queue.rb_node; + parent = &execlists->queue.rb_node; while (*parent) { rb = *parent; p = rb_entry(rb, typeof(*p), node); @@ -316,7 +317,7 @@ find_priolist: } if (prio == I915_PRIORITY_NORMAL) { - p = &engine->default_priolist; + p = &execlists->default_priolist; } else { p = kmem_cache_alloc(engine->i915->priorities, GFP_ATOMIC); /* Convert an allocation failure to a priority bump */ @@ -331,7 +332,7 @@ find_priolist: * requests, so if userspace lied about their * dependencies that reordering may be visible. */ - engine->no_priolist = true; + execlists->no_priolist = true; goto find_priolist; } } @@ -339,10 +340,10 @@ find_priolist: p->priority = prio; INIT_LIST_HEAD(&p->requests); rb_link_node(&p->node, rb, parent); - rb_insert_color(&p->node, &engine->execlist_queue); + rb_insert_color(&p->node, &execlists->queue); if (first) - engine->execlist_first = &p->node; + execlists->first = &p->node; return ptr_pack_bits(p, first, 1); } @@ -393,12 +394,12 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq) static void execlists_submit_ports(struct intel_engine_cs *engine) { - struct execlist_port *port = engine->execlist_port; + struct execlist_port *port = engine->execlists.port; u32 __iomem *elsp = engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); unsigned int n; - for (n = ARRAY_SIZE(engine->execlist_port); n--; ) { + for (n = ARRAY_SIZE(engine->execlists.port); n--; ) { struct drm_i915_gem_request *rq; unsigned int count; u64 desc; @@ -453,7 +454,7 @@ static void port_assign(struct execlist_port *port, static void execlists_dequeue(struct intel_engine_cs *engine) { struct drm_i915_gem_request *last; - struct execlist_port *port = engine->execlist_port; + struct execlist_port *port = engine->execlists.port; struct rb_node *rb; bool submit = false; @@ -491,8 +492,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine) */ spin_lock_irq(&engine->timeline->lock); - rb = engine->execlist_first; - GEM_BUG_ON(rb_first(&engine->execlist_queue) != rb); + rb = engine->execlists.first; + GEM_BUG_ON(rb_first(&engine->execlists.queue) != rb); while (rb) { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); struct drm_i915_gem_request *rq, *rn; @@ -515,7 +516,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * combine this request with the last, then we * are done. */ - if (port != engine->execlist_port) { + if (port != engine->execlists.port) { __list_del_many(&p->requests, &rq->priotree.link); goto done; @@ -552,13 +553,13 @@ static void execlists_dequeue(struct intel_engine_cs *engine) } rb = rb_next(rb); - rb_erase(&p->node, &engine->execlist_queue); + rb_erase(&p->node, &engine->execlists.queue); INIT_LIST_HEAD(&p->requests); if (p->priority != I915_PRIORITY_NORMAL) kmem_cache_free(engine->i915->priorities, p); } done: - engine->execlist_first = rb; + engine->execlists.first = rb; if (submit) port_assign(port, last); spin_unlock_irq(&engine->timeline->lock); @@ -569,7 +570,8 @@ done: static void execlists_cancel_requests(struct intel_engine_cs *engine) { - struct execlist_port *port = engine->execlist_port; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; struct drm_i915_gem_request *rq, *rn; struct rb_node *rb; unsigned long flags; @@ -578,9 +580,9 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) spin_lock_irqsave(&engine->timeline->lock, flags); /* Cancel the requests on the HW and clear the ELSP tracker. */ - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) + for (n = 0; n < ARRAY_SIZE(execlists->port); n++) i915_gem_request_put(port_request(&port[n])); - memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); + memset(execlists->port, 0, sizeof(execlists->port)); /* Mark all executing requests as skipped. */ list_for_each_entry(rq, &engine->timeline->requests, link) { @@ -590,7 +592,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) } /* Flush the queued requests to the timeline list (for retiring). */ - rb = engine->execlist_first; + rb = execlists->first; while (rb) { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); @@ -603,7 +605,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) } rb = rb_next(rb); - rb_erase(&p->node, &engine->execlist_queue); + rb_erase(&p->node, &execlists->queue); INIT_LIST_HEAD(&p->requests); if (p->priority != I915_PRIORITY_NORMAL) kmem_cache_free(engine->i915->priorities, p); @@ -611,8 +613,8 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) /* Remaining _unready_ requests will be nop'ed when submitted */ - engine->execlist_queue = RB_ROOT; - engine->execlist_first = NULL; + execlists->queue = RB_ROOT; + execlists->first = NULL; GEM_BUG_ON(port_isset(&port[0])); /* @@ -628,7 +630,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) static bool execlists_elsp_ready(const struct intel_engine_cs *engine) { - const struct execlist_port *port = engine->execlist_port; + const struct execlist_port *port = engine->execlists.port; return port_count(&port[0]) + port_count(&port[1]) < 2; } @@ -639,8 +641,9 @@ static bool execlists_elsp_ready(const struct intel_engine_cs *engine) */ static void intel_lrc_irq_handler(unsigned long data) { - struct intel_engine_cs *engine = (struct intel_engine_cs *)data; - struct execlist_port *port = engine->execlist_port; + struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; struct drm_i915_private *dev_priv = engine->i915; /* We can skip acquiring intel_runtime_pm_get() here as it was taken @@ -652,7 +655,7 @@ static void intel_lrc_irq_handler(unsigned long data) */ GEM_BUG_ON(!dev_priv->gt.awake); - intel_uncore_forcewake_get(dev_priv, engine->fw_domains); + intel_uncore_forcewake_get(dev_priv, execlists->fw_domains); /* Prefer doing test_and_clear_bit() as a two stage operation to avoid * imposing the cost of a locked atomic transaction when submitting a @@ -665,10 +668,10 @@ static void intel_lrc_irq_handler(unsigned long data) unsigned int head, tail; /* However GVT emulation depends upon intercepting CSB mmio */ - if (unlikely(engine->csb_use_mmio)) { + if (unlikely(execlists->csb_use_mmio)) { buf = (u32 * __force) (dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0))); - engine->csb_head = -1; /* force mmio read of CSB ptrs */ + execlists->csb_head = -1; /* force mmio read of CSB ptrs */ } /* The write will be ordered by the uncached read (itself @@ -682,19 +685,20 @@ static void intel_lrc_irq_handler(unsigned long data) * is set and we do a new loop. */ __clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); - if (unlikely(engine->csb_head == -1)) { /* following a reset */ + if (unlikely(execlists->csb_head == -1)) { /* following a reset */ head = readl(dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine))); tail = GEN8_CSB_WRITE_PTR(head); head = GEN8_CSB_READ_PTR(head); - engine->csb_head = head; + execlists->csb_head = head; } else { const int write_idx = intel_hws_csb_write_index(dev_priv) - I915_HWS_CSB_BUF0_INDEX; - head = engine->csb_head; + head = execlists->csb_head; tail = READ_ONCE(buf[write_idx]); } + while (head != tail) { struct drm_i915_gem_request *rq; unsigned int status; @@ -748,8 +752,8 @@ static void intel_lrc_irq_handler(unsigned long data) !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); } - if (head != engine->csb_head) { - engine->csb_head = head; + if (head != execlists->csb_head) { + execlists->csb_head = head; writel(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, head << 8), dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine))); } @@ -758,7 +762,7 @@ static void intel_lrc_irq_handler(unsigned long data) if (execlists_elsp_ready(engine)) execlists_dequeue(engine); - intel_uncore_forcewake_put(dev_priv, engine->fw_domains); + intel_uncore_forcewake_put(dev_priv, execlists->fw_domains); } static void insert_request(struct intel_engine_cs *engine, @@ -769,7 +773,7 @@ static void insert_request(struct intel_engine_cs *engine, list_add_tail(&pt->link, &ptr_mask_bits(p, 1)->requests); if (ptr_unmask_bits(p, 1) && execlists_elsp_ready(engine)) - tasklet_hi_schedule(&engine->irq_tasklet); + tasklet_hi_schedule(&engine->execlists.irq_tasklet); } static void execlists_submit_request(struct drm_i915_gem_request *request) @@ -782,7 +786,7 @@ static void execlists_submit_request(struct drm_i915_gem_request *request) insert_request(engine, &request->priotree, request->priotree.priority); - GEM_BUG_ON(!engine->execlist_first); + GEM_BUG_ON(!engine->execlists.first); GEM_BUG_ON(list_empty(&request->priotree.link)); spin_unlock_irqrestore(&engine->timeline->lock, flags); @@ -1289,6 +1293,7 @@ static u8 gtiir[] = { static int gen8_init_common_ring(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; + struct intel_engine_execlists * const execlists = &engine->execlists; int ret; ret = intel_mocs_init_engine(engine); @@ -1321,11 +1326,11 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) I915_WRITE(GEN8_GT_IIR(gtiir[engine->id]), GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift); clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); - engine->csb_head = -1; + execlists->csb_head = -1; /* After a GPU reset, we may have requests to replay */ - if (!i915_modparams.enable_guc_submission && engine->execlist_first) - tasklet_schedule(&engine->irq_tasklet); + if (!i915_modparams.enable_guc_submission && execlists->first) + tasklet_schedule(&execlists->irq_tasklet); return 0; } @@ -1366,7 +1371,8 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine) static void reset_common_ring(struct intel_engine_cs *engine, struct drm_i915_gem_request *request) { - struct execlist_port *port = engine->execlist_port; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; struct drm_i915_gem_request *rq, *rn; struct intel_context *ce; unsigned long flags; @@ -1383,9 +1389,9 @@ static void reset_common_ring(struct intel_engine_cs *engine, * guessing the missed context-switch events by looking at what * requests were completed. */ - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) + for (n = 0; n < ARRAY_SIZE(execlists->port); n++) i915_gem_request_put(port_request(&port[n])); - memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); + memset(execlists->port, 0, sizeof(execlists->port)); /* Push back any incomplete requests for replay after the reset. */ list_for_each_entry_safe_reverse(rq, rn, @@ -1719,8 +1725,8 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) * Tasklet cannot be active at this point due intel_mark_active/idle * so this is just for documentation. */ - if (WARN_ON(test_bit(TASKLET_STATE_SCHED, &engine->irq_tasklet.state))) - tasklet_kill(&engine->irq_tasklet); + if (WARN_ON(test_bit(TASKLET_STATE_SCHED, &engine->execlists.irq_tasklet.state))) + tasklet_kill(&engine->execlists.irq_tasklet); dev_priv = engine->i915; @@ -1744,7 +1750,7 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) engine->submit_request = execlists_submit_request; engine->cancel_requests = execlists_cancel_requests; engine->schedule = execlists_schedule; - engine->irq_tasklet.func = intel_lrc_irq_handler; + engine->execlists.irq_tasklet.func = intel_lrc_irq_handler; } static void @@ -1806,7 +1812,7 @@ logical_ring_setup(struct intel_engine_cs *engine) /* Intentionally left blank. */ engine->buffer = NULL; - engine->csb_use_mmio = irq_handler_force_mmio(dev_priv); + engine->execlists.csb_use_mmio = irq_handler_force_mmio(dev_priv); fw_domains = intel_uncore_forcewake_for_reg(dev_priv, RING_ELSP(engine), @@ -1820,9 +1826,9 @@ logical_ring_setup(struct intel_engine_cs *engine) RING_CONTEXT_STATUS_BUF_BASE(engine), FW_REG_READ); - engine->fw_domains = fw_domains; + engine->execlists.fw_domains = fw_domains; - tasklet_init(&engine->irq_tasklet, + tasklet_init(&engine->execlists.irq_tasklet, intel_lrc_irq_handler, (unsigned long)engine); logical_ring_default_vfuncs(engine); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 138116a3b537..421e769adb79 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -184,6 +184,84 @@ struct i915_priolist { int priority; }; +/** + * struct intel_engine_execlists - execlist submission queue and port state + * + * The struct intel_engine_execlists represents the combined logical state of + * driver and the hardware state for execlist mode of submission. + */ +struct intel_engine_execlists { + /** + * @irq_tasklet: softirq tasklet for bottom handler + */ + struct tasklet_struct irq_tasklet; + + /** + * @default_priolist: priority list for I915_PRIORITY_NORMAL + */ + struct i915_priolist default_priolist; + + /** + * @no_priolist: priority lists disabled + */ + bool no_priolist; + + /** + * @port: execlist port states + * + * For each hardware ELSP (ExecList Submission Port) we keep + * track of the last request and the number of times we submitted + * that port to hw. We then count the number of times the hw reports + * a context completion or preemption. As only one context can + * be active on hw, we limit resubmission of context to port[0]. This + * is called Lite Restore, of the context. + */ + struct execlist_port { + /** + * @request_count: combined request and submission count + */ + struct drm_i915_gem_request *request_count; +#define EXECLIST_COUNT_BITS 2 +#define port_request(p) ptr_mask_bits((p)->request_count, EXECLIST_COUNT_BITS) +#define port_count(p) ptr_unmask_bits((p)->request_count, EXECLIST_COUNT_BITS) +#define port_pack(rq, count) ptr_pack_bits(rq, count, EXECLIST_COUNT_BITS) +#define port_unpack(p, count) ptr_unpack_bits((p)->request_count, count, EXECLIST_COUNT_BITS) +#define port_set(p, packed) ((p)->request_count = (packed)) +#define port_isset(p) ((p)->request_count) +#define port_index(p, e) ((p) - (e)->execlists.port) + + /** + * @context_id: context ID for port + */ + GEM_DEBUG_DECL(u32 context_id); + } port[2]; + + /** + * @queue: queue of requests, in priority lists + */ + struct rb_root queue; + + /** + * @first: leftmost level in priority @queue + */ + struct rb_node *first; + + /** + * @fw_domains: forcewake domains for irq tasklet + */ + unsigned int fw_domains; + + /** + * @csb_head: context status buffer head + */ + unsigned int csb_head; + + /** + * @csb_use_mmio: access csb through mmio, instead of hwsp + */ + bool csb_use_mmio; +}; + #define INTEL_ENGINE_CS_MAX_NAME 8 struct intel_engine_cs { @@ -380,27 +458,7 @@ struct intel_engine_cs { u32 *(*signal)(struct drm_i915_gem_request *req, u32 *cs); } semaphore; - /* Execlists */ - struct tasklet_struct irq_tasklet; - struct i915_priolist default_priolist; - bool no_priolist; - struct execlist_port { - struct drm_i915_gem_request *request_count; -#define EXECLIST_COUNT_BITS 2 -#define port_request(p) ptr_mask_bits((p)->request_count, EXECLIST_COUNT_BITS) -#define port_count(p) ptr_unmask_bits((p)->request_count, EXECLIST_COUNT_BITS) -#define port_pack(rq, count) ptr_pack_bits(rq, count, EXECLIST_COUNT_BITS) -#define port_unpack(p, count) ptr_unpack_bits((p)->request_count, count, EXECLIST_COUNT_BITS) -#define port_set(p, packed) ((p)->request_count = (packed)) -#define port_isset(p) ((p)->request_count) -#define port_index(p, e) ((p) - (e)->execlist_port) - GEM_DEBUG_DECL(u32 context_id); - } execlist_port[2]; - struct rb_root execlist_queue; - struct rb_node *execlist_first; - unsigned int fw_domains; - unsigned int csb_head; - bool csb_use_mmio; + struct intel_engine_execlists execlists; /* Contexts are pinned whilst they are active on the GPU. The last * context executed remains active whilst the GPU is idle - the -- cgit v1.2.3 From 19df9a5782f51c900a730dae11e4abf85a0e5ebc Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 22 Sep 2017 15:43:04 +0300 Subject: drm/i915: Move execlist initialization into intel_engine_cs.c Move execlist init into a common engine setup. As it is common to both guc and hw execlists. v2: rebase with csb changes v3: rebase Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170922124307.10914-2-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/intel_engine_cs.c | 30 ++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_lrc.c | 19 ------------------- 2 files changed, 28 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index bf132266a007..30035e59a784 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -382,6 +382,33 @@ static void intel_engine_init_timeline(struct intel_engine_cs *engine) engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; } +static bool csb_force_mmio(struct drm_i915_private *i915) +{ + /* GVT emulation depends upon intercepting CSB mmio */ + if (intel_vgpu_active(i915)) + return true; + + /* + * IOMMU adds unpredictable latency causing the CSB write (from the + * GPU into the HWSP) to only be visible some time after the interrupt + * (missed breadcrumb syndrome). + */ + if (intel_vtd_active()) + return true; + + return false; +} + +static void intel_engine_init_execlist(struct intel_engine_cs *engine) +{ + struct intel_engine_execlists * const execlists = &engine->execlists; + + execlists->csb_use_mmio = csb_force_mmio(engine->i915); + + execlists->queue = RB_ROOT; + execlists->first = NULL; +} + /** * intel_engines_setup_common - setup engine state not requiring hw access * @engine: Engine to setup. @@ -393,8 +420,7 @@ static void intel_engine_init_timeline(struct intel_engine_cs *engine) */ void intel_engine_setup_common(struct intel_engine_cs *engine) { - engine->execlists.queue = RB_ROOT; - engine->execlists.first = NULL; + intel_engine_init_execlist(engine); intel_engine_init_timeline(engine); intel_engine_init_hangcheck(engine); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 4f202b840e3d..3186be54bbd8 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1784,23 +1784,6 @@ logical_ring_default_irqs(struct intel_engine_cs *engine) engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; } -static bool irq_handler_force_mmio(struct drm_i915_private *i915) -{ - /* GVT emulation depends upon intercepting CSB mmio */ - if (intel_vgpu_active(i915)) - return true; - - /* - * IOMMU adds unpredictable latency causing the CSB write (from the - * GPU into the HWSP) to only be visible some time after the interrupt - * (missed breadcrumb syndrome). - */ - if (intel_vtd_active()) - return true; - - return false; -} - static void logical_ring_setup(struct intel_engine_cs *engine) { @@ -1812,8 +1795,6 @@ logical_ring_setup(struct intel_engine_cs *engine) /* Intentionally left blank. */ engine->buffer = NULL; - engine->execlists.csb_use_mmio = irq_handler_force_mmio(dev_priv); - fw_domains = intel_uncore_forcewake_for_reg(dev_priv, RING_ELSP(engine), FW_REG_WRITE); -- cgit v1.2.3 From cf4591d1ce1c85d589a3e8e7e5a0bbc7aa9b0027 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 22 Sep 2017 15:43:05 +0300 Subject: drm/i915: Wrap port cancellation into a function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On reset and wedged path, we want to release the requests that are tied to ports and then mark the ports to be unset. Introduce a function for this. v2: rebase v3: drop local, keep GEM_BUG_ON (Michał, Chris) v4: rebase Cc: Chris Wilson Signed-off-by: Mika Kuoppala Reviewed-by: Michał Winiarski Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170922124307.10914-3-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3186be54bbd8..4f625371b5fe 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -568,21 +568,27 @@ done: execlists_submit_ports(engine); } +static void execlist_cancel_port_requests(struct intel_engine_execlists *execlists) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(execlists->port); i++) + i915_gem_request_put(port_request(&execlists->port[i])); + + memset(execlists->port, 0, sizeof(execlists->port)); +} + static void execlists_cancel_requests(struct intel_engine_cs *engine) { struct intel_engine_execlists * const execlists = &engine->execlists; - struct execlist_port *port = execlists->port; struct drm_i915_gem_request *rq, *rn; struct rb_node *rb; unsigned long flags; - unsigned long n; spin_lock_irqsave(&engine->timeline->lock, flags); /* Cancel the requests on the HW and clear the ELSP tracker. */ - for (n = 0; n < ARRAY_SIZE(execlists->port); n++) - i915_gem_request_put(port_request(&port[n])); - memset(execlists->port, 0, sizeof(execlists->port)); + execlist_cancel_port_requests(execlists); /* Mark all executing requests as skipped. */ list_for_each_entry(rq, &engine->timeline->requests, link) { @@ -613,9 +619,10 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) /* Remaining _unready_ requests will be nop'ed when submitted */ + execlists->queue = RB_ROOT; execlists->first = NULL; - GEM_BUG_ON(port_isset(&port[0])); + GEM_BUG_ON(port_isset(&execlists->port[0])); /* * The port is checked prior to scheduling a tasklet, but @@ -1372,11 +1379,9 @@ static void reset_common_ring(struct intel_engine_cs *engine, struct drm_i915_gem_request *request) { struct intel_engine_execlists * const execlists = &engine->execlists; - struct execlist_port *port = execlists->port; struct drm_i915_gem_request *rq, *rn; struct intel_context *ce; unsigned long flags; - unsigned int n; spin_lock_irqsave(&engine->timeline->lock, flags); @@ -1389,9 +1394,7 @@ static void reset_common_ring(struct intel_engine_cs *engine, * guessing the missed context-switch events by looking at what * requests were completed. */ - for (n = 0; n < ARRAY_SIZE(execlists->port); n++) - i915_gem_request_put(port_request(&port[n])); - memset(execlists->port, 0, sizeof(execlists->port)); + execlist_cancel_port_requests(execlists); /* Push back any incomplete requests for replay after the reset. */ list_for_each_entry_safe_reverse(rq, rn, -- cgit v1.2.3 From 7a62cc6107f31e119a0df6f79fa9fae566b1a22e Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 22 Sep 2017 15:43:06 +0300 Subject: drm/i915: Add execlist_port_complete When first execlist entry is processed, we move the port (contents). Introduce function for this as execlist and guc use this common operation. v2: rebase. s/GEM_DEBUG_BUG/GEM_BUG (Chris) v3: rebase Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170922124307.10914-4-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_guc_submission.c | 8 ++++---- drivers/gpu/drm/i915/intel_lrc.c | 22 +++++++++++----------- drivers/gpu/drm/i915/intel_ringbuffer.h | 14 +++++++++++++- 3 files changed, 28 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index bce3f1b5892b..55e15a57c3d9 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -592,7 +592,7 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine) rq->priotree.priority = INT_MAX; __i915_gem_request_submit(rq); - trace_i915_gem_request_in(rq, port_index(port, engine)); + trace_i915_gem_request_in(rq, port_index(port, execlists)); last = rq; submit = true; } @@ -615,7 +615,8 @@ done: static void i915_guc_irq_handler(unsigned long data) { struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; - struct execlist_port *port = engine->execlists.port; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; struct drm_i915_gem_request *rq; rq = port_request(&port[0]); @@ -623,8 +624,7 @@ static void i915_guc_irq_handler(unsigned long data) trace_i915_gem_request_out(rq); i915_gem_request_put(rq); - port[0] = port[1]; - memset(&port[1], 0, sizeof(port[1])); + execlists_port_complete(execlists, port); rq = port_request(&port[0]); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 4f625371b5fe..3b03f19f1395 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -454,7 +454,8 @@ static void port_assign(struct execlist_port *port, static void execlists_dequeue(struct intel_engine_cs *engine) { struct drm_i915_gem_request *last; - struct execlist_port *port = engine->execlists.port; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; struct rb_node *rb; bool submit = false; @@ -468,8 +469,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) */ last->tail = last->wa_tail; - GEM_BUG_ON(port_isset(&port[1])); - /* Hardware submission is through 2 ports. Conceptually each port * has a (RING_START, RING_HEAD, RING_TAIL) tuple. RING_START is * static for a context, and unique to each, so we only execute @@ -492,8 +491,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine) */ spin_lock_irq(&engine->timeline->lock); - rb = engine->execlists.first; - GEM_BUG_ON(rb_first(&engine->execlists.queue) != rb); + rb = execlists->first; + GEM_BUG_ON(rb_first(&execlists->queue) != rb); while (rb) { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); struct drm_i915_gem_request *rq, *rn; @@ -516,7 +515,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * combine this request with the last, then we * are done. */ - if (port != engine->execlists.port) { + if (port != execlists->port) { __list_del_many(&p->requests, &rq->priotree.link); goto done; @@ -541,25 +540,27 @@ static void execlists_dequeue(struct intel_engine_cs *engine) if (submit) port_assign(port, last); port++; + + GEM_BUG_ON(port_isset(port)); } INIT_LIST_HEAD(&rq->priotree.link); rq->priotree.priority = INT_MAX; __i915_gem_request_submit(rq); - trace_i915_gem_request_in(rq, port_index(port, engine)); + trace_i915_gem_request_in(rq, port_index(port, execlists)); last = rq; submit = true; } rb = rb_next(rb); - rb_erase(&p->node, &engine->execlists.queue); + rb_erase(&p->node, &execlists->queue); INIT_LIST_HEAD(&p->requests); if (p->priority != I915_PRIORITY_NORMAL) kmem_cache_free(engine->i915->priorities, p); } done: - engine->execlists.first = rb; + execlists->first = rb; if (submit) port_assign(port, last); spin_unlock_irq(&engine->timeline->lock); @@ -748,8 +749,7 @@ static void intel_lrc_irq_handler(unsigned long data) trace_i915_gem_request_out(rq); i915_gem_request_put(rq); - port[0] = port[1]; - memset(&port[1], 0, sizeof(port[1])); + execlists_port_complete(execlists, port); } else { port_set(port, port_pack(rq, count)); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 421e769adb79..0eae5936bc3c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -228,7 +228,7 @@ struct intel_engine_execlists { #define port_unpack(p, count) ptr_unpack_bits((p)->request_count, count, EXECLIST_COUNT_BITS) #define port_set(p, packed) ((p)->request_count = (packed)) #define port_isset(p) ((p)->request_count) -#define port_index(p, e) ((p) - (e)->execlists.port) +#define port_index(p, execlists) ((p) - (execlists)->port) /** * @context_id: context ID for port @@ -511,6 +511,18 @@ struct intel_engine_cs { u32 (*get_cmd_length_mask)(u32 cmd_header); }; +static inline void +execlists_port_complete(struct intel_engine_execlists * const execlists, + struct execlist_port * const port) +{ + struct execlist_port * const port1 = &execlists->port[1]; + + GEM_BUG_ON(port_index(port, execlists) != 0); + + *port = *port1; + memset(port1, 0, sizeof(struct execlist_port)); +} + static inline unsigned int intel_engine_flag(const struct intel_engine_cs *engine) { -- cgit v1.2.3 From 76e70087d360fdbe97f24c205d585ada04126e5f Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 22 Sep 2017 15:43:07 +0300 Subject: drm/i915: Make execlist port count variable As we emulate execlists on top of the GuC workqueue, it is not restricted to just 2 ports and we can increase that number arbitrarily to trade-off queue depth (i.e. scheduling latency) against pipeline bubbles. v2: rebase. better commit msg (Chris) v3: rebase Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170922124307.10914-5-mika.kuoppala@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 10 +++++----- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gpu_error.c | 17 ++++++++++++----- drivers/gpu/drm/i915/i915_guc_submission.c | 8 ++++++-- drivers/gpu/drm/i915/intel_engine_cs.c | 4 ++++ drivers/gpu/drm/i915/intel_lrc.c | 6 ++++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 21 +++++++++++++++++---- 7 files changed, 50 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 87e06da55a69..d10d71aa4b0e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3312,6 +3312,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) if (i915_modparams.enable_execlists) { const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX]; + struct intel_engine_execlists * const execlists = &engine->execlists; u32 ptr, read, write; unsigned int idx; @@ -3323,7 +3324,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) read = GEN8_CSB_READ_PTR(ptr); write = GEN8_CSB_WRITE_PTR(ptr); seq_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n", - read, engine->execlists.csb_head, + read, execlists->csb_head, write, intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)), yesno(test_bit(ENGINE_IRQ_EXECLIST, @@ -3345,11 +3346,10 @@ static int i915_engine_info(struct seq_file *m, void *unused) } rcu_read_lock(); - for (idx = 0; idx < ARRAY_SIZE(engine->execlists.port); idx++) { + for (idx = 0; idx < execlists_num_ports(execlists); idx++) { unsigned int count; - rq = port_unpack(&engine->execlists.port[idx], - &count); + rq = port_unpack(&execlists->port[idx], &count); if (rq) { seq_printf(m, "\t\tELSP[%d] count=%d, ", idx, count); @@ -3362,7 +3362,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) rcu_read_unlock(); spin_lock_irq(&engine->timeline->lock); - for (rb = engine->execlists.first; rb; rb = rb_next(rb)) { + for (rb = execlists->first; rb; rb = rb_next(rb)) { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d6babe7d362d..0f26aa57a922 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1001,7 +1001,8 @@ struct i915_gpu_state { u32 seqno; u32 head; u32 tail; - } *requests, execlist[2]; + } *requests, execlist[EXECLIST_MAX_PORTS]; + unsigned int num_ports; struct drm_i915_error_waiter { char comm[TASK_COMM_LEN]; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 20a1f034bf95..881fbe8d179b 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -396,6 +396,8 @@ static void error_print_context(struct drm_i915_error_state_buf *m, static void error_print_engine(struct drm_i915_error_state_buf *m, const struct drm_i915_error_engine *ee) { + int n; + err_printf(m, "%s command stream:\n", engine_str(ee->engine_id)); err_printf(m, " START: 0x%08x\n", ee->start); err_printf(m, " HEAD: 0x%08x [0x%08x]\n", ee->head, ee->rq_head); @@ -465,8 +467,11 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, jiffies_to_msecs(jiffies - ee->hangcheck_timestamp)); err_printf(m, " engine reset count: %u\n", ee->reset_count); - error_print_request(m, " ELSP[0]: ", &ee->execlist[0]); - error_print_request(m, " ELSP[1]: ", &ee->execlist[1]); + for (n = 0; n < ee->num_ports; n++) { + err_printf(m, " ELSP[%d]:", n); + error_print_request(m, " ", &ee->execlist[n]); + } + error_print_context(m, " Active context: ", &ee->context); } @@ -1327,17 +1332,19 @@ static void engine_record_requests(struct intel_engine_cs *engine, static void error_record_engine_execlists(struct intel_engine_cs *engine, struct drm_i915_error_engine *ee) { - const struct execlist_port *port = engine->execlists.port; + const struct intel_engine_execlists * const execlists = &engine->execlists; unsigned int n; - for (n = 0; n < ARRAY_SIZE(engine->execlists.port); n++) { - struct drm_i915_gem_request *rq = port_request(&port[n]); + for (n = 0; n < execlists_num_ports(execlists); n++) { + struct drm_i915_gem_request *rq = port_request(&execlists->port[n]); if (!rq) break; record_request(rq, &ee->execlist[n]); } + + ee->num_ports = n; } static void record_context(struct drm_i915_error_context *e, diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 55e15a57c3d9..04f1281d81a5 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -562,6 +562,8 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine) struct intel_engine_execlists * const execlists = &engine->execlists; struct execlist_port *port = execlists->port; struct drm_i915_gem_request *last = NULL; + const struct execlist_port * const last_port = + &execlists->port[execlists->port_mask]; bool submit = false; struct rb_node *rb; @@ -577,7 +579,7 @@ static void i915_guc_dequeue(struct intel_engine_cs *engine) list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { if (last && rq->ctx != last->ctx) { - if (port != execlists->port) { + if (port == last_port) { __list_del_many(&p->requests, &rq->priotree.link); goto done; @@ -617,6 +619,8 @@ static void i915_guc_irq_handler(unsigned long data) struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; struct intel_engine_execlists * const execlists = &engine->execlists; struct execlist_port *port = execlists->port; + const struct execlist_port * const last_port = + &execlists->port[execlists->port_mask]; struct drm_i915_gem_request *rq; rq = port_request(&port[0]); @@ -629,7 +633,7 @@ static void i915_guc_irq_handler(unsigned long data) rq = port_request(&port[0]); } - if (!port_isset(&port[1])) + if (!port_isset(last_port)) i915_guc_dequeue(engine); } diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 30035e59a784..a28e2a864cf1 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -405,6 +405,10 @@ static void intel_engine_init_execlist(struct intel_engine_cs *engine) execlists->csb_use_mmio = csb_force_mmio(engine->i915); + execlists->port_mask = 1; + BUILD_BUG_ON_NOT_POWER_OF_2(execlists_num_ports(execlists)); + GEM_BUG_ON(execlists_num_ports(execlists) > EXECLIST_MAX_PORTS); + execlists->queue = RB_ROOT; execlists->first = NULL; } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3b03f19f1395..f91e126a7f97 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -399,7 +399,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); unsigned int n; - for (n = ARRAY_SIZE(engine->execlists.port); n--; ) { + for (n = execlists_num_ports(&engine->execlists); n--; ) { struct drm_i915_gem_request *rq; unsigned int count; u64 desc; @@ -456,6 +456,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine) struct drm_i915_gem_request *last; struct intel_engine_execlists * const execlists = &engine->execlists; struct execlist_port *port = execlists->port; + const struct execlist_port * const last_port = + &execlists->port[execlists->port_mask]; struct rb_node *rb; bool submit = false; @@ -515,7 +517,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * combine this request with the last, then we * are done. */ - if (port != execlists->port) { + if (port == last_port) { __list_del_many(&p->requests, &rq->priotree.link); goto done; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 0eae5936bc3c..56d7ae9f298b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -234,7 +234,14 @@ struct intel_engine_execlists { * @context_id: context ID for port */ GEM_DEBUG_DECL(u32 context_id); - } port[2]; + +#define EXECLIST_MAX_PORTS 2 + } port[EXECLIST_MAX_PORTS]; + + /** + * @port_mask: number of execlist ports - 1 + */ + unsigned int port_mask; /** * @queue: queue of requests, in priority lists @@ -511,16 +518,22 @@ struct intel_engine_cs { u32 (*get_cmd_length_mask)(u32 cmd_header); }; +static inline unsigned int +execlists_num_ports(const struct intel_engine_execlists * const execlists) +{ + return execlists->port_mask + 1; +} + static inline void execlists_port_complete(struct intel_engine_execlists * const execlists, struct execlist_port * const port) { - struct execlist_port * const port1 = &execlists->port[1]; + const unsigned int m = execlists->port_mask; GEM_BUG_ON(port_index(port, execlists) != 0); - *port = *port1; - memset(port1, 0, sizeof(struct execlist_port)); + memmove(port, port + 1, m * sizeof(struct execlist_port)); + memset(port + m, 0, sizeof(struct execlist_port)); } static inline unsigned int -- cgit v1.2.3 From 604a8f6f1e33ed53529a117baec92d28e746a601 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Sep 2017 14:54:43 +0100 Subject: drm/i915/lrc: Only enable per-context and per-bb buffers if set The per-context and per-batch workaround buffers are optional, yet we tell the GPU to execute them even if they contain no instructions. Doing so incurs the dispatch latency, which we can avoid if we don't ask the GPU to execute the no-op buffers. Allow ourselves to skip setup of empty buffer, and then to only enable non-empty buffers in the context image. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170921135444.27330-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_lrc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index f91e126a7f97..8d158deda328 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1278,7 +1278,8 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine) ret = -EINVAL; break; } - batch_ptr = wa_bb_fn[i](engine, batch_ptr); + if (wa_bb_fn[i]) + batch_ptr = wa_bb_fn[i](engine, batch_ptr); wa_bb[i]->size = batch_ptr - (batch + wa_bb[i]->offset); } @@ -1986,13 +1987,12 @@ static void execlists_init_reg_state(u32 *regs, CTX_REG(regs, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(base), 0); CTX_REG(regs, CTX_SECOND_BB_STATE, RING_SBBSTATE(base), 0); if (rcs) { - CTX_REG(regs, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(base), 0); + struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx; + CTX_REG(regs, CTX_RCS_INDIRECT_CTX, RING_INDIRECT_CTX(base), 0); CTX_REG(regs, CTX_RCS_INDIRECT_CTX_OFFSET, RING_INDIRECT_CTX_OFFSET(base), 0); - - if (engine->wa_ctx.vma) { - struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx; + if (wa_ctx->indirect_ctx.size) { u32 ggtt_offset = i915_ggtt_offset(wa_ctx->vma); regs[CTX_RCS_INDIRECT_CTX + 1] = @@ -2001,6 +2001,11 @@ static void execlists_init_reg_state(u32 *regs, regs[CTX_RCS_INDIRECT_CTX_OFFSET + 1] = intel_lr_indirect_ctx_offset(engine) << 6; + } + + CTX_REG(regs, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(base), 0); + if (wa_ctx->per_ctx.size) { + u32 ggtt_offset = i915_ggtt_offset(wa_ctx->vma); regs[CTX_BB_PER_CTX_PTR + 1] = (ggtt_offset + wa_ctx->per_ctx.offset) | 0x01; -- cgit v1.2.3 From b8aa223341a9bfc68285c47474f5150225504584 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Sep 2017 14:54:44 +0100 Subject: drm/i915/lrc: Skip no-op per-bb buffer on gen9 Since we inherited the context image setup from gen8 which needed a per-bb workaround (for GPGPU), we are submitting an empty per-bb buffer on gen9. Now that we can skip adding the buffer to the context image, remove the dangling per-bb. This slightly improves execution latency, most notably on an idle engine. References: https://bugs.freedesktop.org/show_bug.cgi?id=87725 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170921135444.27330-2-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_lrc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8d158deda328..3623403a4f2d 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1184,13 +1184,6 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) return batch; } -static u32 *gen9_init_perctx_bb(struct intel_engine_cs *engine, u32 *batch) -{ - *batch++ = MI_BATCH_BUFFER_END; - - return batch; -} - #define CTX_WA_BB_OBJ_SIZE (PAGE_SIZE) static int lrc_setup_wa_ctx(struct intel_engine_cs *engine) @@ -1247,7 +1240,7 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine) return 0; case 9: wa_bb_fn[0] = gen9_init_indirectctx_bb; - wa_bb_fn[1] = gen9_init_perctx_bb; + wa_bb_fn[1] = NULL; break; case 8: wa_bb_fn[0] = gen8_init_indirectctx_bb; -- cgit v1.2.3 From dd59a9ba952752abecf4eb95287fb8c64fdb4499 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 18 Sep 2017 15:21:37 -0700 Subject: drm/i915/mst: Debug log connector name in destroy_connector() Print connector name in destroy_connect() and this doesn't add any extra lines to dmesg. The debug macro has been moved before the unregister call so that we don't lose the connector name and id. Signed-off-by: Dhinakaran Pandiyan Reviewed-by: James Ausmus Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170918222141.4674-1-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_dp_mst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 8e3aad0ea60b..88d1d2b9ac56 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -494,6 +494,7 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_i915_private *dev_priv = to_i915(connector->dev); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); drm_connector_unregister(connector); if (dev_priv->fbdev) @@ -505,7 +506,6 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_modeset_unlock(&connector->dev->mode_config.connection_mutex); drm_connector_unreference(connector); - DRM_DEBUG_KMS("\n"); } static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) -- cgit v1.2.3 From 9b1c581885c985b84d36a9ffa519a9b2e68708e1 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 18 Sep 2017 15:21:38 -0700 Subject: drm/i915/mst: Print active mst links after update Both mst_disable_dp and mst_post_disable_dp print number of active links before the variable has been updated. Move the print statement in mst_disable_dp after the decrement so that the printed values indicate the disabing of a mst connector. Also, add some text to clarify what we are printing. Signed-off-by: Dhinakaran Pandiyan Reviewed-by: James Ausmus Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170918222141.4674-2-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_dp_mst.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 88d1d2b9ac56..9a396f483f8b 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -133,7 +133,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, to_intel_connector(old_conn_state->connector); int ret; - DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); + DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port); @@ -155,8 +155,6 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); - /* this can fail */ drm_dp_check_act_status(&intel_dp->mst_mgr); /* and this can also fail */ @@ -173,6 +171,7 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); } + DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); } static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, @@ -195,7 +194,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, connector->encoder = encoder; intel_mst->connector = connector; - DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); + DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); if (intel_dp->active_mst_links == 0) intel_dig_port->base.pre_enable(&intel_dig_port->base, @@ -229,7 +228,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder, enum port port = intel_dig_port->port; int ret; - DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); + DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); if (intel_wait_for_register(dev_priv, DP_TP_STATUS(port), -- cgit v1.2.3 From e8b2577c5e312d175ed11a35a12346b19059277d Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 18 Sep 2017 15:21:39 -0700 Subject: drm/i915/dp: Fix buffer size for sink_irq_esi read The buffer size defined is 16 bytes whereas only 14 bytes are read. Add a macro to avoid this discrepancy. Signed-off-by: Dhinakaran Pandiyan Reviewed-by: James Ausmus Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170918222141.4674-3-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 48ed6c1b5a76..ff04b3616f95 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -42,6 +42,7 @@ #include "i915_drv.h" #define DP_LINK_CHECK_TIMEOUT (10 * 1000) +#define DP_DPRX_ESI_LEN 14 /* Compliance test status bits */ #define INTEL_DP_RESOLUTION_SHIFT_MASK 0 @@ -4013,15 +4014,9 @@ intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector) static bool intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector) { - int ret; - - ret = drm_dp_dpcd_read(&intel_dp->aux, - DP_SINK_COUNT_ESI, - sink_irq_vector, 14); - if (ret != 14) - return false; - - return true; + return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, + sink_irq_vector, DP_DPRX_ESI_LEN) == + DP_DPRX_ESI_LEN; } static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp) @@ -4221,7 +4216,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp) bool bret; if (intel_dp->is_mst) { - u8 esi[16] = { 0 }; + u8 esi[DP_DPRX_ESI_LEN] = { 0 }; int ret = 0; int retry; bool handled; -- cgit v1.2.3 From 3bc31a7f4d376083b972acdc1a580e05c3a6dc12 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Mon, 18 Sep 2017 15:21:41 -0700 Subject: drm/i915/dp: Remove useless debug about TPS3 support We already print training pattern used during link training and also print if the source or sink does not support TPS3 for HBR2 link rates, see intel_dp_training_pattern(). Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170918222141.4674-5-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ff04b3616f95..90e756c76f10 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4753,10 +4753,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) if (intel_encoder->type != INTEL_OUTPUT_EDP) intel_encoder->type = INTEL_OUTPUT_DP; - DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n", - yesno(intel_dp_source_supports_hbr2(intel_dp)), - yesno(drm_dp_tps3_supported(intel_dp->dpcd))); - if (intel_dp->reset_link_params) { /* Initial max link lane count */ intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); -- cgit v1.2.3 From dff457d74e7eaf8c5280967467597ebfc3e2e44a Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Tue, 5 Sep 2017 16:10:50 +0300 Subject: drm/i915: Speed up DMC firmware loading Currently we're doing: 1. acquire lock 2. write word to hardware 3. release lock 4. repeat from 1 to load the DMC firmware. Due to the cost of acquiring/releasing a lock, and the size of the DMC firmware, this slows down DMC loading a lot. This patch simply acquires the lock, writes the entire firmware, then releases the lock. Testing shows resume speedups in the order of 10ms on platforms with DMC firmware (GEN9+). v2: Per feedback from Chris & Ville there's no need to do the whole forcewake dance, so lose that bit (Chris, Ville) v3: Actually send the new version of the patch... v4: Don't acquire the uncore lock. Disable preempt. (Chris) Signed-off-by: David Weinehall Link: https://patchwork.freedesktop.org/patch/msgid/20170905131050.11655-1-david.weinehall@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_csr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 965988f79a55..cdfb624eb82d 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -252,8 +252,14 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv) } fw_size = dev_priv->csr.dmc_fw_size; + assert_rpm_wakelock_held(dev_priv); + + preempt_disable(); + for (i = 0; i < fw_size; i++) - I915_WRITE(CSR_PROGRAM(i), payload[i]); + I915_WRITE_FW(CSR_PROGRAM(i), payload[i]); + + preempt_enable(); for (i = 0; i < dev_priv->csr.mmio_count; i++) { I915_WRITE(dev_priv->csr.mmioaddr[i], -- cgit v1.2.3 From 6b12ca569bb2f864892c41dbbb0f88f3f9952bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 14 Sep 2017 18:17:31 +0300 Subject: drm/i915: Don't rmw PIPESTAT enable bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i830 seems to occasionally forget the PIPESTAT enable bits when we read the register. These aren't the only registers on i830 that have problems with RMW, as reading the double buffered plane registers returns the latched value rather than the last written value. So something similar is perhaps going on with PIPESTAT. This corruption results on vblank interrupts occasionally turning off on their own, which leads to vblank timeouts and generally a stuck display subsystem. So let's not RMW the pipestat enable bits, and instead use the cached copy we have around. Cc: Imre Deak Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170914151731.5034-1-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_irq.c | 135 ++++++++++++----------------- drivers/gpu/drm/i915/intel_fifo_underrun.c | 14 +-- 3 files changed, 66 insertions(+), 85 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0f26aa57a922..44f5569ed995 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3313,6 +3313,8 @@ static inline bool intel_vgpu_active(struct drm_i915_private *dev_priv) return dev_priv->vgpu.active; } +u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, + enum pipe pipe); void i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index af82bd721dbc..6a07ef38fb47 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -567,62 +567,16 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, POSTING_READ(SDEIMR); } -static void -__i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, - u32 enable_mask, u32 status_mask) +u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, + enum pipe pipe) { - i915_reg_t reg = PIPESTAT(pipe); - u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK; - - lockdep_assert_held(&dev_priv->irq_lock); - WARN_ON(!intel_irqs_enabled(dev_priv)); - - if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || - status_mask & ~PIPESTAT_INT_STATUS_MASK, - "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", - pipe_name(pipe), enable_mask, status_mask)) - return; - - if ((pipestat & enable_mask) == enable_mask) - return; - - dev_priv->pipestat_irq_mask[pipe] |= status_mask; - - /* Enable the interrupt, clear any pending status */ - pipestat |= enable_mask | status_mask; - I915_WRITE(reg, pipestat); - POSTING_READ(reg); -} - -static void -__i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, - u32 enable_mask, u32 status_mask) -{ - i915_reg_t reg = PIPESTAT(pipe); - u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK; + u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; + u32 enable_mask = status_mask << 16; lockdep_assert_held(&dev_priv->irq_lock); - WARN_ON(!intel_irqs_enabled(dev_priv)); - - if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || - status_mask & ~PIPESTAT_INT_STATUS_MASK, - "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", - pipe_name(pipe), enable_mask, status_mask)) - return; - - if ((pipestat & enable_mask) == 0) - return; - - dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; - - pipestat &= ~enable_mask; - I915_WRITE(reg, pipestat); - POSTING_READ(reg); -} -static u32 vlv_get_pipestat_enable_mask(struct drm_device *dev, u32 status_mask) -{ - u32 enable_mask = status_mask << 16; + if (INTEL_GEN(dev_priv) < 5) + goto out; /* * On pipe A we don't support the PSR interrupt yet, @@ -645,35 +599,59 @@ static u32 vlv_get_pipestat_enable_mask(struct drm_device *dev, u32 status_mask) if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; +out: + WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || + status_mask & ~PIPESTAT_INT_STATUS_MASK, + "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", + pipe_name(pipe), enable_mask, status_mask); + return enable_mask; } -void -i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, - u32 status_mask) +void i915_enable_pipestat(struct drm_i915_private *dev_priv, + enum pipe pipe, u32 status_mask) { + i915_reg_t reg = PIPESTAT(pipe); u32 enable_mask; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - enable_mask = vlv_get_pipestat_enable_mask(&dev_priv->drm, - status_mask); - else - enable_mask = status_mask << 16; - __i915_enable_pipestat(dev_priv, pipe, enable_mask, status_mask); + WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, + "pipe %c: status_mask=0x%x\n", + pipe_name(pipe), status_mask); + + lockdep_assert_held(&dev_priv->irq_lock); + WARN_ON(!intel_irqs_enabled(dev_priv)); + + if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) + return; + + dev_priv->pipestat_irq_mask[pipe] |= status_mask; + enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + + I915_WRITE(reg, enable_mask | status_mask); + POSTING_READ(reg); } -void -i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, - u32 status_mask) +void i915_disable_pipestat(struct drm_i915_private *dev_priv, + enum pipe pipe, u32 status_mask) { + i915_reg_t reg = PIPESTAT(pipe); u32 enable_mask; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - enable_mask = vlv_get_pipestat_enable_mask(&dev_priv->drm, - status_mask); - else - enable_mask = status_mask << 16; - __i915_disable_pipestat(dev_priv, pipe, enable_mask, status_mask); + WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, + "pipe %c: status_mask=0x%x\n", + pipe_name(pipe), status_mask); + + lockdep_assert_held(&dev_priv->irq_lock); + WARN_ON(!intel_irqs_enabled(dev_priv)); + + if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) + return; + + dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; + enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + + I915_WRITE(reg, enable_mask | status_mask); + POSTING_READ(reg); } /** @@ -1775,7 +1753,7 @@ static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, for_each_pipe(dev_priv, pipe) { i915_reg_t reg; - u32 mask, iir_bit = 0; + u32 status_mask, enable_mask, iir_bit = 0; /* * PIPESTAT bits get signalled even when the interrupt is @@ -1786,7 +1764,7 @@ static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, */ /* fifo underruns are filterered in the underrun handler. */ - mask = PIPE_FIFO_UNDERRUN_STATUS; + status_mask = PIPE_FIFO_UNDERRUN_STATUS; switch (pipe) { case PIPE_A: @@ -1800,21 +1778,20 @@ static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, break; } if (iir & iir_bit) - mask |= dev_priv->pipestat_irq_mask[pipe]; + status_mask |= dev_priv->pipestat_irq_mask[pipe]; - if (!mask) + if (!status_mask) continue; reg = PIPESTAT(pipe); - mask |= PIPESTAT_INT_ENABLE_MASK; - pipe_stats[pipe] = I915_READ(reg) & mask; + pipe_stats[pipe] = I915_READ(reg) & status_mask; + enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); /* * Clear the PIPE*STAT regs before the IIR */ - if (pipe_stats[pipe] & (PIPE_FIFO_UNDERRUN_STATUS | - PIPESTAT_INT_STATUS_MASK)) - I915_WRITE(reg, pipe_stats[pipe]); + if (pipe_stats[pipe]) + I915_WRITE(reg, enable_mask | pipe_stats[pipe]); } spin_unlock(&dev_priv->irq_lock); } diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 04689600e337..77c123cc8817 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -88,14 +88,15 @@ static void i9xx_check_fifo_underruns(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); i915_reg_t reg = PIPESTAT(crtc->pipe); - u32 pipestat = I915_READ(reg) & 0xffff0000; + u32 enable_mask; lockdep_assert_held(&dev_priv->irq_lock); - if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) + if ((I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0) return; - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); + enable_mask = i915_pipestat_enable_mask(dev_priv, crtc->pipe); + I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS); POSTING_READ(reg); trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe); @@ -108,15 +109,16 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, { struct drm_i915_private *dev_priv = to_i915(dev); i915_reg_t reg = PIPESTAT(pipe); - u32 pipestat = I915_READ(reg) & 0xffff0000; lockdep_assert_held(&dev_priv->irq_lock); if (enable) { - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); + u32 enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + + I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS); POSTING_READ(reg); } else { - if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS) + if (old && I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS) DRM_ERROR("pipe %c underrun\n", pipe_name(pipe)); } } -- cgit v1.2.3 From 3f9e6cd8230a413fdf462aba35ea6b6166fa3631 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Sep 2017 13:49:27 +0100 Subject: drm/i915/execlists: Microoptimise execlists_cancel_port_request() Just rearrange the code slightly to trim the number of iterations required. Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170925124929.16974-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/intel_lrc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3623403a4f2d..2c07f3c08bd3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -571,14 +571,17 @@ done: execlists_submit_ports(engine); } -static void execlist_cancel_port_requests(struct intel_engine_execlists *execlists) +static void +execlist_cancel_port_requests(struct intel_engine_execlists *execlists) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(execlists->port); i++) - i915_gem_request_put(port_request(&execlists->port[i])); + struct execlist_port *port = execlists->port; + unsigned int num_ports = ARRAY_SIZE(execlists->port); - memset(execlists->port, 0, sizeof(execlists->port)); + while (num_ports-- && port_isset(port)) { + i915_gem_request_put(port_request(port)); + memset(port, 0, sizeof(*port)); + port++; + } } static void execlists_cancel_requests(struct intel_engine_cs *engine) @@ -625,7 +628,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) execlists->queue = RB_ROOT; execlists->first = NULL; - GEM_BUG_ON(port_isset(&execlists->port[0])); + GEM_BUG_ON(port_isset(execlists->port)); /* * The port is checked prior to scheduling a tasklet, but -- cgit v1.2.3 From aec0246f3e3882065b5c29916a84b539afe4e4af Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Mon, 25 Sep 2017 19:26:01 +0530 Subject: drm/i915: Enable scanline read based on frame timestamps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For certain platforms on certain encoders, timings are driven from port instead of pipe. Thus, we can't rely on pipe scanline registers to get the timing information. Some cases scanline register read will not be functional. This is causing vblank evasion logic to fail since it relies on scanline, causing atomic update failure warnings. This patch uses pipe framestamp and current timestamp registers to calculate scanline. This is an indirect way to get the scanline. It helps resolve atomic update failure for gen9 dsi platforms. v2: Addressed Ville and Daniel's review comments. Updated the register MACROs, handled race condition for register reads, extracted timings from the hwmode. Removed the dependency on crtc->config to get the encoder type. v3: Made get scanline function generic v4: Addressed Ville's review comments. Added a flag to decide timestamp based scanline reporting. Changed 64bit variables to u32 v5: Adressed Ville's review comments. Put the scanline compute function at the place of caller. Removed hwmode flags from uapi and used a local i915 data structure instead. v6: Used vblank hwmode to get the timings. v7: Fixed sparse warnings, indentation and minor review comments. v8: Limited this only for Gen9 DSI. Credits-to: Ville Syrjälä Signed-off-by: Uma Shankar Signed-off-by: Chandra Konduru Signed-off-by: Vidya Srinivas Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/1506347761-4201-1-git-send-email-vidya.srinivas@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 54 ++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 9 +++++++ drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_dsi.c | 8 ++++++ 4 files changed, 73 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6a07ef38fb47..0b7562135d1c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -783,6 +783,57 @@ static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe) return I915_READ(PIPE_FRMCOUNT_G4X(pipe)); } +/* + * On certain encoders on certain platforms, pipe + * scanline register will not work to get the scanline, + * since the timings are driven from the PORT or issues + * with scanline register updates. + * This function will use Framestamp and current + * timestamp registers to calculate the scanline. + */ +static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_vblank_crtc *vblank = + &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_display_mode *mode = &vblank->hwmode; + u32 vblank_start = mode->crtc_vblank_start; + u32 vtotal = mode->crtc_vtotal; + u32 htotal = mode->crtc_htotal; + u32 clock = mode->crtc_clock; + u32 scanline, scan_prev_time, scan_curr_time, scan_post_time; + + /* + * To avoid the race condition where we might cross into the + * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR + * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR + * during the same frame. + */ + do { + /* + * This field provides read back of the display + * pipe frame time stamp. The time stamp value + * is sampled at every start of vertical blank. + */ + scan_prev_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); + + /* + * The TIMESTAMP_CTR register has the current + * time stamp value. + */ + scan_curr_time = I915_READ_FW(IVB_TIMESTAMP_CTR); + + scan_post_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); + } while (scan_post_time != scan_prev_time); + + scanline = div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, + clock), 1000 * htotal); + scanline = min(scanline, vtotal - 1); + scanline = (scanline + vblank_start) % vtotal; + + return scanline; +} + /* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) { @@ -799,6 +850,9 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; mode = &vblank->hwmode; + if (mode->private_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) + return __intel_get_crtc_scanline_from_timestamp(crtc); + vtotal = mode->crtc_vtotal; if (mode->flags & DRM_MODE_FLAG_INTERLACE) vtotal /= 2; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 82f36dd0cd94..76fd8fda46d2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8808,6 +8808,15 @@ enum skl_power_gate { #define MIPIO_TXESC_CLK_DIV2 _MMIO(0x160008) #define GLK_TX_ESC_CLK_DIV2_MASK 0x3FF +/* Gen4+ Timestamp and Pipe Frame time stamp registers */ +#define GEN4_TIMESTAMP _MMIO(0x2358) +#define ILK_TIMESTAMP_HI _MMIO(0x70070) +#define IVB_TIMESTAMP_CTR _MMIO(0x44070) + +#define _PIPE_FRMTMSTMP_A 0x70048 +#define PIPE_FRMTMSTMP(pipe) \ + _MMIO_PIPE2(pipe, _PIPE_FRMTMSTMP_A) + /* BXT MIPI clock controls */ #define BXT_MAX_VAR_OUTPUT_KHZ 39500 diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 64358d2f2422..0cab667fff57 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -494,6 +494,8 @@ struct intel_crtc_scaler_state { /* drm_mode->private_flags */ #define I915_MODE_FLAG_INHERITED 1 +/* Flag to get scanline using frame time stamps */ +#define I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP (1<<1) struct intel_pipe_wm { struct intel_wm_level wm[5]; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 578254ac799c..20a7b004ffd7 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -330,6 +330,10 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder, adjusted_mode->flags = 0; if (IS_GEN9_LP(dev_priv)) { + /* Enable Frame time stamp based scanline reporting */ + adjusted_mode->private_flags |= + I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP; + /* Dual link goes to DSI transcoder A. */ if (intel_dsi->ports == BIT(PORT_C)) pipe_config->cpu_transcoder = TRANSCODER_DSI_C; @@ -1102,6 +1106,10 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, pixel_format_from_register_bits(fmt)); bpp = pipe_config->pipe_bpp; + /* Enable Frame time stamo based scanline reporting */ + adjusted_mode->private_flags |= + I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP; + /* In terms of pixels */ adjusted_mode->crtc_hdisplay = I915_READ(BXT_MIPI_TRANS_HACTIVE(port)); -- cgit v1.2.3 From 54fea2b974a076799e427e50644de7c6ca662be5 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 25 Sep 2017 10:50:06 +0000 Subject: drm/i915: Make I915_PARAMS_FOR_EACH macro more flexible We should not add trailing ; after each member to allow other than statements-style uses of this helper macro. While here s/func/param for clarity. Signed-off-by: Michal Wajdeczko Cc: Chris Wilson Cc: Jani Nikula Reviewed-by: Chris Wilson Acked-by: Jani Nikula Signed-off-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170925105008.46060-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/i915_params.h | 84 +++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index a2cbb4782fcd..0116bb9713e3 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -27,50 +27,50 @@ #include /* for __read_mostly */ -#define I915_PARAMS_FOR_EACH(func) \ - func(char *, vbt_firmware); \ - func(int, modeset); \ - func(int, panel_ignore_lid); \ - func(int, semaphores); \ - func(int, lvds_channel_mode); \ - func(int, panel_use_ssc); \ - func(int, vbt_sdvo_panel_type); \ - func(int, enable_rc6); \ - func(int, enable_dc); \ - func(int, enable_fbc); \ - func(int, enable_ppgtt); \ - func(int, enable_execlists); \ - func(int, enable_psr); \ - func(int, disable_power_well); \ - func(int, enable_ips); \ - func(int, invert_brightness); \ - func(int, enable_guc_loading); \ - func(int, enable_guc_submission); \ - func(int, guc_log_level); \ - func(char *, guc_firmware_path); \ - func(char *, huc_firmware_path); \ - func(int, use_mmio_flip); \ - func(int, mmio_debug); \ - func(int, edp_vswing); \ - func(int, reset); \ - func(unsigned int, inject_load_failure); \ +#define I915_PARAMS_FOR_EACH(param) \ + param(char *, vbt_firmware) \ + param(int, modeset) \ + param(int, panel_ignore_lid) \ + param(int, semaphores) \ + param(int, lvds_channel_mode) \ + param(int, panel_use_ssc) \ + param(int, vbt_sdvo_panel_type) \ + param(int, enable_rc6) \ + param(int, enable_dc) \ + param(int, enable_fbc) \ + param(int, enable_ppgtt) \ + param(int, enable_execlists) \ + param(int, enable_psr) \ + param(int, disable_power_well) \ + param(int, enable_ips) \ + param(int, invert_brightness) \ + param(int, enable_guc_loading) \ + param(int, enable_guc_submission) \ + param(int, guc_log_level) \ + param(char *, guc_firmware_path) \ + param(char *, huc_firmware_path) \ + param(int, use_mmio_flip) \ + param(int, mmio_debug) \ + param(int, edp_vswing) \ + param(int, reset) \ + param(unsigned int, inject_load_failure) \ /* leave bools at the end to not create holes */ \ - func(bool, alpha_support); \ - func(bool, enable_cmd_parser); \ - func(bool, enable_hangcheck); \ - func(bool, fastboot); \ - func(bool, prefault_disable); \ - func(bool, load_detect_test); \ - func(bool, force_reset_modeset_test); \ - func(bool, error_capture); \ - func(bool, disable_display); \ - func(bool, verbose_state_checks); \ - func(bool, nuclear_pageflip); \ - func(bool, enable_dp_mst); \ - func(bool, enable_dpcd_backlight); \ - func(bool, enable_gvt) + param(bool, alpha_support) \ + param(bool, enable_cmd_parser) \ + param(bool, enable_hangcheck) \ + param(bool, fastboot) \ + param(bool, prefault_disable) \ + param(bool, load_detect_test) \ + param(bool, force_reset_modeset_test) \ + param(bool, error_capture) \ + param(bool, disable_display) \ + param(bool, verbose_state_checks) \ + param(bool, nuclear_pageflip) \ + param(bool, enable_dp_mst) \ + param(bool, enable_dpcd_backlight) \ + param(bool, enable_gvt) -#define MEMBER(T, member) T member +#define MEMBER(T, member) T member; struct i915_params { I915_PARAMS_FOR_EACH(MEMBER); }; -- cgit v1.2.3 From 7075cb855d493487805ecf113874c04218d16014 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 25 Sep 2017 10:50:07 +0000 Subject: drm/i915: Extend I915_PARAMS_FOR_EACH with default member value By combining default value into helper macro we can initialize modparams struct in the same automatic way as it was declared. This will initialize members in the same order as declared and additionally will disallow declaring new member without proper default value for it. v2: make MEMBER macro more robust (Joonas) Signed-off-by: Michal Wajdeczko Cc: Chris Wilson Cc: Jani Nikula Cc: Joonas Lahtinen Reviewed-by: Chris Wilson Acked-by: Jani Nikula Reviewed-by: Joonas Lahtinen Signed-off-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170925105008.46060-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 6 +-- drivers/gpu/drm/i915/i915_params.c | 42 ++---------------- drivers/gpu/drm/i915/i915_params.h | 82 +++++++++++++++++------------------ 4 files changed, 48 insertions(+), 84 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d10d71aa4b0e..86c799ac4b85 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -66,7 +66,7 @@ static int i915_capabilities(struct seq_file *m, void *data) #undef PRINT_FLAG kernel_param_lock(THIS_MODULE); -#define PRINT_PARAM(T, x) seq_print_param(m, #x, #T, &i915_modparams.x); +#define PRINT_PARAM(T, x, ...) seq_print_param(m, #x, #T, &i915_modparams.x); I915_PARAMS_FOR_EACH(PRINT_PARAM); #undef PRINT_PARAM kernel_param_unlock(THIS_MODULE); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 881fbe8d179b..9f7b351621f3 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -572,7 +572,7 @@ static __always_inline void err_print_param(struct drm_i915_error_state_buf *m, static void err_print_params(struct drm_i915_error_state_buf *m, const struct i915_params *p) { -#define PRINT(T, x) err_print_param(m, #x, #T, &p->x); +#define PRINT(T, x, ...) err_print_param(m, #x, #T, &p->x); I915_PARAMS_FOR_EACH(PRINT); #undef PRINT } @@ -866,7 +866,7 @@ void __i915_gpu_state_free(struct kref *error_ref) kfree(error->overlay); kfree(error->display); -#define FREE(T, x) free_param(#T, &error->params.x); +#define FREE(T, x, ...) free_param(#T, &error->params.x); I915_PARAMS_FOR_EACH(FREE); #undef FREE @@ -1704,7 +1704,7 @@ static int capture(void *data) error->i915->gt.last_init_time)); error->params = i915_modparams; -#define DUP(T, x) dup_param(#T, &error->params.x); +#define DUP(T, x, ...) dup_param(#T, &error->params.x); I915_PARAMS_FOR_EACH(DUP); #undef DUP diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index ec6534180d54..9dff323a83d3 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -33,45 +33,9 @@ MODULE_PARM_DESC(name, desc) struct i915_params i915_modparams __read_mostly = { - .modeset = -1, - .panel_ignore_lid = 1, - .semaphores = -1, - .lvds_channel_mode = 0, - .panel_use_ssc = -1, - .vbt_sdvo_panel_type = -1, - .enable_rc6 = -1, - .enable_dc = -1, - .enable_fbc = -1, - .enable_execlists = -1, - .enable_hangcheck = true, - .enable_ppgtt = -1, - .enable_psr = -1, - .alpha_support = IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT), - .disable_power_well = -1, - .enable_ips = 1, - .fastboot = 0, - .prefault_disable = 0, - .load_detect_test = 0, - .force_reset_modeset_test = 0, - .reset = 2, - .error_capture = true, - .invert_brightness = 0, - .disable_display = 0, - .enable_cmd_parser = true, - .use_mmio_flip = 0, - .mmio_debug = 0, - .verbose_state_checks = 1, - .nuclear_pageflip = 0, - .edp_vswing = 0, - .enable_guc_loading = 0, - .enable_guc_submission = 0, - .guc_log_level = -1, - .guc_firmware_path = NULL, - .huc_firmware_path = NULL, - .enable_dp_mst = true, - .inject_load_failure = 0, - .enable_dpcd_backlight = false, - .enable_gvt = false, +#define MEMBER(T, member, value) .member = (value), + I915_PARAMS_FOR_EACH(MEMBER) +#undef MEMBER }; i915_param_named(modeset, int, 0400, diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 0116bb9713e3..da599395f2ba 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -28,49 +28,49 @@ #include /* for __read_mostly */ #define I915_PARAMS_FOR_EACH(param) \ - param(char *, vbt_firmware) \ - param(int, modeset) \ - param(int, panel_ignore_lid) \ - param(int, semaphores) \ - param(int, lvds_channel_mode) \ - param(int, panel_use_ssc) \ - param(int, vbt_sdvo_panel_type) \ - param(int, enable_rc6) \ - param(int, enable_dc) \ - param(int, enable_fbc) \ - param(int, enable_ppgtt) \ - param(int, enable_execlists) \ - param(int, enable_psr) \ - param(int, disable_power_well) \ - param(int, enable_ips) \ - param(int, invert_brightness) \ - param(int, enable_guc_loading) \ - param(int, enable_guc_submission) \ - param(int, guc_log_level) \ - param(char *, guc_firmware_path) \ - param(char *, huc_firmware_path) \ - param(int, use_mmio_flip) \ - param(int, mmio_debug) \ - param(int, edp_vswing) \ - param(int, reset) \ - param(unsigned int, inject_load_failure) \ + param(char *, vbt_firmware, NULL) \ + param(int, modeset, -1) \ + param(int, panel_ignore_lid, 1) \ + param(int, semaphores, -1) \ + param(int, lvds_channel_mode, 0) \ + param(int, panel_use_ssc, -1) \ + param(int, vbt_sdvo_panel_type, -1) \ + param(int, enable_rc6, -1) \ + param(int, enable_dc, -1) \ + param(int, enable_fbc, -1) \ + param(int, enable_ppgtt, -1) \ + param(int, enable_execlists, -1) \ + param(int, enable_psr, -1) \ + param(int, disable_power_well, -1) \ + param(int, enable_ips, 1) \ + param(int, invert_brightness, 0) \ + param(int, enable_guc_loading, 0) \ + param(int, enable_guc_submission, 0) \ + param(int, guc_log_level, -1) \ + param(char *, guc_firmware_path, NULL) \ + param(char *, huc_firmware_path, NULL) \ + param(int, use_mmio_flip, 0) \ + param(int, mmio_debug, 0) \ + param(int, edp_vswing, 0) \ + param(int, reset, 2) \ + param(unsigned int, inject_load_failure, 0) \ /* leave bools at the end to not create holes */ \ - param(bool, alpha_support) \ - param(bool, enable_cmd_parser) \ - param(bool, enable_hangcheck) \ - param(bool, fastboot) \ - param(bool, prefault_disable) \ - param(bool, load_detect_test) \ - param(bool, force_reset_modeset_test) \ - param(bool, error_capture) \ - param(bool, disable_display) \ - param(bool, verbose_state_checks) \ - param(bool, nuclear_pageflip) \ - param(bool, enable_dp_mst) \ - param(bool, enable_dpcd_backlight) \ - param(bool, enable_gvt) + param(bool, alpha_support, IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT)) \ + param(bool, enable_cmd_parser, true) \ + param(bool, enable_hangcheck, true) \ + param(bool, fastboot, 0) \ + param(bool, prefault_disable, 0) \ + param(bool, load_detect_test, 0) \ + param(bool, force_reset_modeset_test, 0) \ + param(bool, error_capture, true) \ + param(bool, disable_display, 0) \ + param(bool, verbose_state_checks, 1) \ + param(bool, nuclear_pageflip, 0) \ + param(bool, enable_dp_mst, true) \ + param(bool, enable_dpcd_backlight, false) \ + param(bool, enable_gvt, false) -#define MEMBER(T, member) T member; +#define MEMBER(T, member, ...) T member; struct i915_params { I915_PARAMS_FOR_EACH(MEMBER); }; -- cgit v1.2.3 From ad0c167252e90531b398bc5f637580733d1789e4 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 25 Sep 2017 10:50:08 +0000 Subject: drm/i915: Fix default values of some modparams Members should be initialized with values of matching types. Signed-off-by: Michal Wajdeczko Cc: Chris Wilson Cc: Jani Nikula Cc: Joonas Lahtinen Reviewed-by: Chris Wilson Acked-by: Jani Nikula Signed-off-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20170925105008.46060-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/i915_params.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index da599395f2ba..4f3f8d650194 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -58,14 +58,14 @@ param(bool, alpha_support, IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT)) \ param(bool, enable_cmd_parser, true) \ param(bool, enable_hangcheck, true) \ - param(bool, fastboot, 0) \ - param(bool, prefault_disable, 0) \ - param(bool, load_detect_test, 0) \ - param(bool, force_reset_modeset_test, 0) \ + param(bool, fastboot, false) \ + param(bool, prefault_disable, false) \ + param(bool, load_detect_test, false) \ + param(bool, force_reset_modeset_test, false) \ param(bool, error_capture, true) \ - param(bool, disable_display, 0) \ - param(bool, verbose_state_checks, 1) \ - param(bool, nuclear_pageflip, 0) \ + param(bool, disable_display, false) \ + param(bool, verbose_state_checks, true) \ + param(bool, nuclear_pageflip, false) \ param(bool, enable_dp_mst, true) \ param(bool, enable_dpcd_backlight, false) \ param(bool, enable_gvt, false) -- cgit v1.2.3 From 9a2cbf2d7b94660e4c4920cfae4a5eecc83ee485 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Tue, 26 Sep 2017 12:47:16 +0530 Subject: drm/i915/huc: Reorganize HuC authentication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepared intel_auth_huc to separate HuC specific functionality from GuC send action. Created new header intel_huc.h to group HuC specific declarations. v2: Changed argument preparation for AUTHENTICATE_HUC. s/intel_auth_huc/intel_huc_auth. Deferred creation of intel_huc.h to later patch. v3: Rebase as intel_guc.h is removed. Added param description to intel_huc_auth. (Michal) v4: Rebase as intel_guc.h is added again. :) v5: Rebase w.r.t removal of GuC code restructuring. v6-v7: Rebase. v8: Tagged subject as drm/i915/huc. (Michal Wajdeczko) Added kernel-doc description to intel_huc_auth and intel_guc_auth_huc. s/dev_priv/i915 and removed unnecessary variable offset. (Joonas) v9: Rebase. Had conflict with i915_modparams change. Signed-off-by: Sagar Arun Kamble Cc: Joonas Lahtinen Cc: Michal Wajdeczko Cc: Michał Winiarski Reviewed-by: Michal Wajdeczko Reviewed-by: Joonas Lahtinen Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/1506410236-17926-1-git-send-email-sagar.a.kamble@intel.com --- drivers/gpu/drm/i915/intel_huc.c | 38 ++++++++++++++++++-------------------- drivers/gpu/drm/i915/intel_uc.c | 23 ++++++++++++++++++++++- drivers/gpu/drm/i915/intel_uc.h | 3 ++- 3 files changed, 42 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 6e1779ba87a9..8b4b53525422 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c @@ -225,19 +225,22 @@ void intel_huc_init_hw(struct intel_huc *huc) } /** - * intel_guc_auth_huc() - authenticate ucode - * @dev_priv: the drm_i915_device + * intel_huc_auth() - Authenticate HuC uCode + * @huc: intel_huc structure + * + * Called after HuC and GuC firmware loading during intel_uc_init_hw(). * - * Triggers a HuC fw authentication request to the GuC via intel_guc_action_ - * authenticate_huc interface. + * This function pins HuC firmware image object into GGTT. + * Then it invokes GuC action to authenticate passing the offset to RSA + * signature through intel_guc_auth_huc(). It then waits for 50ms for + * firmware verification ACK and unpins the object. */ -void intel_guc_auth_huc(struct drm_i915_private *dev_priv) +void intel_huc_auth(struct intel_huc *huc) { - struct intel_guc *guc = &dev_priv->guc; - struct intel_huc *huc = &dev_priv->huc; + struct drm_i915_private *i915 = huc_to_i915(huc); + struct intel_guc *guc = &i915->guc; struct i915_vma *vma; int ret; - u32 data[2]; if (huc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) return; @@ -250,23 +253,19 @@ void intel_guc_auth_huc(struct drm_i915_private *dev_priv) return; } - /* Specify auth action and where public signature is. */ - data[0] = INTEL_GUC_ACTION_AUTHENTICATE_HUC; - data[1] = guc_ggtt_offset(vma) + huc->fw.rsa_offset; - - ret = intel_guc_send(guc, data, ARRAY_SIZE(data)); + ret = intel_guc_auth_huc(guc, + guc_ggtt_offset(vma) + huc->fw.rsa_offset); if (ret) { DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret); goto out; } /* Check authentication status, it should be done by now */ - ret = intel_wait_for_register(dev_priv, - HUC_STATUS2, - HUC_FW_VERIFIED, - HUC_FW_VERIFIED, - 50); - + ret = intel_wait_for_register(i915, + HUC_STATUS2, + HUC_FW_VERIFIED, + HUC_FW_VERIFIED, + 50); if (ret) { DRM_ERROR("HuC: Authentication failed %d\n", ret); goto out; @@ -275,4 +274,3 @@ void intel_guc_auth_huc(struct drm_i915_private *dev_priv) out: i915_vma_unpin(vma); } - diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 901854007664..277477890240 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c @@ -328,6 +328,27 @@ static void guc_disable_communication(struct intel_guc *guc) guc->send = intel_guc_send_nop; } +/** + * intel_guc_auth_huc() - Send action to GuC to authenticate HuC ucode + * @guc: intel_guc structure + * @rsa_offset: rsa offset w.r.t ggtt base of huc vma + * + * Triggers a HuC firmware authentication request to the GuC via intel_guc_send + * INTEL_GUC_ACTION_AUTHENTICATE_HUC interface. This function is invoked by + * intel_huc_auth(). + * + * Return: non-zero code on error + */ +int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset) +{ + u32 action[] = { + INTEL_GUC_ACTION_AUTHENTICATE_HUC, + rsa_offset + }; + + return intel_guc_send(guc, action, ARRAY_SIZE(action)); +} + int intel_uc_init_hw(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; @@ -390,7 +411,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) if (ret) goto err_log_capture; - intel_guc_auth_huc(dev_priv); + intel_huc_auth(&dev_priv->huc); if (i915_modparams.enable_guc_submission) { if (i915_modparams.guc_log_level >= 0) gen9_enable_guc_interrupts(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index 7703c9ad6511..6966349ed737 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -211,6 +211,7 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv); int intel_guc_sample_forcewake(struct intel_guc *guc); int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len); int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); +int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset); static inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) { @@ -254,6 +255,6 @@ static inline u32 guc_ggtt_offset(struct i915_vma *vma) /* intel_huc.c */ void intel_huc_select_fw(struct intel_huc *huc); void intel_huc_init_hw(struct intel_huc *huc); -void intel_guc_auth_huc(struct drm_i915_private *dev_priv); +void intel_huc_auth(struct intel_huc *huc); #endif -- cgit v1.2.3 From 87dc03ad268f285065cdd2e2ac75701a1f04d0b8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Sep 2017 14:09:29 +0100 Subject: drm/i915/selftests: Try to recover from a wedged GPU during reset tests If we see the seqno stop progressing, we abandon the test for fear that the GPU died following the reset. However, during test teardown we still wait for the GPU to idle before continuing, but we have already confirmed that the GPU is dead. Furthermore, since we are inside a reset test, we have disabled the hangchecker, and so there is no safety net and we wait indefinitely. Detect the stuck GPU and declare it wedged as a state of emergency so we can escape. Signed-off-by: Chris Wilson Cc: Jari Tahvanainen Cc: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20170915130929.18892-1-chris@chris-wilson.co.uk Tested-by: Jari Tahvanainen Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index 02e52a146ed8..377c1de766ce 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -621,7 +621,12 @@ static int igt_wait_reset(void *arg) __i915_add_request(rq, true); if (!wait_for_hang(&h, rq)) { - pr_err("Failed to start request %x\n", rq->fence.seqno); + pr_err("Failed to start request %x, at %x\n", + rq->fence.seqno, hws_seqno(&h, rq)); + + i915_reset(i915, 0); + i915_gem_set_wedged(i915); + err = -EIO; goto out_rq; } @@ -708,10 +713,14 @@ static int igt_reset_queue(void *arg) __i915_add_request(rq, true); if (!wait_for_hang(&h, prev)) { - pr_err("Failed to start request %x\n", - prev->fence.seqno); + pr_err("Failed to start request %x, at %x\n", + prev->fence.seqno, hws_seqno(&h, prev)); i915_gem_request_put(rq); i915_gem_request_put(prev); + + i915_reset(i915, 0); + i915_gem_set_wedged(i915); + err = -EIO; goto fini; } @@ -806,7 +815,12 @@ static int igt_handle_error(void *arg) __i915_add_request(rq, true); if (!wait_for_hang(&h, rq)) { - pr_err("Failed to start request %x\n", rq->fence.seqno); + pr_err("Failed to start request %x, at %x\n", + rq->fence.seqno, hws_seqno(&h, rq)); + + i915_reset(i915, 0); + i915_gem_set_wedged(i915); + err = -EIO; goto err_request; } @@ -843,8 +857,8 @@ err_unlock: int intel_hangcheck_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { + SUBTEST(igt_global_reset), /* attempt to recover GPU first */ SUBTEST(igt_hang_sanitycheck), - SUBTEST(igt_global_reset), SUBTEST(igt_reset_engine), SUBTEST(igt_reset_active_engines), SUBTEST(igt_wait_reset), -- cgit v1.2.3 From 5a127a8c4aaf6ea06752ee6404cd7eaea7154a6c Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 20 Sep 2017 10:26:59 +0100 Subject: drm/i915: Add IS_PLATFORM macro This will allow some code re-organization in a following patch. Signed-off-by: Tvrtko Ursulin Cc: Jani Nikula Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170920092701.17963-2-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 52 +++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 44f5569ed995..b5d65d07432d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2907,37 +2907,39 @@ intel_info(const struct drm_i915_private *dev_priv) #define IS_REVID(p, since, until) \ (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until)) -#define IS_I830(dev_priv) ((dev_priv)->info.platform == INTEL_I830) -#define IS_I845G(dev_priv) ((dev_priv)->info.platform == INTEL_I845G) -#define IS_I85X(dev_priv) ((dev_priv)->info.platform == INTEL_I85X) -#define IS_I865G(dev_priv) ((dev_priv)->info.platform == INTEL_I865G) -#define IS_I915G(dev_priv) ((dev_priv)->info.platform == INTEL_I915G) -#define IS_I915GM(dev_priv) ((dev_priv)->info.platform == INTEL_I915GM) -#define IS_I945G(dev_priv) ((dev_priv)->info.platform == INTEL_I945G) -#define IS_I945GM(dev_priv) ((dev_priv)->info.platform == INTEL_I945GM) -#define IS_I965G(dev_priv) ((dev_priv)->info.platform == INTEL_I965G) -#define IS_I965GM(dev_priv) ((dev_priv)->info.platform == INTEL_I965GM) -#define IS_G45(dev_priv) ((dev_priv)->info.platform == INTEL_G45) -#define IS_GM45(dev_priv) ((dev_priv)->info.platform == INTEL_GM45) +#define IS_PLATFORM(dev_priv, p) ((dev_priv)->info.platform == (p)) + +#define IS_I830(dev_priv) IS_PLATFORM(dev_priv, INTEL_I830) +#define IS_I845G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I845G) +#define IS_I85X(dev_priv) IS_PLATFORM(dev_priv, INTEL_I85X) +#define IS_I865G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I865G) +#define IS_I915G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I915G) +#define IS_I915GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I915GM) +#define IS_I945G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I945G) +#define IS_I945GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I945GM) +#define IS_I965G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I965G) +#define IS_I965GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I965GM) +#define IS_G45(dev_priv) IS_PLATFORM(dev_priv, INTEL_G45) +#define IS_GM45(dev_priv) IS_PLATFORM(dev_priv, INTEL_GM45) #define IS_G4X(dev_priv) (IS_G45(dev_priv) || IS_GM45(dev_priv)) #define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001) #define IS_PINEVIEW_M(dev_priv) (INTEL_DEVID(dev_priv) == 0xa011) -#define IS_PINEVIEW(dev_priv) ((dev_priv)->info.platform == INTEL_PINEVIEW) -#define IS_G33(dev_priv) ((dev_priv)->info.platform == INTEL_G33) +#define IS_PINEVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_PINEVIEW) +#define IS_G33(dev_priv) IS_PLATFORM(dev_priv, INTEL_G33) #define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046) -#define IS_IVYBRIDGE(dev_priv) ((dev_priv)->info.platform == INTEL_IVYBRIDGE) +#define IS_IVYBRIDGE(dev_priv) IS_PLATFORM(dev_priv, INTEL_IVYBRIDGE) #define IS_IVB_GT1(dev_priv) (IS_IVYBRIDGE(dev_priv) && \ (dev_priv)->info.gt == 1) -#define IS_VALLEYVIEW(dev_priv) ((dev_priv)->info.platform == INTEL_VALLEYVIEW) -#define IS_CHERRYVIEW(dev_priv) ((dev_priv)->info.platform == INTEL_CHERRYVIEW) -#define IS_HASWELL(dev_priv) ((dev_priv)->info.platform == INTEL_HASWELL) -#define IS_BROADWELL(dev_priv) ((dev_priv)->info.platform == INTEL_BROADWELL) -#define IS_SKYLAKE(dev_priv) ((dev_priv)->info.platform == INTEL_SKYLAKE) -#define IS_BROXTON(dev_priv) ((dev_priv)->info.platform == INTEL_BROXTON) -#define IS_KABYLAKE(dev_priv) ((dev_priv)->info.platform == INTEL_KABYLAKE) -#define IS_GEMINILAKE(dev_priv) ((dev_priv)->info.platform == INTEL_GEMINILAKE) -#define IS_COFFEELAKE(dev_priv) ((dev_priv)->info.platform == INTEL_COFFEELAKE) -#define IS_CANNONLAKE(dev_priv) ((dev_priv)->info.platform == INTEL_CANNONLAKE) +#define IS_VALLEYVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_VALLEYVIEW) +#define IS_CHERRYVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW) +#define IS_HASWELL(dev_priv) IS_PLATFORM(dev_priv, INTEL_HASWELL) +#define IS_BROADWELL(dev_priv) IS_PLATFORM(dev_priv, INTEL_BROADWELL) +#define IS_SKYLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_SKYLAKE) +#define IS_BROXTON(dev_priv) IS_PLATFORM(dev_priv, INTEL_BROXTON) +#define IS_KABYLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_KABYLAKE) +#define IS_GEMINILAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_GEMINILAKE) +#define IS_COFFEELAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_COFFEELAKE) +#define IS_CANNONLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_CANNONLAKE) #define IS_MOBILE(dev_priv) ((dev_priv)->info.is_mobile) #define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00) -- cgit v1.2.3 From 4d34b11e46184bb5762491d32566fade188c6c01 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 20 Sep 2017 10:27:00 +0100 Subject: drm/i915: Compact device info access by a small re-ordering More effort to align members on 4-byte boundary helps with code size a tiny bit: text data bss dec hex filename -1460454 60014 3656 1524124 17419c drivers/gpu/drm/i915/i915.ko +1460254 60014 3656 1523924 1740d4 drivers/gpu/drm/i915/i915.ko Signed-off-by: Tvrtko Ursulin Cc: Jani Nikula Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170920092701.17963-3-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b5d65d07432d..4e2fcdd4ce9e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -852,21 +852,27 @@ enum intel_platform { }; struct intel_device_info { - u32 display_mmio_offset; u16 device_id; - u8 num_pipes; - u8 num_sprites[I915_MAX_PIPES]; - u8 num_scalers[I915_MAX_PIPES]; - u8 gen; u16 gen_mask; - enum intel_platform platform; + + u8 gen; u8 gt; /* GT number, 0 if undefined */ - u8 ring_mask; /* Rings supported by the HW */ u8 num_rings; + u8 ring_mask; /* Rings supported by the HW */ + + enum intel_platform platform; + + u32 display_mmio_offset; + + u8 num_pipes; + u8 num_sprites[I915_MAX_PIPES]; + u8 num_scalers[I915_MAX_PIPES]; + #define DEFINE_FLAG(name) u8 name:1 DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG); #undef DEFINE_FLAG u16 ddb_size; /* in blocks */ + /* Register offsets for the various display pipes and transcoders */ int pipe_offsets[I915_MAX_TRANSCODERS]; int trans_offsets[I915_MAX_TRANSCODERS]; -- cgit v1.2.3 From 4e9767bc28e93139442847f023ff2fc0c2a21d34 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 20 Sep 2017 11:35:24 -0700 Subject: drm/i915/cnl: Add support slice/subslice/eu configs Cannonlake Slice and Subslice information has changed. This patch initially provided by Ben adds the proper sseu initialization. v2: This v2 done by Rodrigo includes: - Fix on Total slices count by avoiding [1][2] and [2][2]. - Inclusion of EU Per Subslice. - Commit message. v3: This v3 done by Rodrigo includes: - Handle all possible bits and extra fuse register. - Use INTEL_GEN macro. - Fully assume uniform distribution so remove union with eu_per_subslice and add proper the comment. v4: This v4 done by Rodrigo includes: - Consider all bits available: 6 bits for slices [27:22] and 4 for subslices [21:18]. v5: This v5 done by Rodrigo includes: - sseu->subslice_mask = (1 << 4) - 1 - missed on previous versions and noticed by Oscar. Cc: Oscar Mateo Signed-off-by: Ben Widawsky Signed-off-by: Rodrigo Vivi Reviewed-by: Oscar Mateo Link: https://patchwork.freedesktop.org/patch/msgid/20170920183525.20530-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 8 +++++++ drivers/gpu/drm/i915/intel_device_info.c | 37 +++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 76fd8fda46d2..e4c424ba5905 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2730,6 +2730,11 @@ enum i915_power_well_id { #define GEN9_F2_SS_DIS_SHIFT 20 #define GEN9_F2_SS_DIS_MASK (0xf << GEN9_F2_SS_DIS_SHIFT) +#define GEN10_F2_S_ENA_SHIFT 22 +#define GEN10_F2_S_ENA_MASK (0x3f << GEN10_F2_S_ENA_SHIFT) +#define GEN10_F2_SS_DIS_SHIFT 18 +#define GEN10_F2_SS_DIS_MASK (0xf << GEN10_F2_SS_DIS_SHIFT) + #define GEN8_EU_DISABLE0 _MMIO(0x9134) #define GEN8_EU_DIS0_S0_MASK 0xffffff #define GEN8_EU_DIS0_S1_SHIFT 24 @@ -2745,6 +2750,9 @@ enum i915_power_well_id { #define GEN9_EU_DISABLE(slice) _MMIO(0x9134 + (slice)*0x4) +#define GEN10_EU_DISABLE3 _MMIO(0x9140) +#define GEN10_EU_DIS_SS_MASK 0xff + #define GEN6_BSD_SLEEP_PSMI_CONTROL _MMIO(0x12050) #define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) #define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2) diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index fdf9b54b71e9..875d428ea75f 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -82,6 +82,39 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv) #undef PRINT_FLAG } +static void gen10_sseu_info_init(struct drm_i915_private *dev_priv) +{ + struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; + const u32 fuse2 = I915_READ(GEN8_FUSE2); + + sseu->slice_mask = (fuse2 & GEN10_F2_S_ENA_MASK) >> + GEN10_F2_S_ENA_SHIFT; + sseu->subslice_mask = (1 << 4) - 1; + sseu->subslice_mask &= ~((fuse2 & GEN10_F2_SS_DIS_MASK) >> + GEN10_F2_SS_DIS_SHIFT); + + sseu->eu_total = hweight32(~I915_READ(GEN8_EU_DISABLE0)); + sseu->eu_total += hweight32(~I915_READ(GEN8_EU_DISABLE1)); + sseu->eu_total += hweight32(~I915_READ(GEN8_EU_DISABLE2)); + sseu->eu_total += hweight8(~(I915_READ(GEN10_EU_DISABLE3) & + GEN10_EU_DIS_SS_MASK)); + + /* + * CNL is expected to always have a uniform distribution + * of EU across subslices with the exception that any one + * EU in any one subslice may be fused off for die + * recovery. + */ + sseu->eu_per_subslice = sseu_subslice_total(sseu) ? + DIV_ROUND_UP(sseu->eu_total, + sseu_subslice_total(sseu)) : 0; + + /* No restrictions on Power Gating */ + sseu->has_slice_pg = 1; + sseu->has_subslice_pg = 1; + sseu->has_eu_pg = 1; +} + static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) { struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; @@ -409,8 +442,10 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) cherryview_sseu_info_init(dev_priv); else if (IS_BROADWELL(dev_priv)) broadwell_sseu_info_init(dev_priv); - else if (INTEL_INFO(dev_priv)->gen >= 9) + else if (INTEL_GEN(dev_priv) == 9) gen9_sseu_info_init(dev_priv); + else if (INTEL_GEN(dev_priv) >= 10) + gen10_sseu_info_init(dev_priv); DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask); DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); -- cgit v1.2.3 From 7e44fc289d54aa3f1f37d6c9e5157f79011c6476 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 26 Sep 2017 11:17:19 +0100 Subject: drm/i915/execlists: Notify context-out for lost requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When cancelling requests, also send the notification to any listeners (gvt) that the request is no longer scheduled on hw. They may require to keep the in/out exactly balanced, and so the reuse after the reset may confuse the listener. Fixes: 221ab9719bf3 ("drm/i915/execlists: Unwind incomplete requests on resets") Signed-off-by: Chris Wilson Cc: "Zhenyu Wang" Cc: "Wang, Zhi A" Cc: Michał Winiarski Cc: Mika Kuoppala Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20170926101720.9479-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/intel_lrc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 2c07f3c08bd3..61cac26a8b05 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -578,7 +578,11 @@ execlist_cancel_port_requests(struct intel_engine_execlists *execlists) unsigned int num_ports = ARRAY_SIZE(execlists->port); while (num_ports-- && port_isset(port)) { - i915_gem_request_put(port_request(port)); + struct drm_i915_gem_request *rq = port_request(port); + + execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); + i915_gem_request_put(rq); + memset(port, 0, sizeof(*port)); port++; } -- cgit v1.2.3 From 516726d46d84096b006e2648d8700d1a04d021cc Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 6 Sep 2017 22:27:52 +0200 Subject: i915: Use %pS printk format for direct addresses Use the %pS printk format for printing symbols from direct addresses. This is important for the ia64, ppc64 and parisc64 architectures, while on other architectures there is no difference between %pS and %pF. Fix it for consistency across the kernel. Signed-off-by: Helge Deller Cc: Jani Nikula Cc: David Airlie Cc: intel-gfx@lists.freedesktop.org Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/1504729681-3504-6-git-send-email-deller@gmx.de --- drivers/gpu/drm/i915/intel_breadcrumbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 4e00e5cb9fa1..29c62d481cef 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -64,7 +64,7 @@ static unsigned long wait_timeout(void) static noinline void missed_breadcrumb(struct intel_engine_cs *engine) { - DRM_DEBUG_DRIVER("%s missed breadcrumb at %pF, irq posted? %s, current seqno=%x, last=%x\n", + DRM_DEBUG_DRIVER("%s missed breadcrumb at %pS, irq posted? %s, current seqno=%x, last=%x\n", engine->name, __builtin_return_address(0), yesno(test_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted)), -- cgit v1.2.3 From bd30ca2d1a98fb9bd1f6ba63438068788b9e396b Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 26 Sep 2017 14:13:46 -0700 Subject: drm/i915: Avoid using dev_priv->info.gen directly. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's stop this usage before it spreads so much. 1. This check is not part of usual searches happening when adding new platform. 2. There is already a duplication here with INTEL_INFO(dev_priv)->gen and INTEL_GEN(dev_priv). So let's please avoid yet another way. Cc: Lyude Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Radhakrishna Sripada Cc: Hans de Goede Cc: Matt Roper Cc: Maarten Lankhorst Cc: Paulo Zanoni Cc: Ville Syrjala Cc: Imre Deak Cc: Shashank Sharma Cc: Jani Nikula Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20170926211346.12009-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8a185971798b..aa9ccc3ecff9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9310,11 +9310,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pipe_config->gamma_mode = I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK; - if (IS_BROADWELL(dev_priv) || dev_priv->info.gen >= 9) { + if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) { u32 tmp = I915_READ(PIPEMISC(crtc->pipe)); bool clrspace_yuv = tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV; - if (IS_GEMINILAKE(dev_priv) || dev_priv->info.gen >= 10) { + if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10) { bool blend_mode_420 = tmp & PIPEMISC_YUV420_MODE_FULL_BLEND; @@ -14280,7 +14280,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) dev_priv->display.fdi_link_train = hsw_fdi_link_train; } - if (dev_priv->info.gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) dev_priv->display.update_crtcs = skl_update_crtcs; else dev_priv->display.update_crtcs = intel_update_crtcs; -- cgit v1.2.3 From ae7617f0ef1820be033eef93859a6bb6174a843f Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 27 Sep 2017 17:41:38 +0100 Subject: drm/i915: Allow optimized platform checks If we store the platform as a bitmask, and convert the IS_PLATFORM macro to use it, we allow the compiler to merge the IS_PLATFORM(a) || IS_PLATFORM(b) || ... checks into a single conditional. As a secondary benefit this saves almost 1k of text: text data bss dec hex filename -1460254 60014 3656 1523924 1740d4 drivers/gpu/drm/i915/i915.ko +1459260 60026 3656 1522942 173cfe drivers/gpu/drm/i915/i915.ko v2: Removed the infamous -1. Signed-off-by: Tvrtko Ursulin Cc: Jani Nikula Reviewed-by: Chris Wilson Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20170927164138.15474-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.c | 4 ++++ drivers/gpu/drm/i915/i915_drv.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7056bb299dc6..59ac9199b35d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -870,6 +870,10 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, memcpy(device_info, match_info, sizeof(*device_info)); device_info->device_id = dev_priv->drm.pdev->device; + BUILD_BUG_ON(INTEL_MAX_PLATFORMS > + sizeof(device_info->platform_mask) * BITS_PER_BYTE); + device_info->platform_mask = BIT(device_info->platform); + BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE); device_info->gen_mask = BIT(device_info->gen - 1); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4e2fcdd4ce9e..59fd4bceec7b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -861,6 +861,7 @@ struct intel_device_info { u8 ring_mask; /* Rings supported by the HW */ enum intel_platform platform; + u32 platform_mask; u32 display_mmio_offset; @@ -2913,7 +2914,7 @@ intel_info(const struct drm_i915_private *dev_priv) #define IS_REVID(p, since, until) \ (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until)) -#define IS_PLATFORM(dev_priv, p) ((dev_priv)->info.platform == (p)) +#define IS_PLATFORM(dev_priv, p) ((dev_priv)->info.platform_mask & BIT(p)) #define IS_I830(dev_priv) IS_PLATFORM(dev_priv, INTEL_I830) #define IS_I845G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I845G) -- cgit v1.2.3 From 977da084cc3c1791ecd6faed55e0ab41e7231660 Mon Sep 17 00:00:00 2001 From: vathsala nagaraju Date: Tue, 26 Sep 2017 15:29:13 +0530 Subject: drm/i915/psr: Set frames before SU entry for psr2 Set frames before SU entry value for max resync frame count of dpcd register 2009, bit field 0:3. v2 : - add macro EDP_PSR2_FRAME_BEFORE_SU (Rodrigo) - remove EDP_FRAMES_BEFORE_SU_ENTRY (Rodrigo) - add check ==1 for dpcd_read call (ville) v3 : (Rodrigo) - move macro EDP_PSR2_FRAME_BEFORE_SU after EDP_PSR2_FRAME_BEFORE_SU - replace with &= v4 : - change the macro to shift value (jani) - updated register names Cc: Rodrigo Vivi CC: Puthikorn Voravootivat Reviewed-by: Rodrigo Vivi Signed-off-by: Vathsala Nagaraju Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/1506419953-32605-2-git-send-email-vathsala.nagaraju@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_psr.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e4c424ba5905..ee0d4f14ac98 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4055,7 +4055,7 @@ enum { #define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) #define EDP_PSR2_IDLE_MASK 0xf -#define EDP_FRAMES_BEFORE_SU_ENTRY (1<<4) +#define EDP_PSR2_FRAME_BEFORE_SU(a) ((a)<<4) #define EDP_PSR2_STATUS_CTL _MMIO(0x6f940) #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 0a17d1f3ca77..5419cda83ba8 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -327,6 +327,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) */ uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); uint32_t val; + uint8_t sink_latency; val = idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; @@ -334,8 +335,16 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) * mesh at all with our frontbuffer tracking. And the hw alone isn't * good enough. */ val |= EDP_PSR2_ENABLE | - EDP_SU_TRACK_ENABLE | - EDP_FRAMES_BEFORE_SU_ENTRY; + EDP_SU_TRACK_ENABLE; + + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_SYNCHRONIZATION_LATENCY_IN_SINK, + &sink_latency) == 1) { + sink_latency &= DP_MAX_RESYNC_FRAME_COUNT_MASK; + } else { + sink_latency = 0; + } + val |= EDP_PSR2_FRAME_BEFORE_SU(sink_latency + 1); if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; -- cgit v1.2.3 From 163e8aecd13e4442fb996ffe031acb8f951dd55f Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 27 Sep 2017 17:20:40 -0700 Subject: drm/i915: Also discard second CRC on gen8+ platforms. One of the differences I spotted for GEN8+ platforms when compared to older platforms is that spec for BDW+ includes this sentence: "The first CRC done indication after CRC is first enabled is from only a partial frame, so it will not have the expected CRC result." This is an indication that on BDW+ platforms, by the time we receive the interrupt the CRC is not accurate yet for the full frame. That would be ok, because we are already skipping the first CRC for all platforms. However the comment on the code state that it is for some unknown reason. Also, on CHV (gen8 lp) we were already discarding the second CRC as well to make sure we have a reliable CRC on hand. So based on all ou tests and bugs it seems that it is not on CHV that needs to discard 2 first CRCs, but all BDW+ platforms. Starting on SKL we have this CRC done bit (24), but the experiments around the use of this bit wasn't that stable as just discarding the second CRC. So, let's for now just move with CHV solution for all gen8+ platforms and make our CI a bit more stable. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102374 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101309 Cc: Mika Kahola Signed-off-by: Rodrigo Vivi Tested-by: Mika Kahola Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20170928002040.7917-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0b7562135d1c..efd7827ff181 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1647,11 +1647,11 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, * bonkers. So let's just wait for the next vblank and read * out the buggy result. * - * On CHV sometimes the second CRC is bonkers as well, so + * On GEN8+ sometimes the second CRC is bonkers as well, so * don't trust that one either. */ if (pipe_crc->skipped == 0 || - (IS_CHERRYVIEW(dev_priv) && pipe_crc->skipped == 1)) { + (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { pipe_crc->skipped++; spin_unlock(&pipe_crc->lock); return; -- cgit v1.2.3 From 4dd504f7d98a6719eb2fc1a400257ca1f13d344b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 26 Sep 2017 10:53:53 +0100 Subject: drm/i915: Use memset64() to prefill the GTT page Take advantage of optimised memset64() instead of open coding it to prefill the GTT pages. Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20170926095353.11036-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 64d785262d14..4c82ceb8d318 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -481,10 +481,8 @@ static void fill_page_dma(struct i915_address_space *vm, const u64 val) { u64 * const vaddr = kmap_atomic(p->page); - int i; - for (i = 0; i < 512; i++) - vaddr[i] = val; + memset64(vaddr, val, PAGE_SIZE / sizeof(val)); kunmap_atomic(vaddr); } -- cgit v1.2.3 From e18063e88bd579c479a2b45820be6c4625f841c3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 29 Sep 2017 13:50:38 +0300 Subject: drm/i915: Update DRIVER_DATE to 20170929 Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8e4280838f14..7ca11318ac69 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -80,8 +80,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20170907" -#define DRIVER_TIMESTAMP 1504772900 +#define DRIVER_DATE "20170929" +#define DRIVER_TIMESTAMP 1506682238 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions -- cgit v1.2.3