Commit 762ce445 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-fixes-2016-04-21' of git://anongit.freedesktop.org/drm-intel into drm-fixes

Hi Dave, fixes all around, all but one are cc: stable material, the most
important ones are likely the Skylake hang fixes from Mika.

* tag 'drm-intel-fixes-2016-04-21' of git://anongit.freedesktop.org/drm-intel:
  drm/i915: Use fw_domains_put_with_fifo() on HSW
  drm/i915: Force ringbuffers to not be at offset 0
  drm/i915: Adjust size of PIPE_CONTROL used for gen8 render seqno write
  drm/i915/skl: Fix spurious gpu hang with gt3/gt4 revs
  drm/i915/skl: Fix rc6 based gpu/system hang
  drm/i915/userptr: Hold mmref whilst calling get-user-pages
  drm/i915: Fixup the free space logic in ring_prepare
  drm/i915/skl+: Use plane size for relative data rate calculation
parents 5f44abd0 31318a92
...@@ -2634,8 +2634,9 @@ struct drm_i915_cmd_table { ...@@ -2634,8 +2634,9 @@ struct drm_i915_cmd_table {
/* WaRsDisableCoarsePowerGating:skl,bxt */ /* WaRsDisableCoarsePowerGating:skl,bxt */
#define NEEDS_WaRsDisableCoarsePowerGating(dev) (IS_BXT_REVID(dev, 0, BXT_REVID_A1) || \ #define NEEDS_WaRsDisableCoarsePowerGating(dev) (IS_BXT_REVID(dev, 0, BXT_REVID_A1) || \
((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && \ IS_SKL_GT3(dev) || \
IS_SKL_REVID(dev, 0, SKL_REVID_F0))) IS_SKL_GT4(dev))
/* /*
* dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts
* even when in MSI mode. This results in spurious interrupt warnings if the * even when in MSI mode. This results in spurious interrupt warnings if the
......
...@@ -501,9 +501,12 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) ...@@ -501,9 +501,12 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
if (pvec != NULL) { if (pvec != NULL) {
struct mm_struct *mm = obj->userptr.mm->mm; struct mm_struct *mm = obj->userptr.mm->mm;
ret = -EFAULT;
if (atomic_inc_not_zero(&mm->mm_users)) {
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
while (pinned < npages) { while (pinned < npages) {
ret = get_user_pages_remote(work->task, mm, ret = get_user_pages_remote
(work->task, mm,
obj->userptr.ptr + pinned * PAGE_SIZE, obj->userptr.ptr + pinned * PAGE_SIZE,
npages - pinned, npages - pinned,
!obj->userptr.read_only, 0, !obj->userptr.read_only, 0,
...@@ -514,6 +517,8 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) ...@@ -514,6 +517,8 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
pinned += ret; pinned += ret;
} }
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
mmput(mm);
}
} }
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
......
...@@ -841,11 +841,11 @@ static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes) ...@@ -841,11 +841,11 @@ static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes)
if (unlikely(total_bytes > remain_usable)) { if (unlikely(total_bytes > remain_usable)) {
/* /*
* The base request will fit but the reserved space * The base request will fit but the reserved space
* falls off the end. So only need to to wait for the * falls off the end. So don't need an immediate wrap
* reserved size after flushing out the remainder. * and only need to effectively wait for the reserved
* size space from the start of ringbuffer.
*/ */
wait_bytes = remain_actual + ringbuf->reserved_size; wait_bytes = remain_actual + ringbuf->reserved_size;
need_wrap = true;
} else if (total_bytes > ringbuf->space) { } else if (total_bytes > ringbuf->space) {
/* No wrapping required, just waiting. */ /* No wrapping required, just waiting. */
wait_bytes = total_bytes; wait_bytes = total_bytes;
...@@ -1913,15 +1913,18 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request) ...@@ -1913,15 +1913,18 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request)
struct intel_ringbuffer *ringbuf = request->ringbuf; struct intel_ringbuffer *ringbuf = request->ringbuf;
int ret; int ret;
ret = intel_logical_ring_begin(request, 6 + WA_TAIL_DWORDS); ret = intel_logical_ring_begin(request, 8 + WA_TAIL_DWORDS);
if (ret) if (ret)
return ret; return ret;
/* We're using qword write, seqno should be aligned to 8 bytes. */
BUILD_BUG_ON(I915_GEM_HWS_INDEX & 1);
/* w/a for post sync ops following a GPGPU operation we /* w/a for post sync ops following a GPGPU operation we
* need a prior CS_STALL, which is emitted by the flush * need a prior CS_STALL, which is emitted by the flush
* following the batch. * following the batch.
*/ */
intel_logical_ring_emit(ringbuf, GFX_OP_PIPE_CONTROL(5)); intel_logical_ring_emit(ringbuf, GFX_OP_PIPE_CONTROL(6));
intel_logical_ring_emit(ringbuf, intel_logical_ring_emit(ringbuf,
(PIPE_CONTROL_GLOBAL_GTT_IVB | (PIPE_CONTROL_GLOBAL_GTT_IVB |
PIPE_CONTROL_CS_STALL | PIPE_CONTROL_CS_STALL |
...@@ -1929,7 +1932,10 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request) ...@@ -1929,7 +1932,10 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request)
intel_logical_ring_emit(ringbuf, hws_seqno_address(request->ring)); intel_logical_ring_emit(ringbuf, hws_seqno_address(request->ring));
intel_logical_ring_emit(ringbuf, 0); intel_logical_ring_emit(ringbuf, 0);
intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request)); intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
/* We're thrashing one dword of HWS. */
intel_logical_ring_emit(ringbuf, 0);
intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT); intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
intel_logical_ring_emit(ringbuf, MI_NOOP);
return intel_logical_ring_advance_and_submit(request); return intel_logical_ring_advance_and_submit(request);
} }
......
...@@ -2876,25 +2876,28 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, ...@@ -2876,25 +2876,28 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
const struct drm_plane_state *pstate, const struct drm_plane_state *pstate,
int y) int y)
{ {
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
struct drm_framebuffer *fb = pstate->fb; struct drm_framebuffer *fb = pstate->fb;
uint32_t width = 0, height = 0;
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
if (intel_rotation_90_or_270(pstate->rotation))
swap(width, height);
/* for planar format */ /* for planar format */
if (fb->pixel_format == DRM_FORMAT_NV12) { if (fb->pixel_format == DRM_FORMAT_NV12) {
if (y) /* y-plane data rate */ if (y) /* y-plane data rate */
return intel_crtc->config->pipe_src_w * return width * height *
intel_crtc->config->pipe_src_h *
drm_format_plane_cpp(fb->pixel_format, 0); drm_format_plane_cpp(fb->pixel_format, 0);
else /* uv-plane data rate */ else /* uv-plane data rate */
return (intel_crtc->config->pipe_src_w/2) * return (width / 2) * (height / 2) *
(intel_crtc->config->pipe_src_h/2) *
drm_format_plane_cpp(fb->pixel_format, 1); drm_format_plane_cpp(fb->pixel_format, 1);
} }
/* for packed formats */ /* for packed formats */
return intel_crtc->config->pipe_src_w * return width * height * drm_format_plane_cpp(fb->pixel_format, 0);
intel_crtc->config->pipe_src_h *
drm_format_plane_cpp(fb->pixel_format, 0);
} }
/* /*
...@@ -2973,8 +2976,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, ...@@ -2973,8 +2976,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
struct drm_framebuffer *fb = plane->state->fb; struct drm_framebuffer *fb = plane->state->fb;
int id = skl_wm_plane_id(intel_plane); int id = skl_wm_plane_id(intel_plane);
if (fb == NULL) if (!to_intel_plane_state(plane->state)->visible)
continue; continue;
if (plane->type == DRM_PLANE_TYPE_CURSOR) if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue; continue;
...@@ -3000,7 +3004,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, ...@@ -3000,7 +3004,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
uint16_t plane_blocks, y_plane_blocks = 0; uint16_t plane_blocks, y_plane_blocks = 0;
int id = skl_wm_plane_id(intel_plane); int id = skl_wm_plane_id(intel_plane);
if (pstate->fb == NULL) if (!to_intel_plane_state(pstate)->visible)
continue; continue;
if (plane->type == DRM_PLANE_TYPE_CURSOR) if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue; continue;
...@@ -3123,26 +3127,36 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv, ...@@ -3123,26 +3127,36 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
{ {
struct drm_plane *plane = &intel_plane->base; struct drm_plane *plane = &intel_plane->base;
struct drm_framebuffer *fb = plane->state->fb; struct drm_framebuffer *fb = plane->state->fb;
struct intel_plane_state *intel_pstate =
to_intel_plane_state(plane->state);
uint32_t latency = dev_priv->wm.skl_latency[level]; uint32_t latency = dev_priv->wm.skl_latency[level];
uint32_t method1, method2; uint32_t method1, method2;
uint32_t plane_bytes_per_line, plane_blocks_per_line; uint32_t plane_bytes_per_line, plane_blocks_per_line;
uint32_t res_blocks, res_lines; uint32_t res_blocks, res_lines;
uint32_t selected_result; uint32_t selected_result;
uint8_t cpp; uint8_t cpp;
uint32_t width = 0, height = 0;
if (latency == 0 || !cstate->base.active || !fb) if (latency == 0 || !cstate->base.active || !intel_pstate->visible)
return false; return false;
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
if (intel_rotation_90_or_270(plane->state->rotation))
swap(width, height);
cpp = drm_format_plane_cpp(fb->pixel_format, 0); cpp = drm_format_plane_cpp(fb->pixel_format, 0);
method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate), method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
cpp, latency); cpp, latency);
method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate), method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
cstate->base.adjusted_mode.crtc_htotal, cstate->base.adjusted_mode.crtc_htotal,
cstate->pipe_src_w, width,
cpp, fb->modifier[0], cpp,
fb->modifier[0],
latency); latency);
plane_bytes_per_line = cstate->pipe_src_w * cpp; plane_bytes_per_line = width * cpp;
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
......
...@@ -968,7 +968,7 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) ...@@ -968,7 +968,7 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
/* WaForceContextSaveRestoreNonCoherent:skl,bxt */ /* WaForceContextSaveRestoreNonCoherent:skl,bxt */
tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT; tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT;
if (IS_SKL_REVID(dev, SKL_REVID_F0, SKL_REVID_F0) || if (IS_SKL_REVID(dev, SKL_REVID_F0, REVID_FOREVER) ||
IS_BXT_REVID(dev, BXT_REVID_B0, REVID_FOREVER)) IS_BXT_REVID(dev, BXT_REVID_B0, REVID_FOREVER))
tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE; tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE;
WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp); WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp);
...@@ -1085,7 +1085,8 @@ static int skl_init_workarounds(struct intel_engine_cs *ring) ...@@ -1085,7 +1085,8 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
WA_SET_BIT_MASKED(HIZ_CHICKEN, WA_SET_BIT_MASKED(HIZ_CHICKEN,
BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
if (IS_SKL_REVID(dev, 0, SKL_REVID_F0)) { /* This is tied to WaForceContextSaveRestoreNonCoherent */
if (IS_SKL_REVID(dev, 0, REVID_FOREVER)) {
/* /*
*Use Force Non-Coherent whenever executing a 3D context. This *Use Force Non-Coherent whenever executing a 3D context. This
* is a workaround for a possible hang in the unlikely event * is a workaround for a possible hang in the unlikely event
...@@ -2090,10 +2091,12 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, ...@@ -2090,10 +2091,12 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
{ {
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj = ringbuf->obj; struct drm_i915_gem_object *obj = ringbuf->obj;
/* Ring wraparound at offset 0 sometimes hangs. No idea why. */
unsigned flags = PIN_OFFSET_BIAS | 4096;
int ret; int ret;
if (HAS_LLC(dev_priv) && !obj->stolen) { if (HAS_LLC(dev_priv) && !obj->stolen) {
ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 0); ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, flags);
if (ret) if (ret)
return ret; return ret;
...@@ -2109,7 +2112,8 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, ...@@ -2109,7 +2112,8 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
return -ENOMEM; return -ENOMEM;
} }
} else { } else {
ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE,
flags | PIN_MAPPABLE);
if (ret) if (ret)
return ret; return ret;
...@@ -2454,11 +2458,11 @@ static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes) ...@@ -2454,11 +2458,11 @@ static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes)
if (unlikely(total_bytes > remain_usable)) { if (unlikely(total_bytes > remain_usable)) {
/* /*
* The base request will fit but the reserved space * The base request will fit but the reserved space
* falls off the end. So only need to to wait for the * falls off the end. So don't need an immediate wrap
* reserved size after flushing out the remainder. * and only need to effectively wait for the reserved
* size space from the start of ringbuffer.
*/ */
wait_bytes = remain_actual + ringbuf->reserved_size; wait_bytes = remain_actual + ringbuf->reserved_size;
need_wrap = true;
} else if (total_bytes > ringbuf->space) { } else if (total_bytes > ringbuf->space) {
/* No wrapping required, just waiting. */ /* No wrapping required, just waiting. */
wait_bytes = total_bytes; wait_bytes = total_bytes;
......
...@@ -1189,6 +1189,10 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev) ...@@ -1189,6 +1189,10 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev)
} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
dev_priv->uncore.funcs.force_wake_get = dev_priv->uncore.funcs.force_wake_get =
fw_domains_get_with_thread_status; fw_domains_get_with_thread_status;
if (IS_HASWELL(dev))
dev_priv->uncore.funcs.force_wake_put =
fw_domains_put_with_fifo;
else
dev_priv->uncore.funcs.force_wake_put = fw_domains_put; dev_priv->uncore.funcs.force_wake_put = fw_domains_put;
fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER, fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER,
FORCEWAKE_MT, FORCEWAKE_ACK_HSW); FORCEWAKE_MT, FORCEWAKE_ACK_HSW);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment