From f05816cbbcd0aa0af1efdd888ea6964644197e13 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 10:15:28 +0000 Subject: drm/i915/selftests: Spin on all engines simultaneously Vanshidhar Konda asked for the simplest test "to verify that the kernel can submit and hardware can execute batch buffers on all the command streamers in parallel." We have a number of tests in userspace that submit load to each engine and verify that it is present, but strictly we have no selftest to prove that the kernel can _simultaneously_ execute on all known engines. (We have tests to demonstrate that we can submit to HW in parallel, but we don't insist that they execute in parallel.) v2: Improve the igt_spinner support for older gen. Suggested-by: Vanshidhar Konda Signed-off-by: Chris Wilson Cc: Vanshidhar Konda Cc: Matthew Auld Reviewed-by: Vanshidhar Konda Link: https://patchwork.freedesktop.org/patch/msgid/20191101101528.10553-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 6 +++ drivers/gpu/drm/i915/selftests/i915_request.c | 76 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/selftests/igt_spinner.c | 40 +++++++++++--- 3 files changed, 115 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1e6118f62b29..c84c41159f2b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -891,6 +891,10 @@ struct intel_cdclk_state { u8 voltage_level; }; +struct i915_selftest_stash { + atomic_t counter; +}; + struct drm_i915_private { struct drm_device drm; @@ -1286,6 +1290,8 @@ struct drm_i915_private { /* Mutex to protect the above hdcp component related values. */ struct mutex hdcp_comp_mutex; + I915_SELFTEST_DECLARE(struct i915_selftest_stash selftest;) + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 8618a4dc0701..9e6d3159cd80 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -32,6 +32,7 @@ #include "i915_random.h" #include "i915_selftest.h" #include "igt_live_test.h" +#include "igt_spinner.h" #include "lib_sw_fence.h" #include "mock_drm.h" @@ -1116,12 +1117,85 @@ static int __live_parallel_engineN(void *arg) return 0; } +static bool wake_all(struct drm_i915_private *i915) +{ + if (atomic_dec_and_test(&i915->selftest.counter)) { + wake_up_var(&i915->selftest.counter); + return true; + } + + return false; +} + +static int wait_for_all(struct drm_i915_private *i915) +{ + if (wake_all(i915)) + return 0; + + if (wait_var_event_timeout(&i915->selftest.counter, + !atomic_read(&i915->selftest.counter), + i915_selftest.timeout_jiffies)) + return 0; + + return -ETIME; +} + +static int __live_parallel_spin(void *arg) +{ + struct intel_engine_cs *engine = arg; + struct igt_spinner spin; + struct i915_request *rq; + int err = 0; + + /* + * Create a spinner running for eternity on each engine. If a second + * spinner is incorrectly placed on the same engine, it will not be + * able to start in time. + */ + + if (igt_spinner_init(&spin, engine->gt)) { + wake_all(engine->i915); + return -ENOMEM; + } + + rq = igt_spinner_create_request(&spin, + engine->kernel_context, + MI_NOOP); /* no preemption */ + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + if (err == -ENODEV) + err = 0; + wake_all(engine->i915); + goto out_spin; + } + + i915_request_get(rq); + i915_request_add(rq); + if (igt_wait_for_spinner(&spin, rq)) { + /* Occupy this engine for the whole test */ + err = wait_for_all(engine->i915); + } else { + pr_err("Failed to start spinner on %s\n", engine->name); + err = -EINVAL; + } + igt_spinner_end(&spin); + + if (err == 0 && i915_request_wait(rq, 0, HZ / 5) < 0) + err = -EIO; + i915_request_put(rq); + +out_spin: + igt_spinner_fini(&spin); + return err; +} + static int live_parallel_engines(void *arg) { struct drm_i915_private *i915 = arg; static int (* const func[])(void *arg) = { __live_parallel_engine1, __live_parallel_engineN, + __live_parallel_spin, NULL, }; const unsigned int nengines = num_uabi_engines(i915); @@ -1147,6 +1221,8 @@ static int live_parallel_engines(void *arg) if (err) break; + atomic_set(&i915->selftest.counter, nengines); + idx = 0; for_each_uabi_engine(engine, i915) { tsk[idx] = kthread_run(*fn, engine, diff --git a/drivers/gpu/drm/i915/selftests/igt_spinner.c b/drivers/gpu/drm/i915/selftests/igt_spinner.c index ee8450b871da..e8a58fe49c39 100644 --- a/drivers/gpu/drm/i915/selftests/igt_spinner.c +++ b/drivers/gpu/drm/i915/selftests/igt_spinner.c @@ -15,8 +15,6 @@ int igt_spinner_init(struct igt_spinner *spin, struct intel_gt *gt) void *vaddr; int err; - GEM_BUG_ON(INTEL_GEN(gt->i915) < 8); - memset(spin, 0, sizeof(*spin)); spin->gt = gt; @@ -95,11 +93,15 @@ igt_spinner_create_request(struct igt_spinner *spin, struct intel_engine_cs *engine = ce->engine; struct i915_request *rq = NULL; struct i915_vma *hws, *vma; + unsigned int flags; u32 *batch; int err; GEM_BUG_ON(spin->gt != ce->vm->gt); + if (!intel_engine_can_store_dword(ce->engine)) + return ERR_PTR(-ENODEV); + vma = i915_vma_instance(spin->obj, ce->vm, NULL); if (IS_ERR(vma)) return ERR_CAST(vma); @@ -132,16 +134,37 @@ igt_spinner_create_request(struct igt_spinner *spin, batch = spin->batch; - *batch++ = MI_STORE_DWORD_IMM_GEN4; - *batch++ = lower_32_bits(hws_address(hws, rq)); - *batch++ = upper_32_bits(hws_address(hws, rq)); + if (INTEL_GEN(rq->i915) >= 8) { + *batch++ = MI_STORE_DWORD_IMM_GEN4; + *batch++ = lower_32_bits(hws_address(hws, rq)); + *batch++ = upper_32_bits(hws_address(hws, rq)); + } else if (INTEL_GEN(rq->i915) >= 6) { + *batch++ = MI_STORE_DWORD_IMM_GEN4; + *batch++ = 0; + *batch++ = hws_address(hws, rq); + } else if (INTEL_GEN(rq->i915) >= 4) { + *batch++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT; + *batch++ = 0; + *batch++ = hws_address(hws, rq); + } else { + *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL; + *batch++ = hws_address(hws, rq); + } *batch++ = rq->fence.seqno; *batch++ = arbitration_command; - *batch++ = MI_BATCH_BUFFER_START | 1 << 8 | 1; + if (INTEL_GEN(rq->i915) >= 8) + *batch++ = MI_BATCH_BUFFER_START | BIT(8) | 1; + else if (IS_HASWELL(rq->i915)) + *batch++ = MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW; + else if (INTEL_GEN(rq->i915) >= 6) + *batch++ = MI_BATCH_BUFFER_START; + else + *batch++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT; *batch++ = lower_32_bits(vma->node.start); *batch++ = upper_32_bits(vma->node.start); + *batch++ = MI_BATCH_BUFFER_END; /* not reached */ intel_gt_chipset_flush(engine->gt); @@ -153,7 +176,10 @@ igt_spinner_create_request(struct igt_spinner *spin, goto cancel_rq; } - err = engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0); + flags = 0; + if (INTEL_GEN(rq->i915) <= 5) + flags |= I915_DISPATCH_SECURE; + err = engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, flags); cancel_rq: if (err) { -- cgit v1.2.3 From 3558cafc31ce8e582f37cf884a7f28c100f5138e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:25:59 +0100 Subject: drm/i915: Handle a few more cases for crtc hw/uapi split, v3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are still looking at drm_crtc_state in a few places, convert those to use intel_crtc_state instead. Changes since v1: - Move to before uapi/hw split. - Add hunks for intel_pm.c as well. Changes since v2: - Incorporate Ville's feedback. Signed-off-by: Maarten Lankhorst Reviewed-by: Matt Roper Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 15 ++++++++------- drivers/gpu/drm/i915/display/intel_dp_mst.c | 12 ++++++++---- drivers/gpu/drm/i915/display/intel_psr.c | 16 +++++++--------- drivers/gpu/drm/i915/intel_pm.c | 6 ++---- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 348ce0456696..9b7c5596d74a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -16714,8 +16714,7 @@ static int intel_initial_commit(struct drm_device *dev) { struct drm_atomic_state *state = NULL; struct drm_modeset_acquire_ctx ctx; - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; + struct intel_crtc *crtc; int ret = 0; state = drm_atomic_state_alloc(dev); @@ -16727,15 +16726,17 @@ static int intel_initial_commit(struct drm_device *dev) retry: state->acquire_ctx = &ctx; - drm_for_each_crtc(crtc, dev) { - crtc_state = drm_atomic_get_crtc_state(state, crtc); + for_each_intel_crtc(dev, crtc) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { ret = PTR_ERR(crtc_state); goto out; } - if (crtc_state->active) { - ret = drm_atomic_add_affected_planes(state, crtc); + if (crtc_state->base.active) { + ret = drm_atomic_add_affected_planes(state, &crtc->base); if (ret) goto out; @@ -16745,7 +16746,7 @@ retry: * having a proper LUT loaded. Remove once we * have readout for pipe gamma enable. */ - crtc_state->color_mgmt_changed = true; + crtc_state->base.color_mgmt_changed = true; } } diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 715b7109c388..00a5540fe250 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -168,7 +168,6 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_crtc *new_crtc = new_conn_state->crtc; - struct drm_crtc_state *crtc_state; struct drm_dp_mst_topology_mgr *mgr; int ret; @@ -183,11 +182,16 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, * connector */ if (new_crtc) { - crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); + struct intel_atomic_state *intel_state = + to_intel_atomic_state(state); + struct intel_crtc *intel_crtc = to_intel_crtc(new_crtc); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(intel_state, + intel_crtc); if (!crtc_state || - !drm_atomic_crtc_needs_modeset(crtc_state) || - crtc_state->enable) + !drm_atomic_crtc_needs_modeset(&crtc_state->base) || + crtc_state->base.enable) return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 6a9f322d3fca..359a60762b49 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -26,6 +26,7 @@ #include "display/intel_dp.h" #include "i915_drv.h" +#include "intel_atomic.h" #include "intel_display_types.h" #include "intel_psr.h" #include "intel_sprite.h" @@ -1096,7 +1097,7 @@ static int intel_psr_fastset_force(struct drm_i915_private *dev_priv) struct drm_device *dev = &dev_priv->drm; struct drm_modeset_acquire_ctx ctx; struct drm_atomic_state *state; - struct drm_crtc *crtc; + struct intel_crtc *crtc; int err; state = drm_atomic_state_alloc(dev); @@ -1107,21 +1108,18 @@ static int intel_psr_fastset_force(struct drm_i915_private *dev_priv) state->acquire_ctx = &ctx; retry: - drm_for_each_crtc(crtc, dev) { - struct drm_crtc_state *crtc_state; - struct intel_crtc_state *intel_crtc_state; + for_each_intel_crtc(dev, crtc) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_crtc_state(state, crtc); - crtc_state = drm_atomic_get_crtc_state(state, crtc); if (IS_ERR(crtc_state)) { err = PTR_ERR(crtc_state); goto error; } - intel_crtc_state = to_intel_crtc_state(crtc_state); - - if (crtc_state->active && intel_crtc_state->has_psr) { + if (crtc_state->base.active && crtc_state->has_psr) { /* Mark mode as changed to trigger a pipe->update() */ - crtc_state->mode_changed = true; + crtc_state->base.mode_changed = true; break; } } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5d2b460d3ee5..d6aed8860db7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3073,11 +3073,9 @@ static bool ilk_validate_pipe_wm(const struct drm_i915_private *dev_priv, /* Compute new watermarks for the pipe */ static int ilk_compute_pipe_wm(struct intel_crtc_state *crtc_state) { - struct drm_atomic_state *state = crtc_state->base.state; + struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); struct intel_pipe_wm *pipe_wm; - struct drm_device *dev = state->dev; - const struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *plane; const struct intel_plane_state *plane_state; const struct intel_plane_state *pristate = NULL; @@ -3772,7 +3770,7 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state) crtc = intel_get_crtc_for_pipe(dev_priv, pipe); crtc_state = to_intel_crtc_state(crtc->base.state); - if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) return false; for_each_intel_plane_on_crtc(dev, crtc, plane) { -- cgit v1.2.3 From 2b808b3a27d1182a26182d622bb1b292fd4ed1f0 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:00 +0100 Subject: drm/i915: Add aliases for uapi and hw to crtc_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare to split up hw and uapi machinally, by adding a uapi and hw alias. We will remove the base in a bit. This is a split from the original uapi/hw patch, which did it all in one go. Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-2-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_atomic.c | 8 +++++-- drivers/gpu/drm/i915/display/intel_display.c | 2 ++ drivers/gpu/drm/i915/display/intel_display.h | 6 ++--- drivers/gpu/drm/i915/display/intel_display_types.h | 27 +++++++++++++++++++++- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 9cd6d2348a1e..4826aa4ee8e7 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -186,9 +186,10 @@ intel_digital_connector_duplicate_state(struct drm_connector *connector) struct drm_crtc_state * intel_crtc_duplicate_state(struct drm_crtc *crtc) { + const struct intel_crtc_state *old_crtc_state = to_intel_crtc_state(crtc->state); struct intel_crtc_state *crtc_state; - crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), GFP_KERNEL); + crtc_state = kmemdup(old_crtc_state, sizeof(*crtc_state), GFP_KERNEL); if (!crtc_state) return NULL; @@ -219,7 +220,10 @@ void intel_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { - drm_atomic_helper_crtc_destroy_state(crtc, state); + struct intel_crtc_state *crtc_state = to_intel_crtc_state(state); + + __drm_atomic_helper_crtc_destroy_state(&crtc_state->base); + kfree(crtc_state); } static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9b7c5596d74a..88e81fad36f1 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -12592,6 +12592,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) /* Keep base drm_crtc_state intact, only clear our extended struct */ BUILD_BUG_ON(offsetof(struct intel_crtc_state, base)); + BUILD_BUG_ON(offsetof(struct intel_crtc_state, uapi)); + BUILD_BUG_ON(offsetof(struct intel_crtc_state, hw)); memcpy(&crtc_state->base + 1, &saved_state->base + 1, sizeof(*crtc_state) - sizeof(crtc_state->base)); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 355c50088589..476bc71e6a83 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -447,10 +447,10 @@ enum phy_fia { #define intel_atomic_crtc_state_for_each_plane_state( \ plane, plane_state, \ crtc_state) \ - for_each_intel_plane_mask(((crtc_state)->base.state->dev), (plane), \ - ((crtc_state)->base.plane_mask)) \ + for_each_intel_plane_mask(((crtc_state)->uapi.state->dev), (plane), \ + ((crtc_state)->uapi.plane_mask)) \ for_each_if ((plane_state = \ - to_intel_plane_state(__drm_atomic_get_current_plane_state((crtc_state)->base.state, &plane->base)))) + to_intel_plane_state(__drm_atomic_get_current_plane_state((crtc_state)->uapi.state, &plane->base)))) void intel_link_compute_m_n(u16 bpp, int nlanes, int pixel_clock, int link_clock, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 4341bd66a418..285b17c9d8d0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -757,7 +757,32 @@ enum intel_output_format { }; struct intel_crtc_state { + union { struct drm_crtc_state base; + /* + * uapi (drm) state. This is the software state shown to userspace. + * In particular, the following members are used for bookkeeping: + * - crtc + * - state + * - *_changed + * - event + * - commit + * - mode_blob + */ + struct drm_crtc_state uapi; + + /* + * actual hardware state, the state we program to the hardware. + * The following members are used to verify the hardware state: + * - enable + * - active + * - mode / adjusted_mode + * - color property blobs. + * + * During initial hw readout, they need to be copied to uapi. + */ + struct drm_crtc_state hw; + }; /** * quirks - bitfield with hw state readout quirks @@ -1112,7 +1137,7 @@ struct cxsr_latency { #define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base) #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) -#define to_intel_crtc_state(x) container_of(x, struct intel_crtc_state, base) +#define to_intel_crtc_state(x) container_of(x, struct intel_crtc_state, uapi) #define to_intel_connector(x) container_of(x, struct intel_connector, base) #define to_intel_encoder(x) container_of(x, struct intel_encoder, base) #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) -- cgit v1.2.3 From aa42a50add1538c8c823232ee32b7096790b41c8 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:01 +0100 Subject: drm/i915: Perform manual conversions for crtc uapi/hw split, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_get_load_detect_pipe() needs to set uapi active, uapi enable is set by the call to drm_atomic_set_mode_for_crtc(), so we can remove it. intel_pipe_config_compare() needs to look at hw state, but I didn't change spatch to look at it. It's easy enough to do manually. intel_atomic_check() definitely needs to check for uapi enable, otherwise intel_modeset_pipe_config cannot copy uapi state to hw. Changes since v1: - Actually set uapi.active in get_load_detect_pipe(). Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-3-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 88e81fad36f1..6033c927c3d6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -11432,7 +11432,7 @@ found: goto fail; } - crtc_state->base.active = crtc_state->base.enable = true; + crtc_state->uapi.active = true; ret = drm_atomic_set_mode_for_crtc(&crtc_state->base, &load_detect_mode); @@ -13077,19 +13077,19 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(output_types); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_start); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_end); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_start); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vdisplay); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vtotal); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_start); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_end); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_start); - PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end); PIPE_CONF_CHECK_I(pixel_multiplier); PIPE_CONF_CHECK_I(output_format); @@ -13106,17 +13106,17 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); - PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, DRM_MODE_FLAG_INTERLACE); if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { - PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, DRM_MODE_FLAG_PHSYNC); - PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, DRM_MODE_FLAG_NHSYNC); - PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, DRM_MODE_FLAG_PVSYNC); - PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags, + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, DRM_MODE_FLAG_NVSYNC); } @@ -13155,7 +13155,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, bp_gamma = intel_color_get_gamma_bit_precision(pipe_config); if (bp_gamma) - PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, base.gamma_lut, bp_gamma); + PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, hw.gamma_lut, bp_gamma); } @@ -13200,7 +13200,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) PIPE_CONF_CHECK_I(pipe_bpp); - PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); PIPE_CONF_CHECK_I(min_voltage_level); @@ -14007,7 +14007,7 @@ static int intel_atomic_check(struct drm_device *dev, if (!needs_modeset(new_crtc_state)) continue; - if (!new_crtc_state->base.enable) { + if (!new_crtc_state->uapi.enable) { any_ms = true; continue; } -- cgit v1.2.3 From 1326a92c346641dc7e600a573295ac4e675368f1 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:02 +0100 Subject: drm/i915: Perform automated conversions for crtc uapi/hw split, base -> hw. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split up crtc_state->base to hw where appropriate. This is done using the following patch: @@ struct intel_crtc_state *T; identifier x =~ "^(active|enable|degamma_lut|gamma_lut|ctm|mode|adjusted_mode)$"; @@ -T->base.x +T->hw.x @@ struct drm_crtc_state *T; identifier x =~ "^(active|enable|degamma_lut|gamma_lut|ctm|mode|adjusted_mode)$"; @@ -to_intel_crtc_state(T)->base.x +to_intel_crtc_state(T)->hw.x Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-4-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 12 +- drivers/gpu/drm/i915/display/intel_audio.c | 4 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 8 +- drivers/gpu/drm/i915/display/intel_color.c | 108 +++++------ drivers/gpu/drm/i915/display/intel_crt.c | 18 +- drivers/gpu/drm/i915/display/intel_ddi.c | 18 +- drivers/gpu/drm/i915/display/intel_display.c | 259 +++++++++++++------------- drivers/gpu/drm/i915/display/intel_dp.c | 22 +-- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 +- drivers/gpu/drm/i915/display/intel_dvo.c | 12 +- drivers/gpu/drm/i915/display/intel_fbc.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 20 +- drivers/gpu/drm/i915/display/intel_lspcon.c | 4 +- drivers/gpu/drm/i915/display/intel_lvds.c | 8 +- drivers/gpu/drm/i915/display/intel_panel.c | 8 +- drivers/gpu/drm/i915/display/intel_pipe_crc.c | 2 +- drivers/gpu/drm/i915/display/intel_psr.c | 12 +- drivers/gpu/drm/i915/display/intel_sdvo.c | 16 +- drivers/gpu/drm/i915/display/intel_sprite.c | 8 +- drivers/gpu/drm/i915/display/intel_tv.c | 4 +- drivers/gpu/drm/i915/display/intel_vdsc.c | 4 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 10 +- drivers/gpu/drm/i915/i915_debugfs.c | 8 +- drivers/gpu/drm/i915/intel_pm.c | 56 +++--- 24 files changed, 316 insertions(+), 313 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 325df29b0447..e62dfabc3cd0 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -276,7 +276,7 @@ static void configure_dual_link_mode(struct intel_encoder *encoder, if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) { const struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; u32 dss_ctl2; u16 hactive = adjusted_mode->crtc_hdisplay; u16 dl_buffer_depth; @@ -768,7 +768,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); const struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; enum port port; enum transcoder dsi_trans; /* horizontal timings */ @@ -1216,7 +1216,7 @@ static void gen11_dsi_get_timings(struct intel_encoder *encoder, { struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; if (intel_dsi->dual_link) { adjusted_mode->crtc_hdisplay *= 2; @@ -1249,9 +1249,9 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder, pipe_config->port_clock = cnl_calc_wrpll_link(dev_priv, &pipe_config->dpll_hw_state); - pipe_config->base.adjusted_mode.crtc_clock = intel_dsi->pclk; + pipe_config->hw.adjusted_mode.crtc_clock = intel_dsi->pclk; if (intel_dsi->dual_link) - pipe_config->base.adjusted_mode.crtc_clock *= 2; + pipe_config->hw.adjusted_mode.crtc_clock *= 2; gen11_dsi_get_timings(encoder, pipe_config); pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI); @@ -1269,7 +1269,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; intel_fixed_panel_mode(fixed_mode, adjusted_mode); diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 85e6b2bbb34f..6740191d3557 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -234,7 +234,7 @@ static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = { static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state) { const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; int i; for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { @@ -695,7 +695,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_connector *connector = conn_state->connector; const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; enum port port = encoder->port; enum pipe pipe = crtc->pipe; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 0caef2592a7e..304fd650a74c 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1937,7 +1937,7 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) to_i915(crtc_state->base.crtc->dev); int min_cdclk; - if (!crtc_state->base.enable) + if (!crtc_state->hw.enable) return 0; min_cdclk = intel_pixel_rate_to_cdclk(crtc_state); @@ -2074,7 +2074,7 @@ static int bxt_compute_min_voltage_level(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { int ret; - if (crtc_state->base.enable) + if (crtc_state->hw.enable) min_voltage_level = crtc_state->min_voltage_level; else min_voltage_level = 0; @@ -2168,7 +2168,7 @@ static int skl_dpll0_vco(struct intel_atomic_state *state) vco = dev_priv->skl_preferred_vco_freq; for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { - if (!crtc_state->base.enable) + if (!crtc_state->hw.enable) continue; if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) @@ -2281,7 +2281,7 @@ static int intel_modeset_all_pipes(struct intel_atomic_state *state) if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); - if (!crtc_state->base.active || + if (!crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&crtc_state->base)) continue; diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index fa44eb73d088..62cc2d9df39f 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -117,10 +117,10 @@ static bool lut_is_legacy(const struct drm_property_blob *lut) static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state) { - return !crtc_state->base.degamma_lut && - !crtc_state->base.ctm && - crtc_state->base.gamma_lut && - lut_is_legacy(crtc_state->base.gamma_lut); + return !crtc_state->hw.degamma_lut && + !crtc_state->hw.ctm && + crtc_state->hw.gamma_lut && + lut_is_legacy(crtc_state->hw.gamma_lut); } /* @@ -219,7 +219,7 @@ static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state) static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state, u16 coeffs[9]) { - const struct drm_color_ctm *ctm = crtc_state->base.ctm->data; + const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data; const u64 *input; u64 temp[9]; int i; @@ -274,7 +274,7 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); bool limited_color_range = ilk_csc_limited_range(crtc_state); - if (crtc_state->base.ctm) { + if (crtc_state->hw.ctm) { u16 coeff[9]; ilk_csc_convert_ctm(crtc_state, coeff); @@ -312,7 +312,7 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - if (crtc_state->base.ctm) { + if (crtc_state->hw.ctm) { u16 coeff[9]; ilk_csc_convert_ctm(crtc_state, coeff); @@ -342,8 +342,8 @@ static void cherryview_load_csc_matrix(const struct intel_crtc_state *crtc_state struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - if (crtc_state->base.ctm) { - const struct drm_color_ctm *ctm = crtc_state->base.ctm->data; + if (crtc_state->hw.ctm) { + const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data; u16 coeffs[9] = {}; int i; @@ -435,7 +435,7 @@ static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state, static void i9xx_load_luts(const struct intel_crtc_state *crtc_state) { - i9xx_load_luts_internal(crtc_state, crtc_state->base.gamma_lut); + i9xx_load_luts_internal(crtc_state, crtc_state->hw.gamma_lut); } static void i9xx_color_commit(const struct intel_crtc_state *crtc_state) @@ -525,7 +525,7 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc, static void i965_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut; + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) i9xx_load_luts(crtc_state); @@ -548,7 +548,7 @@ static void ilk_load_lut_10(struct intel_crtc *crtc, static void ilk_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut; + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) i9xx_load_luts(crtc_state); @@ -655,8 +655,8 @@ static void ivb_load_lut_ext_max(struct intel_crtc *crtc) static void ivb_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut; - const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut; + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) { i9xx_load_luts(crtc_state); @@ -678,8 +678,8 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state) static void bdw_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut; - const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut; + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) { i9xx_load_luts(crtc_state); @@ -704,7 +704,7 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size; - const struct drm_color_lut *lut = crtc_state->base.degamma_lut->data; + const struct drm_color_lut *lut = crtc_state->hw.degamma_lut->data; u32 i; /* @@ -766,7 +766,7 @@ static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_stat static void glk_load_luts(const struct intel_crtc_state *crtc_state) { - const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut; + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); /* @@ -777,7 +777,7 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state) * the degama LUT so that we don't have to reload * it every time the pipe CSC is being enabled. */ - if (crtc_state->base.degamma_lut) + if (crtc_state->hw.degamma_lut) glk_load_degamma_lut(crtc_state); else glk_load_degamma_lut_linear(crtc_state); @@ -823,7 +823,7 @@ static void icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_property_blob *blob = crtc_state->base.gamma_lut; + const struct drm_property_blob *blob = crtc_state->hw.gamma_lut; const struct drm_color_lut *lut = blob->data; struct intel_dsb *dsb = intel_dsb_get(crtc); enum pipe pipe = crtc->pipe; @@ -855,7 +855,7 @@ static void icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_property_blob *blob = crtc_state->base.gamma_lut; + const struct drm_property_blob *blob = crtc_state->hw.gamma_lut; const struct drm_color_lut *lut = blob->data; const struct drm_color_lut *entry; struct intel_dsb *dsb = intel_dsb_get(crtc); @@ -910,11 +910,11 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) static void icl_load_luts(const struct intel_crtc_state *crtc_state) { - const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut; + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct intel_dsb *dsb = intel_dsb_get(crtc); - if (crtc_state->base.degamma_lut) + if (crtc_state->hw.degamma_lut) glk_load_degamma_lut(crtc_state); switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) { @@ -991,8 +991,8 @@ static void chv_load_cgm_gamma(struct intel_crtc *crtc, static void chv_load_luts(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut; - const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut; + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; cherryview_load_csc_matrix(crtc_state); @@ -1063,7 +1063,7 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) intel_atomic_get_old_crtc_state(state, crtc); struct intel_plane *plane; - if (!new_crtc_state->base.active || + if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) return 0; @@ -1107,8 +1107,8 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected) static int check_luts(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut; - const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut; + const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; + const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; u32 gamma_tests, degamma_tests; @@ -1156,7 +1156,7 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state) return ret; crtc_state->gamma_enable = - crtc_state->base.gamma_lut && + crtc_state->hw.gamma_lut && !crtc_state->c8_planes; crtc_state->gamma_mode = i9xx_gamma_mode(crtc_state); @@ -1175,11 +1175,11 @@ static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state) if (crtc_state_is_legacy_gamma(crtc_state)) return 0; - if (crtc_state->base.degamma_lut) + if (crtc_state->hw.degamma_lut) cgm_mode |= CGM_PIPE_MODE_DEGAMMA; - if (crtc_state->base.ctm) + if (crtc_state->hw.ctm) cgm_mode |= CGM_PIPE_MODE_CSC; - if (crtc_state->base.gamma_lut) + if (crtc_state->hw.gamma_lut) cgm_mode |= CGM_PIPE_MODE_GAMMA; return cgm_mode; @@ -1253,7 +1253,7 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) return ret; crtc_state->gamma_enable = - crtc_state->base.gamma_lut && + crtc_state->hw.gamma_lut && !crtc_state->c8_planes; /* @@ -1279,8 +1279,8 @@ static u32 ivb_gamma_mode(const struct intel_crtc_state *crtc_state) if (!crtc_state->gamma_enable || crtc_state_is_legacy_gamma(crtc_state)) return GAMMA_MODE_MODE_8BIT; - else if (crtc_state->base.gamma_lut && - crtc_state->base.degamma_lut) + else if (crtc_state->hw.gamma_lut && + crtc_state->hw.degamma_lut) return GAMMA_MODE_MODE_SPLIT; else return GAMMA_MODE_MODE_10BIT; @@ -1294,7 +1294,7 @@ static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state) * CSC comes after the LUT in degamma, RGB->YCbCr, * and RGB full->limited range mode. */ - if (crtc_state->base.degamma_lut || + if (crtc_state->hw.degamma_lut || crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || limited_color_range) return 0; @@ -1312,13 +1312,13 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) return ret; crtc_state->gamma_enable = - (crtc_state->base.gamma_lut || - crtc_state->base.degamma_lut) && + (crtc_state->hw.gamma_lut || + crtc_state->hw.degamma_lut) && !crtc_state->c8_planes; crtc_state->csc_enable = crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || - crtc_state->base.ctm || limited_color_range; + crtc_state->hw.ctm || limited_color_range; crtc_state->gamma_mode = ivb_gamma_mode(crtc_state); @@ -1349,14 +1349,14 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) return ret; crtc_state->gamma_enable = - crtc_state->base.gamma_lut && + crtc_state->hw.gamma_lut && !crtc_state->c8_planes; /* On GLK+ degamma LUT is controlled by csc_enable */ crtc_state->csc_enable = - crtc_state->base.degamma_lut || + crtc_state->hw.degamma_lut || crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || - crtc_state->base.ctm || crtc_state->limited_color_range; + crtc_state->hw.ctm || crtc_state->limited_color_range; crtc_state->gamma_mode = glk_gamma_mode(crtc_state); @@ -1373,14 +1373,14 @@ static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state) { u32 gamma_mode = 0; - if (crtc_state->base.degamma_lut) + if (crtc_state->hw.degamma_lut) gamma_mode |= PRE_CSC_GAMMA_ENABLE; - if (crtc_state->base.gamma_lut && + if (crtc_state->hw.gamma_lut && !crtc_state->c8_planes) gamma_mode |= POST_CSC_GAMMA_ENABLE; - if (!crtc_state->base.gamma_lut || + if (!crtc_state->hw.gamma_lut || crtc_state_is_legacy_gamma(crtc_state)) gamma_mode |= GAMMA_MODE_MODE_8BIT; else @@ -1393,7 +1393,7 @@ static u32 icl_csc_mode(const struct intel_crtc_state *crtc_state) { u32 csc_mode = 0; - if (crtc_state->base.ctm) + if (crtc_state->hw.ctm) csc_mode |= ICL_CSC_ENABLE; if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB || @@ -1622,7 +1622,7 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state) if (!crtc_state->gamma_enable) return; - crtc_state->base.gamma_lut = i9xx_read_lut_8(crtc_state); + crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state); } static struct drm_property_blob * @@ -1672,9 +1672,9 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) return; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) - crtc_state->base.gamma_lut = i9xx_read_lut_8(crtc_state); + crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state); else - crtc_state->base.gamma_lut = i965_read_lut_10p6(crtc_state); + crtc_state->hw.gamma_lut = i965_read_lut_10p6(crtc_state); } static struct drm_property_blob * @@ -1714,7 +1714,7 @@ chv_read_cgm_lut(const struct intel_crtc_state *crtc_state) static void chv_read_luts(struct intel_crtc_state *crtc_state) { if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA) - crtc_state->base.gamma_lut = chv_read_cgm_lut(crtc_state); + crtc_state->hw.gamma_lut = chv_read_cgm_lut(crtc_state); else i965_read_luts(crtc_state); } @@ -1761,9 +1761,9 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state) return; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) - crtc_state->base.gamma_lut = i9xx_read_lut_8(crtc_state); + crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state); else - crtc_state->base.gamma_lut = ilk_read_lut_10(crtc_state); + crtc_state->hw.gamma_lut = ilk_read_lut_10(crtc_state); } static struct drm_property_blob * @@ -1810,9 +1810,9 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state) return; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) - crtc_state->base.gamma_lut = i9xx_read_lut_8(crtc_state); + crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state); else - crtc_state->base.gamma_lut = glk_read_lut_10(crtc_state, PAL_PREC_INDEX_VALUE(0)); + crtc_state->hw.gamma_lut = glk_read_lut_10(crtc_state, PAL_PREC_INDEX_VALUE(0)); } void intel_color_init(struct intel_crtc *crtc) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 39cc6d79dc85..6e824c80dcbf 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -132,9 +132,9 @@ static void intel_crt_get_config(struct intel_encoder *encoder, { pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG); - pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); + pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder); - pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; + pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock; } static void hsw_crt_get_config(struct intel_encoder *encoder, @@ -144,13 +144,13 @@ static void hsw_crt_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, pipe_config); - pipe_config->base.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | + pipe_config->hw.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC); - pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); + pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder); - pipe_config->base.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv); + pipe_config->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv); } /* Note: The caller is required to filter out dpms modes not supported by the @@ -162,7 +162,7 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crt *crt = intel_encoder_to_crt(encoder); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 adpa; if (INTEL_GEN(dev_priv) >= 5) @@ -358,7 +358,7 @@ static int intel_crt_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; @@ -373,7 +373,7 @@ static int pch_crt_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; @@ -390,7 +390,7 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index b51f244ad7a5..7df02be169d1 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1528,7 +1528,7 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) if (pipe_config->pixel_multiplier) dotclock /= pipe_config->pixel_multiplier; - pipe_config->base.adjusted_mode.crtc_clock = dotclock; + pipe_config->hw.adjusted_mode.crtc_clock = dotclock; } static void icl_ddi_clock_get(struct intel_encoder *encoder, @@ -1860,9 +1860,9 @@ intel_ddi_transcoder_func_reg_val_get(const struct intel_crtc_state *crtc_state) BUG(); } - if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC) + if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC) temp |= TRANS_DDI_PVSYNC; - if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC) + if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC) temp |= TRANS_DDI_PHSYNC; if (cpu_transcoder == TRANSCODER_EDP) { @@ -3376,7 +3376,7 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder, { u32 exit_scanlines; struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); - u32 crtc_vdisplay = cstate->base.adjusted_mode.crtc_vdisplay; + u32 crtc_vdisplay = cstate->hw.adjusted_mode.crtc_vdisplay; cstate->dc3co_exitline = 0; @@ -3388,7 +3388,7 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder, encoder->port != PORT_A) return; - if (!cstate->has_psr2 || !cstate->base.active) + if (!cstate->has_psr2 || !cstate->hw.active) return; /* @@ -3396,7 +3396,7 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder, * PSR2 transcoder Early Exit scanlines = ROUNDUP(200 / line time) + 1 */ exit_scanlines = - intel_usecs_to_scanlines(&cstate->base.adjusted_mode, 200) + 1; + intel_usecs_to_scanlines(&cstate->hw.adjusted_mode, 200) + 1; if (WARN_ON(exit_scanlines > crtc_vdisplay)) return; @@ -4083,7 +4083,7 @@ intel_ddi_update_prepare(struct intel_atomic_state *state, WARN_ON(crtc && crtc->active); intel_tc_port_get_link(enc_to_dig_port(&encoder->base), required_lanes); - if (crtc_state && crtc_state->base.active) + if (crtc_state && crtc_state->hw.active) intel_update_active_dpll(state, crtc, encoder); } @@ -4231,7 +4231,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, else flags |= DRM_MODE_FLAG_NVSYNC; - pipe_config->base.adjusted_mode.flags |= flags; + pipe_config->hw.adjusted_mode.flags |= flags; switch (temp & TRANS_DDI_BPC_MASK) { case TRANS_DDI_BPC_6: @@ -4514,7 +4514,7 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder, WARN_ON(!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)); - if (!crtc_state->base.active) + if (!crtc_state->hw.active) return 0; if (!crtc_state->hdmi_high_tmds_clock_ratio && diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6033c927c3d6..2d7b1a1301a1 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1040,7 +1040,7 @@ bool intel_crtc_active(struct intel_crtc *crtc) * for atomic. */ return crtc->active && crtc->base.primary->state->fb && - crtc->config->base.adjusted_mode.crtc_clock; + crtc->config->hw.adjusted_mode.crtc_clock; } enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, @@ -5086,7 +5086,7 @@ static void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int clock = crtc_state->base.adjusted_mode.crtc_clock; + int clock = crtc_state->hw.adjusted_mode.crtc_clock; u32 divsel, phaseinc, auxdiv, phasedir = 0; u32 temp; @@ -5359,7 +5359,7 @@ static void ironlake_pch_enable(const struct intel_atomic_state *state, if (HAS_PCH_CPT(dev_priv) && intel_crtc_has_dp_encoder(crtc_state)) { const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; i915_reg_t reg = TRANS_DP_CTL(pipe); enum port port; @@ -5509,7 +5509,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, to_intel_crtc(crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; /* * Src coordinates are already rotated by 270 degrees for @@ -5525,7 +5525,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, * Once NV12 is enabled, handle it here while allocating scaler * for NV12. */ - if (INTEL_GEN(dev_priv) >= 9 && crtc_state->base.enable && + if (INTEL_GEN(dev_priv) >= 9 && crtc_state->hw.enable && need_scaler && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { DRM_DEBUG_KMS("Pipe/Plane scaling not supported with IF-ID mode\n"); return -EINVAL; @@ -5597,13 +5597,13 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, */ int skl_update_scaler_crtc(struct intel_crtc_state *state) { - const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &state->hw.adjusted_mode; bool need_scaler = false; if (state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) need_scaler = true; - return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX, + return skl_update_scaler(state, !state->hw.active, SKL_CRTC_INDEX, &state->scaler_state.scaler_id, state->pipe_src_w, state->pipe_src_h, adjusted_mode->crtc_hdisplay, @@ -5958,7 +5958,7 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s * forcibly enable IPS on the first fastset. */ if (new_crtc_state->update_pipe && - old_crtc_state->base.adjusted_mode.private_flags & I915_MODE_FLAG_INHERITED) + old_crtc_state->hw.adjusted_mode.private_flags & I915_MODE_FLAG_INHERITED) return true; return !old_crtc_state->ips_enabled; @@ -6002,7 +6002,7 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) intel_frontbuffer_flip(to_i915(crtc->base.dev), pipe_config->fb_bits); - if (pipe_config->update_wm_post && pipe_config->base.active) + if (pipe_config->update_wm_post && pipe_config->hw.active) intel_update_watermarks(crtc); if (hsw_post_update_enable_ips(old_crtc_state, pipe_config)) @@ -6080,7 +6080,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, * event which is after the vblank start event, so we need to have a * wait-for-vblank between disabling the plane and the pipe. */ - if (HAS_GMCH(dev_priv) && old_crtc_state->base.active && + if (HAS_GMCH(dev_priv) && old_crtc_state->hw.active && pipe_config->disable_cxsr && intel_set_memory_cxsr(dev_priv, false)) intel_wait_for_vblank(dev_priv, crtc->pipe); @@ -6092,7 +6092,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, * WaCxSRDisabledForSpriteScaling:ivb */ if (pipe_config->disable_lp_wm && ilk_disable_lp_wm(dev) && - old_crtc_state->base.active) + old_crtc_state->hw.active) intel_wait_for_vblank(dev_priv, crtc->pipe); /* @@ -6896,7 +6896,7 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state) u64 mask; enum transcoder transcoder = crtc_state->cpu_transcoder; - if (!crtc_state->base.active) + if (!crtc_state->hw.active) return 0; mask = BIT_ULL(POWER_DOMAIN_PIPE(pipe)); @@ -7253,8 +7253,8 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state, if (!crtc_state) return; - I915_STATE_WARN(!crtc_state->base.active, - "connector is active, but attached crtc isn't\n"); + I915_STATE_WARN(!crtc_state->hw.active, + "connector is active, but attached crtc isn't\n"); if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST) return; @@ -7265,8 +7265,8 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state, I915_STATE_WARN(conn_state->crtc != encoder->base.crtc, "attached encoder crtc differs from connector crtc\n"); } else { - I915_STATE_WARN(crtc_state && crtc_state->base.active, - "attached crtc is active, but connector isn't\n"); + I915_STATE_WARN(crtc_state && crtc_state->hw.active, + "attached crtc is active, but connector isn't\n"); I915_STATE_WARN(!crtc_state && conn_state->best_encoder, "best encoder set without crtc!\n"); } @@ -7274,7 +7274,7 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state, static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state) { - if (crtc_state->base.enable && crtc_state->has_pch_encoder) + if (crtc_state->hw.enable && crtc_state->has_pch_encoder) return crtc_state->fdi_lanes; return 0; @@ -7357,7 +7357,7 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, struct intel_crtc_state *pipe_config) { struct drm_device *dev = intel_crtc->base.dev; - const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int lane, link_bw, fdi_dotclock, ret; bool needs_recompute = false; @@ -7474,7 +7474,7 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config) { u32 pixel_rate; - pixel_rate = pipe_config->base.adjusted_mode.crtc_clock; + pixel_rate = pipe_config->hw.adjusted_mode.crtc_clock; /* * We only use IF-ID interlacing. If we ever use @@ -7512,7 +7512,7 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) if (HAS_GMCH(dev_priv)) /* FIXME calculate proper pipe pixel rate for GMCH pfit */ crtc_state->pixel_rate = - crtc_state->base.adjusted_mode.crtc_clock; + crtc_state->hw.adjusted_mode.crtc_clock; else crtc_state->pixel_rate = ilk_pipe_pixel_rate(crtc_state); @@ -7522,7 +7522,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int clock_limit = dev_priv->max_dotclk_freq; if (INTEL_GEN(dev_priv) < 4) { @@ -7548,7 +7548,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, if ((pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 || pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) && - pipe_config->base.ctm) { + pipe_config->hw.ctm) { /* * There is only one pipe CSC unit per pipe, and we need that * for output conversion from RGB->YCBCR. So if CTM is already @@ -8246,7 +8246,7 @@ static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 crtc_vtotal, crtc_vblank_end; int vsyncshift = 0; @@ -8340,39 +8340,39 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc, u32 tmp; tmp = I915_READ(HTOTAL(cpu_transcoder)); - pipe_config->base.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1; - pipe_config->base.adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1; + pipe_config->hw.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1; + pipe_config->hw.adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1; if (!transcoder_is_dsi(cpu_transcoder)) { tmp = I915_READ(HBLANK(cpu_transcoder)); - pipe_config->base.adjusted_mode.crtc_hblank_start = + pipe_config->hw.adjusted_mode.crtc_hblank_start = (tmp & 0xffff) + 1; - pipe_config->base.adjusted_mode.crtc_hblank_end = + pipe_config->hw.adjusted_mode.crtc_hblank_end = ((tmp >> 16) & 0xffff) + 1; } tmp = I915_READ(HSYNC(cpu_transcoder)); - pipe_config->base.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1; - pipe_config->base.adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1; + pipe_config->hw.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1; + pipe_config->hw.adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1; tmp = I915_READ(VTOTAL(cpu_transcoder)); - pipe_config->base.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1; - pipe_config->base.adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1; + pipe_config->hw.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1; + pipe_config->hw.adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1; if (!transcoder_is_dsi(cpu_transcoder)) { tmp = I915_READ(VBLANK(cpu_transcoder)); - pipe_config->base.adjusted_mode.crtc_vblank_start = + pipe_config->hw.adjusted_mode.crtc_vblank_start = (tmp & 0xffff) + 1; - pipe_config->base.adjusted_mode.crtc_vblank_end = + pipe_config->hw.adjusted_mode.crtc_vblank_end = ((tmp >> 16) & 0xffff) + 1; } tmp = I915_READ(VSYNC(cpu_transcoder)); - pipe_config->base.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1; - pipe_config->base.adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1; + pipe_config->hw.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1; + pipe_config->hw.adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1; if (intel_pipe_is_interlaced(pipe_config)) { - pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE; - pipe_config->base.adjusted_mode.crtc_vtotal += 1; - pipe_config->base.adjusted_mode.crtc_vblank_end += 1; + pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE; + pipe_config->hw.adjusted_mode.crtc_vtotal += 1; + pipe_config->hw.adjusted_mode.crtc_vblank_end += 1; } } @@ -8387,27 +8387,27 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc, pipe_config->pipe_src_h = (tmp & 0xffff) + 1; pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1; - pipe_config->base.mode.vdisplay = pipe_config->pipe_src_h; - pipe_config->base.mode.hdisplay = pipe_config->pipe_src_w; + pipe_config->hw.mode.vdisplay = pipe_config->pipe_src_h; + pipe_config->hw.mode.hdisplay = pipe_config->pipe_src_w; } void intel_mode_from_pipe_config(struct drm_display_mode *mode, struct intel_crtc_state *pipe_config) { - mode->hdisplay = pipe_config->base.adjusted_mode.crtc_hdisplay; - mode->htotal = pipe_config->base.adjusted_mode.crtc_htotal; - mode->hsync_start = pipe_config->base.adjusted_mode.crtc_hsync_start; - mode->hsync_end = pipe_config->base.adjusted_mode.crtc_hsync_end; + mode->hdisplay = pipe_config->hw.adjusted_mode.crtc_hdisplay; + mode->htotal = pipe_config->hw.adjusted_mode.crtc_htotal; + mode->hsync_start = pipe_config->hw.adjusted_mode.crtc_hsync_start; + mode->hsync_end = pipe_config->hw.adjusted_mode.crtc_hsync_end; - mode->vdisplay = pipe_config->base.adjusted_mode.crtc_vdisplay; - mode->vtotal = pipe_config->base.adjusted_mode.crtc_vtotal; - mode->vsync_start = pipe_config->base.adjusted_mode.crtc_vsync_start; - mode->vsync_end = pipe_config->base.adjusted_mode.crtc_vsync_end; + mode->vdisplay = pipe_config->hw.adjusted_mode.crtc_vdisplay; + mode->vtotal = pipe_config->hw.adjusted_mode.crtc_vtotal; + mode->vsync_start = pipe_config->hw.adjusted_mode.crtc_vsync_start; + mode->vsync_end = pipe_config->hw.adjusted_mode.crtc_vsync_end; - mode->flags = pipe_config->base.adjusted_mode.flags; + mode->flags = pipe_config->hw.adjusted_mode.flags; mode->type = DRM_MODE_TYPE_DRIVER; - mode->clock = pipe_config->base.adjusted_mode.crtc_clock; + mode->clock = pipe_config->hw.adjusted_mode.crtc_clock; mode->hsync = drm_mode_hsync(mode); mode->vrefresh = drm_mode_vrefresh(mode); @@ -8453,7 +8453,7 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) } } - if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { + if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { if (INTEL_GEN(dev_priv) < 4 || intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO)) pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; @@ -8986,7 +8986,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, * but in case the pipe is enabled w/o any ports we need a sane * default. */ - pipe_config->base.adjusted_mode.crtc_clock = + pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock / pipe_config->pixel_multiplier; ret = true; @@ -9530,7 +9530,7 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state) if (crtc_state->dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); - if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) val |= PIPECONF_INTERLACED_ILK; else val |= PIPECONF_PROGRESSIVE; @@ -9564,7 +9564,7 @@ static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state) if (IS_HASWELL(dev_priv) && crtc_state->dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); - if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) val |= PIPECONF_INTERLACED_ILK; else val |= PIPECONF_PROGRESSIVE; @@ -11643,7 +11643,7 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, * we may need some idea for the dotclock anyway. * Calculate one based on the FDI configuration. */ - pipe_config->base.adjusted_mode.crtc_clock = + pipe_config->hw.adjusted_mode.crtc_clock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config), &pipe_config->fdi_m_n); } @@ -11748,8 +11748,8 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); bool mode_changed = needs_modeset(crtc_state); - bool was_crtc_enabled = old_crtc_state->base.active; - bool is_crtc_enabled = crtc_state->base.active; + bool was_crtc_enabled = old_crtc_state->hw.active; + bool is_crtc_enabled = crtc_state->hw.active; bool turn_off, turn_on, visible, was_visible; int ret; @@ -12026,8 +12026,8 @@ static int icl_add_sync_mode_crtcs(struct intel_crtc_state *crtc_state) continue; if (!connector->has_tile) continue; - if (crtc_state->base.mode.hdisplay != connector->tile_h_size || - crtc_state->base.mode.vdisplay != connector->tile_v_size) + if (crtc_state->hw.mode.hdisplay != connector->tile_h_size || + crtc_state->hw.mode.vdisplay != connector->tile_v_size) return 0; if (connector->tile_h_loc == connector->num_h_tile - 1 && connector->tile_v_loc == connector->num_v_tile - 1) @@ -12093,10 +12093,10 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, int ret; if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv) && - mode_changed && !crtc_state->base.active) + mode_changed && !crtc_state->hw.active) crtc_state->update_wm_post = true; - if (mode_changed && crtc_state->base.enable && + if (mode_changed && crtc_state->hw.enable && dev_priv->display.crtc_compute_clock && !WARN_ON(crtc_state->shared_dpll)) { ret = dev_priv->display.crtc_compute_clock(crtc, crtc_state); @@ -12387,14 +12387,14 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, DRM_DEBUG_KMS("[CRTC:%d:%s] enable: %s %s\n", crtc->base.base.id, crtc->base.name, - yesno(pipe_config->base.enable), context); + yesno(pipe_config->hw.enable), context); - if (!pipe_config->base.enable) + if (!pipe_config->hw.enable) goto dump_planes; snprintf_output_types(buf, sizeof(buf), pipe_config->output_types); DRM_DEBUG_KMS("active: %s, output_types: %s (0x%x), output format: %s\n", - yesno(pipe_config->base.active), + yesno(pipe_config->hw.active), buf, pipe_config->output_types, output_formats(pipe_config->output_format)); @@ -12434,10 +12434,10 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, intel_dump_infoframe(dev_priv, &pipe_config->infoframes.hdmi); DRM_DEBUG_KMS("requested mode:\n"); - drm_mode_debug_printmodeline(&pipe_config->base.mode); + drm_mode_debug_printmodeline(&pipe_config->hw.mode); DRM_DEBUG_KMS("adjusted mode:\n"); - drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode); - intel_dump_crtc_timings(&pipe_config->base.adjusted_mode); + drm_mode_debug_printmodeline(&pipe_config->hw.adjusted_mode); + intel_dump_crtc_timings(&pipe_config->hw.adjusted_mode); DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d, pixel rate %d\n", pipe_config->port_clock, pipe_config->pipe_src_w, pipe_config->pipe_src_h, @@ -12625,13 +12625,13 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config) * positive or negative polarity is requested, treat this as meaning * negative polarity. */ - if (!(pipe_config->base.adjusted_mode.flags & + if (!(pipe_config->hw.adjusted_mode.flags & (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))) - pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; + pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC; - if (!(pipe_config->base.adjusted_mode.flags & + if (!(pipe_config->hw.adjusted_mode.flags & (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) - pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC; + pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC; ret = compute_baseline_pipe_bpp(to_intel_crtc(crtc), pipe_config); @@ -12648,7 +12648,7 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config) * computation to clearly distinguish it from the adjusted mode, which * can be changed by the connectors in the below retry loop. */ - drm_mode_get_hv_timing(&pipe_config->base.mode, + drm_mode_get_hv_timing(&pipe_config->hw.mode, &pipe_config->pipe_src_w, &pipe_config->pipe_src_h); @@ -12681,7 +12681,7 @@ encoder_retry: pipe_config->pixel_multiplier = 1; /* Fill in default crtc timings, allow encoders to overwrite them. */ - drm_mode_set_crtcinfo(&pipe_config->base.adjusted_mode, + drm_mode_set_crtcinfo(&pipe_config->hw.adjusted_mode, CRTC_STEREO_DOUBLE); /* Set the crtc_state defaults for trans_port_sync */ @@ -12715,7 +12715,7 @@ encoder_retry: /* Set default port clock if not overwritten by the encoder. Needs to be * done afterwards in case the encoder adjusts the mode. */ if (!pipe_config->port_clock) - pipe_config->port_clock = pipe_config->base.adjusted_mode.crtc_clock + pipe_config->port_clock = pipe_config->hw.adjusted_mode.crtc_clock * pipe_config->pixel_multiplier; ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config); @@ -12887,8 +12887,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, bool ret = true; u32 bp_gamma = 0; bool fixup_inherited = fastset && - (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) && - !(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED); + (current_config->hw.mode.private_flags & I915_MODE_FLAG_INHERITED) && + !(pipe_config->hw.mode.private_flags & I915_MODE_FLAG_INHERITED); if (fixup_inherited && !fastboot_enabled(dev_priv)) { DRM_DEBUG_KMS("initial modeset and fastboot not set\n"); @@ -13234,7 +13234,7 @@ static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv, if (pipe_config->has_pch_encoder) { int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config), &pipe_config->fdi_m_n); - int dotclock = pipe_config->base.adjusted_mode.crtc_clock; + int dotclock = pipe_config->hw.adjusted_mode.crtc_clock; /* * FDI already provided one idea for the dotclock. @@ -13262,7 +13262,7 @@ static void verify_wm_state(struct intel_crtc *crtc, const enum pipe pipe = crtc->pipe; int plane, level, max_level = ilk_wm_max_level(dev_priv); - if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->base.active) + if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->hw.active) return; hw = kzalloc(sizeof(*hw), GFP_KERNEL); @@ -13484,23 +13484,26 @@ verify_crtc_state(struct intel_crtc *crtc, /* we keep both pipes enabled on 830 */ if (IS_I830(dev_priv)) - active = new_crtc_state->base.active; + active = new_crtc_state->hw.active; - I915_STATE_WARN(new_crtc_state->base.active != active, - "crtc active state doesn't match with hw state " - "(expected %i, found %i)\n", new_crtc_state->base.active, active); + I915_STATE_WARN(new_crtc_state->hw.active != active, + "crtc active state doesn't match with hw state " + "(expected %i, found %i)\n", + new_crtc_state->hw.active, active); - I915_STATE_WARN(crtc->active != new_crtc_state->base.active, - "transitional active state does not match atomic hw state " - "(expected %i, found %i)\n", new_crtc_state->base.active, crtc->active); + I915_STATE_WARN(crtc->active != new_crtc_state->hw.active, + "transitional active state does not match atomic hw state " + "(expected %i, found %i)\n", + new_crtc_state->hw.active, crtc->active); for_each_encoder_on_crtc(dev, &crtc->base, encoder) { enum pipe pipe; active = encoder->get_hw_state(encoder, &pipe); - I915_STATE_WARN(active != new_crtc_state->base.active, - "[ENCODER:%i] active %i with crtc active %i\n", - encoder->base.base.id, active, new_crtc_state->base.active); + I915_STATE_WARN(active != new_crtc_state->hw.active, + "[ENCODER:%i] active %i with crtc active %i\n", + encoder->base.base.id, active, + new_crtc_state->hw.active); I915_STATE_WARN(active && crtc->pipe != pipe, "Encoder connected to wrong pipe %c\n", @@ -13512,7 +13515,7 @@ verify_crtc_state(struct intel_crtc *crtc, intel_crtc_compute_pixel_rate(pipe_config); - if (!new_crtc_state->base.active) + if (!new_crtc_state->hw.active) return; intel_pipe_config_sanity_check(dev_priv, pipe_config); @@ -13574,7 +13577,7 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv, crtc_mask = drm_crtc_mask(&crtc->base); - if (new_crtc_state->base.active) + if (new_crtc_state->hw.active) I915_STATE_WARN(!(pll->active_mask & crtc_mask), "pll active mismatch (expected pipe %c in active mask 0x%02x)\n", pipe_name(drm_crtc_index(&crtc->base)), pll->active_mask); @@ -13656,7 +13659,7 @@ intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; drm_calc_timestamping_constants(&crtc->base, adjusted_mode); @@ -13738,7 +13741,7 @@ static int haswell_mode_set_planes_workaround(struct intel_atomic_state *state) /* look at all crtc's that are going to be enabled in during modeset */ for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { - if (!crtc_state->base.active || + if (!crtc_state->hw.active || !needs_modeset(crtc_state)) continue; @@ -13763,7 +13766,7 @@ static int haswell_mode_set_planes_workaround(struct intel_atomic_state *state) crtc_state->hsw_workaround_pipe = INVALID_PIPE; - if (!crtc_state->base.active || + if (!crtc_state->hw.active || needs_modeset(crtc_state)) continue; @@ -13800,12 +13803,12 @@ static int intel_modeset_checks(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (new_crtc_state->base.active) + if (new_crtc_state->hw.active) state->active_pipes |= BIT(crtc->pipe); else state->active_pipes &= ~BIT(crtc->pipe); - if (old_crtc_state->base.active != new_crtc_state->base.active) + if (old_crtc_state->hw.active != new_crtc_state->hw.active) state->active_pipe_changes |= BIT(crtc->pipe); } @@ -13993,8 +13996,8 @@ static int intel_atomic_check(struct drm_device *dev, /* Catch I915_MODE_FLAG_INHERITED */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (new_crtc_state->base.mode.private_flags != - old_crtc_state->base.mode.private_flags) + if (new_crtc_state->hw.mode.private_flags != + old_crtc_state->hw.mode.private_flags) new_crtc_state->base.mode_changed = true; } @@ -14233,7 +14236,7 @@ static void intel_update_crtc(struct intel_crtc *crtc, * of enabling them on the CRTC's first fastset. */ if (new_crtc_state->update_pipe && !modeset && - old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED) + old_crtc_state->hw.mode.private_flags & I915_MODE_FLAG_INHERITED) intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); } @@ -14277,7 +14280,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, intel_check_pch_fifo_underruns(dev_priv); /* FIXME unify this for all platforms */ - if (!new_crtc_state->base.active && + if (!new_crtc_state->hw.active && !HAS_GMCH(dev_priv) && dev_priv->display.initial_watermarks) dev_priv->display.initial_watermarks(state, @@ -14300,7 +14303,7 @@ static void intel_trans_port_sync_modeset_disables(struct intel_atomic_state *st /* Disable Slave first */ intel_pre_plane_update(old_slave_crtc_state, new_slave_crtc_state); - if (old_slave_crtc_state->base.active) + if (old_slave_crtc_state->hw.active) intel_old_crtc_state_disables(state, old_slave_crtc_state, new_slave_crtc_state, @@ -14308,7 +14311,7 @@ static void intel_trans_port_sync_modeset_disables(struct intel_atomic_state *st /* Disable Master */ intel_pre_plane_update(old_crtc_state, new_crtc_state); - if (old_crtc_state->base.active) + if (old_crtc_state->hw.active) intel_old_crtc_state_disables(state, old_crtc_state, new_crtc_state, @@ -14349,7 +14352,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) } else { intel_pre_plane_update(old_crtc_state, new_crtc_state); - if (old_crtc_state->base.active) + if (old_crtc_state->hw.active) intel_old_crtc_state_disables(state, old_crtc_state, new_crtc_state, @@ -14365,7 +14368,7 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state) int i; for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (!new_crtc_state->base.active) + if (!new_crtc_state->hw.active) continue; intel_update_crtc(crtc, state, old_crtc_state, @@ -14430,7 +14433,7 @@ static void intel_post_crtc_enable_updates(struct intel_crtc *crtc, * of enabling them on the CRTC's first fastset. */ if (new_crtc_state->update_pipe && !modeset && - old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED) + old_crtc_state->hw.mode.private_flags & I915_MODE_FLAG_INHERITED) intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); } @@ -14494,7 +14497,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) /* ignore allocations for crtc's that have been turned off. */ - if (new_crtc_state->base.active) + if (new_crtc_state->hw.active) entries[i] = old_crtc_state->wm.skl.ddb; /* If 2nd DBuf slice required, enable it here */ @@ -14515,7 +14518,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) bool vbl_wait = false; bool modeset = needs_modeset(new_crtc_state); - if (updated & BIT(crtc->pipe) || !new_crtc_state->base.active) + if (updated & BIT(crtc->pipe) || !new_crtc_state->hw.active) continue; if (skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb, @@ -14677,7 +14680,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) bool modeset = needs_modeset(new_crtc_state); /* Complete events for now disable pipes here. */ - if (modeset && !new_crtc_state->base.active && new_crtc_state->base.event) { + if (modeset && !new_crtc_state->hw.active && new_crtc_state->base.event) { spin_lock_irq(&dev->event_lock); drm_crtc_send_vblank_event(&crtc->base, new_crtc_state->base.event); spin_unlock_irq(&dev->event_lock); @@ -14713,7 +14716,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) drm_atomic_helper_wait_for_flip_done(dev, &state->base); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { - if (new_crtc_state->base.active && + if (new_crtc_state->hw.active && !needs_modeset(new_crtc_state) && (new_crtc_state->base.color_mgmt_changed || new_crtc_state->update_pipe)) @@ -15280,7 +15283,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane, * When crtc is inactive or there is a modeset pending, * wait for it to complete in the slowpath */ - if (!crtc_state->base.active || needs_modeset(crtc_state) || + if (!crtc_state->hw.active || needs_modeset(crtc_state) || crtc_state->update_pipe) goto slow; @@ -16737,7 +16740,7 @@ retry: goto out; } - if (crtc_state->base.active) { + if (crtc_state->hw.active) { ret = drm_atomic_add_affected_planes(state, &crtc->base); if (ret) goto out; @@ -17087,7 +17090,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); } - if (crtc_state->base.active) { + if (crtc_state->hw.active) { struct intel_plane *plane; /* Disable everything but the primary plane */ @@ -17112,10 +17115,10 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, /* Adjust the state of the output pipe according to whether we * have active connectors/encoders. */ - if (crtc_state->base.active && !intel_crtc_has_encoders(crtc)) + if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc)) intel_crtc_disable_noatomic(&crtc->base, ctx); - if (crtc_state->base.active || HAS_GMCH(dev_priv)) { + if (crtc_state->hw.active || HAS_GMCH(dev_priv)) { /* * We start out with underrun reporting disabled to avoid races. * For correct bookkeeping mark this on active crtcs. @@ -17159,7 +17162,7 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) * road. */ return IS_GEN(dev_priv, 6) && - crtc_state->base.active && + crtc_state->hw.active && crtc_state->shared_dpll && crtc_state->port_clock == 0; } @@ -17176,7 +17179,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) * encoder is active and trying to read from a pipe) and the * pipe itself being active. */ bool has_active_crtc = crtc_state && - crtc_state->base.active; + crtc_state->hw.active; if (crtc_state && has_bogus_dpll_config(crtc_state)) { DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n", @@ -17284,18 +17287,18 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) memset(crtc_state, 0, sizeof(*crtc_state)); __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->base); - crtc_state->base.active = crtc_state->base.enable = + crtc_state->hw.active = crtc_state->hw.enable = dev_priv->display.get_pipe_config(crtc, crtc_state); - crtc->base.enabled = crtc_state->base.enable; - crtc->active = crtc_state->base.active; + crtc->base.enabled = crtc_state->hw.enable; + crtc->active = crtc_state->hw.active; - if (crtc_state->base.active) + if (crtc_state->hw.active) dev_priv->active_pipes |= BIT(crtc->pipe); DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n", crtc->base.base.id, crtc->base.name, - enableddisabled(crtc_state->base.active)); + enableddisabled(crtc_state->hw.active)); } readout_plane_state(dev_priv); @@ -17317,7 +17320,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - if (crtc_state->base.active && + if (crtc_state->hw.active && crtc_state->shared_dpll == pll) pll->state.crtc_mask |= 1 << crtc->pipe; } @@ -17362,7 +17365,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) crtc = to_intel_crtc(encoder->base.crtc); crtc_state = crtc ? to_intel_crtc_state(crtc->base.state) : NULL; - if (crtc_state && crtc_state->base.active) { + if (crtc_state && crtc_state->hw.active) { /* * This has to be done during hardware readout * because anything calling .crtc_disable may @@ -17391,13 +17394,13 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) struct intel_plane *plane; int min_cdclk = 0; - if (crtc_state->base.active) { + if (crtc_state->hw.active) { struct drm_display_mode mode; - intel_mode_from_pipe_config(&crtc_state->base.adjusted_mode, + intel_mode_from_pipe_config(&crtc_state->hw.adjusted_mode, crtc_state); - mode = crtc_state->base.adjusted_mode; + mode = crtc_state->hw.adjusted_mode; mode.hdisplay = crtc_state->pipe_src_w; mode.vdisplay = crtc_state->pipe_src_h; WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->base, &mode)); @@ -17411,7 +17414,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) * set a flag to indicate that a full recalculation is * needed on the next commit. */ - crtc_state->base.mode.private_flags = I915_MODE_FLAG_INHERITED; + crtc_state->hw.mode.private_flags = I915_MODE_FLAG_INHERITED; intel_crtc_compute_pixel_rate(crtc_state); @@ -17447,7 +17450,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) crtc_state->min_cdclk[plane->id]); } - if (crtc_state->base.active) { + if (crtc_state->hw.active) { min_cdclk = intel_crtc_compute_min_cdclk(crtc_state); if (WARN_ON(min_cdclk < 0)) min_cdclk = 0; @@ -17607,7 +17610,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev, drm_crtc_vblank_reset(&crtc->base); - if (crtc_state->base.active) + if (crtc_state->hw.active) intel_crtc_vblank_on(crtc_state); } diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index d958e789ab96..1602a8dbbfa9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1999,7 +1999,7 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, const struct link_config_limits *limits) { - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int bpp, clock, lane_count; int mode_rate, link_clock, link_avail; @@ -2053,7 +2053,7 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; u8 dsc_max_bpc; int pipe_bpp; int ret; @@ -2164,7 +2164,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct link_config_limits limits; int common_len; @@ -2252,7 +2252,7 @@ intel_dp_ycbcr420_config(struct intel_dp *intel_dp, { const struct drm_display_info *info = &connector->display_info; const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); int ret; @@ -2281,7 +2281,7 @@ bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state, const struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(conn_state); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; /* * Our YCbCr output is always limited range. @@ -2314,7 +2314,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_lspcon *lspcon = enc_to_intel_lspcon(&encoder->base); enum port port = encoder->port; @@ -2437,7 +2437,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = encoder->port; struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); - const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; intel_dp_set_link_params(intel_dp, pipe_config->port_clock, pipe_config->lane_count, @@ -3269,7 +3269,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, flags |= DRM_MODE_FLAG_NVSYNC; } - pipe_config->base.adjusted_mode.flags |= flags; + pipe_config->hw.adjusted_mode.flags |= flags; if (IS_G4X(dev_priv) && tmp & DP_COLOR_RANGE_16_235) pipe_config->limited_color_range = true; @@ -3286,7 +3286,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->port_clock = 270000; } - pipe_config->base.adjusted_mode.crtc_clock = + pipe_config->hw.adjusted_mode.crtc_clock = intel_dotclock_calculate(pipe_config->port_clock, &pipe_config->dp_m_n); @@ -5079,7 +5079,7 @@ int intel_dp_retrain_link(struct intel_encoder *encoder, WARN_ON(!intel_crtc_has_dp_encoder(crtc_state)); - if (!crtc_state->base.active) + if (!crtc_state->hw.active) return 0; if (conn_state->commit && @@ -6947,7 +6947,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, return; } - if (!crtc_state->base.active) { + if (!crtc_state->hw.active) { DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n"); return; } diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 00a5540fe250..8a1dc7212db7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -48,7 +48,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; void *port = connector->port; bool constant_n = drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_CONSTANT_N); @@ -99,7 +99,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(conn_state); const struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; void *port = connector->port; struct link_config_limits limits; int ret; @@ -191,7 +191,7 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, if (!crtc_state || !drm_atomic_crtc_needs_modeset(&crtc_state->base) || - crtc_state->base.enable) + crtc_state->hw.enable) return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index bcfbcb743e7d..e45da2216e06 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -178,9 +178,9 @@ static void intel_dvo_get_config(struct intel_encoder *encoder, else flags |= DRM_MODE_FLAG_NVSYNC; - pipe_config->base.adjusted_mode.flags |= flags; + pipe_config->hw.adjusted_mode.flags |= flags; - pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; + pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock; } static void intel_disable_dvo(struct intel_encoder *encoder, @@ -207,8 +207,8 @@ static void intel_enable_dvo(struct intel_encoder *encoder, u32 temp = I915_READ(dvo_reg); intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, - &pipe_config->base.mode, - &pipe_config->base.adjusted_mode); + &pipe_config->hw.mode, + &pipe_config->hw.adjusted_mode); I915_WRITE(dvo_reg, temp | DVO_ENABLE); I915_READ(dvo_reg); @@ -253,7 +253,7 @@ static int intel_dvo_compute_config(struct intel_encoder *encoder, struct intel_dvo *intel_dvo = enc_to_dvo(encoder); const struct drm_display_mode *fixed_mode = intel_dvo->attached_connector->panel.fixed_mode; - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; /* * If we have timings from the BIOS for the panel, put them in @@ -278,7 +278,7 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); - const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dvo *intel_dvo = enc_to_dvo(encoder); enum pipe pipe = crtc->pipe; u32 dvo_val; diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 3111ecaeabd0..c6cc3775f3b8 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -667,7 +667,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->vma = NULL; cache->flags = 0; - cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags; + cache->crtc.mode_flags = crtc_state->hw.adjusted_mode.flags; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index f6f5312205c4..434031fec430 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -708,7 +708,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder, { struct hdmi_avi_infoframe *frame = &crtc_state->infoframes.avi.avi; const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; struct drm_connector *connector = conn_state->connector; int ret; @@ -804,7 +804,7 @@ intel_hdmi_compute_hdmi_infoframe(struct intel_encoder *encoder, ret = drm_hdmi_vendor_infoframe_from_display_mode(frame, conn_state->connector, - &crtc_state->base.adjusted_mode); + &crtc_state->hw.adjusted_mode); if (WARN_ON(ret)) return false; @@ -1027,7 +1027,7 @@ static void intel_hdmi_compute_gcp_infoframe(struct intel_encoder *encoder, /* Enable default_phase whenever the display mode is suitably aligned */ if (gcp_default_phase_possible(crtc_state->pipe_bpp, - &crtc_state->base.adjusted_mode)) + &crtc_state->hw.adjusted_mode)) crtc_state->infoframes.gcp |= GCP_DEFAULT_PHASE_ENABLE; } @@ -1738,7 +1738,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); - const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 hdmi_val; intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); @@ -1829,7 +1829,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, tmp & HDMI_COLOR_RANGE_16_235) pipe_config->limited_color_range = true; - pipe_config->base.adjusted_mode.flags |= flags; + pipe_config->hw.adjusted_mode.flags |= flags; if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc) dotclock = pipe_config->port_clock * 2 / 3; @@ -1839,7 +1839,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, if (pipe_config->pixel_multiplier) dotclock /= pipe_config->pixel_multiplier; - pipe_config->base.adjusted_mode.crtc_clock = dotclock; + pipe_config->hw.adjusted_mode.crtc_clock = dotclock; pipe_config->lane_count = 4; @@ -2215,7 +2215,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, struct drm_connector_state *connector_state; struct drm_connector *connector; const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; int i; if (HAS_GMCH(dev_priv)) @@ -2336,7 +2336,7 @@ static int intel_hdmi_compute_clock(struct intel_encoder *encoder, { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; int bpc, clock = adjusted_mode->crtc_clock; if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) @@ -2378,7 +2378,7 @@ static bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_s const struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(conn_state); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; /* * Our YCbCr output is always limited range. @@ -2406,7 +2406,7 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct drm_connector *connector = conn_state->connector; struct drm_scdc *scdc = &connector->display_info.hdmi.scdc; struct intel_digital_connector_state *intel_conn_state = diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index f8f1308643a9..5145ff8b962b 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -189,7 +189,7 @@ void lspcon_ycbcr420_config(struct drm_connector *connector, { const struct drm_display_info *info = &connector->display_info; const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; if (drm_mode_is_420_only(info, adjusted_mode) && connector->ycbcr_420_allowed) { @@ -475,7 +475,7 @@ void lspcon_set_infoframes(struct intel_encoder *encoder, struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); struct intel_lspcon *lspcon = &dig_port->lspcon; const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; if (!lspcon->active) { DRM_ERROR("Writing infoframes while LSPCON disabled ?\n"); diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index b1bc78623647..40ae0b7377ce 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -135,7 +135,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, else flags |= DRM_MODE_FLAG_PVSYNC; - pipe_config->base.adjusted_mode.flags |= flags; + pipe_config->hw.adjusted_mode.flags |= flags; if (INTEL_GEN(dev_priv) < 5) pipe_config->gmch_pfit.lvds_border_bits = @@ -148,7 +148,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE; } - pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; + pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock; } static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv, @@ -231,7 +231,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); - const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; enum pipe pipe = crtc->pipe; u32 temp; @@ -392,7 +392,7 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder, to_lvds_encoder(&intel_encoder->base); struct intel_connector *intel_connector = lvds_encoder->attached_connector; - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); unsigned int lvds_bpp; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index bc14e9c0285a..5e3fd37d9471 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -178,7 +178,7 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, struct intel_crtc_state *pipe_config, int fitting_mode) { - const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int x = 0, y = 0, width = 0, height = 0; /* Native modes don't need fitting */ @@ -300,7 +300,7 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target) static void i965_scale_aspect(struct intel_crtc_state *pipe_config, u32 *pfit_control) { - const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_config->pipe_src_h; u32 scaled_height = pipe_config->pipe_src_w * @@ -321,7 +321,7 @@ static void i9xx_scale_aspect(struct intel_crtc_state *pipe_config, u32 *pfit_control, u32 *pfit_pgm_ratios, u32 *border) { - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_config->pipe_src_h; u32 scaled_height = pipe_config->pipe_src_w * @@ -380,7 +380,7 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, { struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; /* Native modes don't need fitting */ if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w && diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index 6260a2082719..fc602533a602 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -313,7 +313,7 @@ retry: pipe_config->crc_enabled = enable; if (IS_HASWELL(dev_priv) && - pipe_config->base.active && crtc->pipe == PIPE_A && + pipe_config->hw.active && crtc->pipe == PIPE_A && pipe_config->cpu_transcoder == TRANSCODER_EDP) pipe_config->base.mode_changed = true; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 359a60762b49..f75f759ad6ee 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -537,11 +537,11 @@ transcoder_has_psr2(struct drm_i915_private *dev_priv, enum transcoder trans) static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate) { - if (!cstate || !cstate->base.active) + if (!cstate || !cstate->hw.active) return 0; return DIV_ROUND_UP(1000 * 1000, - drm_mode_vrefresh(&cstate->base.adjusted_mode)); + drm_mode_vrefresh(&cstate->hw.adjusted_mode)); } static void psr2_program_idle_frames(struct drm_i915_private *dev_priv, @@ -606,8 +606,8 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - int crtc_hdisplay = crtc_state->base.adjusted_mode.crtc_hdisplay; - int crtc_vdisplay = crtc_state->base.adjusted_mode.crtc_vdisplay; + int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay; + int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay; int psr_max_h = 0, psr_max_v = 0; if (!dev_priv->psr.sink_psr2_support) @@ -673,7 +673,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; int psr_setup_time; if (!CAN_PSR(dev_priv)) @@ -1117,7 +1117,7 @@ retry: goto error; } - if (crtc_state->base.active && crtc_state->has_psr) { + if (crtc_state->hw.active && crtc_state->has_psr) { /* Mark mode as changed to trigger a pipe->update() */ crtc_state->base.mode_changed = true; break; diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 5b7f4baf7348..b5ed19da7d63 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -1087,7 +1087,7 @@ static bool intel_sdvo_compute_avi_infoframe(struct intel_sdvo *intel_sdvo, { struct hdmi_avi_infoframe *frame = &crtc_state->infoframes.avi.avi; const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; int ret; if (!crtc_state->has_hdmi_sink) @@ -1276,8 +1276,8 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, to_intel_sdvo_connector_state(conn_state); struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(conn_state->connector); - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - struct drm_display_mode *mode = &pipe_config->base.mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; + struct drm_display_mode *mode = &pipe_config->hw.mode; DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n"); pipe_config->pipe_bpp = 8*3; @@ -1430,12 +1430,12 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, { struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; const struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(conn_state); const struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(conn_state->connector); - const struct drm_display_mode *mode = &crtc_state->base.mode; + const struct drm_display_mode *mode = &crtc_state->hw.mode; struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder); u32 sdvox; struct intel_sdvo_in_out_map in_out; @@ -1629,7 +1629,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, flags |= DRM_MODE_FLAG_NVSYNC; } - pipe_config->base.adjusted_mode.flags |= flags; + pipe_config->hw.adjusted_mode.flags |= flags; /* * pixel multiplier readout is tricky: Only on i915g/gm it is stored in @@ -1649,7 +1649,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, if (pipe_config->pixel_multiplier) dotclock /= pipe_config->pixel_multiplier; - pipe_config->base.adjusted_mode.crtc_clock = dotclock; + pipe_config->hw.adjusted_mode.crtc_clock = dotclock; /* Cross check the port pixel multiplier with the sdvo encoder state. */ if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT, @@ -1701,7 +1701,7 @@ static void intel_sdvo_enable_audio(struct intel_sdvo *intel_sdvo, const struct drm_connector_state *conn_state) { const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; struct drm_connector *connector = conn_state->connector; u8 *eld = connector->eld; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index edc41fc40726..fcd7355eaa34 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -83,7 +83,7 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode; long timeout = msecs_to_jiffies_timeout(1); int scanline, min, max, vblank_start; wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); @@ -1891,7 +1891,7 @@ g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, const struct drm_rect *dst = &plane_state->base.dst; int src_x, src_w, src_h, crtc_w, crtc_h; const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; unsigned int stride = plane_state->color_plane[0].stride; unsigned int cpp = fb->format->cpp[0]; unsigned int width_bytes; @@ -2105,8 +2105,8 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, } /* Y-tiling is not supported in IF-ID Interlace mode */ - if (crtc_state->base.enable && - crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && + if (crtc_state->hw.enable && + crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && (fb->modifier == I915_FORMAT_MOD_Y_TILED || fb->modifier == I915_FORMAT_MOD_Yf_TILED || fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 9983fadf6c28..9bc5e91e5d54 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -1085,7 +1085,7 @@ intel_tv_get_config(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; struct drm_display_mode mode = {}; u32 tv_ctl, hctl1, hctl3, vctl1, vctl2, tmp; struct tv_mode tv_mode = {}; @@ -1188,7 +1188,7 @@ intel_tv_compute_config(struct intel_encoder *encoder, to_intel_tv_connector_state(conn_state); const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state); struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; int hdisplay = adjusted_mode->crtc_hdisplay; int vdisplay = adjusted_mode->crtc_vdisplay; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 896b0c334f5e..757b276eb3fc 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -329,8 +329,8 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, int column_index = 0; u8 line_buf_depth = 0; - vdsc_cfg->pic_width = pipe_config->base.adjusted_mode.crtc_hdisplay; - vdsc_cfg->pic_height = pipe_config->base.adjusted_mode.crtc_vdisplay; + vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay; + vdsc_cfg->pic_height = pipe_config->hw.adjusted_mode.crtc_vdisplay; vdsc_cfg->slice_width = DIV_ROUND_UP(vdsc_cfg->pic_width, pipe_config->dsc.slice_count); /* diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 0ca49b1604c6..5681b388452d 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -263,7 +263,7 @@ static int intel_dsi_compute_config(struct intel_encoder *encoder, struct intel_connector *intel_connector = intel_dsi->attached_connector; struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; - struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int ret; DRM_DEBUG_KMS("\n"); @@ -1032,7 +1032,7 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_display_mode *adjusted_mode = - &pipe_config->base.adjusted_mode; + &pipe_config->hw.adjusted_mode; struct drm_display_mode *adjusted_mode_sw; struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -1045,7 +1045,7 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, crtc_hblank_start_sw, crtc_hblank_end_sw; /* FIXME: hw readout should not depend on SW state */ - adjusted_mode_sw = &crtc->config->base.adjusted_mode; + adjusted_mode_sw = &crtc->config->hw.adjusted_mode; /* * Atleast one port is active as encoder->get_config called only if @@ -1204,7 +1204,7 @@ static void intel_dsi_get_config(struct intel_encoder *encoder, } if (pclk) { - pipe_config->base.adjusted_mode.crtc_clock = pclk; + pipe_config->hw.adjusted_mode.crtc_clock = pclk; pipe_config->port_clock = pclk; } } @@ -1317,7 +1317,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; enum port port; unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); u32 val, tmp; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8016484ebcd3..73808fd26625 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2684,11 +2684,11 @@ static int i915_display_info(struct seq_file *m, void *unused) seq_printf(m, "CRTC %d: pipe: %c, active=%s, (size=%dx%d), dither=%s, bpp=%d\n", crtc->base.base.id, pipe_name(crtc->pipe), - yesno(pipe_config->base.active), + yesno(pipe_config->hw.active), pipe_config->pipe_src_w, pipe_config->pipe_src_h, yesno(pipe_config->dither), pipe_config->pipe_bpp); - if (pipe_config->base.active) { + if (pipe_config->hw.active) { struct intel_plane *cursor = to_intel_plane(crtc->base.cursor); @@ -4161,7 +4161,7 @@ static int i915_drrs_ctl_set(void *data, u64 val) crtc_state = to_intel_crtc_state(crtc->base.state); - if (!crtc_state->base.active || + if (!crtc_state->hw.active || !crtc_state->has_drrs) goto out; @@ -4243,7 +4243,7 @@ i915_fifo_underrun_reset_write(struct file *filp, ret = wait_for_completion_interruptible(&commit->flip_done); } - if (!ret && crtc_state->base.active) { + if (!ret && crtc_state->hw.active) { DRM_DEBUG_KMS("Re-arming FIFO underruns on pipe %c\n", pipe_name(intel_crtc->pipe)); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d6aed8860db7..eb0c29b0f8c5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -789,7 +789,7 @@ static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->base.plane); /* FIXME check the 'enable' instead */ - if (!crtc_state->base.active) + if (!crtc_state->hw.active) return false; /* @@ -842,7 +842,7 @@ static void pineview_update_wm(struct intel_crtc *unused_crtc) crtc = single_enabled_crtc(dev_priv); if (crtc) { const struct drm_display_mode *adjusted_mode = - &crtc->config->base.adjusted_mode; + &crtc->config->hw.adjusted_mode; const struct drm_framebuffer *fb = crtc->base.primary->state->fb; int cpp = fb->format->cpp[0]; @@ -1078,7 +1078,7 @@ static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; unsigned int latency = dev_priv->wm.pri_latency[level] * 10; unsigned int clock, htotal, cpp, width, wm; @@ -1390,7 +1390,7 @@ static int g4x_compute_intermediate_wm(struct intel_crtc_state *new_crtc_state) const struct g4x_wm_state *active = &old_crtc_state->wm.g4x.optimal; enum plane_id plane_id; - if (!new_crtc_state->base.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) { + if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) { *intermediate = *optimal; intermediate->cxsr = false; @@ -1584,7 +1584,7 @@ static u16 vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; unsigned int clock, htotal, cpp, width, wm; if (dev_priv->wm.pri_latency[level] == 0) @@ -2023,7 +2023,7 @@ static int vlv_compute_intermediate_wm(struct intel_crtc_state *new_crtc_state) const struct vlv_wm_state *active = &old_crtc_state->wm.vlv.optimal; int level; - if (!new_crtc_state->base.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) { + if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) { *intermediate = *optimal; intermediate->cxsr = false; @@ -2179,7 +2179,7 @@ static void i965_update_wm(struct intel_crtc *unused_crtc) /* self-refresh has much higher latency */ static const int sr_latency_ns = 12000; const struct drm_display_mode *adjusted_mode = - &crtc->config->base.adjusted_mode; + &crtc->config->hw.adjusted_mode; const struct drm_framebuffer *fb = crtc->base.primary->state->fb; int clock = adjusted_mode->crtc_clock; @@ -2260,7 +2260,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) crtc = intel_get_crtc_for_plane(dev_priv, PLANE_A); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = - &crtc->config->base.adjusted_mode; + &crtc->config->hw.adjusted_mode; const struct drm_framebuffer *fb = crtc->base.primary->state->fb; int cpp; @@ -2287,7 +2287,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) crtc = intel_get_crtc_for_plane(dev_priv, PLANE_B); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = - &crtc->config->base.adjusted_mode; + &crtc->config->hw.adjusted_mode; const struct drm_framebuffer *fb = crtc->base.primary->state->fb; int cpp; @@ -2335,7 +2335,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) /* self-refresh has much higher latency */ static const int sr_latency_ns = 6000; const struct drm_display_mode *adjusted_mode = - &enabled->config->base.adjusted_mode; + &enabled->config->hw.adjusted_mode; const struct drm_framebuffer *fb = enabled->base.primary->state->fb; int clock = adjusted_mode->crtc_clock; @@ -2393,7 +2393,7 @@ static void i845_update_wm(struct intel_crtc *unused_crtc) if (crtc == NULL) return; - adjusted_mode = &crtc->config->base.adjusted_mode; + adjusted_mode = &crtc->config->hw.adjusted_mode; planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, &i845_wm_info, dev_priv->display.get_fifo_size(dev_priv, PLANE_A), @@ -2483,7 +2483,7 @@ static u32 ilk_compute_pri_wm(const struct intel_crtc_state *crtc_state, return method1; method2 = ilk_wm_method2(crtc_state->pixel_rate, - crtc_state->base.adjusted_mode.crtc_htotal, + crtc_state->hw.adjusted_mode.crtc_htotal, drm_rect_width(&plane_state->base.dst), cpp, mem_value); @@ -2511,7 +2511,7 @@ static u32 ilk_compute_spr_wm(const struct intel_crtc_state *crtc_state, method1 = ilk_wm_method1(crtc_state->pixel_rate, cpp, mem_value); method2 = ilk_wm_method2(crtc_state->pixel_rate, - crtc_state->base.adjusted_mode.crtc_htotal, + crtc_state->hw.adjusted_mode.crtc_htotal, drm_rect_width(&plane_state->base.dst), cpp, mem_value); return min(method1, method2); @@ -2536,7 +2536,7 @@ static u32 ilk_compute_cur_wm(const struct intel_crtc_state *crtc_state, cpp = plane_state->base.fb->format->cpp[0]; return ilk_wm_method2(crtc_state->pixel_rate, - crtc_state->base.adjusted_mode.crtc_htotal, + crtc_state->hw.adjusted_mode.crtc_htotal, drm_rect_width(&plane_state->base.dst), cpp, mem_value); } @@ -2760,10 +2760,10 @@ hsw_compute_linetime_wm(const struct intel_crtc_state *crtc_state) const struct intel_atomic_state *intel_state = to_intel_atomic_state(crtc_state->base.state); const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; u32 linetime, ips_linetime; - if (!crtc_state->base.active) + if (!crtc_state->hw.active) return 0; if (WARN_ON(adjusted_mode->crtc_clock == 0)) return 0; @@ -3095,7 +3095,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *crtc_state) curstate = plane_state; } - pipe_wm->pipe_enabled = crtc_state->base.active; + pipe_wm->pipe_enabled = crtc_state->hw.active; if (sprstate) { pipe_wm->sprites_enabled = sprstate->base.visible; pipe_wm->sprites_scaled = sprstate->base.visible && @@ -3168,7 +3168,7 @@ static int ilk_compute_intermediate_wm(struct intel_crtc_state *newstate) * and after the vblank. */ *a = newstate->wm.ilk.optimal; - if (!newstate->base.active || drm_atomic_crtc_needs_modeset(&newstate->base) || + if (!newstate->hw.active || drm_atomic_crtc_needs_modeset(&newstate->base) || intel_state->skip_intermediate_wm) return 0; @@ -3770,7 +3770,7 @@ bool intel_can_enable_sagv(struct intel_atomic_state *state) crtc = intel_get_crtc_for_pipe(dev_priv, pipe); crtc_state = to_intel_crtc_state(crtc->base.state); - if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) return false; for_each_intel_plane_on_crtc(dev, crtc, plane) { @@ -3820,7 +3820,7 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv, if (INTEL_GEN(dev_priv) < 11) return ddb_size - 4; /* 4 blocks for bypass path allocation */ - adjusted_mode = &crtc_state->base.adjusted_mode; + adjusted_mode = &crtc_state->hw.adjusted_mode; total_data_bw = total_data_rate * drm_mode_vrefresh(adjusted_mode); /* @@ -3858,7 +3858,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv, u16 ddb_size; u32 i; - if (WARN_ON(!state) || !crtc_state->base.active) { + if (WARN_ON(!state) || !crtc_state->hw.active) { alloc->start = 0; alloc->end = 0; *num_active = hweight8(dev_priv->active_pipes); @@ -3897,11 +3897,11 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv, */ for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) { const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; + &crtc_state->hw.adjusted_mode; enum pipe pipe = crtc->pipe; int hdisplay, vdisplay; - if (!crtc_state->base.enable) + if (!crtc_state->hw.enable) continue; drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay); @@ -4238,7 +4238,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state, if (WARN_ON(!state)) return 0; - if (!crtc_state->base.active) { + if (!crtc_state->hw.active) { alloc->start = alloc->end = 0; return 0; } @@ -4480,7 +4480,7 @@ intel_get_linetime_us(const struct intel_crtc_state *crtc_state) u32 crtc_htotal; uint_fixed_16_16_t linetime_us; - if (!crtc_state->base.active) + if (!crtc_state->hw.active) return u32_to_fixed16(0); pixel_rate = crtc_state->pixel_rate; @@ -4488,7 +4488,7 @@ intel_get_linetime_us(const struct intel_crtc_state *crtc_state) if (WARN_ON(pixel_rate == 0)) return u32_to_fixed16(0); - crtc_htotal = crtc_state->base.adjusted_mode.crtc_htotal; + crtc_htotal = crtc_state->hw.adjusted_mode.crtc_htotal; linetime_us = div_fixed16(crtc_htotal * 1000, pixel_rate); return linetime_us; @@ -4670,14 +4670,14 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, method1 = skl_wm_method1(dev_priv, wp->plane_pixel_rate, wp->cpp, latency, wp->dbuf_block_size); method2 = skl_wm_method2(wp->plane_pixel_rate, - crtc_state->base.adjusted_mode.crtc_htotal, + crtc_state->hw.adjusted_mode.crtc_htotal, latency, wp->plane_blocks_per_line); if (wp->y_tiled) { selected_result = max_fixed16(method2, wp->y_tile_minimum); } else { - if ((wp->cpp * crtc_state->base.adjusted_mode.crtc_htotal / + if ((wp->cpp * crtc_state->hw.adjusted_mode.crtc_htotal / wp->dbuf_block_size < 1) && (wp->plane_bytes_per_line / wp->dbuf_block_size < 1)) { selected_result = method2; -- cgit v1.2.3 From 2225f3c6f1d793cabd7f509254ba10bb1da871ad Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:03 +0100 Subject: drm/i915: Perform automated conversions for crtc uapi/hw split, base -> uapi. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split up crtc_state->base to uapi. This is done using the following patch, ran after the previous commit that splits out any hw references: @@ struct intel_crtc_state *T; @@ -T->base +T->uapi Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-5-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 6 +- drivers/gpu/drm/i915/display/intel_atomic.c | 8 +- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 6 +- drivers/gpu/drm/i915/display/intel_audio.c | 8 +- drivers/gpu/drm/i915/display/intel_bw.c | 4 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 12 +- drivers/gpu/drm/i915/display/intel_color.c | 70 +++--- drivers/gpu/drm/i915/display/intel_crt.c | 6 +- drivers/gpu/drm/i915/display/intel_ddi.c | 32 +-- drivers/gpu/drm/i915/display/intel_display.c | 253 +++++++++++----------- drivers/gpu/drm/i915/display/intel_dp.c | 20 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 +- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 14 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 20 +- drivers/gpu/drm/i915/display/intel_dvo.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 44 ++-- drivers/gpu/drm/i915/display/intel_lvds.c | 4 +- drivers/gpu/drm/i915/display/intel_panel.c | 6 +- drivers/gpu/drm/i915/display/intel_pipe_crc.c | 4 +- drivers/gpu/drm/i915/display/intel_psr.c | 6 +- drivers/gpu/drm/i915/display/intel_sdvo.c | 6 +- drivers/gpu/drm/i915/display/intel_sprite.c | 17 +- drivers/gpu/drm/i915/display/intel_tv.c | 4 +- drivers/gpu/drm/i915/display/intel_vdsc.c | 8 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 10 +- drivers/gpu/drm/i915/i915_debugfs.c | 6 +- drivers/gpu/drm/i915/intel_pm.c | 110 +++++----- 27 files changed, 346 insertions(+), 344 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index e62dfabc3cd0..8eb2d7f29c82 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -625,7 +625,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); enum pipe pipe = intel_crtc->pipe; u32 tmp; enum port port; @@ -1242,7 +1242,7 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); /* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */ @@ -1265,7 +1265,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, base); struct intel_connector *intel_connector = intel_dsi->attached_connector; - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; struct drm_display_mode *adjusted_mode = diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 4826aa4ee8e7..48964f33c0c1 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -193,7 +193,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) if (!crtc_state) return NULL; - __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base); + __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->uapi); crtc_state->update_pipe = false; crtc_state->disable_lp_wm = false; @@ -205,7 +205,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->fb_bits = 0; crtc_state->update_planes = 0; - return &crtc_state->base; + return &crtc_state->uapi; } /** @@ -222,7 +222,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, { struct intel_crtc_state *crtc_state = to_intel_crtc_state(state); - __drm_atomic_helper_crtc_destroy_state(&crtc_state->base); + __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); kfree(crtc_state); } @@ -322,7 +322,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, struct intel_plane_state *plane_state = NULL; struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; - struct drm_atomic_state *drm_state = crtc_state->base.state; + struct drm_atomic_state *drm_state = crtc_state->uapi.state; struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state); int num_scalers_need; int i; diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 98f557a9f8ee..4558c0b29fc1 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -307,7 +307,7 @@ void intel_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); trace_intel_update_plane(&plane->base, crtc); plane->update_plane(plane, crtc_state, plane_state); @@ -317,7 +317,7 @@ void intel_update_slave(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); trace_intel_update_plane(&plane->base, crtc); plane->update_slave(plane, crtc_state, plane_state); @@ -326,7 +326,7 @@ void intel_update_slave(struct intel_plane *plane, void intel_disable_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); trace_intel_disable_plane(&plane->base, crtc); plane->disable_plane(plane, crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 6740191d3557..27710098d056 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -555,7 +555,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder, const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum pipe pipe = crtc->pipe; enum port port = encoder->port; u32 tmp, eldv; @@ -602,7 +602,7 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_connector *connector = conn_state->connector; enum pipe pipe = crtc->pipe; enum port port = encoder->port; @@ -692,7 +692,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct i915_audio_component *acomp = dev_priv->audio_component; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_connector *connector = conn_state->connector; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; @@ -753,7 +753,7 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct i915_audio_component *acomp = dev_priv->audio_component; - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum port port = encoder->port; enum pipe pipe = crtc->pipe; diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 22e83f857de8..3f6e29f61323 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -297,7 +297,7 @@ static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_stat static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); unsigned int data_rate = 0; enum plane_id plane_id; @@ -318,7 +318,7 @@ static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_ void intel_bw_crtc_update(struct intel_bw_state *bw_state, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); bw_state->data_rate[crtc->pipe] = intel_bw_crtc_data_rate(crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 304fd650a74c..8b702317557e 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1902,7 +1902,7 @@ intel_set_cdclk_post_plane_update(struct drm_i915_private *dev_priv, static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); int pixel_rate = crtc_state->pixel_rate; if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) @@ -1920,7 +1920,7 @@ static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state) static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_plane *plane; int min_cdclk = 0; @@ -1934,7 +1934,7 @@ static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state) int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = - to_i915(crtc_state->base.crtc->dev); + to_i915(crtc_state->uapi.crtc->dev); int min_cdclk; if (!crtc_state->hw.enable) @@ -2282,10 +2282,10 @@ static int intel_modeset_all_pipes(struct intel_atomic_state *state) return PTR_ERR(crtc_state); if (!crtc_state->hw.active || - drm_atomic_crtc_needs_modeset(&crtc_state->base)) + drm_atomic_crtc_needs_modeset(&crtc_state->uapi)) continue; - crtc_state->base.mode_changed = true; + crtc_state->uapi.mode_changed = true; ret = drm_atomic_add_affected_connectors(&state->base, &crtc->base); @@ -2366,7 +2366,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); - if (drm_atomic_crtc_needs_modeset(&crtc_state->base)) + if (drm_atomic_crtc_needs_modeset(&crtc_state->uapi)) pipe = INVALID_PIPE; } else { pipe = INVALID_PIPE; diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 62cc2d9df39f..5008a3fca484 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -205,7 +205,7 @@ static void icl_update_output_csc(struct intel_crtc *crtc, static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); /* * FIXME if there's a gamma LUT after the CSC, we should @@ -270,7 +270,7 @@ static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state, static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); bool limited_color_range = ilk_csc_limited_range(crtc_state); @@ -309,7 +309,7 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state) static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (crtc_state->hw.ctm) { @@ -338,7 +338,7 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state) */ static void cherryview_load_csc_matrix(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -404,7 +404,7 @@ static u32 ilk_lut_10(const struct drm_color_lut *color) static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; int i; @@ -440,7 +440,7 @@ static void i9xx_load_luts(const struct intel_crtc_state *crtc_state) static void i9xx_color_commit(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; u32 val; @@ -453,7 +453,7 @@ static void i9xx_color_commit(const struct intel_crtc_state *crtc_state) static void ilk_color_commit(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; u32 val; @@ -468,7 +468,7 @@ static void ilk_color_commit(const struct intel_crtc_state *crtc_state) static void hsw_color_commit(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode); @@ -478,7 +478,7 @@ static void hsw_color_commit(const struct intel_crtc_state *crtc_state) static void skl_color_commit(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; u32 val = 0; @@ -524,7 +524,7 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc, static void i965_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) @@ -547,7 +547,7 @@ static void ilk_load_lut_10(struct intel_crtc *crtc, static void ilk_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) @@ -654,7 +654,7 @@ static void ivb_load_lut_ext_max(struct intel_crtc *crtc) static void ivb_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; @@ -677,7 +677,7 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state) static void bdw_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; @@ -700,7 +700,7 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state) static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size; @@ -739,7 +739,7 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state) static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size; @@ -767,7 +767,7 @@ static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_stat static void glk_load_luts(const struct intel_crtc_state *crtc_state) { const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); /* * On GLK+ both pipe CSC and degamma LUT are controlled @@ -808,7 +808,7 @@ static void icl_load_gcmax(const struct intel_crtc_state *crtc_state, const struct drm_color_lut *color) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_dsb *dsb = intel_dsb_get(crtc); enum pipe pipe = crtc->pipe; @@ -822,7 +822,7 @@ icl_load_gcmax(const struct intel_crtc_state *crtc_state, static void icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *blob = crtc_state->hw.gamma_lut; const struct drm_color_lut *lut = blob->data; struct intel_dsb *dsb = intel_dsb_get(crtc); @@ -854,7 +854,7 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) static void icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *blob = crtc_state->hw.gamma_lut; const struct drm_color_lut *lut = blob->data; const struct drm_color_lut *entry; @@ -911,7 +911,7 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) static void icl_load_luts(const struct intel_crtc_state *crtc_state) { const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_dsb *dsb = intel_dsb_get(crtc); if (crtc_state->hw.degamma_lut) @@ -990,7 +990,7 @@ static void chv_load_cgm_gamma(struct intel_crtc *crtc, static void chv_load_luts(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; @@ -1010,28 +1010,28 @@ static void chv_load_luts(const struct intel_crtc_state *crtc_state) void intel_color_load_luts(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); dev_priv->display.load_luts(crtc_state); } void intel_color_commit(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); dev_priv->display.color_commit(crtc_state); } int intel_color_check(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); return dev_priv->display.color_check(crtc_state); } void intel_color_get_config(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); if (dev_priv->display.read_luts) dev_priv->display.read_luts(crtc_state); @@ -1055,16 +1055,16 @@ static bool need_plane_update(struct intel_plane *plane, static int intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_atomic_state *state = - to_intel_atomic_state(new_crtc_state->base.state); + to_intel_atomic_state(new_crtc_state->uapi.state); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); struct intel_plane *plane; if (!new_crtc_state->hw.active || - drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) + drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) return 0; if (new_crtc_state->gamma_enable == old_crtc_state->gamma_enable && @@ -1106,7 +1106,7 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected) static int check_luts(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; @@ -1479,7 +1479,7 @@ static int glk_gamma_precision(const struct intel_crtc_state *crtc_state) int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (HAS_GMCH(dev_priv)) { @@ -1585,7 +1585,7 @@ static u32 intel_color_lut_pack(u32 val, u32 bit_precision) static struct drm_property_blob * i9xx_read_lut_8(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; struct drm_property_blob *blob; @@ -1628,7 +1628,7 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob * i965_read_lut_10p6(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; enum pipe pipe = crtc->pipe; @@ -1680,7 +1680,7 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob * chv_read_cgm_lut(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; enum pipe pipe = crtc->pipe; @@ -1722,7 +1722,7 @@ static void chv_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob * ilk_read_lut_10(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; enum pipe pipe = crtc->pipe; @@ -1769,7 +1769,7 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state) static struct drm_property_blob * glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); int hw_lut_size = ivb_lut_10_size(prec_index); enum pipe pipe = crtc->pipe; diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 6e824c80dcbf..7a2d36905155 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -161,7 +161,7 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crt *crt = intel_encoder_to_crt(encoder); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 adpa; @@ -271,7 +271,7 @@ static void hsw_pre_enable_crt(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum pipe pipe = crtc->pipe; WARN_ON(!crtc_state->has_pch_encoder); @@ -288,7 +288,7 @@ static void hsw_enable_crt(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum pipe pipe = crtc->pipe; WARN_ON(!crtc_state->has_pch_encoder); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 7df02be169d1..7deae472be5f 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1744,7 +1744,7 @@ static void intel_ddi_clock_get(struct intel_encoder *encoder, void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 temp; @@ -1806,7 +1806,7 @@ void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state, void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, bool state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 temp; @@ -1828,7 +1828,7 @@ void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, static u32 intel_ddi_transcoder_func_reg_val_get(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -1918,7 +1918,7 @@ intel_ddi_transcoder_func_reg_val_get(const struct intel_crtc_state *crtc_state) void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 temp; @@ -1934,7 +1934,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state) static void intel_ddi_config_transcoder_func(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 temp; @@ -1946,7 +1946,7 @@ intel_ddi_config_transcoder_func(const struct intel_crtc_state *crtc_state) void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); @@ -2244,7 +2244,7 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder, void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc); enum port port = encoder->port; @@ -2262,7 +2262,7 @@ void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state) void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; if (cpu_transcoder != TRANSCODER_EDP) { @@ -3342,7 +3342,7 @@ static void intel_ddi_disable_fec_state(struct intel_encoder *encoder, static void tgl_clear_psr2_transcoder_exitline(const struct intel_crtc_state *cstate) { - struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev); u32 val; if (!cstate->dc3co_exitline) @@ -3357,7 +3357,7 @@ static void tgl_set_psr2_transcoder_exitline(const struct intel_crtc_state *cstate) { u32 val, exit_scanlines; - struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev); if (!cstate->dc3co_exitline) return; @@ -3375,7 +3375,7 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *cstate) { u32 exit_scanlines; - struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev); u32 crtc_vdisplay = cstate->hw.adjusted_mode.crtc_vdisplay; cstate->dc3co_exitline = 0; @@ -3384,7 +3384,7 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder, return; /* B.Specs:49196 DC3CO only works with pipeA and DDIA.*/ - if (to_intel_crtc(cstate->base.crtc)->pipe != PIPE_A || + if (to_intel_crtc(cstate->uapi.crtc)->pipe != PIPE_A || encoder->port != PORT_A) return; @@ -3408,7 +3408,7 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder, static void tgl_dc3co_exitline_get_config(struct intel_crtc_state *crtc_state) { u32 val; - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); if (INTEL_GEN(dev_priv) < 12) return; @@ -3656,7 +3656,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -4213,7 +4213,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; u32 temp, flags = 0; @@ -4380,7 +4380,7 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = encoder->port; int ret; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2d7b1a1301a1..4da61e9194c1 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -529,7 +529,7 @@ icl_wa_scalerclkgating(struct drm_i915_private *dev_priv, enum pipe pipe, static bool needs_modeset(const struct intel_crtc_state *state) { - return drm_atomic_crtc_needs_modeset(&state->base); + return drm_atomic_crtc_needs_modeset(&state->uapi); } bool @@ -657,7 +657,7 @@ i9xx_select_p2_div(const struct intel_limit *limit, const struct intel_crtc_state *crtc_state, int target) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { /* @@ -693,7 +693,7 @@ i9xx_find_best_dpll(const struct intel_limit *limit, int target, int refclk, struct dpll *match_clock, struct dpll *best_clock) { - struct drm_device *dev = crtc_state->base.crtc->dev; + struct drm_device *dev = crtc_state->uapi.crtc->dev; struct dpll clock; int err = target; @@ -751,7 +751,7 @@ pnv_find_best_dpll(const struct intel_limit *limit, int target, int refclk, struct dpll *match_clock, struct dpll *best_clock) { - struct drm_device *dev = crtc_state->base.crtc->dev; + struct drm_device *dev = crtc_state->uapi.crtc->dev; struct dpll clock; int err = target; @@ -807,7 +807,7 @@ g4x_find_best_dpll(const struct intel_limit *limit, int target, int refclk, struct dpll *match_clock, struct dpll *best_clock) { - struct drm_device *dev = crtc_state->base.crtc->dev; + struct drm_device *dev = crtc_state->uapi.crtc->dev; struct dpll clock; int max_n; bool found = false; @@ -901,7 +901,7 @@ vlv_find_best_dpll(const struct intel_limit *limit, int target, int refclk, struct dpll *match_clock, struct dpll *best_clock) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; struct dpll clock; unsigned int bestppm = 1000000; @@ -961,7 +961,7 @@ chv_find_best_dpll(const struct intel_limit *limit, int target, int refclk, struct dpll *match_clock, struct dpll *best_clock) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; unsigned int best_error_ppm; struct dpll clock; @@ -1094,7 +1094,7 @@ static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) static void intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (INTEL_GEN(dev_priv) >= 4) { @@ -1553,7 +1553,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc, static void i9xx_disable_pll(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -1644,7 +1644,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; i915_reg_t reg; @@ -1788,7 +1788,7 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); /* * On i965gm the hardware frame counter reads @@ -1808,7 +1808,7 @@ static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state static void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); drm_crtc_set_max_vblank_count(&crtc->base, intel_crtc_max_vblank_count(crtc_state)); @@ -1817,7 +1817,7 @@ static void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder; enum pipe pipe = crtc->pipe; @@ -1875,7 +1875,7 @@ static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state) static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; enum pipe pipe = crtc->pipe; @@ -3132,14 +3132,14 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state, plane_state->base.visible = visible; if (visible) - crtc_state->base.plane_mask |= drm_plane_mask(&plane->base); + crtc_state->uapi.plane_mask |= drm_plane_mask(&plane->base); else - crtc_state->base.plane_mask &= ~drm_plane_mask(&plane->base); + crtc_state->uapi.plane_mask &= ~drm_plane_mask(&plane->base); } static void fixup_active_planes(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); struct drm_plane *plane; /* @@ -3150,7 +3150,7 @@ static void fixup_active_planes(struct intel_crtc_state *crtc_state) crtc_state->active_planes = 0; drm_for_each_plane_mask(plane, &dev_priv->drm, - crtc_state->base.plane_mask) + crtc_state->uapi.plane_mask) crtc_state->active_planes |= BIT(to_intel_plane(plane)->id); } @@ -3669,7 +3669,7 @@ i9xx_plane_max_stride(struct intel_plane *plane, static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dspcntr = 0; @@ -3831,7 +3831,7 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state, return ret; ret = drm_atomic_helper_check_plane_state(&plane_state->base, - &crtc_state->base, + &crtc_state->uapi, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, i9xx_plane_has_windowing(plane), @@ -4007,7 +4007,7 @@ static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) */ static void skl_detach_scalers(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; int i; @@ -4202,7 +4202,7 @@ static u32 cnl_plane_ctl_flip(unsigned int reflect) u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); u32 plane_ctl = 0; if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) @@ -4258,7 +4258,7 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); u32 plane_color_ctl = 0; if (INTEL_GEN(dev_priv) >= 11) @@ -4479,7 +4479,7 @@ static void icl_set_pipe_chicken(struct intel_crtc *crtc) static void icl_enable_trans_port_sync(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 trans_ddi_func_ctl2_val; u8 master_select; @@ -4509,7 +4509,7 @@ static void icl_enable_trans_port_sync(const struct intel_crtc_state *crtc_state static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); i915_reg_t reg; u32 trans_ddi_func_ctl2_val; @@ -4923,7 +4923,7 @@ train_done: static void ironlake_fdi_pll_enable(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); enum pipe pipe = intel_crtc->pipe; i915_reg_t reg; @@ -5084,7 +5084,7 @@ void lpt_disable_iclkip(struct drm_i915_private *dev_priv) /* Program iCLKIP clock to the desired frequency */ static void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); int clock = crtc_state->hw.adjusted_mode.crtc_clock; u32 divsel, phaseinc, auxdiv, phasedir = 0; @@ -5200,7 +5200,7 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv) static void ironlake_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state, enum pipe pch_transcoder) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -5243,7 +5243,7 @@ static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool e static void ivybridge_update_fdi_bc_bifurcation(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); switch (crtc->pipe) { @@ -5273,7 +5273,7 @@ static struct intel_encoder * intel_get_crtc_new_encoder(const struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_connector_state *connector_state; const struct drm_connector *connector; struct intel_encoder *encoder = NULL; @@ -5305,7 +5305,7 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, static void ironlake_pch_enable(const struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); enum pipe pipe = crtc->pipe; @@ -5389,7 +5389,7 @@ static void ironlake_pch_enable(const struct intel_atomic_state *state, static void lpt_pch_enable(const struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -5506,7 +5506,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; struct intel_crtc *intel_crtc = - to_intel_crtc(crtc_state->base.crtc); + to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; @@ -5706,7 +5706,7 @@ static void skylake_scaler_disable(struct intel_crtc *crtc) static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; const struct intel_crtc_scaler_state *scaler_state = @@ -5743,7 +5743,7 @@ static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state) static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -5764,7 +5764,7 @@ static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state) void hsw_enable_ips(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -5800,7 +5800,7 @@ void hsw_enable_ips(const struct intel_crtc_state *crtc_state) void hsw_disable_ips(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -5905,7 +5905,7 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!old_crtc_state->ips_enabled) @@ -5921,7 +5921,7 @@ static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_s * Disable IPS before we program the LUT. */ if (IS_HASWELL(dev_priv) && - (new_crtc_state->base.color_mgmt_changed || + (new_crtc_state->uapi.color_mgmt_changed || new_crtc_state->update_pipe) && new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) return true; @@ -5932,7 +5932,7 @@ static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_s static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!new_crtc_state->ips_enabled) @@ -5948,7 +5948,7 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s * Re-enable IPS after the LUT has been programmed. */ if (IS_HASWELL(dev_priv) && - (new_crtc_state->base.color_mgmt_changed || + (new_crtc_state->uapi.color_mgmt_changed || new_crtc_state->update_pipe) && new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) return true; @@ -5989,10 +5989,10 @@ static bool needs_scalerclk_wa(struct drm_i915_private *dev_priv, static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_atomic_state *state = old_crtc_state->base.state; + struct drm_atomic_state *state = old_crtc_state->uapi.state; struct intel_crtc_state *pipe_config = intel_atomic_get_new_crtc_state(to_intel_atomic_state(state), crtc); @@ -6032,10 +6032,10 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *pipe_config) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_atomic_state *state = old_crtc_state->base.state; + struct drm_atomic_state *state = old_crtc_state->uapi.state; struct drm_plane *primary = crtc->base.primary; struct drm_plane_state *old_primary_state = drm_atomic_get_old_plane_state(state, primary); @@ -6387,7 +6387,7 @@ static void intel_encoders_update_pipe(struct intel_crtc *crtc, static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_plane *plane = to_intel_plane(crtc->base.primary); plane->disable_plane(plane, crtc_state); @@ -6396,7 +6396,7 @@ static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_stat static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { - struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_crtc *crtc = pipe_config->uapi.crtc; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -6530,7 +6530,7 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc) static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { - struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_crtc *crtc = pipe_config->uapi.crtc; struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe, hsw_workaround_pipe; @@ -6641,7 +6641,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -6657,7 +6657,7 @@ static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state) static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, struct intel_atomic_state *state) { - struct drm_crtc *crtc = old_crtc_state->base.crtc; + struct drm_crtc *crtc = old_crtc_state->uapi.crtc; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -6716,7 +6716,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, struct intel_atomic_state *state) { - struct drm_crtc *crtc = old_crtc_state->base.crtc; + struct drm_crtc *crtc = old_crtc_state->uapi.crtc; struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; @@ -6753,7 +6753,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!crtc_state->gmch_pfit.control) @@ -6889,7 +6889,7 @@ intel_aux_power_domain(struct intel_digital_port *dig_port) static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct drm_encoder *encoder; enum pipe pipe = crtc->pipe; @@ -6906,7 +6906,7 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state) mask |= BIT_ULL(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe)); drm_for_each_encoder_mask(encoder, &dev_priv->drm, - crtc_state->base.encoder_mask) { + crtc_state->uapi.encoder_mask) { struct intel_encoder *intel_encoder = to_intel_encoder(encoder); mask |= BIT_ULL(intel_encoder->power_domain); @@ -6924,7 +6924,7 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state) static u64 modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum intel_display_power_domain domain; u64 domains, new_domains, old_domains; @@ -6953,7 +6953,7 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv, static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { - struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_crtc *crtc = pipe_config->uapi.crtc; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -7009,7 +7009,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); I915_WRITE(FP0(crtc->pipe), crtc_state->dpll_hw_state.fp0); @@ -7019,7 +7019,7 @@ static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state) static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { - struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_crtc *crtc = pipe_config->uapi.crtc; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -7069,7 +7069,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!old_crtc_state->gmch_pfit.control) @@ -7085,7 +7085,7 @@ static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, struct intel_atomic_state *state) { - struct drm_crtc *crtc = old_crtc_state->base.crtc; + struct drm_crtc *crtc = old_crtc_state->uapi.crtc; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -7284,7 +7284,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_atomic_state *state = pipe_config->base.state; + struct drm_atomic_state *state = pipe_config->uapi.state; struct intel_crtc *other_crtc; struct intel_crtc_state *other_crtc_state; @@ -7403,7 +7403,7 @@ retry: bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); /* IPS only exists on ULT machines and is tied to pipe A. */ @@ -7433,9 +7433,9 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state) static bool hsw_compute_ips_config(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = - to_i915(crtc_state->base.crtc->dev); + to_i915(crtc_state->uapi.crtc->dev); struct intel_atomic_state *intel_state = - to_intel_atomic_state(crtc_state->base.state); + to_intel_atomic_state(crtc_state->uapi.state); if (!hsw_crtc_state_ips_capable(crtc_state)) return false; @@ -7507,7 +7507,7 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config) static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); if (HAS_GMCH(dev_priv)) /* FIXME calculate proper pipe pixel rate for GMCH pfit */ @@ -7742,7 +7742,7 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe static void intel_pch_transcoder_set_m_n(const struct intel_crtc_state *crtc_state, const struct intel_link_m_n *m_n) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -7769,7 +7769,7 @@ static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_sta const struct intel_link_m_n *m_n, const struct intel_link_m_n *m2_n2) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; enum transcoder transcoder = crtc_state->cpu_transcoder; @@ -8082,7 +8082,7 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe, if (!pipe_config) return -ENOMEM; - pipe_config->base.crtc = &crtc->base; + pipe_config->uapi.crtc = &crtc->base; pipe_config->pixel_multiplier = 1; pipe_config->dpll = *dpll; @@ -8242,7 +8242,7 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc, static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -8304,7 +8304,7 @@ static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state) static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -8318,7 +8318,7 @@ static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state) static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; if (IS_GEN(dev_priv, 2)) @@ -8416,7 +8416,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 pipeconf; @@ -8862,7 +8862,7 @@ bdw_get_pipemisc_output_format(struct intel_crtc *crtc) static void i9xx_get_pipe_color_config(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_plane *plane = to_intel_plane(crtc->base.primary); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; @@ -9502,7 +9502,7 @@ void intel_init_pch_refclk(struct drm_i915_private *dev_priv) static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; u32 val; @@ -9556,7 +9556,7 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state) static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 val = 0; @@ -9579,7 +9579,7 @@ static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state) static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 val = 0; @@ -9765,7 +9765,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_atomic_state *state = - to_intel_atomic_state(crtc_state->base.state); + to_intel_atomic_state(crtc_state->uapi.state); const struct intel_limit *limit; int refclk = 120000; @@ -10191,7 +10191,7 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_atomic_state *state = - to_intel_atomic_state(crtc_state->base.state); + to_intel_atomic_state(crtc_state->uapi.state); if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) || INTEL_GEN(dev_priv) >= 11) { @@ -10557,7 +10557,7 @@ static enum transcoder transcoder_master_readout(struct drm_i915_private *dev_pr static void icelake_get_trans_port_sync_config(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); u32 transcoders; enum transcoder cpu_transcoder; @@ -10834,7 +10834,7 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, } ret = drm_atomic_helper_check_plane_state(&plane_state->base, - &crtc_state->base, + &crtc_state->uapi, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, true, true); @@ -11021,7 +11021,7 @@ i9xx_cursor_max_stride(struct intel_plane *plane, static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 cntl = 0; @@ -11434,7 +11434,7 @@ found: crtc_state->uapi.active = true; - ret = drm_atomic_set_mode_for_crtc(&crtc_state->base, + ret = drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &load_detect_mode); if (ret) goto fail; @@ -11673,7 +11673,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder) return NULL; } - crtc_state->base.crtc = &crtc->base; + crtc_state->uapi.crtc = &crtc->base; if (!dev_priv->display.get_pipe_config(crtc, crtc_state)) { kfree(crtc_state); @@ -11744,7 +11744,7 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat const struct intel_plane_state *old_plane_state, struct intel_plane_state *plane_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); bool mode_changed = needs_modeset(crtc_state); @@ -11917,9 +11917,9 @@ static int icl_add_linked_planes(struct intel_atomic_state *state) static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->base.state); + struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); struct intel_plane *plane, *linked; struct intel_plane_state *plane_state; int i; @@ -11989,9 +11989,9 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) static bool c8_planes_changed(const struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct intel_atomic_state *state = - to_intel_atomic_state(new_crtc_state->base.state); + to_intel_atomic_state(new_crtc_state->uapi.state); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); @@ -12000,9 +12000,9 @@ static bool c8_planes_changed(const struct intel_crtc_state *new_crtc_state) static int icl_add_sync_mode_crtcs(struct intel_crtc_state *crtc_state) { - struct drm_crtc *crtc = crtc_state->base.crtc; - struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->base.state); - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_crtc *crtc = crtc_state->uapi.crtc; + struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); struct drm_connector *master_connector, *connector; struct drm_connector_state *connector_state; struct drm_connector_list_iter conn_iter; @@ -12076,7 +12076,7 @@ static int icl_add_sync_mode_crtcs(struct intel_crtc_state *crtc_state) BIT(crtc_state->cpu_transcoder); DRM_DEBUG_KMS("Master Transcoder = %s added for Slave CRTC = %d, slave transcoder bitmask = %d\n", transcoder_name(crtc_state->master_transcoder), - crtc_state->base.crtc->base.id, + crtc_state->uapi.crtc->base.id, master_pipe_config->sync_mode_slaves_mask); } @@ -12109,10 +12109,10 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, * when C8 planes are getting enabled/disabled. */ if (c8_planes_changed(crtc_state)) - crtc_state->base.color_mgmt_changed = true; + crtc_state->uapi.color_mgmt_changed = true; if (mode_changed || crtc_state->update_pipe || - crtc_state->base.color_mgmt_changed) { + crtc_state->uapi.color_mgmt_changed) { ret = intel_color_check(crtc_state); if (ret) return ret; @@ -12225,7 +12225,7 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_atomic_state *state = pipe_config->base.state; + struct drm_atomic_state *state = pipe_config->uapi.state; struct drm_connector *connector; struct drm_connector_state *connector_state; int bpp, i; @@ -12378,7 +12378,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, struct intel_atomic_state *state, const char *context) { - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct intel_plane_state *plane_state; struct intel_plane *plane; @@ -12561,7 +12561,7 @@ static int clear_intel_crtc_state(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = - to_i915(crtc_state->base.crtc->dev); + to_i915(crtc_state->uapi.crtc->dev); struct intel_crtc_state *saved_state; saved_state = kzalloc(sizeof(*saved_state), GFP_KERNEL); @@ -12594,8 +12594,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) BUILD_BUG_ON(offsetof(struct intel_crtc_state, base)); BUILD_BUG_ON(offsetof(struct intel_crtc_state, uapi)); BUILD_BUG_ON(offsetof(struct intel_crtc_state, hw)); - memcpy(&crtc_state->base + 1, &saved_state->base + 1, - sizeof(*crtc_state) - sizeof(crtc_state->base)); + memcpy(&crtc_state->uapi + 1, &saved_state->uapi + 1, + sizeof(*crtc_state) - sizeof(crtc_state->uapi)); kfree(saved_state); return 0; @@ -12604,8 +12604,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) static int intel_modeset_pipe_config(struct intel_crtc_state *pipe_config) { - struct drm_crtc *crtc = pipe_config->base.crtc; - struct drm_atomic_state *state = pipe_config->base.state; + struct drm_crtc *crtc = pipe_config->uapi.crtc; + struct drm_atomic_state *state = pipe_config->uapi.state; struct intel_encoder *encoder; struct drm_connector *connector; struct drm_connector_state *connector_state; @@ -12882,8 +12882,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, const struct intel_crtc_state *pipe_config, bool fastset) { - struct drm_i915_private *dev_priv = to_i915(current_config->base.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); bool ret = true; u32 bp_gamma = 0; bool fixup_inherited = fastset && @@ -13471,12 +13471,12 @@ verify_crtc_state(struct intel_crtc *crtc, struct drm_atomic_state *state; bool active; - state = old_crtc_state->base.state; - __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->base); + state = old_crtc_state->uapi.state; + __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); pipe_config = old_crtc_state; memset(pipe_config, 0, sizeof(*pipe_config)); - pipe_config->base.crtc = &crtc->base; - pipe_config->base.state = state; + pipe_config->uapi.crtc = &crtc->base; + pipe_config->uapi.state = state; DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.base.id, crtc->base.name); @@ -13656,7 +13656,7 @@ intel_modeset_verify_disabled(struct drm_i915_private *dev_priv, static void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; @@ -13853,7 +13853,7 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true)) return; - new_crtc_state->base.mode_changed = false; + new_crtc_state->uapi.mode_changed = false; new_crtc_state->update_pipe = true; /* @@ -13998,7 +13998,7 @@ static int intel_atomic_check(struct drm_device *dev, new_crtc_state, i) { if (new_crtc_state->hw.mode.private_flags != old_crtc_state->hw.mode.private_flags) - new_crtc_state->base.mode_changed = true; + new_crtc_state->uapi.mode_changed = true; } ret = drm_atomic_helper_check_modeset(dev, &state->base); @@ -14126,7 +14126,7 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); /* @@ -14168,7 +14168,7 @@ static void commit_pipe_config(struct intel_atomic_state *state, * CRTC was enabled. */ if (!modeset) { - if (new_crtc_state->base.color_mgmt_changed || + if (new_crtc_state->uapi.color_mgmt_changed || new_crtc_state->update_pipe) intel_color_commit(new_crtc_state); @@ -14242,7 +14242,7 @@ static void intel_update_crtc(struct intel_crtc *crtc, static struct intel_crtc *intel_get_slave_crtc(const struct intel_crtc_state *new_crtc_state) { - struct drm_i915_private *dev_priv = to_i915(new_crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(new_crtc_state->uapi.crtc->dev); enum transcoder slave_transcoder; WARN_ON(!is_power_of_2(new_crtc_state->sync_mode_slaves_mask)); @@ -14680,12 +14680,13 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) bool modeset = needs_modeset(new_crtc_state); /* Complete events for now disable pipes here. */ - if (modeset && !new_crtc_state->hw.active && new_crtc_state->base.event) { + if (modeset && !new_crtc_state->hw.active && new_crtc_state->uapi.event) { spin_lock_irq(&dev->event_lock); - drm_crtc_send_vblank_event(&crtc->base, new_crtc_state->base.event); + drm_crtc_send_vblank_event(&crtc->base, + new_crtc_state->uapi.event); spin_unlock_irq(&dev->event_lock); - new_crtc_state->base.event = NULL; + new_crtc_state->uapi.event = NULL; } } @@ -14718,7 +14719,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->hw.active && !needs_modeset(new_crtc_state) && - (new_crtc_state->base.color_mgmt_changed || + (new_crtc_state->uapi.color_mgmt_changed || new_crtc_state->update_pipe)) intel_color_load_luts(new_crtc_state); } @@ -15368,7 +15369,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane, out_free: if (new_crtc_state) - intel_crtc_destroy_state(&crtc->base, &new_crtc_state->base); + intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi); if (ret) intel_plane_destroy_state(&plane->base, &new_plane_state->base); else @@ -15722,7 +15723,7 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) ret = -ENOMEM; goto fail; } - __drm_atomic_helper_crtc_reset(&intel_crtc->base, &crtc_state->base); + __drm_atomic_helper_crtc_reset(&intel_crtc->base, &crtc_state->uapi); intel_crtc->config = crtc_state; primary = intel_primary_plane_create(dev_priv, pipe); @@ -16751,7 +16752,7 @@ retry: * having a proper LUT loaded. Remove once we * have readout for pipe gamma enable. */ - crtc_state->base.color_mgmt_changed = true; + crtc_state->uapi.color_mgmt_changed = true; } } @@ -17149,7 +17150,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); /* * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram @@ -17283,9 +17284,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - __drm_atomic_helper_crtc_destroy_state(&crtc_state->base); + __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); memset(crtc_state, 0, sizeof(*crtc_state)); - __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->base); + __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->uapi); crtc_state->hw.active = crtc_state->hw.enable = dev_priv->display.get_pipe_config(crtc, crtc_state); @@ -17371,9 +17372,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) * because anything calling .crtc_disable may * rely on the connector_mask being accurate. */ - crtc_state->base.connector_mask |= + crtc_state->uapi.connector_mask |= drm_connector_mask(&connector->base); - crtc_state->base.encoder_mask |= + crtc_state->uapi.encoder_mask |= drm_encoder_mask(&encoder->base); } } else { @@ -17403,7 +17404,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) mode = crtc_state->hw.adjusted_mode; mode.hdisplay = crtc_state->pipe_src_w; mode.vdisplay = crtc_state->pipe_src_h; - WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->base, &mode)); + WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &mode)); /* * The initial mode needs to be set in order to keep diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 1602a8dbbfa9..b03696944c16 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2253,7 +2253,7 @@ intel_dp_ycbcr420_config(struct intel_dp *intel_dp, const struct drm_display_info *info = &connector->display_info; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); int ret; if (!drm_mode_is_420_only(info, adjusted_mode) || @@ -2318,7 +2318,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_lspcon *lspcon = enc_to_intel_lspcon(&encoder->base); enum port port = encoder->port; - struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_connector *intel_connector = intel_dp->attached_connector; struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(conn_state); @@ -2436,7 +2436,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = encoder->port; - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; intel_dp_set_link_params(intel_dp, pipe_config->port_clock, @@ -3034,7 +3034,7 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state) static void ironlake_edp_pll_on(struct intel_dp *intel_dp, const struct intel_crtc_state *pipe_config) { - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); assert_pipe_disabled(dev_priv, crtc->pipe); @@ -3074,7 +3074,7 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp, static void ironlake_edp_pll_off(struct intel_dp *intel_dp, const struct intel_crtc_state *old_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); assert_pipe_disabled(dev_priv, crtc->pipe); @@ -3234,7 +3234,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); u32 tmp, flags = 0; enum port port = encoder->port; - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); if (encoder->type == INTEL_OUTPUT_EDP) pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP); @@ -3501,7 +3501,7 @@ static void intel_enable_dp(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); u32 dp_reg = I915_READ(intel_dp->output_reg); enum pipe pipe = crtc->pipe; intel_wakeref_t wakeref; @@ -3634,7 +3634,7 @@ static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); lockdep_assert_held(&dev_priv->pps_mutex); @@ -4156,7 +4156,7 @@ intel_dp_link_down(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum port port = encoder->port; u32 DP = intel_dp->DP; @@ -6914,7 +6914,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, int refresh_rate) { struct intel_dp *intel_dp = dev_priv->drrs.dp; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); enum drrs_refresh_rate_type index = DRRS_HIGH_RR; if (refresh_rate <= 0) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 8a1dc7212db7..5b2ca81f5cd6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -42,7 +42,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state, struct link_config_limits *limits) { - struct drm_atomic_state *state = crtc_state->base.state; + struct drm_atomic_state *state = crtc_state->uapi.state; struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_dp *intel_dp = &intel_mst->primary->dp; struct intel_connector *connector = @@ -190,7 +190,7 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, intel_crtc); if (!crtc_state || - !drm_atomic_crtc_needs_modeset(&crtc_state->base) || + !drm_atomic_crtc_needs_modeset(&crtc_state->uapi) || crtc_state->hw.enable) return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 556d1b30f06a..704f38681c4b 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -739,7 +739,7 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum pipe pipe = crtc->pipe; u32 val; @@ -783,7 +783,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dport_to_channel(dport); enum pipe pipe = crtc->pipe; unsigned int lane_mask = @@ -864,7 +864,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_digital_port *dport = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dport_to_channel(dport); enum pipe pipe = crtc->pipe; int data, i, stagger; @@ -953,7 +953,7 @@ void chv_phy_post_pll_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum pipe pipe = to_intel_crtc(old_crtc_state->base.crtc)->pipe; + enum pipe pipe = to_intel_crtc(old_crtc_state->uapi.crtc)->pipe; u32 val; vlv_dpio_get(dev_priv); @@ -1016,7 +1016,7 @@ void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel port = vlv_dport_to_channel(dport); enum pipe pipe = crtc->pipe; @@ -1046,7 +1046,7 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_digital_port *dport = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel port = vlv_dport_to_channel(dport); enum pipe pipe = crtc->pipe; u32 val; @@ -1075,7 +1075,7 @@ void vlv_phy_reset_lanes(struct intel_encoder *encoder, { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum dpio_channel port = vlv_dport_to_channel(dport); enum pipe pipe = crtc->pipe; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 3ce0a023eee0..728a4b045de7 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -136,7 +136,7 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, */ void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll = crtc_state->shared_dpll; @@ -163,7 +163,7 @@ void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_state) */ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll = crtc_state->shared_dpll; unsigned int crtc_mask = drm_crtc_mask(&crtc->base); @@ -208,7 +208,7 @@ out: */ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll = crtc_state->shared_dpll; unsigned int crtc_mask = drm_crtc_mask(&crtc->base); @@ -842,7 +842,7 @@ hsw_ddi_hdmi_get_dpll(struct intel_atomic_state *state, static struct intel_shared_dpll * hsw_ddi_dp_get_dpll(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); struct intel_shared_dpll *pll; enum intel_dpll_id pll_id; int clock = crtc_state->port_clock; @@ -1751,7 +1751,7 @@ static bool bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state, struct bxt_clk_div *clk_div) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct dpll best_clock; /* Calculate HDMI div */ @@ -2274,7 +2274,7 @@ static bool cnl_ddi_calculate_wrpll(struct intel_crtc_state *crtc_state, struct skl_wrpll_params *wrpll_params) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); u32 afe_clock = crtc_state->port_clock * 5; u32 ref_clock; u32 dco_min = 7998000; @@ -2553,7 +2553,7 @@ static const struct skl_wrpll_params tgl_tbt_pll_24MHz_values = { static bool icl_calc_dp_combo_pll(struct intel_crtc_state *crtc_state, struct skl_wrpll_params *pll_params) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); const struct icl_combo_pll_params *params = dev_priv->cdclk.hw.ref == 24000 ? icl_dp_combo_pll_24MHz_values : @@ -2575,7 +2575,7 @@ static bool icl_calc_dp_combo_pll(struct intel_crtc_state *crtc_state, static bool icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, struct skl_wrpll_params *pll_params) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); if (INTEL_GEN(dev_priv) >= 12) { switch (dev_priv->cdclk.hw.ref) { @@ -2612,7 +2612,7 @@ static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder, struct intel_dpll_hw_state *pll_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); u32 cfgcr0, cfgcr1; struct skl_wrpll_params pll_params = { 0 }; bool ret; @@ -2744,7 +2744,7 @@ static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, struct intel_dpll_hw_state *pll_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); int refclk_khz = dev_priv->cdclk.hw.ref; int clock = crtc_state->port_clock; u32 dco_khz, m1div, m2div_int, m2div_rem, m2div_frac; diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index e45da2216e06..a74dc5b915d1 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -277,7 +277,7 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dvo *intel_dvo = enc_to_dvo(encoder); enum pipe pipe = crtc->pipe; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 434031fec430..e084c2f75379 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -285,7 +285,7 @@ static void ibx_write_infoframe(struct intel_encoder *encoder, { const u32 *data = frame; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); int i; @@ -321,7 +321,7 @@ static void ibx_read_infoframe(struct intel_encoder *encoder, void *frame, ssize_t len) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); u32 val, *data = frame; int i; @@ -340,7 +340,7 @@ static u32 ibx_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe; + enum pipe pipe = to_intel_crtc(pipe_config->uapi.crtc)->pipe; i915_reg_t reg = TVIDEO_DIP_CTL(pipe); u32 val = I915_READ(reg); @@ -362,7 +362,7 @@ static void cpt_write_infoframe(struct intel_encoder *encoder, { const u32 *data = frame; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); int i; @@ -401,7 +401,7 @@ static void cpt_read_infoframe(struct intel_encoder *encoder, void *frame, ssize_t len) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); u32 val, *data = frame; int i; @@ -420,7 +420,7 @@ static u32 cpt_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe; + enum pipe pipe = to_intel_crtc(pipe_config->uapi.crtc)->pipe; u32 val = I915_READ(TVIDEO_DIP_CTL(pipe)); if ((val & VIDEO_DIP_ENABLE) == 0) @@ -438,7 +438,7 @@ static void vlv_write_infoframe(struct intel_encoder *encoder, { const u32 *data = frame; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); int i; @@ -474,7 +474,7 @@ static void vlv_read_infoframe(struct intel_encoder *encoder, void *frame, ssize_t len) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); u32 val, *data = frame; int i; @@ -493,7 +493,7 @@ static u32 vlv_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum pipe pipe = to_intel_crtc(pipe_config->base.crtc)->pipe; + enum pipe pipe = to_intel_crtc(pipe_config->uapi.crtc)->pipe; u32 val = I915_READ(VLV_TVIDEO_DIP_CTL(pipe)); if ((val & VIDEO_DIP_ENABLE) == 0) @@ -965,7 +965,7 @@ static bool intel_hdmi_set_gcp_infoframe(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); i915_reg_t reg; if ((crtc_state->infoframes.enable & @@ -990,7 +990,7 @@ void intel_hdmi_read_gcp_infoframe(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); i915_reg_t reg; if ((crtc_state->infoframes.enable & @@ -1037,7 +1037,7 @@ static void ibx_set_infoframes(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); @@ -1096,7 +1096,7 @@ static void cpt_set_infoframes(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); i915_reg_t reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); @@ -1145,7 +1145,7 @@ static void vlv_set_infoframes(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); i915_reg_t reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); @@ -1736,7 +1736,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder, { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 hdmi_val; @@ -1860,7 +1860,7 @@ static void intel_enable_hdmi_audio(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); WARN_ON(!pipe_config->has_hdmi_sink); DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", @@ -1946,7 +1946,7 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder, { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); enum pipe pipe = crtc->pipe; u32 temp; @@ -2010,7 +2010,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct intel_digital_port *intel_dig_port = hdmi_to_dig_port(intel_hdmi); - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); u32 temp; temp = I915_READ(intel_hdmi->hdmi_reg); @@ -2210,8 +2210,8 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, int bpc) { struct drm_i915_private *dev_priv = - to_i915(crtc_state->base.crtc->dev); - struct drm_atomic_state *state = crtc_state->base.state; + to_i915(crtc_state->uapi.crtc->dev); + struct drm_atomic_state *state = crtc_state->uapi.state; struct drm_connector_state *connector_state; struct drm_connector *connector; const struct drm_display_mode *adjusted_mode = @@ -2240,7 +2240,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, for_each_new_connector_in_state(state, connector, connector_state, i) { const struct drm_display_info *info = &connector->display_info; - if (connector_state->crtc != crtc_state->base.crtc) + if (connector_state->crtc != crtc_state->uapi.crtc) continue; if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { @@ -2281,7 +2281,7 @@ static bool intel_hdmi_ycbcr420_config(struct drm_connector *connector, struct intel_crtc_state *config) { - struct intel_crtc *intel_crtc = to_intel_crtc(config->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(config->uapi.crtc); if (!connector->ycbcr_420_allowed) { DRM_ERROR("Platform doesn't support YCBCR420 output\n"); diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 40ae0b7377ce..10696bb99dcf 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -230,7 +230,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, { struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; enum pipe pipe = crtc->pipe; u32 temp; @@ -393,7 +393,7 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder, struct intel_connector *intel_connector = lvds_encoder->attached_connector; struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; - struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); unsigned int lvds_bpp; /* Should never happen!! */ diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 5e3fd37d9471..6f3eaae3761f 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -1047,7 +1047,7 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state, struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe; + enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; u32 ctl, ctl2; ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); @@ -1077,7 +1077,7 @@ static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state, struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe; + enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; u32 pwm_ctl, val; /* Controller 1 uses the utility pin. */ @@ -1189,7 +1189,7 @@ void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state, struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe; + enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; if (!panel->backlight.present) return; diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index fc602533a602..2746512f4466 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -309,13 +309,13 @@ retry: goto put_state; } - pipe_config->base.mode_changed = pipe_config->has_psr; + pipe_config->uapi.mode_changed = pipe_config->has_psr; pipe_config->crc_enabled = enable; if (IS_HASWELL(dev_priv) && pipe_config->hw.active && crtc->pipe == PIPE_A && pipe_config->cpu_transcoder == TRANSCODER_EDP) - pipe_config->base.mode_changed = true; + pipe_config->uapi.mode_changed = true; ret = drm_atomic_commit(state); diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index f75f759ad6ee..c1d133362b76 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -793,7 +793,7 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, dev_priv->psr.psr2_enabled = intel_psr2_enabled(dev_priv, crtc_state); dev_priv->psr.busy_frontbuffer_bits = 0; - dev_priv->psr.pipe = to_intel_crtc(crtc_state->base.crtc)->pipe; + dev_priv->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; dev_priv->psr.dc3co_enabled = !!crtc_state->dc3co_exitline; dev_priv->psr.dc3co_exit_delay = intel_get_frame_time_us(crtc_state); dev_priv->psr.transcoder = crtc_state->cpu_transcoder; @@ -1040,7 +1040,7 @@ unlock: int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state, u32 *out_value) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!dev_priv->psr.enabled || !new_crtc_state->has_psr) @@ -1119,7 +1119,7 @@ retry: if (crtc_state->hw.active && crtc_state->has_psr) { /* Mark mode as changed to trigger a pipe->update() */ - crtc_state->base.mode_changed = true; + crtc_state->uapi.mode_changed = true; break; } } diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index b5ed19da7d63..a4b1339fcc00 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -1429,7 +1429,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; const struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(conn_state); @@ -1723,7 +1723,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_sdvo *intel_sdvo = to_sdvo(encoder); - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); u32 temp; if (old_crtc_state->has_audio) @@ -1785,7 +1785,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder, struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_sdvo *intel_sdvo = to_sdvo(encoder); - struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); u32 temp; bool input1, input2; int i; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index fcd7355eaa34..5ba8faf0ccfe 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -81,7 +81,7 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, */ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode; long timeout = msecs_to_jiffies_timeout(1); @@ -190,7 +190,7 @@ irq_disable: */ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); enum pipe pipe = crtc->pipe; int scanline_end = intel_get_crtc_scanline(crtc); u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc); @@ -203,14 +203,15 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) * Would be slightly nice to just grab the vblank count and arm the * event outside of the critical section - the spinlock might spin for a * while ... */ - if (new_crtc_state->base.event) { + if (new_crtc_state->uapi.event) { WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0); spin_lock(&crtc->base.dev->event_lock); - drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event); + drm_crtc_arm_vblank_event(&crtc->base, + new_crtc_state->uapi.event); spin_unlock(&crtc->base.dev->event_lock); - new_crtc_state->base.event = NULL; + new_crtc_state->uapi.event = NULL; } local_irq_enable(); @@ -1964,7 +1965,7 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, } ret = drm_atomic_helper_check_plane_state(&plane_state->base, - &crtc_state->base, + &crtc_state->uapi, min_scale, max_scale, true, true); if (ret) @@ -2021,7 +2022,7 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, return ret; ret = drm_atomic_helper_check_plane_state(&plane_state->base, - &crtc_state->base, + &crtc_state->uapi, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, true, true); @@ -2202,7 +2203,7 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, } ret = drm_atomic_helper_check_plane_state(&plane_state->base, - &crtc_state->base, + &crtc_state->uapi, min_scale, max_scale, true, true); if (ret) diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 9bc5e91e5d54..50703536436c 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -924,7 +924,7 @@ intel_enable_tv(struct intel_encoder *encoder, /* Prevents vblank waits from timing out in intel_tv_detect_type() */ intel_wait_for_vblank(dev_priv, - to_intel_crtc(pipe_config->base.crtc)->pipe); + to_intel_crtc(pipe_config->uapi.crtc)->pipe); I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE); } @@ -1417,7 +1417,7 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_tv *intel_tv = enc_to_tv(encoder); const struct intel_tv_connector_state *tv_conn_state = to_intel_tv_connector_state(conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 757b276eb3fc..9cb36f855f07 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -459,7 +459,7 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, enum intel_display_power_domain intel_dsc_power_domain(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; /* @@ -483,7 +483,7 @@ intel_dsc_power_domain(const struct intel_crtc_state *crtc_state) static void intel_configure_pps_for_dsc_encoder(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; enum pipe pipe = crtc->pipe; @@ -902,7 +902,7 @@ static void intel_dp_write_dsc_pps_sdp(struct intel_encoder *encoder, void intel_dsc_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum pipe pipe = crtc->pipe; i915_reg_t dss_ctl1_reg, dss_ctl2_reg; @@ -938,7 +938,7 @@ void intel_dsc_enable(struct intel_encoder *encoder, void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; i915_reg_t dss_ctl1_reg, dss_ctl2_reg; diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 5681b388452d..8398a265b6a3 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -261,7 +261,7 @@ static int intel_dsi_compute_config(struct intel_encoder *encoder, struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, base); struct intel_connector *intel_connector = intel_dsi->attached_connector; - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int ret; @@ -624,7 +624,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; @@ -746,7 +746,7 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_crtc *crtc = pipe_config->uapi.crtc; struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; @@ -1034,7 +1034,7 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct drm_display_mode *adjusted_mode_sw; - struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); unsigned int lane_count = intel_dsi->lane_count; unsigned int bpp, fmt; @@ -1315,7 +1315,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, struct drm_encoder *encoder = &intel_encoder->base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; enum port port; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 73808fd26625..cab632791f73 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4165,7 +4165,7 @@ static int i915_drrs_ctl_set(void *data, u64 val) !crtc_state->has_drrs) goto out; - commit = crtc_state->base.commit; + commit = crtc_state->uapi.commit; if (commit) { ret = wait_for_completion_interruptible(&commit->hw_done); if (ret) @@ -4177,7 +4177,7 @@ static int i915_drrs_ctl_set(void *data, u64 val) struct intel_encoder *encoder; struct intel_dp *intel_dp; - if (!(crtc_state->base.connector_mask & + if (!(crtc_state->uapi.connector_mask & drm_connector_mask(connector))) continue; @@ -4236,7 +4236,7 @@ i915_fifo_underrun_reset_write(struct file *filp, return ret; crtc_state = to_intel_crtc_state(intel_crtc->base.state); - commit = crtc_state->base.commit; + commit = crtc_state->uapi.commit; if (commit) { ret = wait_for_completion_interruptible(&commit->hw_done); if (!ret) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index eb0c29b0f8c5..b03795f92c84 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -455,7 +455,7 @@ static const int pessimal_latency_ns = 5000; static void vlv_get_fifo_size(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state; enum pipe pipe = crtc->pipe; @@ -1135,7 +1135,7 @@ static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state, static bool g4x_raw_plane_wm_set(struct intel_crtc_state *crtc_state, int level, enum plane_id plane_id, u16 value) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); bool dirty = false; for (; level < intel_wm_num_levels(dev_priv); level++) { @@ -1151,7 +1151,7 @@ static bool g4x_raw_plane_wm_set(struct intel_crtc_state *crtc_state, static bool g4x_raw_fbc_wm_set(struct intel_crtc_state *crtc_state, int level, u16 value) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); bool dirty = false; /* NORMAL level doesn't have an FBC watermark */ @@ -1253,7 +1253,7 @@ static bool g4x_raw_plane_wm_is_valid(const struct intel_crtc_state *crtc_state, static bool g4x_raw_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state, int level) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); if (level > dev_priv->wm.max_level) return false; @@ -1291,9 +1291,9 @@ static void g4x_invalidate_wms(struct intel_crtc *crtc, static int g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_atomic_state *state = - to_intel_atomic_state(crtc_state->base.state); + to_intel_atomic_state(crtc_state->uapi.state); struct g4x_wm_state *wm_state = &crtc_state->wm.g4x.optimal; int num_active_planes = hweight8(crtc_state->active_planes & ~BIT(PLANE_CURSOR)); @@ -1380,17 +1380,17 @@ static int g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state) static int g4x_compute_intermediate_wm(struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct g4x_wm_state *intermediate = &new_crtc_state->wm.g4x.intermediate; const struct g4x_wm_state *optimal = &new_crtc_state->wm.g4x.optimal; struct intel_atomic_state *intel_state = - to_intel_atomic_state(new_crtc_state->base.state); + to_intel_atomic_state(new_crtc_state->uapi.state); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(intel_state, crtc); const struct g4x_wm_state *active = &old_crtc_state->wm.g4x.optimal; enum plane_id plane_id; - if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) { + if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) { *intermediate = *optimal; intermediate->cxsr = false; @@ -1522,8 +1522,8 @@ static void g4x_program_watermarks(struct drm_i915_private *dev_priv) static void g4x_initial_watermarks(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); mutex_lock(&dev_priv->wm.wm_mutex); crtc->wm.active.g4x = crtc_state->wm.g4x.intermediate; @@ -1534,8 +1534,8 @@ static void g4x_initial_watermarks(struct intel_atomic_state *state, static void g4x_optimize_watermarks(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); if (!crtc_state->wm.need_postvbl_update) return; @@ -1622,7 +1622,7 @@ static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes) static int vlv_compute_fifo(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct g4x_pipe_wm *raw = &crtc_state->wm.vlv.raw[VLV_WM_LEVEL_PM2]; struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state; @@ -1734,7 +1734,7 @@ static u16 vlv_invert_wm_value(u16 wm, u16 fifo_size) static bool vlv_raw_plane_wm_set(struct intel_crtc_state *crtc_state, int level, enum plane_id plane_id, u16 value) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); int num_levels = intel_wm_num_levels(dev_priv); bool dirty = false; @@ -1809,16 +1809,16 @@ static bool vlv_raw_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state, static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_atomic_state *state = - to_intel_atomic_state(crtc_state->base.state); + to_intel_atomic_state(crtc_state->uapi.state); struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal; const struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state; int num_active_planes = hweight8(crtc_state->active_planes & ~BIT(PLANE_CURSOR)); - bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->base); + bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->uapi); const struct intel_plane_state *old_plane_state; const struct intel_plane_state *new_plane_state; struct intel_plane *plane; @@ -1917,7 +1917,7 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state) static void vlv_atomic_update_fifo(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_uncore *uncore = &dev_priv->uncore; const struct vlv_fifo_state *fifo_state = @@ -2013,17 +2013,17 @@ static void vlv_atomic_update_fifo(struct intel_atomic_state *state, static int vlv_compute_intermediate_wm(struct intel_crtc_state *new_crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct vlv_wm_state *intermediate = &new_crtc_state->wm.vlv.intermediate; const struct vlv_wm_state *optimal = &new_crtc_state->wm.vlv.optimal; struct intel_atomic_state *intel_state = - to_intel_atomic_state(new_crtc_state->base.state); + to_intel_atomic_state(new_crtc_state->uapi.state); const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(intel_state, crtc); const struct vlv_wm_state *active = &old_crtc_state->wm.vlv.optimal; int level; - if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->base)) { + if (!new_crtc_state->hw.active || drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) { *intermediate = *optimal; intermediate->cxsr = false; @@ -2141,8 +2141,8 @@ static void vlv_program_watermarks(struct drm_i915_private *dev_priv) static void vlv_initial_watermarks(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); mutex_lock(&dev_priv->wm.wm_mutex); crtc->wm.active.vlv = crtc_state->wm.vlv.intermediate; @@ -2153,8 +2153,8 @@ static void vlv_initial_watermarks(struct intel_atomic_state *state, static void vlv_optimize_watermarks(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); if (!crtc_state->wm.need_postvbl_update) return; @@ -2758,7 +2758,7 @@ static u32 hsw_compute_linetime_wm(const struct intel_crtc_state *crtc_state) { const struct intel_atomic_state *intel_state = - to_intel_atomic_state(crtc_state->base.state); + to_intel_atomic_state(crtc_state->uapi.state); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 linetime, ips_linetime; @@ -3073,8 +3073,8 @@ static bool ilk_validate_pipe_wm(const struct drm_i915_private *dev_priv, /* Compute new watermarks for the pipe */ static int ilk_compute_pipe_wm(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_pipe_wm *pipe_wm; struct intel_plane *plane; const struct intel_plane_state *plane_state; @@ -3152,11 +3152,11 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *crtc_state) */ static int ilk_compute_intermediate_wm(struct intel_crtc_state *newstate) { - struct intel_crtc *intel_crtc = to_intel_crtc(newstate->base.crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(newstate->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate; struct intel_atomic_state *intel_state = - to_intel_atomic_state(newstate->base.state); + to_intel_atomic_state(newstate->uapi.state); const struct intel_crtc_state *oldstate = intel_atomic_get_old_crtc_state(intel_state, intel_crtc); const struct intel_pipe_wm *b = &oldstate->wm.ilk.optimal; @@ -3168,7 +3168,7 @@ static int ilk_compute_intermediate_wm(struct intel_crtc_state *newstate) * and after the vblank. */ *a = newstate->wm.ilk.optimal; - if (!newstate->hw.active || drm_atomic_crtc_needs_modeset(&newstate->base) || + if (!newstate->hw.active || drm_atomic_crtc_needs_modeset(&newstate->uapi) || intel_state->skip_intermediate_wm) return 0; @@ -3849,9 +3849,9 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv, struct skl_ddb_entry *alloc, /* out */ int *num_active /* out */) { - struct drm_atomic_state *state = crtc_state->base.state; + struct drm_atomic_state *state = crtc_state->uapi.state; struct intel_atomic_state *intel_state = to_intel_atomic_state(state); - struct drm_crtc *for_crtc = crtc_state->base.crtc; + struct drm_crtc *for_crtc = crtc_state->uapi.crtc; const struct intel_crtc *crtc; u32 pipe_width = 0, total_width = 0, width_before_pipe = 0; enum pipe for_pipe = to_intel_crtc(for_crtc)->pipe; @@ -3932,7 +3932,7 @@ static unsigned int skl_cursor_allocation(const struct intel_crtc_state *crtc_state, int num_active) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); int level, max_level = ilk_wm_max_level(dev_priv); struct skl_wm_level wm = {}; int ret, min_ddb_alloc = 0; @@ -4136,7 +4136,7 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state, u64 *plane_data_rate, u64 *uv_plane_data_rate) { - struct drm_atomic_state *state = crtc_state->base.state; + struct drm_atomic_state *state = crtc_state->uapi.state; struct intel_plane *plane; const struct intel_plane_state *plane_state; u64 total_data_rate = 0; @@ -4171,7 +4171,7 @@ icl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state; u64 total_data_rate = 0; - if (WARN_ON(!crtc_state->base.state)) + if (WARN_ON(!crtc_state->uapi.state)) return 0; /* Calculate and cache data rate for each plane */ @@ -4215,8 +4215,8 @@ static int skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state, struct skl_ddb_allocation *ddb /* out */) { - struct drm_atomic_state *state = crtc_state->base.state; - struct drm_crtc *crtc = crtc_state->base.crtc; + struct drm_atomic_state *state = crtc_state->uapi.state; + struct drm_crtc *crtc = crtc_state->uapi.crtc; struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct skl_ddb_entry *alloc = &crtc_state->wm.skl.ddb; @@ -4523,7 +4523,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state, u32 plane_pixel_rate, struct skl_wm_params *wp, int color_plane) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 interm_pbpl; @@ -4644,7 +4644,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, const struct skl_wm_level *result_prev, struct skl_wm_level *result /* out */) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); u32 latency = dev_priv->wm.skl_latency[level]; uint_fixed_16_16_t method1, method2; uint_fixed_16_16_t selected_result; @@ -4768,7 +4768,7 @@ skl_compute_wm_levels(const struct intel_crtc_state *crtc_state, const struct skl_wm_params *wm_params, struct skl_wm_level *levels) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); int level, max_level = ilk_wm_max_level(dev_priv); struct skl_wm_level *result_prev = &levels[0]; @@ -4785,7 +4785,7 @@ skl_compute_wm_levels(const struct intel_crtc_state *crtc_state, static u32 skl_compute_linetime_wm(const struct intel_crtc_state *crtc_state) { - struct drm_atomic_state *state = crtc_state->base.state; + struct drm_atomic_state *state = crtc_state->uapi.state; struct drm_i915_private *dev_priv = to_i915(state->dev); uint_fixed_16_16_t linetime_us; u32 linetime_wm; @@ -4804,7 +4804,7 @@ static void skl_compute_transition_wm(const struct intel_crtc_state *crtc_state, const struct skl_wm_params *wp, struct skl_plane_wm *wm) { - struct drm_device *dev = crtc_state->base.crtc->dev; + struct drm_device *dev = crtc_state->uapi.crtc->dev; const struct drm_i915_private *dev_priv = to_i915(dev); u16 trans_min, trans_y_tile_min; const u16 trans_amount = 10; /* This is configurable amount */ @@ -4964,7 +4964,7 @@ static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, static int skl_build_pipe_wm(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; struct intel_plane *plane; const struct intel_plane_state *plane_state; @@ -5141,8 +5141,8 @@ static int skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state) { - struct intel_atomic_state *state = to_intel_atomic_state(new_crtc_state->base.state); - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct intel_atomic_state *state = to_intel_atomic_state(new_crtc_state->uapi.state); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_plane *plane; @@ -5426,7 +5426,7 @@ static int skl_wm_add_affected_planes(struct intel_atomic_state *state, * power well the hardware state will go out of sync * with the software state. */ - if (!drm_atomic_crtc_needs_modeset(&new_crtc_state->base) && + if (!drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi) && skl_plane_wm_equals(dev_priv, &old_crtc_state->wm.skl.optimal.planes[plane_id], &new_crtc_state->wm.skl.optimal.planes[plane_id])) @@ -5492,7 +5492,7 @@ skl_compute_wm(struct intel_atomic_state *state) static void skl_atomic_update_crtc_wm(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; enum pipe pipe = crtc->pipe; @@ -5506,7 +5506,7 @@ static void skl_atomic_update_crtc_wm(struct intel_atomic_state *state, static void skl_initial_wm(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct skl_ddb_values *results = &state->wm_results; @@ -5515,7 +5515,7 @@ static void skl_initial_wm(struct intel_atomic_state *state, mutex_lock(&dev_priv->wm.wm_mutex); - if (crtc_state->base.active_changed) + if (crtc_state->uapi.active_changed) skl_atomic_update_crtc_wm(state, crtc_state); mutex_unlock(&dev_priv->wm.wm_mutex); @@ -5574,8 +5574,8 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv) static void ilk_initial_watermarks(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); mutex_lock(&dev_priv->wm.wm_mutex); crtc->wm.active.ilk = crtc_state->wm.ilk.intermediate; @@ -5586,8 +5586,8 @@ static void ilk_initial_watermarks(struct intel_atomic_state *state, static void ilk_optimize_watermarks(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); if (!crtc_state->wm.need_postvbl_update) return; -- cgit v1.2.3 From 58d124ea2739e1440ddd743d46c470fe724aca9a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:04 +0100 Subject: drm/i915: Complete crtc hw/uapi split, v6. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we separated everything into uapi and hw, it's time to make the split definitive. Remove the union and make a copy of the hw state on modeset and fastset. Color blobs are copied in crtc atomic_check(), right before color management is checked. Changes since v1: - Copy all blobs immediately after drm_atomic_helper_check_modeset(). - Clear crtc_state->hw on disable, instead of using clear_intel_crtc_state(). Changes since v2: - Use intel_crtc_free_hw_state + clear in intel_crtc_disable_noatomic(). - Make a intel_crtc_prepare_state() function that clears the crtc_state and copies hw members. - Remove setting uapi.adjusted_mode, we now have a direct call to drm_calc_timestamping_constants(). Changes since v3: - Rename prefix copy_hw_to_uapi_state() with intel_crtc. - Copy color blobs to uapi as well. - Add a intel_crtc_copy_uapi_to_hw_state_nomodeset() function for clarity. Changes since v4: - Copy hw.adjusted_mode back to uapi.adjusted_mode, to shut up the call to drm_calc_timestamping_constants() in drm_atomic_helper_update_legacy_modeset_state(). - Use drm_property_replace_blob (Ville). Changes since v5: - Use hw->mode in intel_modeset_readout_hw_state(). (Ville) - Copy to uapi.mode using drm_atomic_set_mode_for_crtc(). (Ville) Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-6-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_atomic.c | 31 ++++++++ drivers/gpu/drm/i915/display/intel_atomic.h | 2 + drivers/gpu/drm/i915/display/intel_display.c | 90 +++++++++++++++++----- drivers/gpu/drm/i915/display/intel_display_types.h | 9 ++- 4 files changed, 109 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 48964f33c0c1..3301c178da03 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -195,6 +195,14 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->uapi); + /* copy color blobs */ + if (crtc_state->hw.degamma_lut) + drm_property_blob_get(crtc_state->hw.degamma_lut); + if (crtc_state->hw.ctm) + drm_property_blob_get(crtc_state->hw.ctm); + if (crtc_state->hw.gamma_lut) + drm_property_blob_get(crtc_state->hw.gamma_lut); + crtc_state->update_pipe = false; crtc_state->disable_lp_wm = false; crtc_state->disable_cxsr = false; @@ -208,6 +216,28 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) return &crtc_state->uapi; } +static void intel_crtc_put_color_blobs(struct intel_crtc_state *crtc_state) +{ + drm_property_blob_put(crtc_state->hw.degamma_lut); + drm_property_blob_put(crtc_state->hw.gamma_lut); + drm_property_blob_put(crtc_state->hw.ctm); +} + +void intel_crtc_free_hw_state(struct intel_crtc_state *crtc_state) +{ + intel_crtc_put_color_blobs(crtc_state); +} + +void intel_crtc_copy_color_blobs(struct intel_crtc_state *crtc_state) +{ + drm_property_replace_blob(&crtc_state->hw.degamma_lut, + crtc_state->uapi.degamma_lut); + drm_property_replace_blob(&crtc_state->hw.gamma_lut, + crtc_state->uapi.gamma_lut); + drm_property_replace_blob(&crtc_state->hw.ctm, + crtc_state->uapi.ctm); +} + /** * intel_crtc_destroy_state - destroy crtc state * @crtc: drm crtc @@ -223,6 +253,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, struct intel_crtc_state *crtc_state = to_intel_crtc_state(state); __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); + intel_crtc_free_hw_state(crtc_state); kfree(crtc_state); } diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h index 49d5cb1b9e0a..7b49623419ba 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.h +++ b/drivers/gpu/drm/i915/display/intel_atomic.h @@ -36,6 +36,8 @@ intel_digital_connector_duplicate_state(struct drm_connector *connector); struct drm_crtc_state *intel_crtc_duplicate_state(struct drm_crtc *crtc); void intel_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); +void intel_crtc_free_hw_state(struct intel_crtc_state *crtc_state); +void intel_crtc_copy_color_blobs(struct intel_crtc_state *crtc_state); struct drm_atomic_state *intel_atomic_state_alloc(struct drm_device *dev); void intel_atomic_state_clear(struct drm_atomic_state *state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4da61e9194c1..800061715bac 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7185,6 +7185,8 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, crtc->enabled = false; crtc->state->connector_mask = 0; crtc->state->encoder_mask = 0; + intel_crtc_free_hw_state(crtc_state); + memset(&crtc_state->hw, 0, sizeof(crtc_state->hw)); for_each_encoder_on_crtc(crtc->dev, crtc, encoder) encoder->base.crtc = NULL; @@ -12557,8 +12559,41 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state) return ret; } +static void +intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_crtc_state *crtc_state) +{ + intel_crtc_copy_color_blobs(crtc_state); +} + +static void +intel_crtc_copy_uapi_to_hw_state(struct intel_crtc_state *crtc_state) +{ + crtc_state->hw.enable = crtc_state->uapi.enable; + crtc_state->hw.active = crtc_state->uapi.active; + crtc_state->hw.mode = crtc_state->uapi.mode; + crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode; + intel_crtc_copy_uapi_to_hw_state_nomodeset(crtc_state); +} + +static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) +{ + crtc_state->uapi.enable = crtc_state->hw.enable; + crtc_state->uapi.active = crtc_state->hw.active; + WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &crtc_state->hw.mode) < 0); + + crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode; + + /* copy color blobs to uapi */ + drm_property_replace_blob(&crtc_state->uapi.degamma_lut, + crtc_state->hw.degamma_lut); + drm_property_replace_blob(&crtc_state->uapi.gamma_lut, + crtc_state->hw.gamma_lut); + drm_property_replace_blob(&crtc_state->uapi.ctm, + crtc_state->hw.ctm); +} + static int -clear_intel_crtc_state(struct intel_crtc_state *crtc_state) +intel_crtc_prepare_cleared_state(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); @@ -12568,11 +12603,15 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) if (!saved_state) return -ENOMEM; + /* free the old crtc_state->hw members */ + intel_crtc_free_hw_state(crtc_state); + /* FIXME: before the switch to atomic started, a new pipe_config was * kzalloc'd. Code that depends on any field being zero should be * fixed, so that the crtc_state can be safely duplicated. For now, * only fields that are know to not cause problems are preserved. */ + saved_state->uapi = crtc_state->uapi; saved_state->scaler_state = crtc_state->scaler_state; saved_state->shared_dpll = crtc_state->shared_dpll; saved_state->dpll_hw_state = crtc_state->dpll_hw_state; @@ -12590,14 +12629,11 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) saved_state->sync_mode_slaves_mask = crtc_state->sync_mode_slaves_mask; - /* Keep base drm_crtc_state intact, only clear our extended struct */ - BUILD_BUG_ON(offsetof(struct intel_crtc_state, base)); - BUILD_BUG_ON(offsetof(struct intel_crtc_state, uapi)); - BUILD_BUG_ON(offsetof(struct intel_crtc_state, hw)); - memcpy(&crtc_state->uapi + 1, &saved_state->uapi + 1, - sizeof(*crtc_state) - sizeof(crtc_state->uapi)); - + memcpy(crtc_state, saved_state, sizeof(*crtc_state)); kfree(saved_state); + + intel_crtc_copy_uapi_to_hw_state(crtc_state); + return 0; } @@ -12613,10 +12649,6 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config) int i; bool retry = true; - ret = clear_intel_crtc_state(pipe_config); - if (ret) - return ret; - pipe_config->cpu_transcoder = (enum transcoder) to_intel_crtc(crtc)->pipe; @@ -12744,6 +12776,12 @@ encoder_retry: DRM_DEBUG_KMS("hw max bpp: %i, pipe bpp: %i, dithering: %i\n", base_bpp, pipe_config->pipe_bpp, pipe_config->dither); + /* + * Make drm_calc_timestamping_constants in + * drm_atomic_helper_update_legacy_modeset_state() happy + */ + pipe_config->uapi.adjusted_mode = pipe_config->hw.adjusted_mode; + return 0; } @@ -13473,6 +13511,8 @@ verify_crtc_state(struct intel_crtc *crtc, state = old_crtc_state->uapi.state; __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); + intel_crtc_free_hw_state(old_crtc_state); + pipe_config = old_crtc_state; memset(pipe_config, 0, sizeof(*pipe_config)); pipe_config->uapi.crtc = &crtc->base; @@ -14007,14 +14047,24 @@ static int intel_atomic_check(struct drm_device *dev, for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (!needs_modeset(new_crtc_state)) + if (!needs_modeset(new_crtc_state)) { + /* Light copy */ + intel_crtc_copy_uapi_to_hw_state_nomodeset(new_crtc_state); + continue; + } if (!new_crtc_state->uapi.enable) { + intel_crtc_copy_uapi_to_hw_state(new_crtc_state); + any_ms = true; continue; } + ret = intel_crtc_prepare_cleared_state(new_crtc_state); + if (ret) + goto fail; + ret = intel_modeset_pipe_config(new_crtc_state); if (ret) goto fail; @@ -17285,6 +17335,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) to_intel_crtc_state(crtc->base.state); __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); + intel_crtc_free_hw_state(crtc_state); memset(crtc_state, 0, sizeof(*crtc_state)); __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->uapi); @@ -17396,15 +17447,14 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) int min_cdclk = 0; if (crtc_state->hw.active) { - struct drm_display_mode mode; + struct drm_display_mode *mode = &crtc_state->hw.mode; intel_mode_from_pipe_config(&crtc_state->hw.adjusted_mode, crtc_state); - mode = crtc_state->hw.adjusted_mode; - mode.hdisplay = crtc_state->pipe_src_w; - mode.vdisplay = crtc_state->pipe_src_h; - WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &mode)); + *mode = crtc_state->hw.adjusted_mode; + mode->hdisplay = crtc_state->pipe_src_w; + mode->vdisplay = crtc_state->pipe_src_h; /* * The initial mode needs to be set in order to keep @@ -17415,11 +17465,13 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) * set a flag to indicate that a full recalculation is * needed on the next commit. */ - crtc_state->hw.mode.private_flags = I915_MODE_FLAG_INHERITED; + mode->private_flags = I915_MODE_FLAG_INHERITED; intel_crtc_compute_pixel_rate(crtc_state); intel_crtc_update_active_timings(crtc_state); + + intel_crtc_copy_hw_to_uapi_state(crtc_state); } for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 285b17c9d8d0..dfa7bfc9c9a2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -757,8 +757,6 @@ enum intel_output_format { }; struct intel_crtc_state { - union { - struct drm_crtc_state base; /* * uapi (drm) state. This is the software state shown to userspace. * In particular, the following members are used for bookkeeping: @@ -781,8 +779,11 @@ struct intel_crtc_state { * * During initial hw readout, they need to be copied to uapi. */ - struct drm_crtc_state hw; - }; + struct { + bool active, enable; + struct drm_property_blob *degamma_lut, *gamma_lut, *ctm; + struct drm_display_mode mode, adjusted_mode; + } hw; /** * quirks - bitfield with hw state readout quirks -- cgit v1.2.3 From 5b6edb88008fe7988186fd4e4e4211396cde25bc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:05 +0100 Subject: drm/i915: Add aliases for uapi and hw to plane_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare to split up hw and uapi machinally, by adding a uapi and hw alias. We will remove the base in a bit. This is a split from the original uapi/hw patch, which did it all in one go. Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-7-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 16 ++++++++-------- drivers/gpu/drm/i915/display/intel_display_types.h | 8 ++++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 4558c0b29fc1..393fb97a3dca 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -80,22 +80,20 @@ void intel_plane_free(struct intel_plane *plane) struct drm_plane_state * intel_plane_duplicate_state(struct drm_plane *plane) { - struct drm_plane_state *state; struct intel_plane_state *intel_state; - intel_state = kmemdup(plane->state, sizeof(*intel_state), GFP_KERNEL); + intel_state = to_intel_plane_state(plane->state); + intel_state = kmemdup(intel_state, sizeof(*intel_state), GFP_KERNEL); if (!intel_state) return NULL; - state = &intel_state->base; - - __drm_atomic_helper_plane_duplicate_state(plane, state); + __drm_atomic_helper_plane_duplicate_state(plane, &intel_state->base); intel_state->vma = NULL; intel_state->flags = 0; - return state; + return &intel_state->base; } /** @@ -110,9 +108,11 @@ void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { - WARN_ON(to_intel_plane_state(state)->vma); + struct intel_plane_state *plane_state = to_intel_plane_state(state); + WARN_ON(plane_state->vma); - drm_atomic_helper_plane_destroy_state(plane, state); + __drm_atomic_helper_plane_destroy_state(&plane_state->base); + kfree(plane_state); } unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index dfa7bfc9c9a2..7f338c130ed7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -523,7 +523,11 @@ struct intel_atomic_state { }; struct intel_plane_state { - struct drm_plane_state base; + union { + struct drm_plane_state base; + struct drm_plane_state uapi; + struct drm_plane_state hw; + }; struct i915_ggtt_view view; struct i915_vma *vma; unsigned long flags; @@ -1143,7 +1147,7 @@ struct cxsr_latency { #define to_intel_encoder(x) container_of(x, struct intel_encoder, base) #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) #define to_intel_plane(x) container_of(x, struct intel_plane, base) -#define to_intel_plane_state(x) container_of(x, struct intel_plane_state, base) +#define to_intel_plane_state(x) container_of(x, struct intel_plane_state, uapi) #define intel_fb_obj(x) ((x) ? to_intel_bo((x)->obj[0]) : NULL) struct intel_hdmi { -- cgit v1.2.3 From a456f65f89637ac10dfc14dc0045e3dee062dc2d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:06 +0100 Subject: drm/i915: Perform manual conversions for plane uapi/hw split, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_crtc_from_states() is called before plane_state is copied to uapi, so use the uapi state there. intel_legacy_cursor_update() could probably get away with looking at the hw state, but for clarity always look at the uapi state. Changes since v1: - Convert entirety of intel_legacy_cursor_update (Ville). Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-8-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 8 ++-- drivers/gpu/drm/i915/display/intel_display.c | 45 ++++++++++++----------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 393fb97a3dca..416cfa439f33 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -225,11 +225,11 @@ static struct intel_crtc * get_crtc_from_states(const struct intel_plane_state *old_plane_state, const struct intel_plane_state *new_plane_state) { - if (new_plane_state->base.crtc) - return to_intel_crtc(new_plane_state->base.crtc); + if (new_plane_state->uapi.crtc) + return to_intel_crtc(new_plane_state->uapi.crtc); - if (old_plane_state->base.crtc) - return to_intel_crtc(old_plane_state->base.crtc); + if (old_plane_state->uapi.crtc) + return to_intel_crtc(old_plane_state->uapi.crtc); return NULL; } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 800061715bac..d1a546d4fdb0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15352,12 +15352,12 @@ intel_legacy_cursor_update(struct drm_plane *_plane, * take the slowpath. Only changing fb or position should be * in the fastpath. */ - if (old_plane_state->base.crtc != &crtc->base || - old_plane_state->base.src_w != src_w || - old_plane_state->base.src_h != src_h || - old_plane_state->base.crtc_w != crtc_w || - old_plane_state->base.crtc_h != crtc_h || - !old_plane_state->base.fb != !fb) + if (old_plane_state->uapi.crtc != &crtc->base || + old_plane_state->uapi.src_w != src_w || + old_plane_state->uapi.src_h != src_h || + old_plane_state->uapi.crtc_w != crtc_w || + old_plane_state->uapi.crtc_h != crtc_h || + !old_plane_state->uapi.fb != !fb) goto slow; new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base)); @@ -15370,16 +15370,16 @@ intel_legacy_cursor_update(struct drm_plane *_plane, goto out_free; } - drm_atomic_set_fb_for_plane(&new_plane_state->base, fb); + drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb); - new_plane_state->base.src_x = src_x; - new_plane_state->base.src_y = src_y; - new_plane_state->base.src_w = src_w; - new_plane_state->base.src_h = src_h; - new_plane_state->base.crtc_x = crtc_x; - new_plane_state->base.crtc_y = crtc_y; - new_plane_state->base.crtc_w = crtc_w; - new_plane_state->base.crtc_h = crtc_h; + new_plane_state->uapi.src_x = src_x; + new_plane_state->uapi.src_y = src_y; + new_plane_state->uapi.src_w = src_w; + new_plane_state->uapi.src_h = src_h; + new_plane_state->uapi.crtc_x = crtc_x; + new_plane_state->uapi.crtc_y = crtc_y; + new_plane_state->uapi.crtc_w = crtc_w; + new_plane_state->uapi.crtc_h = crtc_h; ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state, old_plane_state, new_plane_state); @@ -15390,13 +15390,14 @@ intel_legacy_cursor_update(struct drm_plane *_plane, if (ret) goto out_free; - intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->base.fb), ORIGIN_FLIP); - intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->base.fb), - to_intel_frontbuffer(new_plane_state->base.fb), + intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb), + ORIGIN_FLIP); + intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb), + to_intel_frontbuffer(new_plane_state->hw.fb), plane->frontbuffer_bit); /* Swap plane state */ - plane->base.state = &new_plane_state->base; + plane->base.state = &new_plane_state->uapi; /* * We cannot swap crtc_state as it may be in use by an atomic commit or @@ -15410,7 +15411,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane, */ crtc_state->active_planes = new_crtc_state->active_planes; - if (new_plane_state->base.visible) + if (new_plane_state->uapi.visible) intel_update_plane(plane, crtc_state, new_plane_state); else intel_disable_plane(plane, crtc_state); @@ -15421,9 +15422,9 @@ out_free: if (new_crtc_state) intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi); if (ret) - intel_plane_destroy_state(&plane->base, &new_plane_state->base); + intel_plane_destroy_state(&plane->base, &new_plane_state->uapi); else - intel_plane_destroy_state(&plane->base, &old_plane_state->base); + intel_plane_destroy_state(&plane->base, &old_plane_state->uapi); return ret; slow: -- cgit v1.2.3 From 7b3cb17a48dc1b33f287e866a0218da378ba21c8 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:07 +0100 Subject: drm/i915: Perform automated conversions for plane uapi/hw split, base -> hw. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split up plane_state->base to hw. This is done using the following patch: @@ struct intel_plane_state *T; identifier x =~ "^(crtc|fb|alpha|pixel_blend_mode|rotation|color_encoding|color_range)$"; @@ -T->base.x +T->hw.x Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-9-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/intel_atomic.c | 6 +- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 8 +- drivers/gpu/drm/i915/display/intel_display.c | 126 +++++++++++----------- drivers/gpu/drm/i915/display/intel_fbc.c | 8 +- drivers/gpu/drm/i915/display/intel_overlay.c | 2 +- drivers/gpu/drm/i915/display/intel_sprite.c | 90 ++++++++-------- drivers/gpu/drm/i915/intel_pm.c | 32 +++--- 7 files changed, 136 insertions(+), 136 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 3301c178da03..0a5eee4c350f 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -283,9 +283,9 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta return; /* set scaler mode */ - if (plane_state && plane_state->base.fb && - plane_state->base.fb->format->is_yuv && - plane_state->base.fb->format->num_planes > 1) { + if (plane_state && plane_state->hw.fb && + plane_state->hw.fb->format->is_yuv && + plane_state->hw.fb->format->num_planes > 1) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv)) { diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 416cfa439f33..6335355555b3 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -118,7 +118,7 @@ intel_plane_destroy_state(struct drm_plane *plane, unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int cpp; if (!plane_state->base.visible) @@ -144,7 +144,7 @@ bool intel_plane_calc_min_cdclk(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); - struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); struct intel_crtc_state *crtc_state; if (!plane_state->base.visible || !plane->min_cdclk) @@ -182,7 +182,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ struct intel_plane_state *new_plane_state) { struct intel_plane *plane = to_intel_plane(new_plane_state->base.plane); - const struct drm_framebuffer *fb = new_plane_state->base.fb; + const struct drm_framebuffer *fb = new_plane_state->hw.fb; int ret; new_crtc_state->active_planes &= ~BIT(plane->id); @@ -192,7 +192,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ new_crtc_state->min_cdclk[plane->id] = 0; new_plane_state->base.visible = false; - if (!new_plane_state->base.crtc && !old_plane_state->base.crtc) + if (!new_plane_state->hw.crtc && !old_plane_state->hw.crtc) return 0; ret = plane->check_plane(new_crtc_state, new_plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d1a546d4fdb0..9bfb9e6b95b4 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2215,7 +2215,7 @@ u32 intel_fb_xy_to_linear(int x, int y, const struct intel_plane_state *state, int color_plane) { - const struct drm_framebuffer *fb = state->base.fb; + const struct drm_framebuffer *fb = state->hw.fb; unsigned int cpp = fb->format->cpp[color_plane]; unsigned int pitch = state->color_plane[color_plane].stride; @@ -2316,8 +2316,8 @@ static u32 intel_plane_adjust_aligned_offset(int *x, int *y, int color_plane, u32 old_offset, u32 new_offset) { - return intel_adjust_aligned_offset(x, y, state->base.fb, color_plane, - state->base.rotation, + return intel_adjust_aligned_offset(x, y, state->hw.fb, color_plane, + state->hw.rotation, state->color_plane[color_plane].stride, old_offset, new_offset); } @@ -2393,8 +2393,8 @@ static u32 intel_plane_compute_aligned_offset(int *x, int *y, { struct intel_plane *intel_plane = to_intel_plane(state->base.plane); struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); - const struct drm_framebuffer *fb = state->base.fb; - unsigned int rotation = state->base.rotation; + const struct drm_framebuffer *fb = state->hw.fb; + unsigned int rotation = state->hw.rotation; int pitch = state->color_plane[color_plane].stride; u32 alignment; @@ -2581,7 +2581,7 @@ bool intel_plane_can_remap(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int i; /* We don't want to deal with remapping with cursors */ @@ -2620,8 +2620,8 @@ bool intel_plane_can_remap(const struct intel_plane_state *plane_state) static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; u32 stride, max_stride; /* @@ -2812,10 +2812,10 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_framebuffer *fb = plane_state->hw.fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct intel_rotation_info *info = &plane_state->view.rotated; - unsigned int rotation = plane_state->base.rotation; + unsigned int rotation = plane_state->hw.rotation; int i, num_planes = fb->format->num_planes; unsigned int tile_size = intel_tile_size(dev_priv); unsigned int src_x, src_y; @@ -2921,8 +2921,8 @@ static int intel_plane_compute_gtt(struct intel_plane_state *plane_state) { const struct intel_framebuffer *fb = - to_intel_framebuffer(plane_state->base.fb); - unsigned int rotation = plane_state->base.rotation; + to_intel_framebuffer(plane_state->hw.fb); + unsigned int rotation = plane_state->hw.rotation; int i, num_planes; if (!fb) @@ -3225,7 +3225,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, continue; if (intel_plane_ggtt_offset(state) == plane_config->base) { - fb = state->base.fb; + fb = state->hw.fb; drm_framebuffer_get(fb); goto valid_fb; } @@ -3243,11 +3243,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, return; valid_fb: - intel_state->base.rotation = plane_config->rotation; + intel_state->hw.rotation = plane_config->rotation; intel_fill_fb_ggtt_view(&intel_state->view, fb, - intel_state->base.rotation); + intel_state->hw.rotation); intel_state->color_plane[0].stride = - intel_fb_pitch(fb, 0, intel_state->base.rotation); + intel_fb_pitch(fb, 0, intel_state->hw.rotation); intel_state->vma = intel_pin_and_fence_fb_obj(fb, @@ -3374,7 +3374,7 @@ static int icl_max_plane_height(void) static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, int main_x, int main_y, u32 main_offset) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int hsub = fb->format->hsub; int vsub = fb->format->vsub; int aux_x = plane_state->color_plane[1].x; @@ -3412,8 +3412,8 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state static int skl_check_main_surface(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; int x = plane_state->base.src.x1 >> 16; int y = plane_state->base.src.y1 >> 16; int w = drm_rect_width(&plane_state->base.src) >> 16; @@ -3508,8 +3508,8 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; int max_width = skl_max_plane_width(fb, 1, rotation); int max_height = 4096; int x = plane_state->base.src.x1 >> 17; @@ -3537,7 +3537,7 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int src_x = plane_state->base.src.x1 >> 16; int src_y = plane_state->base.src.y1 >> 16; int hsub = fb->format->hsub; @@ -3558,7 +3558,7 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) int skl_check_plane_surface(struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int ret; ret = intel_plane_compute_gtt(plane_state); @@ -3597,7 +3597,7 @@ static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, unsigned int *num, unsigned int *den) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int cpp = fb->format->cpp[0]; /* @@ -3690,8 +3690,8 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; u32 dspcntr; dspcntr = DISPLAY_PLANE_ENABLE; @@ -3747,7 +3747,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int src_x, src_y, src_w; u32 offset; int ret; @@ -3784,7 +3784,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) /* HSW/BDW do this automagically in hardware */ if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { - unsigned int rotation = plane_state->base.rotation; + unsigned int rotation = plane_state->hw.rotation; int src_w = drm_rect_width(&plane_state->base.src) >> 16; int src_h = drm_rect_height(&plane_state->base.src) >> 16; @@ -4037,8 +4037,8 @@ static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb, u32 skl_plane_stride(const struct intel_plane_state *plane_state, int color_plane) { - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; u32 stride = plane_state->color_plane[color_plane].stride; if (color_plane >= fb->format->num_planes) @@ -4107,10 +4107,10 @@ static u32 skl_plane_ctl_format(u32 pixel_format) static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state) { - if (!plane_state->base.fb->format->has_alpha) + if (!plane_state->hw.fb->format->has_alpha) return PLANE_CTL_ALPHA_DISABLE; - switch (plane_state->base.pixel_blend_mode) { + switch (plane_state->hw.pixel_blend_mode) { case DRM_MODE_BLEND_PIXEL_NONE: return PLANE_CTL_ALPHA_DISABLE; case DRM_MODE_BLEND_PREMULTI: @@ -4118,17 +4118,17 @@ static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state) case DRM_MODE_BLEND_COVERAGE: return PLANE_CTL_ALPHA_HW_PREMULTIPLY; default: - MISSING_CASE(plane_state->base.pixel_blend_mode); + MISSING_CASE(plane_state->hw.pixel_blend_mode); return PLANE_CTL_ALPHA_DISABLE; } } static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state) { - if (!plane_state->base.fb->format->has_alpha) + if (!plane_state->hw.fb->format->has_alpha) return PLANE_COLOR_ALPHA_DISABLE; - switch (plane_state->base.pixel_blend_mode) { + switch (plane_state->hw.pixel_blend_mode) { case DRM_MODE_BLEND_PIXEL_NONE: return PLANE_COLOR_ALPHA_DISABLE; case DRM_MODE_BLEND_PREMULTI: @@ -4136,7 +4136,7 @@ static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state case DRM_MODE_BLEND_COVERAGE: return PLANE_COLOR_ALPHA_HW_PREMULTIPLY; default: - MISSING_CASE(plane_state->base.pixel_blend_mode); + MISSING_CASE(plane_state->hw.pixel_blend_mode); return PLANE_COLOR_ALPHA_DISABLE; } } @@ -4222,8 +4222,8 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 plane_ctl; @@ -4233,10 +4233,10 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, plane_ctl |= skl_plane_ctl_alpha(plane_state); plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; - if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) + if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709; - if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE; } @@ -4278,7 +4278,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; struct intel_plane *plane = to_intel_plane(plane_state->base.plane); u32 plane_color_ctl = 0; @@ -4286,12 +4286,12 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) { - if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) + if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; else plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709; - if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; } else if (fb->format->is_yuv) { plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; @@ -5625,7 +5625,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); - struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_framebuffer *fb = plane_state->hw.fb; int ret; bool force_detach = !fb || !plane_state->base.visible; bool need_scaler = false; @@ -10729,7 +10729,7 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; const struct drm_i915_gem_object *obj = intel_fb_obj(fb); u32 base; @@ -10777,7 +10777,7 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - unsigned int rotation = plane_state->base.rotation; + unsigned int rotation = plane_state->hw.rotation; int src_x, src_y; u32 offset; int ret; @@ -10810,7 +10810,7 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state) /* ILK+ do this automagically in hardware */ if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int src_w = drm_rect_width(&plane_state->base.src) >> 16; int src_h = drm_rect_height(&plane_state->base.src) >> 16; @@ -10827,7 +10827,7 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state) static int intel_check_cursor(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int ret; if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) { @@ -10901,7 +10901,7 @@ static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state) static int i845_check_cursor(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int ret; ret = intel_check_cursor(crtc_state, plane_state); @@ -11067,7 +11067,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, return 0; } - if (plane_state->base.rotation & DRM_MODE_ROTATE_180) + if (plane_state->hw.rotation & DRM_MODE_ROTATE_180) cntl |= MCURSOR_ROTATE_180; return cntl; @@ -11100,7 +11100,7 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state) * cursors. */ if (HAS_CUR_FBC(dev_priv) && - plane_state->base.rotation & DRM_MODE_ROTATE_0) { + plane_state->hw.rotation & DRM_MODE_ROTATE_0) { if (height < 8 || height > width) return false; } else { @@ -11116,7 +11116,7 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; int ret; @@ -11717,11 +11717,11 @@ static bool intel_wm_need_update(const struct intel_plane_state *cur, if (new->base.visible != cur->base.visible) return true; - if (!cur->base.fb || !new->base.fb) + if (!cur->hw.fb || !new->hw.fb) return false; - if (cur->base.fb->modifier != new->base.fb->modifier || - cur->base.rotation != new->base.rotation || + if (cur->hw.fb->modifier != new->hw.fb->modifier || + cur->hw.rotation != new->hw.rotation || drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) || drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) || drm_rect_width(&new->base.dst) != drm_rect_width(&cur->base.dst) || @@ -12353,7 +12353,7 @@ static const char *output_formats(enum intel_output_format format) static void intel_dump_plane_state(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; struct drm_format_name_buf format_name; if (!fb) { @@ -12369,7 +12369,7 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state) drm_get_format_name(fb->format->format, &format_name), yesno(plane_state->base.visible)); DRM_DEBUG_KMS("\trotation: 0x%x, scaler: %d\n", - plane_state->base.rotation, plane_state->scaler_id); + plane_state->hw.rotation, plane_state->scaler_id); if (plane_state->base.visible) DRM_DEBUG_KMS("\tsrc: " DRM_RECT_FP_FMT " dst: " DRM_RECT_FMT "\n", DRM_RECT_FP_ARG(&plane_state->base.src), @@ -14869,8 +14869,8 @@ static void intel_atomic_track_fbs(struct intel_atomic_state *state) for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, new_plane_state, i) - intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->base.fb), - to_intel_frontbuffer(new_plane_state->base.fb), + intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb), + to_intel_frontbuffer(new_plane_state->hw.fb), plane->frontbuffer_bit); } @@ -15039,7 +15039,7 @@ static int intel_plane_pin_fb(struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_framebuffer *fb = plane_state->hw.fb; struct i915_vma *vma; if (plane->id == PLANE_CURSOR && @@ -15104,7 +15104,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, struct intel_atomic_state *intel_state = to_intel_atomic_state(new_plane_state->base.state); struct drm_i915_private *dev_priv = to_i915(plane->dev); - struct drm_framebuffer *fb = new_plane_state->base.fb; + struct drm_framebuffer *fb = new_plane_state->hw.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb); int ret; @@ -15172,12 +15172,12 @@ intel_prepare_plane_fb(struct drm_plane *plane, fence = dma_resv_get_excl_rcu(obj->base.resv); if (fence) { - add_rps_boost_after_vblank(new_plane_state->base.crtc, + add_rps_boost_after_vblank(new_plane_state->hw.crtc, fence); dma_fence_put(fence); } } else { - add_rps_boost_after_vblank(new_plane_state->base.crtc, + add_rps_boost_after_vblank(new_plane_state->hw.crtc, new_plane_state->base.fence); } diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index c6cc3775f3b8..3ea8d010db6c 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -662,7 +662,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; - struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_framebuffer *fb = plane_state->hw.fb; cache->vma = NULL; cache->flags = 0; @@ -671,7 +671,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate; - cache->plane.rotation = plane_state->base.rotation; + cache->plane.rotation = plane_state->hw.rotation; /* * Src coordinates are already rotated by 270 degrees for * the 90/270 degree plane rotation cases (to match the @@ -684,7 +684,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->plane.adjusted_y = plane_state->color_plane[0].y; cache->plane.y = plane_state->base.src.y1 >> 16; - cache->plane.pixel_blend_mode = plane_state->base.pixel_blend_mode; + cache->plane.pixel_blend_mode = plane_state->hw.pixel_blend_mode; if (!cache->plane.visible) return; @@ -1047,7 +1047,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, * to pipe or plane A. */ for_each_new_intel_plane_in_state(state, plane, plane_state, i) { struct intel_crtc_state *crtc_state; - struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc); + struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); if (!plane->has_fbc) continue; diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 848ce07a8ec2..46e3d6cf5976 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -669,7 +669,7 @@ static void update_colorkey(struct intel_overlay *overlay, flags |= DST_KEY_ENABLE; if (state->base.visible) - format = state->base.fb->format->format; + format = state->hw.fb->format->format; switch (format) { case DRM_FORMAT_C8: diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 5ba8faf0ccfe..b2116d123548 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -241,8 +241,8 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) int intel_plane_check_stride(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; u32 stride, max_stride; /* @@ -272,10 +272,10 @@ int intel_plane_check_stride(const struct intel_plane_state *plane_state) int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; struct drm_rect *src = &plane_state->base.src; u32 src_x, src_y, src_w, src_h, hsub, vsub; - bool rotated = drm_rotation_90_or_270(plane_state->base.rotation); + bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation); /* * Hardware doesn't handle subpixel coordinates. @@ -329,7 +329,7 @@ skl_plane_ratio(const struct intel_crtc_state *crtc_state, unsigned int *num, unsigned int *den) { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; if (fb->format->cpp[0] == 8) { if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { @@ -396,7 +396,7 @@ skl_program_scaler(struct intel_plane *plane, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; int scaler_id = plane_state->scaler_id; const struct intel_scaler *scaler = @@ -542,10 +542,10 @@ icl_program_input_csc(struct intel_plane *plane, }; const u16 *csc; - if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) - csc = input_csc_matrix[plane_state->base.color_encoding]; + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) + csc = input_csc_matrix[plane_state->hw.color_encoding]; else - csc = input_csc_matrix_lr[plane_state->base.color_encoding]; + csc = input_csc_matrix_lr[plane_state->hw.color_encoding]; I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) | GOFF(csc[1])); @@ -559,7 +559,7 @@ icl_program_input_csc(struct intel_plane *plane, I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0), PREOFF_YUV_TO_RGB_HI); - if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 0); else I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), @@ -591,8 +591,8 @@ skl_program_plane(struct intel_plane *plane, u32 src_w = drm_rect_width(&plane_state->base.src) >> 16; u32 src_h = drm_rect_height(&plane_state->base.src) >> 16; struct intel_plane *linked = plane_state->planar_linked_plane; - const struct drm_framebuffer *fb = plane_state->base.fb; - u8 alpha = plane_state->base.alpha >> 8; + const struct drm_framebuffer *fb = plane_state->hw.fb; + u8 alpha = plane_state->hw.alpha >> 8; u32 plane_color_ctl = 0; unsigned long irqflags; u32 keymsk, keymax; @@ -768,7 +768,7 @@ chv_update_csc(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum plane_id plane_id = plane->id; /* * |r| | c0 c1 c2 | |cr| @@ -794,7 +794,7 @@ chv_update_csc(const struct intel_plane_state *plane_state) 0, 4096, 7601, }, }; - const s16 *csc = csc_matrix[plane_state->base.color_encoding]; + const s16 *csc = csc_matrix[plane_state->hw.color_encoding]; /* Seems RGB data bypasses the CSC always */ if (!fb->format->is_yuv) @@ -827,13 +827,13 @@ vlv_update_clrc(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; enum plane_id plane_id = plane->id; int contrast, brightness, sh_scale, sh_sin, sh_cos; if (fb->format->is_yuv && - plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) { + plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) { /* * Expand limited range to full range: * Contrast is applied first and is used to expand Y range. @@ -867,7 +867,7 @@ vlv_plane_ratio(const struct intel_crtc_state *crtc_state, unsigned int *num, unsigned int *den) { u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int cpp = fb->format->cpp[0]; /* @@ -953,8 +953,8 @@ static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 sprctl; @@ -999,7 +999,7 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, return 0; } - if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) + if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) sprctl |= SP_YUV_FORMAT_BT709; if (fb->modifier == I915_FORMAT_MOD_X_TILED) @@ -1021,7 +1021,7 @@ static void vlv_update_gamma(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; enum plane_id plane_id = plane->id; u16 gamma[8]; @@ -1151,7 +1151,7 @@ static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state, unsigned int *num, unsigned int *den) { u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int cpp = fb->format->cpp[0]; if (hweight8(active_planes) == 2) { @@ -1187,7 +1187,7 @@ static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, unsigned int *num, unsigned int *den) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int cpp = fb->format->cpp[0]; switch (cpp) { @@ -1265,7 +1265,7 @@ static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state, unsigned int *num, unsigned int *den) { u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int cpp = fb->format->cpp[0]; if (hweight8(active_planes) == 2) { @@ -1321,7 +1321,7 @@ static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; return fb->format->cpp[0] == 8 && (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)); @@ -1332,8 +1332,8 @@ static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 sprctl; @@ -1375,10 +1375,10 @@ static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, if (!ivb_need_sprite_gamma(plane_state)) sprctl |= SPRITE_INT_GAMMA_DISABLE; - if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) + if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709; - if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE; if (fb->modifier == I915_FORMAT_MOD_X_TILED) @@ -1567,7 +1567,7 @@ ivb_plane_get_hw_state(struct intel_plane *plane, static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int hscale, pixel_rate; unsigned int limit, decimate; @@ -1637,8 +1637,8 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 dvscntr; @@ -1677,10 +1677,10 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, return 0; } - if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709) + if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) dvscntr |= DVS_YUV_FORMAT_BT709; - if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE) + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE; if (fb->modifier == I915_FORMAT_MOD_X_TILED) @@ -1701,7 +1701,7 @@ static void g4x_update_gamma(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; u16 gamma[8]; int i; @@ -1733,7 +1733,7 @@ static void ilk_update_gamma(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; u16 gamma[17]; int i; @@ -1887,7 +1887,7 @@ static int g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; const struct drm_rect *src = &plane_state->base.src; const struct drm_rect *dst = &plane_state->base.dst; int src_x, src_w, src_h, crtc_w, crtc_h; @@ -1954,7 +1954,7 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, int max_scale = DRM_PLANE_HELPER_NO_SCALING; int ret; - if (intel_fb_scalable(plane_state->base.fb)) { + if (intel_fb_scalable(plane_state->hw.fb)) { if (INTEL_GEN(dev_priv) < 7) { min_scale = 1; max_scale = 16 << 16; @@ -1998,7 +1998,7 @@ int chv_plane_check_rotation(const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - unsigned int rotation = plane_state->base.rotation; + unsigned int rotation = plane_state->hw.rotation; /* CHV ignores the mirror bit when the rotate bit is set :( */ if (IS_CHERRYVIEW(dev_priv) && @@ -2050,8 +2050,8 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; struct drm_format_name_buf format_name; if (!fb) @@ -2151,8 +2151,8 @@ static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_s static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; - unsigned int rotation = plane_state->base.rotation; + const struct drm_framebuffer *fb = plane_state->hw.fb; + unsigned int rotation = plane_state->hw.rotation; int src_w = drm_rect_width(&plane_state->base.src) >> 16; /* Display WA #1106 */ @@ -2187,7 +2187,7 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int min_scale = DRM_PLANE_HELPER_NO_SCALING; int max_scale = DRM_PLANE_HELPER_NO_SCALING; int ret; @@ -2229,7 +2229,7 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, return ret; /* HW only has 8 bits pixel precision, disable plane if invisible */ - if (!(plane_state->base.alpha >> 8)) + if (!(plane_state->hw.alpha >> 8)) plane_state->base.visible = false; plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b03795f92c84..0a0103ecf7bc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -801,7 +801,7 @@ static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, * around this problem with the watermark code. */ if (plane->id == PLANE_CURSOR) - return plane_state->base.fb != NULL; + return plane_state->hw.fb != NULL; else return plane_state->base.visible; } @@ -1088,7 +1088,7 @@ static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state, if (!intel_wm_plane_visible(crtc_state, plane_state)) return 0; - cpp = plane_state->base.fb->format->cpp[0]; + cpp = plane_state->hw.fb->format->cpp[0]; /* * Not 100% sure which way ELK should go here as the @@ -1308,8 +1308,8 @@ static int g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state) for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { - if (new_plane_state->base.crtc != &crtc->base && - old_plane_state->base.crtc != &crtc->base) + if (new_plane_state->hw.crtc != &crtc->base && + old_plane_state->hw.crtc != &crtc->base) continue; if (g4x_raw_plane_wm_compute(crtc_state, new_plane_state)) @@ -1593,7 +1593,7 @@ static u16 vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, if (!intel_wm_plane_visible(crtc_state, plane_state)) return 0; - cpp = plane_state->base.fb->format->cpp[0]; + cpp = plane_state->hw.fb->format->cpp[0]; clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->crtc_htotal; width = crtc_state->pipe_src_w; @@ -1829,8 +1829,8 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state) for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { - if (new_plane_state->base.crtc != &crtc->base && - old_plane_state->base.crtc != &crtc->base) + if (new_plane_state->hw.crtc != &crtc->base && + old_plane_state->hw.crtc != &crtc->base) continue; if (vlv_raw_plane_wm_compute(crtc_state, new_plane_state)) @@ -2475,7 +2475,7 @@ static u32 ilk_compute_pri_wm(const struct intel_crtc_state *crtc_state, if (!intel_wm_plane_visible(crtc_state, plane_state)) return 0; - cpp = plane_state->base.fb->format->cpp[0]; + cpp = plane_state->hw.fb->format->cpp[0]; method1 = ilk_wm_method1(crtc_state->pixel_rate, cpp, mem_value); @@ -2507,7 +2507,7 @@ static u32 ilk_compute_spr_wm(const struct intel_crtc_state *crtc_state, if (!intel_wm_plane_visible(crtc_state, plane_state)) return 0; - cpp = plane_state->base.fb->format->cpp[0]; + cpp = plane_state->hw.fb->format->cpp[0]; method1 = ilk_wm_method1(crtc_state->pixel_rate, cpp, mem_value); method2 = ilk_wm_method2(crtc_state->pixel_rate, @@ -2533,7 +2533,7 @@ static u32 ilk_compute_cur_wm(const struct intel_crtc_state *crtc_state, if (!intel_wm_plane_visible(crtc_state, plane_state)) return 0; - cpp = plane_state->base.fb->format->cpp[0]; + cpp = plane_state->hw.fb->format->cpp[0]; return ilk_wm_method2(crtc_state->pixel_rate, crtc_state->hw.adjusted_mode.crtc_htotal, @@ -2551,7 +2551,7 @@ static u32 ilk_compute_fbc_wm(const struct intel_crtc_state *crtc_state, if (!intel_wm_plane_visible(crtc_state, plane_state)) return 0; - cpp = plane_state->base.fb->format->cpp[0]; + cpp = plane_state->hw.fb->format->cpp[0]; return ilk_wm_fbc(pri_val, drm_rect_width(&plane_state->base.dst), cpp); } @@ -4091,7 +4091,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, int color_plane) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; u32 data_rate; u32 width = 0, height = 0; uint_fixed_16_16_t down_scale_amount; @@ -4612,7 +4612,7 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, struct skl_wm_params *wp, int color_plane) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; int width; /* @@ -4624,7 +4624,7 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *crtc_state, return skl_compute_wm_params(crtc_state, width, fb->format, fb->modifier, - plane_state->base.rotation, + plane_state->hw.rotation, skl_adjusted_plane_pixel_rate(crtc_state, plane_state), wp, color_plane); } @@ -4903,7 +4903,7 @@ static int skl_build_plane_wm(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum plane_id plane_id = plane->id; int ret; @@ -4936,7 +4936,7 @@ static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, return 0; if (plane_state->planar_linked_plane) { - const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_framebuffer *fb = plane_state->hw.fb; enum plane_id y_plane_id = plane_state->planar_linked_plane->id; WARN_ON(!intel_wm_plane_visible(crtc_state, plane_state)); -- cgit v1.2.3 From f90a85e76c2a89e0925edb9e4255867dfde85a21 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:08 +0100 Subject: drm/i915: Perform automated conversions for plane uapi/hw split, base -> uapi. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split up plane_state->base to uapi. This is done using the following patch, ran after the previous commit that splits out any hw references: @@ struct intel_plane_state *T; identifier x; @@ -T->base.x +T->uapi.x @@ struct intel_plane_state *T; @@ -T->base +T->uapi Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-10-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/intel_atomic.c | 2 +- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 30 +-- drivers/gpu/drm/i915/display/intel_display.c | 262 +++++++++++----------- drivers/gpu/drm/i915/display/intel_fbc.c | 12 +- drivers/gpu/drm/i915/display/intel_overlay.c | 2 +- drivers/gpu/drm/i915/display/intel_sprite.c | 136 +++++------ drivers/gpu/drm/i915/intel_pm.c | 57 ++--- 7 files changed, 251 insertions(+), 250 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 0a5eee4c350f..ea24a45dab86 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -286,7 +286,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta if (plane_state && plane_state->hw.fb && plane_state->hw.fb->format->is_yuv && plane_state->hw.fb->format->num_planes > 1) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv)) { mode = SKL_PS_SCALER_MODE_NV12; diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 6335355555b3..d456b3dc200c 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -56,7 +56,7 @@ struct intel_plane *intel_plane_alloc(void) return ERR_PTR(-ENOMEM); } - __drm_atomic_helper_plane_reset(&plane->base, &plane_state->base); + __drm_atomic_helper_plane_reset(&plane->base, &plane_state->uapi); plane_state->scaler_id = -1; return plane; @@ -88,12 +88,12 @@ intel_plane_duplicate_state(struct drm_plane *plane) if (!intel_state) return NULL; - __drm_atomic_helper_plane_duplicate_state(plane, &intel_state->base); + __drm_atomic_helper_plane_duplicate_state(plane, &intel_state->uapi); intel_state->vma = NULL; intel_state->flags = 0; - return &intel_state->base; + return &intel_state->uapi; } /** @@ -111,7 +111,7 @@ intel_plane_destroy_state(struct drm_plane *plane, struct intel_plane_state *plane_state = to_intel_plane_state(state); WARN_ON(plane_state->vma); - __drm_atomic_helper_plane_destroy_state(&plane_state->base); + __drm_atomic_helper_plane_destroy_state(&plane_state->uapi); kfree(plane_state); } @@ -121,7 +121,7 @@ unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int cpp; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; cpp = fb->format->cpp[0]; @@ -147,7 +147,7 @@ bool intel_plane_calc_min_cdclk(struct intel_atomic_state *state, struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); struct intel_crtc_state *crtc_state; - if (!plane_state->base.visible || !plane->min_cdclk) + if (!plane_state->uapi.visible || !plane->min_cdclk) return false; crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -181,7 +181,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ const struct intel_plane_state *old_plane_state, struct intel_plane_state *new_plane_state) { - struct intel_plane *plane = to_intel_plane(new_plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); const struct drm_framebuffer *fb = new_plane_state->hw.fb; int ret; @@ -190,7 +190,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ new_crtc_state->c8_planes &= ~BIT(plane->id); new_crtc_state->data_rate[plane->id] = 0; new_crtc_state->min_cdclk[plane->id] = 0; - new_plane_state->base.visible = false; + new_plane_state->uapi.visible = false; if (!new_plane_state->hw.crtc && !old_plane_state->hw.crtc) return 0; @@ -200,18 +200,18 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ return ret; /* FIXME pre-g4x don't work like this */ - if (new_plane_state->base.visible) + if (new_plane_state->uapi.visible) new_crtc_state->active_planes |= BIT(plane->id); - if (new_plane_state->base.visible && + if (new_plane_state->uapi.visible && drm_format_info_is_yuv_semiplanar(fb->format)) new_crtc_state->nv12_planes |= BIT(plane->id); - if (new_plane_state->base.visible && + if (new_plane_state->uapi.visible && fb->format->format == DRM_FORMAT_C8) new_crtc_state->c8_planes |= BIT(plane->id); - if (new_plane_state->base.visible || old_plane_state->base.visible) + if (new_plane_state->uapi.visible || old_plane_state->uapi.visible) new_crtc_state->update_planes |= BIT(plane->id); new_crtc_state->data_rate[plane->id] = @@ -246,7 +246,7 @@ int intel_plane_atomic_check(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state; struct intel_crtc_state *new_crtc_state; - new_plane_state->base.visible = false; + new_plane_state->uapi.visible = false; if (!crtc) return 0; @@ -355,7 +355,7 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); - if (new_plane_state->base.visible) { + if (new_plane_state->uapi.visible) { intel_update_plane(plane, new_crtc_state, new_plane_state); } else if (new_plane_state->planar_slave) { struct intel_plane *master = @@ -395,7 +395,7 @@ void i9xx_update_planes_on_crtc(struct intel_atomic_state *state, !(update_mask & BIT(plane->id))) continue; - if (new_plane_state->base.visible) + if (new_plane_state->uapi.visible) intel_update_plane(plane, new_crtc_state, new_plane_state); else intel_disable_plane(plane, new_crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9bfb9e6b95b4..27ce6d7c3971 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2082,7 +2082,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, static bool intel_plane_uses_fence(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); return INTEL_GEN(dev_priv) < 4 || @@ -2391,7 +2391,7 @@ static u32 intel_plane_compute_aligned_offset(int *x, int *y, const struct intel_plane_state *state, int color_plane) { - struct intel_plane *intel_plane = to_intel_plane(state->base.plane); + struct intel_plane *intel_plane = to_intel_plane(state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); const struct drm_framebuffer *fb = state->hw.fb; unsigned int rotation = state->hw.rotation; @@ -2579,7 +2579,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) bool intel_plane_can_remap(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; int i; @@ -2619,7 +2619,7 @@ bool intel_plane_can_remap(const struct intel_plane_state *plane_state) static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; u32 stride, max_stride; @@ -2628,7 +2628,7 @@ static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state) * No remapping for invisible planes since we don't have * an actual source viewport to remap. */ - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return false; if (!intel_plane_can_remap(plane_state)) @@ -2811,7 +2811,7 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); struct drm_framebuffer *fb = plane_state->hw.fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct intel_rotation_info *info = &plane_state->view.rotated; @@ -2826,20 +2826,20 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state) plane_state->view.type = drm_rotation_90_or_270(rotation) ? I915_GGTT_VIEW_ROTATED : I915_GGTT_VIEW_REMAPPED; - src_x = plane_state->base.src.x1 >> 16; - src_y = plane_state->base.src.y1 >> 16; - src_w = drm_rect_width(&plane_state->base.src) >> 16; - src_h = drm_rect_height(&plane_state->base.src) >> 16; + src_x = plane_state->uapi.src.x1 >> 16; + src_y = plane_state->uapi.src.y1 >> 16; + src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + src_h = drm_rect_height(&plane_state->uapi.src) >> 16; WARN_ON(is_ccs_modifier(fb->modifier)); /* Make src coordinates relative to the viewport */ - drm_rect_translate(&plane_state->base.src, + drm_rect_translate(&plane_state->uapi.src, -(src_x << 16), -(src_y << 16)); /* Rotate src coordinates to match rotated GTT view */ if (drm_rotation_90_or_270(rotation)) - drm_rect_rotate(&plane_state->base.src, + drm_rect_rotate(&plane_state->uapi.src, src_w << 16, src_h << 16, DRM_MODE_ROTATE_270); @@ -2959,7 +2959,7 @@ intel_plane_compute_gtt(struct intel_plane_state *plane_state) /* Rotate src coordinates to match rotated GTT view */ if (drm_rotation_90_or_270(rotation)) - drm_rect_rotate(&plane_state->base.src, + drm_rect_rotate(&plane_state->uapi.src, fb->base.width << 16, fb->base.height << 16, DRM_MODE_ROTATE_270); @@ -3127,9 +3127,9 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state, bool visible) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - plane_state->base.visible = visible; + plane_state->uapi.visible = visible; if (visible) crtc_state->uapi.plane_mask |= drm_plane_mask(&plane->base); @@ -3275,8 +3275,8 @@ valid_fb: plane_state->crtc_w = fb->width; plane_state->crtc_h = fb->height; - intel_state->base.src = drm_plane_state_src(plane_state); - intel_state->base.dst = drm_plane_state_dest(plane_state); + intel_state->uapi.src = drm_plane_state_src(plane_state); + intel_state->uapi.dst = drm_plane_state_dest(plane_state); if (plane_config->tiling) dev_priv->preserve_bios_swizzle = true; @@ -3411,13 +3411,13 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state static int skl_check_main_surface(struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); + struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; - int x = plane_state->base.src.x1 >> 16; - int y = plane_state->base.src.y1 >> 16; - int w = drm_rect_width(&plane_state->base.src) >> 16; - int h = drm_rect_height(&plane_state->base.src) >> 16; + int x = plane_state->uapi.src.x1 >> 16; + int y = plane_state->uapi.src.y1 >> 16; + int w = drm_rect_width(&plane_state->uapi.src) >> 16; + int h = drm_rect_height(&plane_state->uapi.src) >> 16; int max_width; int max_height; u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset; @@ -3500,7 +3500,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) * Put the final coordinates back so that the src * coordinate checks will see the right values. */ - drm_rect_translate_to(&plane_state->base.src, + drm_rect_translate_to(&plane_state->uapi.src, x << 16, y << 16); return 0; @@ -3512,10 +3512,10 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) unsigned int rotation = plane_state->hw.rotation; int max_width = skl_max_plane_width(fb, 1, rotation); int max_height = 4096; - int x = plane_state->base.src.x1 >> 17; - int y = plane_state->base.src.y1 >> 17; - int w = drm_rect_width(&plane_state->base.src) >> 17; - int h = drm_rect_height(&plane_state->base.src) >> 17; + int x = plane_state->uapi.src.x1 >> 17; + int y = plane_state->uapi.src.y1 >> 17; + int w = drm_rect_width(&plane_state->uapi.src) >> 17; + int h = drm_rect_height(&plane_state->uapi.src) >> 17; u32 offset; intel_add_fb_offsets(&x, &y, plane_state, 1); @@ -3538,8 +3538,8 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->hw.fb; - int src_x = plane_state->base.src.x1 >> 16; - int src_y = plane_state->base.src.y1 >> 16; + int src_x = plane_state->uapi.src.x1 >> 16; + int src_y = plane_state->uapi.src.y1 >> 16; int hsub = fb->format->hsub; int vsub = fb->format->vsub; int x = src_x / hsub; @@ -3565,7 +3565,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) if (ret) return ret; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; /* @@ -3689,7 +3689,7 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; u32 dspcntr; @@ -3746,7 +3746,7 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, int i9xx_check_plane_surface(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; int src_x, src_y, src_w; u32 offset; @@ -3756,12 +3756,12 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) if (ret) return ret; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; - src_w = drm_rect_width(&plane_state->base.src) >> 16; - src_x = plane_state->base.src.x1 >> 16; - src_y = plane_state->base.src.y1 >> 16; + src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + src_x = plane_state->uapi.src.x1 >> 16; + src_y = plane_state->uapi.src.y1 >> 16; /* Undocumented hardware limit on i965/g4x/vlv/chv */ if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048) @@ -3779,14 +3779,14 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) * Put the final coordinates back so that the src * coordinate checks will see the right values. */ - drm_rect_translate_to(&plane_state->base.src, + drm_rect_translate_to(&plane_state->uapi.src, src_x << 16, src_y << 16); /* HSW/BDW do this automagically in hardware */ if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { unsigned int rotation = plane_state->hw.rotation; - int src_w = drm_rect_width(&plane_state->base.src) >> 16; - int src_h = drm_rect_height(&plane_state->base.src) >> 16; + int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; if (rotation & DRM_MODE_ROTATE_180) { src_x += src_w - 1; @@ -3823,14 +3823,14 @@ static int i9xx_plane_check(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); int ret; ret = chv_plane_check_rotation(plane_state); if (ret) return ret; - ret = drm_atomic_helper_check_plane_state(&plane_state->base, + ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, &crtc_state->uapi, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, @@ -3843,7 +3843,7 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state, if (ret) return ret; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; ret = intel_plane_check_src_coordinates(plane_state); @@ -3864,10 +3864,10 @@ static void i9xx_update_plane(struct intel_plane *plane, u32 linear_offset; int x = plane_state->color_plane[0].x; int y = plane_state->color_plane[0].y; - int crtc_x = plane_state->base.dst.x1; - int crtc_y = plane_state->base.dst.y1; - int crtc_w = drm_rect_width(&plane_state->base.dst); - int crtc_h = drm_rect_height(&plane_state->base.dst); + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + int crtc_w = drm_rect_width(&plane_state->uapi.dst); + int crtc_h = drm_rect_height(&plane_state->uapi.dst); unsigned long irqflags; u32 dspaddr_offset; u32 dspcntr; @@ -4221,7 +4221,7 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; @@ -4277,9 +4277,9 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); u32 plane_color_ctl = 0; plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; @@ -5623,11 +5623,11 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { struct intel_plane *intel_plane = - to_intel_plane(plane_state->base.plane); + to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); struct drm_framebuffer *fb = plane_state->hw.fb; int ret; - bool force_detach = !fb || !plane_state->base.visible; + bool force_detach = !fb || !plane_state->uapi.visible; bool need_scaler = false; /* Pre-gen11 and SDR planes always need a scaler for planar formats. */ @@ -5638,10 +5638,10 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, ret = skl_update_scaler(crtc_state, force_detach, drm_plane_index(&intel_plane->base), &plane_state->scaler_id, - drm_rect_width(&plane_state->base.src) >> 16, - drm_rect_height(&plane_state->base.src) >> 16, - drm_rect_width(&plane_state->base.dst), - drm_rect_height(&plane_state->base.dst), + drm_rect_width(&plane_state->uapi.src) >> 16, + drm_rect_height(&plane_state->uapi.src) >> 16, + drm_rect_width(&plane_state->uapi.dst), + drm_rect_height(&plane_state->uapi.dst), fb ? fb->format : NULL, need_scaler); if (ret || plane_state->scaler_id < 0) @@ -6057,7 +6057,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, * So disable underrun reporting before all the planes get disabled. */ if (IS_GEN(dev_priv, 2) && old_primary_state->visible && - (modeset || !new_primary_state->base.visible)) + (modeset || !new_primary_state->uapi.visible)) intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); } @@ -6144,7 +6144,7 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state, intel_disable_plane(plane, new_crtc_state); - if (old_plane_state->base.visible) + if (old_plane_state->uapi.visible) fb_bits |= plane->frontbuffer_bit; } @@ -7153,7 +7153,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, const struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); - if (plane_state->base.visible) + if (plane_state->uapi.visible) intel_plane_disable_noatomic(intel_crtc, plane); } @@ -10728,7 +10728,7 @@ out: static u32 intel_cursor_base(const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; const struct drm_i915_gem_object *obj = intel_fb_obj(fb); u32 base; @@ -10743,8 +10743,8 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state) static u32 intel_cursor_position(const struct intel_plane_state *plane_state) { - int x = plane_state->base.dst.x1; - int y = plane_state->base.dst.y1; + int x = plane_state->uapi.dst.x1; + int y = plane_state->uapi.dst.y1; u32 pos = 0; if (x < 0) { @@ -10765,9 +10765,9 @@ static u32 intel_cursor_position(const struct intel_plane_state *plane_state) static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state) { const struct drm_mode_config *config = - &plane_state->base.plane->dev->mode_config; - int width = drm_rect_width(&plane_state->base.dst); - int height = drm_rect_height(&plane_state->base.dst); + &plane_state->uapi.plane->dev->mode_config; + int width = drm_rect_width(&plane_state->uapi.dst); + int height = drm_rect_height(&plane_state->uapi.dst); return width > 0 && width <= config->cursor_width && height > 0 && height <= config->cursor_height; @@ -10776,7 +10776,7 @@ static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state) static int intel_cursor_check_surface(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); unsigned int rotation = plane_state->hw.rotation; int src_x, src_y; u32 offset; @@ -10786,11 +10786,11 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state) if (ret) return ret; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; - src_x = plane_state->base.src.x1 >> 16; - src_y = plane_state->base.src.y1 >> 16; + src_x = plane_state->uapi.src.x1 >> 16; + src_y = plane_state->uapi.src.y1 >> 16; intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); offset = intel_plane_compute_aligned_offset(&src_x, &src_y, @@ -10805,14 +10805,14 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state) * Put the final coordinates back so that the src * coordinate checks will see the right values. */ - drm_rect_translate_to(&plane_state->base.src, + drm_rect_translate_to(&plane_state->uapi.src, src_x << 16, src_y << 16); /* ILK+ do this automagically in hardware */ if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) { const struct drm_framebuffer *fb = plane_state->hw.fb; - int src_w = drm_rect_width(&plane_state->base.src) >> 16; - int src_h = drm_rect_height(&plane_state->base.src) >> 16; + int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; offset += (src_h * src_w - 1) * fb->format->cpp[0]; } @@ -10835,7 +10835,7 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, return -EINVAL; } - ret = drm_atomic_helper_check_plane_state(&plane_state->base, + ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, &crtc_state->uapi, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, @@ -10844,14 +10844,14 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, return ret; /* Use the unclipped src/dst rectangles, which we program to hw */ - plane_state->base.src = drm_plane_state_src(&plane_state->base); - plane_state->base.dst = drm_plane_state_dest(&plane_state->base); + plane_state->uapi.src = drm_plane_state_src(&plane_state->uapi); + plane_state->uapi.dst = drm_plane_state_dest(&plane_state->uapi); ret = intel_cursor_check_surface(plane_state); if (ret) return ret; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; ret = intel_plane_check_src_coordinates(plane_state); @@ -10889,7 +10889,7 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state, static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state) { - int width = drm_rect_width(&plane_state->base.dst); + int width = drm_rect_width(&plane_state->uapi.dst); /* * 845g/865g are only limited by the width of their cursors, @@ -10915,12 +10915,12 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state, /* Check for which cursor types we support */ if (!i845_cursor_size_ok(plane_state)) { DRM_DEBUG("Cursor dimension %dx%d not supported\n", - drm_rect_width(&plane_state->base.dst), - drm_rect_height(&plane_state->base.dst)); + drm_rect_width(&plane_state->uapi.dst), + drm_rect_height(&plane_state->uapi.dst)); return -EINVAL; } - WARN_ON(plane_state->base.visible && + WARN_ON(plane_state->uapi.visible && plane_state->color_plane[0].stride != fb->pitches[0]); switch (fb->pitches[0]) { @@ -10948,9 +10948,9 @@ static void i845_update_cursor(struct intel_plane *plane, u32 cntl = 0, base = 0, pos = 0, size = 0; unsigned long irqflags; - if (plane_state && plane_state->base.visible) { - unsigned int width = drm_rect_width(&plane_state->base.dst); - unsigned int height = drm_rect_height(&plane_state->base.dst); + if (plane_state && plane_state->uapi.visible) { + unsigned int width = drm_rect_width(&plane_state->uapi.dst); + unsigned int height = drm_rect_height(&plane_state->uapi.dst); cntl = plane_state->ctl | i845_cursor_ctl_crtc(crtc_state); @@ -11046,13 +11046,13 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); u32 cntl = 0; if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) cntl |= MCURSOR_TRICKLE_FEED_DISABLE; - switch (drm_rect_width(&plane_state->base.dst)) { + switch (drm_rect_width(&plane_state->uapi.dst)) { case 64: cntl |= MCURSOR_MODE_64_ARGB_AX; break; @@ -11063,7 +11063,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, cntl |= MCURSOR_MODE_256_ARGB_AX; break; default: - MISSING_CASE(drm_rect_width(&plane_state->base.dst)); + MISSING_CASE(drm_rect_width(&plane_state->uapi.dst)); return 0; } @@ -11076,9 +11076,9 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); - int width = drm_rect_width(&plane_state->base.dst); - int height = drm_rect_height(&plane_state->base.dst); + to_i915(plane_state->uapi.plane->dev); + int width = drm_rect_width(&plane_state->uapi.dst); + int height = drm_rect_height(&plane_state->uapi.dst); if (!intel_cursor_size_ok(plane_state)) return false; @@ -11114,7 +11114,7 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state) static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; @@ -11131,19 +11131,19 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, /* Check for which cursor types we support */ if (!i9xx_cursor_size_ok(plane_state)) { DRM_DEBUG("Cursor dimension %dx%d not supported\n", - drm_rect_width(&plane_state->base.dst), - drm_rect_height(&plane_state->base.dst)); + drm_rect_width(&plane_state->uapi.dst), + drm_rect_height(&plane_state->uapi.dst)); return -EINVAL; } - WARN_ON(plane_state->base.visible && + WARN_ON(plane_state->uapi.visible && plane_state->color_plane[0].stride != fb->pitches[0]); if (fb->pitches[0] != - drm_rect_width(&plane_state->base.dst) * fb->format->cpp[0]) { + drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) { DRM_DEBUG_KMS("Invalid cursor stride (%u) (cursor width %d)\n", fb->pitches[0], - drm_rect_width(&plane_state->base.dst)); + drm_rect_width(&plane_state->uapi.dst)); return -EINVAL; } @@ -11158,7 +11158,7 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, * Refuse the put the cursor into that compromised position. */ if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C && - plane_state->base.visible && plane_state->base.dst.x1 < 0) { + plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) { DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); return -EINVAL; } @@ -11177,9 +11177,9 @@ static void i9xx_update_cursor(struct intel_plane *plane, u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0; unsigned long irqflags; - if (plane_state && plane_state->base.visible) { - unsigned width = drm_rect_width(&plane_state->base.dst); - unsigned height = drm_rect_height(&plane_state->base.dst); + if (plane_state && plane_state->uapi.visible) { + unsigned width = drm_rect_width(&plane_state->uapi.dst); + unsigned height = drm_rect_height(&plane_state->uapi.dst); cntl = plane_state->ctl | i9xx_cursor_ctl_crtc(crtc_state); @@ -11714,7 +11714,7 @@ static bool intel_wm_need_update(const struct intel_plane_state *cur, struct intel_plane_state *new) { /* Update watermarks on tiling or size changes. */ - if (new->base.visible != cur->base.visible) + if (new->uapi.visible != cur->uapi.visible) return true; if (!cur->hw.fb || !new->hw.fb) @@ -11722,10 +11722,10 @@ static bool intel_wm_need_update(const struct intel_plane_state *cur, if (cur->hw.fb->modifier != new->hw.fb->modifier || cur->hw.rotation != new->hw.rotation || - drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) || - drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) || - drm_rect_width(&new->base.dst) != drm_rect_width(&cur->base.dst) || - drm_rect_height(&new->base.dst) != drm_rect_height(&cur->base.dst)) + drm_rect_width(&new->uapi.src) != drm_rect_width(&cur->uapi.src) || + drm_rect_height(&new->uapi.src) != drm_rect_height(&cur->uapi.src) || + drm_rect_width(&new->uapi.dst) != drm_rect_width(&cur->uapi.dst) || + drm_rect_height(&new->uapi.dst) != drm_rect_height(&cur->uapi.dst)) return true; return false; @@ -11733,10 +11733,10 @@ static bool intel_wm_need_update(const struct intel_plane_state *cur, static bool needs_scaling(const struct intel_plane_state *state) { - int src_w = drm_rect_width(&state->base.src) >> 16; - int src_h = drm_rect_height(&state->base.src) >> 16; - int dst_w = drm_rect_width(&state->base.dst); - int dst_h = drm_rect_height(&state->base.dst); + int src_w = drm_rect_width(&state->uapi.src) >> 16; + int src_h = drm_rect_height(&state->uapi.src) >> 16; + int dst_w = drm_rect_width(&state->uapi.dst); + int dst_h = drm_rect_height(&state->uapi.dst); return (src_w != dst_w || src_h != dst_h); } @@ -11747,7 +11747,7 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat struct intel_plane_state *plane_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); bool mode_changed = needs_modeset(crtc_state); bool was_crtc_enabled = old_crtc_state->hw.active; @@ -11761,8 +11761,8 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat return ret; } - was_visible = old_plane_state->base.visible; - visible = plane_state->base.visible; + was_visible = old_plane_state->uapi.visible; + visible = plane_state->uapi.visible; if (!was_crtc_enabled && WARN_ON(was_visible)) was_visible = false; @@ -11778,7 +11778,7 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat * only combine the results from all planes in the current place? */ if (!is_crtc_enabled) { - plane_state->base.visible = visible = false; + plane_state->uapi.visible = visible = false; crtc_state->active_planes &= ~BIT(plane->id); crtc_state->data_rate[plane->id] = 0; crtc_state->min_cdclk[plane->id] = 0; @@ -11938,7 +11938,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) continue; plane_state->planar_linked_plane = NULL; - if (plane_state->planar_slave && !plane_state->base.visible) { + if (plane_state->planar_slave && !plane_state->uapi.visible) { crtc_state->active_planes &= ~BIT(plane->id); crtc_state->update_planes |= BIT(plane->id); } @@ -12352,14 +12352,14 @@ static const char *output_formats(enum intel_output_format format) static void intel_dump_plane_state(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct drm_framebuffer *fb = plane_state->hw.fb; struct drm_format_name_buf format_name; if (!fb) { DRM_DEBUG_KMS("[PLANE:%d:%s] fb: [NOFB], visible: %s\n", plane->base.base.id, plane->base.name, - yesno(plane_state->base.visible)); + yesno(plane_state->uapi.visible)); return; } @@ -12367,13 +12367,13 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state) plane->base.base.id, plane->base.name, fb->base.id, fb->width, fb->height, drm_get_format_name(fb->format->format, &format_name), - yesno(plane_state->base.visible)); + yesno(plane_state->uapi.visible)); DRM_DEBUG_KMS("\trotation: 0x%x, scaler: %d\n", plane_state->hw.rotation, plane_state->scaler_id); - if (plane_state->base.visible) + if (plane_state->uapi.visible) DRM_DEBUG_KMS("\tsrc: " DRM_RECT_FP_FMT " dst: " DRM_RECT_FMT "\n", - DRM_RECT_FP_ARG(&plane_state->base.src), - DRM_RECT_ARG(&plane_state->base.dst)); + DRM_RECT_FP_ARG(&plane_state->uapi.src), + DRM_RECT_ARG(&plane_state->uapi.dst)); } static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, @@ -13578,7 +13578,7 @@ intel_verify_planes(struct intel_atomic_state *state) for_each_new_intel_plane_in_state(state, plane, plane_state, i) assert_plane(plane, plane_state->planar_slave || - plane_state->base.visible); + plane_state->uapi.visible); } static void @@ -15037,7 +15037,7 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc, static int intel_plane_pin_fb(struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); struct drm_framebuffer *fb = plane_state->hw.fb; struct i915_vma *vma; @@ -15102,7 +15102,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, struct intel_plane_state *new_plane_state = to_intel_plane_state(_new_plane_state); struct intel_atomic_state *intel_state = - to_intel_atomic_state(new_plane_state->base.state); + to_intel_atomic_state(new_plane_state->uapi.state); struct drm_i915_private *dev_priv = to_i915(plane->dev); struct drm_framebuffer *fb = new_plane_state->hw.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); @@ -15135,9 +15135,9 @@ intel_prepare_plane_fb(struct drm_plane *plane, } } - if (new_plane_state->base.fence) { /* explicit fencing */ + if (new_plane_state->uapi.fence) { /* explicit fencing */ ret = i915_sw_fence_await_dma_fence(&intel_state->commit_ready, - new_plane_state->base.fence, + new_plane_state->uapi.fence, I915_FENCE_TIMEOUT, GFP_KERNEL); if (ret < 0) @@ -15160,7 +15160,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, fb_obj_bump_render_priority(obj); intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB); - if (!new_plane_state->base.fence) { /* implicit fencing */ + if (!new_plane_state->uapi.fence) { /* implicit fencing */ struct dma_fence *fence; ret = i915_sw_fence_await_reservation(&intel_state->commit_ready, @@ -15178,7 +15178,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, } } else { add_rps_boost_after_vblank(new_plane_state->hw.crtc, - new_plane_state->base.fence); + new_plane_state->uapi.fence); } /* @@ -15211,7 +15211,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane, struct intel_plane_state *old_plane_state = to_intel_plane_state(_old_plane_state); struct intel_atomic_state *intel_state = - to_intel_atomic_state(old_plane_state->base.state); + to_intel_atomic_state(old_plane_state->uapi.state); struct drm_i915_private *dev_priv = to_i915(plane->dev); if (intel_state->rps_interactive) { @@ -15343,8 +15343,8 @@ intel_legacy_cursor_update(struct drm_plane *_plane, * the plane. This prevents our async update's changes from getting * overridden by a previous synchronous update's state. */ - if (old_plane_state->base.commit && - !try_wait_for_completion(&old_plane_state->base.commit->hw_done)) + if (old_plane_state->uapi.commit && + !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done)) goto slow; /* @@ -17150,7 +17150,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, const struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); - if (plane_state->base.visible && + if (plane_state->uapi.visible && plane->base.type != DRM_PLANE_TYPE_PRIMARY) intel_plane_disable_noatomic(crtc, plane); } @@ -17483,14 +17483,14 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) * FIXME don't have the fb yet, so can't * use intel_plane_data_rate() :( */ - if (plane_state->base.visible) + if (plane_state->uapi.visible) crtc_state->data_rate[plane->id] = 4 * crtc_state->pixel_rate; /* * FIXME don't have the fb yet, so can't * use plane->min_cdclk() :( */ - if (plane_state->base.visible && plane->min_cdclk) { + if (plane_state->uapi.visible && plane->min_cdclk) { if (crtc_state->double_wide || INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) crtc_state->min_cdclk[plane->id] = diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 3ea8d010db6c..92c7eb243559 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -430,7 +430,7 @@ static bool multiple_pipes_ok(struct intel_crtc *crtc, if (!no_fbc_on_multiple_pipes(dev_priv)) return true; - if (plane_state->base.visible) + if (plane_state->uapi.visible) fbc->visible_pipes_mask |= (1 << pipe); else fbc->visible_pipes_mask &= ~(1 << pipe); @@ -677,12 +677,12 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, * the 90/270 degree plane rotation cases (to match the * GTT mapping), hence no need to account for rotation here. */ - cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16; - cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16; - cache->plane.visible = plane_state->base.visible; + cache->plane.src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + cache->plane.src_h = drm_rect_height(&plane_state->uapi.src) >> 16; + cache->plane.visible = plane_state->uapi.visible; cache->plane.adjusted_x = plane_state->color_plane[0].x; cache->plane.adjusted_y = plane_state->color_plane[0].y; - cache->plane.y = plane_state->base.src.y1 >> 16; + cache->plane.y = plane_state->uapi.src.y1 >> 16; cache->plane.pixel_blend_mode = plane_state->hw.pixel_blend_mode; @@ -1052,7 +1052,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, if (!plane->has_fbc) continue; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) continue; crtc_state = intel_atomic_get_new_crtc_state(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 46e3d6cf5976..8cfb785e761c 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -668,7 +668,7 @@ static void update_colorkey(struct intel_overlay *overlay, if (overlay->color_key_enabled) flags |= DST_KEY_ENABLE; - if (state->base.visible) + if (state->uapi.visible) format = state->hw.fb->format->format; switch (format) { diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index b2116d123548..ef7409f695f9 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -240,7 +240,7 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) int intel_plane_check_stride(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; u32 stride, max_stride; @@ -252,7 +252,7 @@ int intel_plane_check_stride(const struct intel_plane_state *plane_state) * kick in due the plane being invisible. */ if (intel_plane_can_remap(plane_state) && - !plane_state->base.visible) + !plane_state->uapi.visible) return 0; /* FIXME other color planes? */ @@ -273,7 +273,7 @@ int intel_plane_check_stride(const struct intel_plane_state *plane_state) int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->hw.fb; - struct drm_rect *src = &plane_state->base.src; + struct drm_rect *src = &plane_state->uapi.src; u32 src_x, src_y, src_w, src_h, hsub, vsub; bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation); @@ -328,7 +328,7 @@ skl_plane_ratio(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, unsigned int *num, unsigned int *den) { - struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); + struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; if (fb->format->cpp[0] == 8) { @@ -348,7 +348,7 @@ skl_plane_ratio(const struct intel_crtc_state *crtc_state, static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); + struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); unsigned int pixel_rate = crtc_state->pixel_rate; unsigned int src_w, src_h, dst_w, dst_h; unsigned int num, den; @@ -359,10 +359,10 @@ static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state, if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) den *= 2; - src_w = drm_rect_width(&plane_state->base.src) >> 16; - src_h = drm_rect_height(&plane_state->base.src) >> 16; - dst_w = drm_rect_width(&plane_state->base.dst); - dst_h = drm_rect_height(&plane_state->base.dst); + src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + src_h = drm_rect_height(&plane_state->uapi.src) >> 16; + dst_w = drm_rect_width(&plane_state->uapi.dst); + dst_h = drm_rect_height(&plane_state->uapi.dst); /* Downscaling limits the maximum pixel rate */ dst_w = min(src_w, dst_w); @@ -401,19 +401,19 @@ skl_program_scaler(struct intel_plane *plane, int scaler_id = plane_state->scaler_id; const struct intel_scaler *scaler = &crtc_state->scaler_state.scalers[scaler_id]; - int crtc_x = plane_state->base.dst.x1; - int crtc_y = plane_state->base.dst.y1; - u32 crtc_w = drm_rect_width(&plane_state->base.dst); - u32 crtc_h = drm_rect_height(&plane_state->base.dst); + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); + u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); u16 y_hphase, uv_rgb_hphase; u16 y_vphase, uv_rgb_vphase; int hscale, vscale; - hscale = drm_rect_calc_hscale(&plane_state->base.src, - &plane_state->base.dst, + hscale = drm_rect_calc_hscale(&plane_state->uapi.src, + &plane_state->uapi.dst, 0, INT_MAX); - vscale = drm_rect_calc_vscale(&plane_state->base.src, - &plane_state->base.dst, + vscale = drm_rect_calc_vscale(&plane_state->uapi.src, + &plane_state->uapi.dst, 0, INT_MAX); /* TODO: handle sub-pixel coordinates */ @@ -584,12 +584,12 @@ skl_program_plane(struct intel_plane *plane, u32 surf_addr = plane_state->color_plane[color_plane].offset; u32 stride = skl_plane_stride(plane_state, color_plane); u32 aux_stride = skl_plane_stride(plane_state, 1); - int crtc_x = plane_state->base.dst.x1; - int crtc_y = plane_state->base.dst.y1; + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; u32 x = plane_state->color_plane[color_plane].x; u32 y = plane_state->color_plane[color_plane].y; - u32 src_w = drm_rect_width(&plane_state->base.src) >> 16; - u32 src_h = drm_rect_height(&plane_state->base.src) >> 16; + u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; struct intel_plane *linked = plane_state->planar_linked_plane; const struct drm_framebuffer *fb = plane_state->hw.fb; u8 alpha = plane_state->hw.alpha >> 8; @@ -766,7 +766,7 @@ static void i9xx_plane_linear_gamma(u16 gamma[8]) static void chv_update_csc(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; enum plane_id plane_id = plane->id; @@ -825,7 +825,7 @@ chv_update_csc(const struct intel_plane_state *plane_state) static void vlv_update_clrc(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; @@ -1019,7 +1019,7 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, static void vlv_update_gamma(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; @@ -1053,10 +1053,10 @@ vlv_update_plane(struct intel_plane *plane, u32 sprsurf_offset = plane_state->color_plane[0].offset; u32 linear_offset; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; - int crtc_x = plane_state->base.dst.x1; - int crtc_y = plane_state->base.dst.y1; - u32 crtc_w = drm_rect_width(&plane_state->base.dst); - u32 crtc_h = drm_rect_height(&plane_state->base.dst); + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); + u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); u32 x = plane_state->color_plane[0].x; u32 y = plane_state->color_plane[0].y; unsigned long irqflags; @@ -1245,8 +1245,8 @@ static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state, */ pixel_rate = crtc_state->pixel_rate; - src_w = drm_rect_width(&plane_state->base.src) >> 16; - dst_w = drm_rect_width(&plane_state->base.dst); + src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + dst_w = drm_rect_width(&plane_state->uapi.dst); if (src_w != dst_w) ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den); @@ -1320,7 +1320,7 @@ static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state) static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; return fb->format->cpp[0] == 8 && @@ -1331,7 +1331,7 @@ static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; @@ -1422,7 +1422,7 @@ static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state, static void ivb_update_gamma(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; u16 gamma[18]; @@ -1461,14 +1461,14 @@ ivb_update_plane(struct intel_plane *plane, u32 sprsurf_offset = plane_state->color_plane[0].offset; u32 linear_offset; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; - int crtc_x = plane_state->base.dst.x1; - int crtc_y = plane_state->base.dst.y1; - u32 crtc_w = drm_rect_width(&plane_state->base.dst); - u32 crtc_h = drm_rect_height(&plane_state->base.dst); + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); + u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); u32 x = plane_state->color_plane[0].x; u32 y = plane_state->color_plane[0].y; - u32 src_w = drm_rect_width(&plane_state->base.src) >> 16; - u32 src_h = drm_rect_height(&plane_state->base.src) >> 16; + u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; u32 sprctl, sprscale = 0; unsigned long irqflags; @@ -1581,8 +1581,8 @@ static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state, pixel_rate = crtc_state->pixel_rate; /* Horizontal downscaling limits the maximum pixel rate */ - hscale = drm_rect_calc_hscale(&plane_state->base.src, - &plane_state->base.dst, + hscale = drm_rect_calc_hscale(&plane_state->uapi.src, + &plane_state->uapi.dst, 0, INT_MAX); if (hscale < 0x10000) return pixel_rate; @@ -1636,7 +1636,7 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); + to_i915(plane_state->uapi.plane->dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; @@ -1699,7 +1699,7 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, static void g4x_update_gamma(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; @@ -1731,7 +1731,7 @@ static void ilk_sprite_linear_gamma(u16 gamma[17]) static void ilk_update_gamma(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; enum pipe pipe = plane->pipe; @@ -1767,14 +1767,14 @@ g4x_update_plane(struct intel_plane *plane, u32 dvssurf_offset = plane_state->color_plane[0].offset; u32 linear_offset; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; - int crtc_x = plane_state->base.dst.x1; - int crtc_y = plane_state->base.dst.y1; - u32 crtc_w = drm_rect_width(&plane_state->base.dst); - u32 crtc_h = drm_rect_height(&plane_state->base.dst); + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); + u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); u32 x = plane_state->color_plane[0].x; u32 y = plane_state->color_plane[0].y; - u32 src_w = drm_rect_width(&plane_state->base.src) >> 16; - u32 src_h = drm_rect_height(&plane_state->base.src) >> 16; + u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; u32 dvscntr, dvsscale = 0; unsigned long irqflags; @@ -1888,8 +1888,8 @@ g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->hw.fb; - const struct drm_rect *src = &plane_state->base.src; - const struct drm_rect *dst = &plane_state->base.dst; + const struct drm_rect *src = &plane_state->uapi.src; + const struct drm_rect *dst = &plane_state->uapi.dst; int src_x, src_w, src_h, crtc_w, crtc_h; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; @@ -1948,7 +1948,7 @@ static int g4x_sprite_check(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); int min_scale = DRM_PLANE_HELPER_NO_SCALING; int max_scale = DRM_PLANE_HELPER_NO_SCALING; @@ -1964,7 +1964,7 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, } } - ret = drm_atomic_helper_check_plane_state(&plane_state->base, + ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, &crtc_state->uapi, min_scale, max_scale, true, true); @@ -1975,7 +1975,7 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, if (ret) return ret; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; ret = intel_plane_check_src_coordinates(plane_state); @@ -1996,7 +1996,7 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, int chv_plane_check_rotation(const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); unsigned int rotation = plane_state->hw.rotation; @@ -2021,7 +2021,7 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, if (ret) return ret; - ret = drm_atomic_helper_check_plane_state(&plane_state->base, + ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, &crtc_state->uapi, DRM_PLANE_HELPER_NO_SCALING, DRM_PLANE_HELPER_NO_SCALING, @@ -2033,7 +2033,7 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, if (ret) return ret; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; ret = intel_plane_check_src_coordinates(plane_state); @@ -2048,7 +2048,7 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; @@ -2123,9 +2123,9 @@ static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_s const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); - int crtc_x = plane_state->base.dst.x1; - int crtc_w = drm_rect_width(&plane_state->base.dst); + to_i915(plane_state->uapi.plane->dev); + int crtc_x = plane_state->uapi.dst.x1; + int crtc_w = drm_rect_width(&plane_state->uapi.dst); int pipe_src_w = crtc_state->pipe_src_w; /* @@ -2153,7 +2153,7 @@ static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_s { const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; - int src_w = drm_rect_width(&plane_state->base.src) >> 16; + int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; /* Display WA #1106 */ if (drm_format_info_is_yuv_semiplanar(fb->format) && src_w & 3 && @@ -2185,7 +2185,7 @@ static int skl_plane_max_scale(struct drm_i915_private *dev_priv, static int skl_plane_check(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; int min_scale = DRM_PLANE_HELPER_NO_SCALING; @@ -2202,7 +2202,7 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, max_scale = skl_plane_max_scale(dev_priv, fb); } - ret = drm_atomic_helper_check_plane_state(&plane_state->base, + ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, &crtc_state->uapi, min_scale, max_scale, true, true); @@ -2213,7 +2213,7 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, if (ret) return ret; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; ret = skl_plane_check_dst_coordinates(crtc_state, plane_state); @@ -2230,7 +2230,7 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, /* HW only has 8 bits pixel precision, disable plane if invisible */ if (!(plane_state->hw.alpha >> 8)) - plane_state->base.visible = false; + plane_state->uapi.visible = false; plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); @@ -2249,7 +2249,7 @@ static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv) static void intel_plane_set_ckey(struct intel_plane_state *plane_state, const struct drm_intel_sprite_colorkey *set) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); struct drm_intel_sprite_colorkey *key = &plane_state->ckey; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0a0103ecf7bc..2d389e437e87 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -786,7 +786,7 @@ static int intel_wm_num_levels(struct drm_i915_private *dev_priv) static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); /* FIXME check the 'enable' instead */ if (!crtc_state->hw.active) @@ -803,7 +803,7 @@ static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, if (plane->id == PLANE_CURSOR) return plane_state->hw.fb != NULL; else - return plane_state->base.visible; + return plane_state->uapi.visible; } static struct intel_crtc *single_enabled_crtc(struct drm_i915_private *dev_priv) @@ -1075,7 +1075,7 @@ static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, int level) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; @@ -1108,7 +1108,7 @@ static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state, clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->crtc_htotal; - width = drm_rect_width(&plane_state->base.dst); + width = drm_rect_width(&plane_state->uapi.dst); if (plane->id == PLANE_CURSOR) { wm = intel_wm_method2(clock, htotal, width, cpp, latency); @@ -1174,7 +1174,7 @@ static u32 ilk_compute_fbc_wm(const struct intel_crtc_state *crtc_state, static bool g4x_raw_plane_wm_compute(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); int num_levels = intel_wm_num_levels(to_i915(plane->base.dev)); enum plane_id plane_id = plane->id; bool dirty = false; @@ -1581,7 +1581,7 @@ static u16 vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, int level) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; @@ -1751,7 +1751,7 @@ static bool vlv_raw_plane_wm_set(struct intel_crtc_state *crtc_state, static bool vlv_raw_plane_wm_compute(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); enum plane_id plane_id = plane->id; int num_levels = intel_wm_num_levels(to_i915(plane->base.dev)); int level; @@ -2484,7 +2484,7 @@ static u32 ilk_compute_pri_wm(const struct intel_crtc_state *crtc_state, method2 = ilk_wm_method2(crtc_state->pixel_rate, crtc_state->hw.adjusted_mode.crtc_htotal, - drm_rect_width(&plane_state->base.dst), + drm_rect_width(&plane_state->uapi.dst), cpp, mem_value); return min(method1, method2); @@ -2512,7 +2512,7 @@ static u32 ilk_compute_spr_wm(const struct intel_crtc_state *crtc_state, method1 = ilk_wm_method1(crtc_state->pixel_rate, cpp, mem_value); method2 = ilk_wm_method2(crtc_state->pixel_rate, crtc_state->hw.adjusted_mode.crtc_htotal, - drm_rect_width(&plane_state->base.dst), + drm_rect_width(&plane_state->uapi.dst), cpp, mem_value); return min(method1, method2); } @@ -2537,7 +2537,7 @@ static u32 ilk_compute_cur_wm(const struct intel_crtc_state *crtc_state, return ilk_wm_method2(crtc_state->pixel_rate, crtc_state->hw.adjusted_mode.crtc_htotal, - drm_rect_width(&plane_state->base.dst), + drm_rect_width(&plane_state->uapi.dst), cpp, mem_value); } @@ -2553,7 +2553,8 @@ static u32 ilk_compute_fbc_wm(const struct intel_crtc_state *crtc_state, cpp = plane_state->hw.fb->format->cpp[0]; - return ilk_wm_fbc(pri_val, drm_rect_width(&plane_state->base.dst), cpp); + return ilk_wm_fbc(pri_val, drm_rect_width(&plane_state->uapi.dst), + cpp); } static unsigned int @@ -3097,10 +3098,10 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *crtc_state) pipe_wm->pipe_enabled = crtc_state->hw.active; if (sprstate) { - pipe_wm->sprites_enabled = sprstate->base.visible; - pipe_wm->sprites_scaled = sprstate->base.visible && - (drm_rect_width(&sprstate->base.dst) != drm_rect_width(&sprstate->base.src) >> 16 || - drm_rect_height(&sprstate->base.dst) != drm_rect_height(&sprstate->base.src) >> 16); + pipe_wm->sprites_enabled = sprstate->uapi.visible; + pipe_wm->sprites_scaled = sprstate->uapi.visible && + (drm_rect_width(&sprstate->uapi.dst) != drm_rect_width(&sprstate->uapi.src) >> 16 || + drm_rect_height(&sprstate->uapi.dst) != drm_rect_height(&sprstate->uapi.src) >> 16); } usable_level = max_level; @@ -4072,10 +4073,10 @@ skl_plane_downscale_amount(const struct intel_crtc_state *crtc_state, * * n.b., src is 16.16 fixed point, dst is whole integer. */ - src_w = drm_rect_width(&plane_state->base.src) >> 16; - src_h = drm_rect_height(&plane_state->base.src) >> 16; - dst_w = drm_rect_width(&plane_state->base.dst); - dst_h = drm_rect_height(&plane_state->base.dst); + src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + src_h = drm_rect_height(&plane_state->uapi.src) >> 16; + dst_w = drm_rect_width(&plane_state->uapi.dst); + dst_h = drm_rect_height(&plane_state->uapi.dst); fp_w_ratio = div_fixed16(src_w, dst_w); fp_h_ratio = div_fixed16(src_h, dst_h); @@ -4090,14 +4091,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, int color_plane) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct drm_framebuffer *fb = plane_state->hw.fb; u32 data_rate; u32 width = 0, height = 0; uint_fixed_16_16_t down_scale_amount; u64 rate; - if (!plane_state->base.visible) + if (!plane_state->uapi.visible) return 0; if (plane->id == PLANE_CURSOR) @@ -4112,8 +4113,8 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, * the 90/270 degree plane rotation cases (to match the * GTT mapping), hence no need to account for rotation here. */ - width = drm_rect_width(&plane_state->base.src) >> 16; - height = drm_rect_height(&plane_state->base.src) >> 16; + width = drm_rect_width(&plane_state->uapi.src) >> 16; + height = drm_rect_height(&plane_state->uapi.src) >> 16; /* UV plane does 1/2 pixel sub-sampling */ if (color_plane == 1) { @@ -4620,7 +4621,7 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *crtc_state, * the 90/270 degree plane rotation cases (to match the * GTT mapping), hence no need to account for rotation here. */ - width = drm_rect_width(&plane_state->base.src) >> 16; + width = drm_rect_width(&plane_state->uapi.src) >> 16; return skl_compute_wm_params(crtc_state, width, fb->format, fb->modifier, @@ -4902,7 +4903,7 @@ static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state, static int skl_build_plane_wm(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct drm_framebuffer *fb = plane_state->hw.fb; enum plane_id plane_id = plane->id; int ret; @@ -4928,7 +4929,7 @@ static int skl_build_plane_wm(struct intel_crtc_state *crtc_state, static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - enum plane_id plane_id = to_intel_plane(plane_state->base.plane)->id; + enum plane_id plane_id = to_intel_plane(plane_state->uapi.plane)->id; int ret; /* Watermarks calculated in master */ @@ -5928,7 +5929,7 @@ void g4x_wm_sanitize(struct drm_i915_private *dev_priv) enum plane_id plane_id = plane->id; int level; - if (plane_state->base.visible) + if (plane_state->uapi.visible) continue; for (level = 0; level < 3; level++) { @@ -6083,7 +6084,7 @@ void vlv_wm_sanitize(struct drm_i915_private *dev_priv) enum plane_id plane_id = plane->id; int level; - if (plane_state->base.visible) + if (plane_state->uapi.visible) continue; for (level = 0; level < wm_state->num_levels; level++) { -- cgit v1.2.3 From 380015bfd9ceea7eb790ecd222dedb9f15613e59 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:09 +0100 Subject: drm/i915: Complete plane hw and uapi split, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Splitting plane state is easier than splitting crtc_state, before plane check we copy the drm properties to hw so we can do the same in bigjoiner later on. We copy the state after we did all the modeset handling, but fortunately i915 seems to be split correctly and nothing during modeset looks at plane_state. Changes since v1: - Do not clear hw state on duplication. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-11-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 37 +++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_atomic_plane.h | 2 ++ drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_display_types.h | 23 +++++++++++--- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index d456b3dc200c..133e6a75c8a0 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -93,6 +93,10 @@ intel_plane_duplicate_state(struct drm_plane *plane) intel_state->vma = NULL; intel_state->flags = 0; + /* add reference to fb */ + if (intel_state->hw.fb) + drm_framebuffer_get(intel_state->hw.fb); + return &intel_state->uapi; } @@ -112,6 +116,8 @@ intel_plane_destroy_state(struct drm_plane *plane, WARN_ON(plane_state->vma); __drm_atomic_helper_plane_destroy_state(&plane_state->uapi); + if (plane_state->hw.fb) + drm_framebuffer_put(plane_state->hw.fb); kfree(plane_state); } @@ -176,15 +182,44 @@ bool intel_plane_calc_min_cdclk(struct intel_atomic_state *state, return false; } +static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state) +{ + if (plane_state->hw.fb) + drm_framebuffer_put(plane_state->hw.fb); + + memset(&plane_state->hw, 0, sizeof(plane_state->hw)); +} + +void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, + const struct intel_plane_state *from_plane_state) +{ + intel_plane_clear_hw_state(plane_state); + + plane_state->hw.crtc = from_plane_state->uapi.crtc; + plane_state->hw.fb = from_plane_state->uapi.fb; + if (plane_state->hw.fb) + drm_framebuffer_get(plane_state->hw.fb); + + plane_state->hw.alpha = from_plane_state->uapi.alpha; + plane_state->hw.pixel_blend_mode = + from_plane_state->uapi.pixel_blend_mode; + plane_state->hw.rotation = from_plane_state->uapi.rotation; + plane_state->hw.color_encoding = from_plane_state->uapi.color_encoding; + plane_state->hw.color_range = from_plane_state->uapi.color_range; +} + int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state, const struct intel_plane_state *old_plane_state, struct intel_plane_state *new_plane_state) { struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); - const struct drm_framebuffer *fb = new_plane_state->hw.fb; + const struct drm_framebuffer *fb; int ret; + intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state); + fb = new_plane_state->hw.fb; + new_crtc_state->active_planes &= ~BIT(plane->id); new_crtc_state->nv12_planes &= ~BIT(plane->id); new_crtc_state->c8_planes &= ~BIT(plane->id); diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index e61e9a82aadf..cdb0f97d09f9 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -20,6 +20,8 @@ extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); +void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, + const struct intel_plane_state *from_plane_state); void intel_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 27ce6d7c3971..137a8bdfd869 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3283,6 +3283,7 @@ valid_fb: plane_state->fb = fb; plane_state->crtc = &intel_crtc->base; + intel_plane_copy_uapi_to_hw_state(intel_state, intel_state); atomic_or(to_intel_plane(primary)->frontbuffer_bit, &to_intel_frontbuffer(fb)->bits); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 7f338c130ed7..cf1d71624783 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -523,11 +523,24 @@ struct intel_atomic_state { }; struct intel_plane_state { - union { - struct drm_plane_state base; - struct drm_plane_state uapi; - struct drm_plane_state hw; - }; + struct drm_plane_state uapi; + + /* + * actual hardware state, the state we program to the hardware. + * The following members are used to verify the hardware state: + * During initial hw readout, they need to be copied from uapi. + */ + struct { + struct drm_crtc *crtc; + struct drm_framebuffer *fb; + + u16 alpha; + uint16_t pixel_blend_mode; + unsigned int rotation; + enum drm_color_encoding color_encoding; + enum drm_color_range color_range; + } hw; + struct i915_ggtt_view view; struct i915_vma *vma; unsigned long flags; -- cgit v1.2.3 From 1f594b209fe1c5fedd79e44939459f7e5ea525bb Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 31 Oct 2019 12:26:10 +0100 Subject: drm/i915: Remove special case slave handling during hw programming, v3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we split plane_state which I didn't want to do yet, we can program the slave plane without requiring the master plane. This is useful for programming bigjoiner slave planes as well. We will no longer need the master's plane_state. Changes since v1: - set src/dst rectangles after copy_uapi_to_hw_state. Changes since v2: - Use the correct color_plane for pre-gen11 by using planar_linked_plane != NULL. - Use drm_format_info_is_yuv_semiplanar in skl_plane_check() to fix gen11+. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191031112610.27608-12-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 30 +----------- drivers/gpu/drm/i915/display/intel_atomic_plane.h | 3 -- drivers/gpu/drm/i915/display/intel_display.c | 18 +++++++ drivers/gpu/drm/i915/display/intel_display_types.h | 6 +-- drivers/gpu/drm/i915/display/intel_sprite.c | 57 +++++++--------------- 5 files changed, 40 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 133e6a75c8a0..42b3b3449d2e 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -348,16 +348,6 @@ void intel_update_plane(struct intel_plane *plane, plane->update_plane(plane, crtc_state, plane_state); } -void intel_update_slave(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - - trace_intel_update_plane(&plane->base, crtc); - plane->update_slave(plane, crtc_state, plane_state); -} - void intel_disable_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) { @@ -390,25 +380,9 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state, struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); - if (new_plane_state->uapi.visible) { + if (new_plane_state->uapi.visible || + new_plane_state->planar_slave) { intel_update_plane(plane, new_crtc_state, new_plane_state); - } else if (new_plane_state->planar_slave) { - struct intel_plane *master = - new_plane_state->planar_linked_plane; - - /* - * We update the slave plane from this function because - * programming it from the master plane's update_plane - * callback runs into issues when the Y plane is - * reassigned, disabled or used by a different plane. - * - * The slave plane is updated with the master plane's - * plane_state. - */ - new_plane_state = - intel_atomic_get_new_plane_state(state, master); - - intel_update_slave(plane, new_crtc_state, new_plane_state); } else { intel_disable_plane(plane, new_crtc_state); } diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index cdb0f97d09f9..5cedafdddb55 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -25,9 +25,6 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, void intel_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); -void intel_update_slave(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state); void intel_disable_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state); struct intel_plane *intel_plane_alloc(void); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 137a8bdfd869..c689cb5f94d3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -11985,6 +11985,24 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) crtc_state->active_planes |= BIT(linked->id); crtc_state->update_planes |= BIT(linked->id); DRM_DEBUG_KMS("Using %s as Y plane for %s\n", linked->base.name, plane->base.name); + + /* Copy parameters to slave plane */ + linked_state->ctl = plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE; + linked_state->color_ctl = plane_state->color_ctl; + linked_state->color_plane[0] = plane_state->color_plane[0]; + + intel_plane_copy_uapi_to_hw_state(linked_state, plane_state); + linked_state->uapi.src = plane_state->uapi.src; + linked_state->uapi.dst = plane_state->uapi.dst; + + if (icl_is_hdr_plane(dev_priv, plane->id)) { + if (linked->id == PLANE_SPRITE5) + plane_state->cus_ctl |= PLANE_CUS_PLANE_7; + else if (linked->id == PLANE_SPRITE4) + plane_state->cus_ctl |= PLANE_CUS_PLANE_6; + else + MISSING_CASE(linked->id); + } } return 0; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index cf1d71624783..764a715c5d1c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -563,6 +563,9 @@ struct intel_plane_state { /* plane color control register */ u32 color_ctl; + /* chroma upsampler control register */ + u32 cus_ctl; + /* * scaler_id * = -1 : not using a scaler @@ -1122,9 +1125,6 @@ struct intel_plane { void (*update_plane)(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); - void (*update_slave)(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state); void (*disable_plane)(struct intel_plane *plane, const struct intel_crtc_state *crtc_state); bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe); diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index ef7409f695f9..14b35678a363 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -575,7 +575,7 @@ static void skl_program_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, - int color_plane, bool slave, u32 plane_ctl) + int color_plane) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; @@ -590,12 +590,12 @@ skl_program_plane(struct intel_plane *plane, u32 y = plane_state->color_plane[color_plane].y; u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; - struct intel_plane *linked = plane_state->planar_linked_plane; const struct drm_framebuffer *fb = plane_state->hw.fb; u8 alpha = plane_state->hw.alpha >> 8; u32 plane_color_ctl = 0; unsigned long irqflags; u32 keymsk, keymax; + u32 plane_ctl = plane_state->ctl; plane_ctl |= skl_plane_ctl_crtc(crtc_state); @@ -627,26 +627,8 @@ skl_program_plane(struct intel_plane *plane, I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), (plane_state->color_plane[1].offset - surf_addr) | aux_stride); - if (icl_is_hdr_plane(dev_priv, plane_id)) { - u32 cus_ctl = 0; - - if (linked) { - /* Enable and use MPEG-2 chroma siting */ - cus_ctl = PLANE_CUS_ENABLE | - PLANE_CUS_HPHASE_0 | - PLANE_CUS_VPHASE_SIGN_NEGATIVE | - PLANE_CUS_VPHASE_0_25; - - if (linked->id == PLANE_SPRITE5) - cus_ctl |= PLANE_CUS_PLANE_7; - else if (linked->id == PLANE_SPRITE4) - cus_ctl |= PLANE_CUS_PLANE_6; - else - MISSING_CASE(linked->id); - } - - I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), cus_ctl); - } + if (icl_is_hdr_plane(dev_priv, plane_id)) + I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), plane_state->cus_ctl); if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl); @@ -676,7 +658,7 @@ skl_program_plane(struct intel_plane *plane, I915_WRITE_FW(PLANE_SURF(pipe, plane_id), intel_plane_ggtt_offset(plane_state) + surf_addr); - if (!slave && plane_state->scaler_id >= 0) + if (plane_state->scaler_id >= 0) skl_program_scaler(plane, crtc_state, plane_state); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); @@ -689,24 +671,12 @@ skl_update_plane(struct intel_plane *plane, { int color_plane = 0; - if (plane_state->planar_linked_plane) { - /* Program the UV plane */ + if (plane_state->planar_linked_plane && !plane_state->planar_slave) + /* Program the UV plane on planar master */ color_plane = 1; - } - - skl_program_plane(plane, crtc_state, plane_state, - color_plane, false, plane_state->ctl); -} -static void -icl_update_slave(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) -{ - skl_program_plane(plane, crtc_state, plane_state, 0, true, - plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE); + skl_program_plane(plane, crtc_state, plane_state, color_plane); } - static void skl_disable_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state) @@ -2238,6 +2208,15 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, plane_state->color_ctl = glk_plane_color_ctl(crtc_state, plane_state); + if (drm_format_info_is_yuv_semiplanar(fb->format) && + icl_is_hdr_plane(dev_priv, plane->id)) + /* Enable and use MPEG-2 chroma siting */ + plane_state->cus_ctl = PLANE_CUS_ENABLE | + PLANE_CUS_HPHASE_0 | + PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25; + else + plane_state->cus_ctl = 0; + return 0; } @@ -2917,8 +2896,6 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, plane->get_hw_state = skl_plane_get_hw_state; plane->check_plane = skl_plane_check; plane->min_cdclk = skl_plane_min_cdclk; - if (icl_is_nv12_y_plane(plane_id)) - plane->update_slave = icl_update_slave; if (INTEL_GEN(dev_priv) >= 11) formats = icl_get_plane_formats(dev_priv, pipe, -- cgit v1.2.3 From 4605bb73a81938a33a5db49d841466303f24b581 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 13:04:06 +0000 Subject: drm/i915/gt: Pull timeline initialise to intel_gt_init_early Our timelines are currently contained within an intel_gt, and we only need to perform list/spinlock initialisation, so we can pull the intel_timelines_init() into our intel_gt_init_early(). Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191101130406.4142-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt.c | 2 ++ drivers/gpu/drm/i915/gt/intel_timeline.c | 14 ++------------ drivers/gpu/drm/i915/gt/intel_timeline.h | 4 ++-- drivers/gpu/drm/i915/i915_gem.c | 4 ---- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 5 ----- 5 files changed, 6 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 898662c158ad..15c0a0dfc424 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -25,6 +25,7 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) intel_gt_init_reset(gt); intel_gt_init_requests(gt); + intel_gt_init_timelines(gt); intel_gt_pm_init_early(gt); intel_rps_init_early(>->rps); @@ -395,4 +396,5 @@ void intel_gt_driver_late_release(struct intel_gt *gt) { intel_uc_driver_late_release(>->uc); intel_gt_fini_reset(gt); + intel_gt_fini_timelines(gt); } diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 14ad10acd548..16a9e88d93de 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -262,7 +262,7 @@ int intel_timeline_init(struct intel_timeline *timeline, return 0; } -static void timelines_init(struct intel_gt *gt) +void intel_gt_init_timelines(struct intel_gt *gt) { struct intel_gt_timelines *timelines = >->timelines; @@ -273,11 +273,6 @@ static void timelines_init(struct intel_gt *gt) INIT_LIST_HEAD(&timelines->hwsp_free_list); } -void intel_timelines_init(struct drm_i915_private *i915) -{ - timelines_init(&i915->gt); -} - void intel_timeline_fini(struct intel_timeline *timeline) { GEM_BUG_ON(atomic_read(&timeline->pin_count)); @@ -562,7 +557,7 @@ void __intel_timeline_free(struct kref *kref) kfree_rcu(timeline, rcu); } -static void timelines_fini(struct intel_gt *gt) +void intel_gt_fini_timelines(struct intel_gt *gt) { struct intel_gt_timelines *timelines = >->timelines; @@ -570,11 +565,6 @@ static void timelines_fini(struct intel_gt *gt) GEM_BUG_ON(!list_empty(&timelines->hwsp_free_list)); } -void intel_timelines_fini(struct drm_i915_private *i915) -{ - timelines_fini(&i915->gt); -} - #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "gt/selftests/mock_timeline.c" #include "gt/selftest_timeline.c" diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.h b/drivers/gpu/drm/i915/gt/intel_timeline.h index f583af1ba18d..f5b7eade3809 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline.h @@ -88,7 +88,7 @@ int intel_timeline_read_hwsp(struct i915_request *from, struct i915_request *until, u32 *hwsp_offset); -void intel_timelines_init(struct drm_i915_private *i915); -void intel_timelines_fini(struct drm_i915_private *i915); +void intel_gt_init_timelines(struct intel_gt *gt); +void intel_gt_fini_timelines(struct intel_gt *gt); #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b1574ab104d7..af2cdc8eddeb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1227,8 +1227,6 @@ int i915_gem_init(struct drm_i915_private *dev_priv) mkwrite_device_info(dev_priv)->page_sizes = I915_GTT_PAGE_SIZE_4K; - intel_timelines_init(dev_priv); - ret = i915_gem_init_userptr(dev_priv); if (ret) return ret; @@ -1342,7 +1340,6 @@ err_unlock: if (ret != -EIO) { intel_uc_cleanup_firmwares(&dev_priv->gt.uc); i915_gem_cleanup_userptr(dev_priv); - intel_timelines_fini(dev_priv); } if (ret == -EIO) { @@ -1406,7 +1403,6 @@ void i915_gem_driver_release(struct drm_i915_private *dev_priv) intel_uc_cleanup_firmwares(&dev_priv->gt.uc); i915_gem_cleanup_userptr(dev_priv); - intel_timelines_fini(dev_priv); i915_gem_drain_freed_objects(dev_priv); diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index a0da5944dd33..01edc3c7eb21 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -65,8 +65,6 @@ static void mock_device_release(struct drm_device *dev) mock_engine_free(engine); i915_gem_driver_release__contexts(i915); - intel_timelines_fini(i915); - drain_workqueue(i915->wq); i915_gem_drain_freed_objects(i915); @@ -180,8 +178,6 @@ struct drm_i915_private *mock_gem_device(void) mock_init_contexts(i915); - intel_timelines_init(i915); - mock_init_ggtt(i915, &i915->ggtt); i915->gt.ggtt = &i915->ggtt; @@ -207,7 +203,6 @@ err_context: err_engine: mock_engine_free(i915->engine[RCS0]); err_unlock: - intel_timelines_fini(i915); destroy_workqueue(i915->wq); err_drv: intel_memory_regions_driver_release(i915); -- cgit v1.2.3 From 797a615357ac0feb79c9ce41f5eaac3eb738a51f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 14:10:06 +0000 Subject: drm/i915/gt: Call intel_gt_sanitize() directly Assume all responsibility for operating on the HW to sanitize the GT state upon load/resume in intel_gt_sanitize() itself. Signed-off-by: Chris Wilson Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191101141009.15581-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_pm.c | 5 ---- drivers/gpu/drm/i915/gt/intel_gt.c | 6 ++-- drivers/gpu/drm/i915/gt/intel_gt.h | 2 +- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 36 ++++++++++++++++++++++- drivers/gpu/drm/i915/i915_drv.c | 8 ++--- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_gem.c | 37 ------------------------ drivers/gpu/drm/i915/selftests/i915_gem.c | 1 - drivers/gpu/drm/i915/selftests/mock_gem_device.c | 1 - drivers/gpu/drm/i915/selftests/mock_gtt.c | 3 +- 10 files changed, 43 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c index c99bb94fe41e..e2ee9c04ece8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c @@ -74,7 +74,6 @@ void i915_gem_suspend(struct drm_i915_private *i915) * not rely on its state. */ intel_gt_suspend(&i915->gt); - intel_uc_suspend(&i915->gt.uc); i915_gem_drain_freed_objects(i915); } @@ -140,8 +139,6 @@ void i915_gem_suspend_late(struct drm_i915_private *i915) list_splice_tail(&keep, *phase); } spin_unlock_irqrestore(&i915->mm.obj_lock, flags); - - i915_gem_sanitize(i915); } void i915_gem_resume(struct drm_i915_private *i915) @@ -161,8 +158,6 @@ void i915_gem_resume(struct drm_i915_private *i915) if (intel_gt_resume(&i915->gt)) goto err_wedged; - intel_uc_resume(&i915->gt.uc); - /* Always reload a context for powersaving. */ if (!switch_to_kernel_context_sync(&i915->gt)) goto err_wedged; diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 15c0a0dfc424..c39b21c8d328 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -32,9 +32,11 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) intel_uc_init_early(>->uc); } -void intel_gt_init_hw_early(struct drm_i915_private *i915) +void intel_gt_init_hw_early(struct intel_gt *gt, struct i915_ggtt *ggtt) { - i915->gt.ggtt = &i915->ggtt; + gt->ggtt = ggtt; + + intel_gt_sanitize(gt, false); } static void init_unused_ring(struct intel_gt *gt, u32 base) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index 5b6effed3713..5436f8c30708 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -28,7 +28,7 @@ static inline struct intel_gt *huc_to_gt(struct intel_huc *huc) } void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915); -void intel_gt_init_hw_early(struct drm_i915_private *i915); +void intel_gt_init_hw_early(struct intel_gt *gt, struct i915_ggtt *ggtt); int __must_check intel_gt_init_hw(struct intel_gt *gt); int intel_gt_init(struct intel_gt *gt); void intel_gt_driver_register(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 32becf15d4e0..1679f4f78d65 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -118,8 +118,22 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force) { struct intel_engine_cs *engine; enum intel_engine_id id; + intel_wakeref_t wakeref; - GEM_TRACE("\n"); + GEM_TRACE("force:%s\n", yesno(force)); + + /* Use a raw wakeref to avoid calling intel_display_power_get early */ + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); + + /* + * As we have just resumed the machine and woken the device up from + * deep PCI sleep (presumably D3_cold), assume the HW has been reset + * back to defaults, recovering from whatever wedged state we left it + * in and so worth trying to use the device once more. + */ + if (intel_gt_is_wedged(gt)) + intel_gt_unset_wedged(gt); intel_uc_sanitize(>->uc); @@ -127,6 +141,8 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force) if (engine->reset.prepare) engine->reset.prepare(engine); + intel_uc_reset_prepare(>->uc); + if (reset_engines(gt) || force) { for_each_engine(engine, gt, id) __intel_engine_reset(engine, false); @@ -135,6 +151,9 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force) for_each_engine(engine, gt, id) if (engine->reset.finish) engine->reset.finish(engine); + + intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); + intel_runtime_pm_put(gt->uncore->rpm, wakeref); } void intel_gt_pm_fini(struct intel_gt *gt) @@ -148,6 +167,8 @@ int intel_gt_resume(struct intel_gt *gt) enum intel_engine_id id; int err = 0; + GEM_TRACE("\n"); + /* * After resume, we may need to poke into the pinned kernel * contexts to paper over any damage caused by the sudden suspend. @@ -186,6 +207,9 @@ int intel_gt_resume(struct intel_gt *gt) } intel_rc6_enable(>->rc6); + + intel_uc_resume(>->uc); + intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); intel_gt_pm_put(gt); @@ -212,20 +236,30 @@ void intel_gt_suspend(struct intel_gt *gt) /* We expect to be idle already; but also want to be independent */ wait_for_idle(gt); + intel_uc_suspend(>->uc); + with_intel_runtime_pm(gt->uncore->rpm, wakeref) { intel_rps_disable(>->rps); intel_rc6_disable(>->rc6); intel_llc_disable(>->llc); } + + intel_gt_sanitize(gt, false); + + GEM_TRACE("\n"); } void intel_gt_runtime_suspend(struct intel_gt *gt) { intel_uc_runtime_suspend(>->uc); + + GEM_TRACE("\n"); } int intel_gt_runtime_resume(struct intel_gt *gt) { + GEM_TRACE("\n"); + intel_gt_init_swizzling(gt); return intel_uc_runtime_resume(>->uc); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3340485c12e3..ccb5b566795f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -603,8 +603,6 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) if (ret) goto err_uncore; - i915_gem_init_mmio(dev_priv); - return 0; err_uncore: @@ -1177,7 +1175,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) if (ret) goto err_ggtt; - intel_gt_init_hw_early(dev_priv); + intel_gt_init_hw_early(&dev_priv->gt, &dev_priv->ggtt); ret = i915_ggtt_enable_hw(dev_priv); if (ret) { @@ -1821,7 +1819,7 @@ static int i915_drm_resume(struct drm_device *dev) disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); - i915_gem_sanitize(dev_priv); + intel_gt_sanitize(&dev_priv->gt, true); ret = i915_ggtt_enable_hw(dev_priv); if (ret) @@ -1952,8 +1950,6 @@ static int i915_drm_resume_early(struct drm_device *dev) intel_power_domains_resume(dev_priv); - intel_gt_sanitize(&dev_priv->gt, true); - enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); return ret; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c84c41159f2b..7e0f67babe20 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1785,7 +1785,6 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, /* i915_gem.c */ int i915_gem_init_userptr(struct drm_i915_private *dev_priv); void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv); -void i915_gem_sanitize(struct drm_i915_private *i915); void i915_gem_init_early(struct drm_i915_private *dev_priv); void i915_gem_cleanup_early(struct drm_i915_private *dev_priv); int i915_gem_freeze(struct drm_i915_private *dev_priv); @@ -1869,7 +1868,6 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error, return atomic_read(&error->reset_engine_count[engine->uabi_class]); } -void i915_gem_init_mmio(struct drm_i915_private *i915); int __must_check i915_gem_init(struct drm_i915_private *dev_priv); void i915_gem_driver_register(struct drm_i915_private *i915); void i915_gem_driver_unregister(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index af2cdc8eddeb..143a8952b736 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1039,38 +1039,6 @@ out: return err; } -void i915_gem_sanitize(struct drm_i915_private *i915) -{ - intel_wakeref_t wakeref; - - GEM_TRACE("\n"); - - wakeref = intel_runtime_pm_get(&i915->runtime_pm); - intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL); - - /* - * As we have just resumed the machine and woken the device up from - * deep PCI sleep (presumably D3_cold), assume the HW has been reset - * back to defaults, recovering from whatever wedged state we left it - * in and so worth trying to use the device once more. - */ - if (intel_gt_is_wedged(&i915->gt)) - intel_gt_unset_wedged(&i915->gt); - - /* - * If we inherit context state from the BIOS or earlier occupants - * of the GPU, the GPU may be in an inconsistent state when we - * try to take over. The only way to remove the earlier state - * is by resetting. However, resetting on earlier gen is tricky as - * it may impact the display and we are uncertain about the stability - * of the reset, so this could be applied to even earlier gen. - */ - intel_gt_sanitize(&i915->gt, false); - - intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL); - intel_runtime_pm_put(&i915->runtime_pm, wakeref); -} - static int __intel_engines_record_defaults(struct intel_gt *gt) { struct i915_request *requests[I915_NUM_ENGINES] = {}; @@ -1409,11 +1377,6 @@ void i915_gem_driver_release(struct drm_i915_private *dev_priv) WARN_ON(!list_empty(&dev_priv->gem.contexts.list)); } -void i915_gem_init_mmio(struct drm_i915_private *i915) -{ - i915_gem_sanitize(i915); -} - static void i915_gem_init__mm(struct drm_i915_private *i915) { spin_lock_init(&i915->mm.obj_lock); diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index e378543ed453..d83f6bf6d9d4 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -124,7 +124,6 @@ static void pm_resume(struct drm_i915_private *i915) */ with_intel_runtime_pm(&i915->runtime_pm, wakeref) { intel_gt_sanitize(&i915->gt, false); - i915_gem_sanitize(i915); i915_gem_restore_gtt_mappings(i915); i915_gem_restore_fences(&i915->ggtt); diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 01edc3c7eb21..e58b0bc9cdb6 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -179,7 +179,6 @@ struct drm_i915_private *mock_gem_device(void) mock_init_contexts(i915); mock_init_ggtt(i915, &i915->ggtt); - i915->gt.ggtt = &i915->ggtt; mkwrite_device_info(i915)->engine_mask = BIT(0); diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index 9ec93dc27fb5..20ac3844edec 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -118,8 +118,7 @@ void mock_init_ggtt(struct drm_i915_private *i915, struct i915_ggtt *ggtt) ggtt->vm.vma_ops.clear_pages = clear_pages; i915_address_space_init(&ggtt->vm, VM_CLASS_GGTT); - - intel_gt_init_hw_early(i915); + i915->gt.ggtt = ggtt; } void mock_fini_ggtt(struct i915_ggtt *ggtt) -- cgit v1.2.3 From c8f6cfc56fc86999725e71a19d91269482bd2c01 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 14:10:07 +0000 Subject: drm/i915/gem: Leave reloading kernel context on resume to GT As we already do reload the kernel context in intel_gt_resume, repeating that action inside i915_gem_resume() as well is redundant. Signed-off-by: Chris Wilson Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191101141009.15581-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_pm.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c index e2ee9c04ece8..64dd04ae3d57 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c @@ -11,32 +11,6 @@ #include "i915_drv.h" -static bool switch_to_kernel_context_sync(struct intel_gt *gt) -{ - bool result = !intel_gt_is_wedged(gt); - - if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) { - /* XXX hide warning from gem_eio */ - if (i915_modparams.reset) { - dev_err(gt->i915->drm.dev, - "Failed to idle engines, declaring wedged!\n"); - GEM_TRACE_DUMP(); - } - - /* - * Forcibly cancel outstanding work and leave - * the gpu quiet. - */ - intel_gt_set_wedged(gt); - result = false; - } - - if (intel_gt_pm_wait_for_idle(gt)) - result = false; - - return result; -} - static void user_forcewake(struct intel_gt *gt, bool suspend) { int count = atomic_read(>->user_wakeref); @@ -158,10 +132,6 @@ void i915_gem_resume(struct drm_i915_private *i915) if (intel_gt_resume(&i915->gt)) goto err_wedged; - /* Always reload a context for powersaving. */ - if (!switch_to_kernel_context_sync(&i915->gt)) - goto err_wedged; - user_forcewake(&i915->gt, false); out_unlock: -- cgit v1.2.3 From 9ab3fe2d7dc39b088591b0121f041cbfd6bb1ef8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 14:10:08 +0000 Subject: drm/i915/gt: Move user_forcewake application to GT We already track the debugfs user_forcewake on the GT, so it is natural to pull the suspend/resume handling under gt/ as well. Signed-off-by: Chris Wilson Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191101141009.15581-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_pm.c | 22 ---------------------- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c index 64dd04ae3d57..6779ab34101b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c @@ -11,24 +11,6 @@ #include "i915_drv.h" -static void user_forcewake(struct intel_gt *gt, bool suspend) -{ - int count = atomic_read(>->user_wakeref); - - /* Inside suspend/resume so single threaded, no races to worry about. */ - if (likely(!count)) - return; - - intel_gt_pm_get(gt); - if (suspend) { - GEM_BUG_ON(count > atomic_read(>->wakeref.count)); - atomic_sub(count, >->wakeref.count); - } else { - atomic_add(count, >->wakeref.count); - } - intel_gt_pm_put(gt); -} - void i915_gem_suspend(struct drm_i915_private *i915) { GEM_TRACE("\n"); @@ -36,8 +18,6 @@ void i915_gem_suspend(struct drm_i915_private *i915) intel_wakeref_auto(&i915->ggtt.userfault_wakeref, 0); flush_workqueue(i915->wq); - user_forcewake(&i915->gt, true); - /* * We have to flush all the executing contexts to main memory so * that they can saved in the hibernation image. To ensure the last @@ -132,8 +112,6 @@ void i915_gem_resume(struct drm_i915_private *i915) if (intel_gt_resume(&i915->gt)) goto err_wedged; - user_forcewake(&i915->gt, false); - out_unlock: intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL); return; diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 1679f4f78d65..11661de8c40b 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -18,6 +18,24 @@ #include "intel_rps.h" #include "intel_wakeref.h" +static void user_forcewake(struct intel_gt *gt, bool suspend) +{ + int count = atomic_read(>->user_wakeref); + + /* Inside suspend/resume so single threaded, no races to worry about. */ + if (likely(!count)) + return; + + intel_gt_pm_get(gt); + if (suspend) { + GEM_BUG_ON(count > atomic_read(>->wakeref.count)); + atomic_sub(count, >->wakeref.count); + } else { + atomic_add(count, >->wakeref.count); + } + intel_gt_pm_put(gt); +} + static int __gt_unpark(struct intel_wakeref *wf) { struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref); @@ -210,6 +228,8 @@ int intel_gt_resume(struct intel_gt *gt) intel_uc_resume(>->uc); + user_forcewake(gt, false); + intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); intel_gt_pm_put(gt); @@ -233,6 +253,8 @@ void intel_gt_suspend(struct intel_gt *gt) { intel_wakeref_t wakeref; + user_forcewake(gt, true); + /* We expect to be idle already; but also want to be independent */ wait_for_idle(gt); -- cgit v1.2.3 From c601cb2135fda0b5fb9d08153b0125fcb153c7e0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 14:10:09 +0000 Subject: drm/i915: Defer rc6 shutdown to suspend_late Currently we shutdown rc6 during i915_gem_resume() but this is called during the preparation phase (i915_drm_prepare) for all suspend paths, but we only want to shutdown rc6 for S3+. Move the actual shutdown to i915_gem_suspend_late(). We then need to differentiate between suspend targets, to distinguish S0 (s2idle) where the device is kept awake but needs to be in a low power mode (the same as runtime suspend) from the device suspend levels where we lose control of HW and so must disable any HW access to dangling memory. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111909 Fixes: c113236718e8 ("drm/i915: Extract GT render sleep (rc6) management") Testcase: igt/gem_exec_suspend/power-S0 Signed-off-by: Chris Wilson Cc: Andi Shyti Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191101141009.15581-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_pm.c | 4 ++- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 44 +++++++++++++++++++++++++++----- drivers/gpu/drm/i915/gt/intel_gt_pm.h | 3 ++- drivers/gpu/drm/i915/gt/intel_rc6.c | 5 ++++ drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 2 +- 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c index 6779ab34101b..f88ee1317bb4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c @@ -27,7 +27,7 @@ void i915_gem_suspend(struct drm_i915_private *i915) * state. Fortunately, the kernel_context is disposable and we do * not rely on its state. */ - intel_gt_suspend(&i915->gt); + intel_gt_suspend_prepare(&i915->gt); i915_gem_drain_freed_objects(i915); } @@ -69,6 +69,8 @@ void i915_gem_suspend_late(struct drm_i915_private *i915) * machine in an unusable condition. */ + intel_gt_suspend_late(&i915->gt); + spin_lock_irqsave(&i915->mm.obj_lock, flags); for (phase = phases; *phase; phase++) { LIST_HEAD(keep); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 11661de8c40b..6374744bb65e 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -4,6 +4,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include "i915_drv.h" #include "i915_globals.h" #include "i915_params.h" @@ -236,8 +238,11 @@ int intel_gt_resume(struct intel_gt *gt) return err; } -static void wait_for_idle(struct intel_gt *gt) +static void wait_for_suspend(struct intel_gt *gt) { + if (!intel_gt_pm_is_awake(gt)) + return; + if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) { /* * Forcibly cancel outstanding work and leave @@ -246,19 +251,46 @@ static void wait_for_idle(struct intel_gt *gt) intel_gt_set_wedged(gt); } + GEM_BUG_ON(atomic_read(>->user_wakeref)); intel_gt_pm_wait_for_idle(gt); } -void intel_gt_suspend(struct intel_gt *gt) +void intel_gt_suspend_prepare(struct intel_gt *gt) { - intel_wakeref_t wakeref; - user_forcewake(gt, true); + wait_for_suspend(gt); + + intel_uc_suspend(>->uc); +} + +static suspend_state_t pm_suspend_target(void) +{ +#if IS_ENABLED(CONFIG_PM_SLEEP) + return pm_suspend_target_state; +#else + return PM_SUSPEND_TO_IDLE; +#endif +} + +void intel_gt_suspend_late(struct intel_gt *gt) +{ + intel_wakeref_t wakeref; /* We expect to be idle already; but also want to be independent */ - wait_for_idle(gt); + wait_for_suspend(gt); - intel_uc_suspend(>->uc); + /* + * On disabling the device, we want to turn off HW access to memory + * that we no longer own. + * + * However, not all suspend-states disable the device. S0 (s2idle) + * is effectively runtime-suspend, the device is left powered on + * but needs to be put into a low power state. We need to keep + * powermanagement enabled, but we also retain system state and so + * it remains safe to keep on using our allocated memory. + */ + if (pm_suspend_target() == PM_SUSPEND_TO_IDLE) + return; with_intel_runtime_pm(gt->uncore->rpm, wakeref) { intel_rps_disable(>->rps); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index d924c984c74d..b3e17399be9b 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -43,8 +43,9 @@ void intel_gt_pm_fini(struct intel_gt *gt); void intel_gt_sanitize(struct intel_gt *gt, bool force); +void intel_gt_suspend_prepare(struct intel_gt *gt); +void intel_gt_suspend_late(struct intel_gt *gt); int intel_gt_resume(struct intel_gt *gt); -void intel_gt_suspend(struct intel_gt *gt); void intel_gt_runtime_suspend(struct intel_gt *gt); int intel_gt_runtime_resume(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 70f0e01a38b9..5ad4a92a9582 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -525,6 +525,11 @@ void intel_rc6_init(struct intel_rc6 *rc6) void intel_rc6_sanitize(struct intel_rc6 *rc6) { + if (rc6->enabled) { /* unbalanced suspend/resume */ + rpm_get(rc6); + rc6->enabled = false; + } + if (rc6->supported) __intel_rc6_disable(rc6); } diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c index 5d429037cdad..3d4e6a008af8 100644 --- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c @@ -15,7 +15,7 @@ static int live_gt_resume(void *arg) /* Do several suspend/resume cycles to check we don't explode! */ do { - intel_gt_suspend(gt); + intel_gt_suspend_late(gt); if (gt->rc6.enabled) { pr_err("rc6 still enabled after suspend!\n"); -- cgit v1.2.3 From 833e979db36c0202f21e1e0bdd7339a27e50b8e3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 17:44:05 +0000 Subject: drm/i915/selftests: Add intel_gt_suspend_prepare Call suspend_prepare first so that we don't leave GuC so confused. Signed-off-by: Chris Wilson Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191101174405.7389-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c index 3d4e6a008af8..d1752f15702a 100644 --- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c @@ -15,6 +15,7 @@ static int live_gt_resume(void *arg) /* Do several suspend/resume cycles to check we don't explode! */ do { + intel_gt_suspend_prepare(gt); intel_gt_suspend_late(gt); if (gt->rc6.enabled) { -- cgit v1.2.3 From 9278bbb6e43cde306f07f9a60274195b5b24f90a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 19:21:16 +0000 Subject: drm/i915/perf: Reverse a ternary to make sparse happy Avoid drivers/gpu/drm/i915/i915_perf.c:2442:85: warning: dubious: x | !y simply by inverting the predicate and reversing the ternary. v2: Move the long lines into their own function so there is no confusion on operator precedence. Signed-off-by: Chris Wilson Cc: Umesh Nerlige Ramappa Cc: Lionel Landwerlin Reviewed-by: Umesh Nerlige Ramappa Link: https://patchwork.freedesktop.org/patch/msgid/20191101192116.12647-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_perf.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index a8c2318d3d5e..2c380aba1ce9 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2428,6 +2428,13 @@ static int gen8_enable_metric_set(struct i915_perf_stream *stream) return emit_oa_config(stream, oa_config, oa_context(stream)); } +static u32 oag_report_ctx_switches(const struct i915_perf_stream *stream) +{ + return _MASKED_FIELD(GEN12_OAG_OA_DEBUG_DISABLE_CTX_SWITCH_REPORTS, + (stream->sample_flags & SAMPLE_OA_REPORT) ? + 0 : GEN12_OAG_OA_DEBUG_DISABLE_CTX_SWITCH_REPORTS); +} + static int gen12_enable_metric_set(struct i915_perf_stream *stream) { struct intel_uncore *uncore = stream->uncore; @@ -2441,12 +2448,10 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream) _MASKED_BIT_ENABLE(GEN12_OAG_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS | GEN12_OAG_OA_DEBUG_INCLUDE_CLK_RATIO) | /* - * If the user didn't require OA reports, instruct the - * hardware not to emit ctx switch reports. + * If the user didn't require OA reports, instruct + * the hardware not to emit ctx switch reports. */ - !(stream->sample_flags & SAMPLE_OA_REPORT) ? - _MASKED_BIT_ENABLE(GEN12_OAG_OA_DEBUG_DISABLE_CTX_SWITCH_REPORTS) : - _MASKED_BIT_DISABLE(GEN12_OAG_OA_DEBUG_DISABLE_CTX_SWITCH_REPORTS)); + oag_report_ctx_switches(stream)); intel_uncore_write(uncore, GEN12_OAG_OAGLBCTXCTRL, periodic ? (GEN12_OAG_OAGLBCTXCTRL_COUNTER_RESUME | -- cgit v1.2.3 From 38813767c7c5d9f8e0bd6b14136add861cc79b33 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 18:10:22 +0000 Subject: drm/i915/selftests: Flush all active callbacks Flushing the outer i915_active is not enough, as we need the barrier to be applied across all the active dma_fence callbacks. So we must serialise with each outstanding fence. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112096 References: f79520bb3337 ("drm/i915/selftests: Synchronize checking active status with retirement") Signed-off-by: Chris Wilson Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191101181022.25633-1-chris@chris-wilson.co.uk --- .../gpu/drm/i915/gt/selftest_engine_heartbeat.c | 4 +-- drivers/gpu/drm/i915/i915_active.h | 1 + drivers/gpu/drm/i915/selftests/i915_active.c | 33 ++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c index e864406bd2d9..f665a0e23c61 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c @@ -53,9 +53,7 @@ static struct pulse *pulse_create(void) static void pulse_unlock_wait(struct pulse *p) { - mutex_lock(&p->active.mutex); - mutex_unlock(&p->active.mutex); - flush_work(&p->active.work); + i915_active_unlock_wait(&p->active); } static int __live_idle_pulse(struct intel_engine_cs *engine, diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index 44859356ce97..5dd62323b92a 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -215,5 +215,6 @@ void i915_active_acquire_barrier(struct i915_active *ref); void i915_request_add_active_barriers(struct i915_request *rq); void i915_active_print(struct i915_active *ref, struct drm_printer *m); +void i915_active_unlock_wait(struct i915_active *ref); #endif /* _I915_ACTIVE_H_ */ diff --git a/drivers/gpu/drm/i915/selftests/i915_active.c b/drivers/gpu/drm/i915/selftests/i915_active.c index 260b0ee5d1e3..f3fa05c78d78 100644 --- a/drivers/gpu/drm/i915/selftests/i915_active.c +++ b/drivers/gpu/drm/i915/selftests/i915_active.c @@ -250,3 +250,36 @@ void i915_active_print(struct i915_active *ref, struct drm_printer *m) i915_active_release(ref); } } + +static void spin_unlock_wait(spinlock_t *lock) +{ + spin_lock_irq(lock); + spin_unlock_irq(lock); +} + +void i915_active_unlock_wait(struct i915_active *ref) +{ + if (i915_active_acquire_if_busy(ref)) { + struct active_node *it, *n; + + rcu_read_lock(); + rbtree_postorder_for_each_entry_safe(it, n, &ref->tree, node) { + struct dma_fence *f; + + /* Wait for all active callbacks */ + f = rcu_dereference(it->base.fence); + if (f) + spin_unlock_wait(f->lock); + } + rcu_read_unlock(); + + i915_active_release(ref); + } + + /* And wait for the retire callback */ + mutex_lock(&ref->mutex); + mutex_unlock(&ref->mutex); + + /* ... which may have been on a thread instead */ + flush_work(&ref->work); +} -- cgit v1.2.3 From b0b10248866455a19b4dd4ac186eb131d83df452 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 2 Nov 2019 12:57:39 +0000 Subject: drm/i915/execlists: Verify context register state before execution Check that the context's ring register state still matches our expectations prior to execution. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191102125739.24626-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 71 ++++++++++++++++++++++++++------- drivers/gpu/drm/i915/gt/intel_lrc_reg.h | 4 +- drivers/gpu/drm/i915/gt/selftest_lrc.c | 6 +-- 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 51aef2a233cb..f2b31c96a309 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -990,6 +990,58 @@ static void intel_engine_context_out(struct intel_engine_cs *engine) write_sequnlock_irqrestore(&engine->stats.lock, flags); } +static int lrc_ring_mi_mode(const struct intel_engine_cs *engine) +{ + if (INTEL_GEN(engine->i915) >= 12) + return 0x60; + else if (INTEL_GEN(engine->i915) >= 9) + return 0x54; + else if (engine->class == RENDER_CLASS) + return 0x58; + else + return -1; +} + +static void +execlists_check_context(const struct intel_context *ce, + const struct intel_engine_cs *engine) +{ + const struct intel_ring *ring = ce->ring; + u32 *regs = ce->lrc_reg_state; + bool valid = true; + int x; + + if (regs[CTX_RING_START] != i915_ggtt_offset(ring->vma)) { + pr_err("%s: context submitted with incorrect RING_START [%08x], expected %08x\n", + engine->name, + regs[CTX_RING_START], + i915_ggtt_offset(ring->vma)); + regs[CTX_RING_START] = i915_ggtt_offset(ring->vma); + valid = false; + } + + if ((regs[CTX_RING_CTL] & ~(RING_WAIT | RING_WAIT_SEMAPHORE)) != + (RING_CTL_SIZE(ring->size) | RING_VALID)) { + pr_err("%s: context submitted with incorrect RING_CTL [%08x], expected %08x\n", + engine->name, + regs[CTX_RING_CTL], + (u32)(RING_CTL_SIZE(ring->size) | RING_VALID)); + regs[CTX_RING_CTL] = RING_CTL_SIZE(ring->size) | RING_VALID; + valid = false; + } + + x = lrc_ring_mi_mode(engine); + if (x != -1 && regs[x + 1] & (regs[x + 1] >> 16) & STOP_RING) { + pr_err("%s: context submitted with STOP_RING [%08x] in RING_MI_MODE\n", + engine->name, regs[x + 1]); + regs[x + 1] &= ~STOP_RING; + regs[x + 1] |= STOP_RING << 16; + valid = false; + } + + WARN_ONCE(!valid, "Invalid lrc state found before submission\n"); +} + static inline struct intel_engine_cs * __execlists_schedule_in(struct i915_request *rq) { @@ -998,6 +1050,9 @@ __execlists_schedule_in(struct i915_request *rq) intel_context_get(ce); + if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) + execlists_check_context(ce, rq->engine); + if (ce->tag) { /* Use a fixed tag for OA and friends */ ce->lrc_desc |= (u64)ce->tag << 32; @@ -2353,7 +2408,7 @@ __execlists_update_reg_state(const struct intel_context *ce, GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->head)); GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->tail)); - regs[CTX_RING_BUFFER_START] = i915_ggtt_offset(ring->vma); + regs[CTX_RING_START] = i915_ggtt_offset(ring->vma); regs[CTX_RING_HEAD] = ring->head; regs[CTX_RING_TAIL] = ring->tail; @@ -2940,18 +2995,6 @@ static void reset_csb_pointers(struct intel_engine_cs *engine) &execlists->csb_status[reset_value]); } -static int lrc_ring_mi_mode(const struct intel_engine_cs *engine) -{ - if (INTEL_GEN(engine->i915) >= 12) - return 0x60; - else if (INTEL_GEN(engine->i915) >= 9) - return 0x54; - else if (engine->class == RENDER_CLASS) - return 0x58; - else - return -1; -} - static void __execlists_reset_reg_state(const struct intel_context *ce, const struct intel_engine_cs *engine) { @@ -3885,7 +3928,7 @@ static void init_common_reg_state(u32 * const regs, _MASKED_BIT_DISABLE(CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT | CTX_CTRL_RS_CTX_ENABLE); - regs[CTX_RING_BUFFER_CONTROL] = RING_CTL_SIZE(ring->size) | RING_VALID; + regs[CTX_RING_CTL] = RING_CTL_SIZE(ring->size) | RING_VALID; regs[CTX_BB_STATE] = RING_BB_PPGTT; } diff --git a/drivers/gpu/drm/i915/gt/intel_lrc_reg.h b/drivers/gpu/drm/i915/gt/intel_lrc_reg.h index 06ab0276e10e..08a3be65f700 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc_reg.h +++ b/drivers/gpu/drm/i915/gt/intel_lrc_reg.h @@ -13,8 +13,8 @@ #define CTX_CONTEXT_CONTROL (0x02 + 1) #define CTX_RING_HEAD (0x04 + 1) #define CTX_RING_TAIL (0x06 + 1) -#define CTX_RING_BUFFER_START (0x08 + 1) -#define CTX_RING_BUFFER_CONTROL (0x0a + 1) +#define CTX_RING_START (0x08 + 1) +#define CTX_RING_CTL (0x0a + 1) #define CTX_BB_STATE (0x10 + 1) #define CTX_BB_PER_CTX_PTR (0x18 + 1) #define CTX_PDP3_UDW (0x24 + 1) diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index eb71ac2f992c..d1ed3c0f851c 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -3207,12 +3207,12 @@ static int live_lrc_fixed(void *arg) } tbl[] = { { i915_mmio_reg_offset(RING_START(engine->mmio_base)), - CTX_RING_BUFFER_START - 1, + CTX_RING_START - 1, "RING_START" }, { i915_mmio_reg_offset(RING_CTL(engine->mmio_base)), - CTX_RING_BUFFER_CONTROL - 1, + CTX_RING_CTL - 1, "RING_CTL" }, { @@ -3231,7 +3231,7 @@ static int live_lrc_fixed(void *arg) "RING_MI_MODE" }, { - engine->mmio_base + 0x110, + i915_mmio_reg_offset(RING_BBSTATE(engine->mmio_base)), CTX_BB_STATE - 1, "BB_STATE" }, -- cgit v1.2.3 From 38098750719cb5f3f8bf7587ed5ba2f7a0b4dd87 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Nov 2019 08:29:19 +0000 Subject: drm/i915/execlists: Ignore the inactive kernel context in assert_pending_valid Filter out warnings for the kernel context that is used to flush inactive contexts, as they do no not pose a risk. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191101082919.21122-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index f2b31c96a309..8d79a965f341 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1291,7 +1291,8 @@ assert_pending_valid(const struct intel_engine_execlists *execlists, for (port = execlists->pending; (rq = *port); port++) { if (ce == rq->hw_context) { - GEM_TRACE_ERR("Duplicate context in pending[%zd]\n", + GEM_TRACE_ERR("Dup context:%llx in pending[%zd]\n", + ce->timeline->fence_context, port - execlists->pending); return false; } @@ -1300,20 +1301,24 @@ assert_pending_valid(const struct intel_engine_execlists *execlists, if (i915_request_completed(rq)) continue; - if (i915_active_is_idle(&ce->active)) { - GEM_TRACE_ERR("Inactive context in pending[%zd]\n", + if (i915_active_is_idle(&ce->active) && + !i915_gem_context_is_kernel(ce->gem_context)) { + GEM_TRACE_ERR("Inactive context:%llx in pending[%zd]\n", + ce->timeline->fence_context, port - execlists->pending); return false; } if (!i915_vma_is_pinned(ce->state)) { - GEM_TRACE_ERR("Unpinned context in pending[%zd]\n", + GEM_TRACE_ERR("Unpinned context:%llx in pending[%zd]\n", + ce->timeline->fence_context, port - execlists->pending); return false; } if (!i915_vma_is_pinned(ce->ring->vma)) { - GEM_TRACE_ERR("Unpinned ringbuffer in pending[%zd]\n", + GEM_TRACE_ERR("Unpinned ring:%llx in pending[%zd]\n", + ce->timeline->fence_context, port - execlists->pending); return false; } -- cgit v1.2.3 From 83c55ee82f3ac5a1c36dab9f7150554c4da773a8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Nov 2019 09:50:38 +0000 Subject: drm/i915/gt: Drop false assertion on user_forcewake The counter is removed from the pm wakeref count, but it remains intact so that we can restore it upon resume. Ergo inside suspend, it may have a value. Signed-off-by: Chris Wilson Acked-by: Andi Shyti Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191104090158.2959-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 6374744bb65e..060a27d9af34 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -251,7 +251,6 @@ static void wait_for_suspend(struct intel_gt *gt) intel_gt_set_wedged(gt); } - GEM_BUG_ON(atomic_read(>->user_wakeref)); intel_gt_pm_wait_for_idle(gt); } -- cgit v1.2.3 From 7d148635253328dda7cfe55d57e3c828e9564427 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Nov 2019 16:23:05 +0000 Subject: drm/i915: Protect request peeking with RCU Since the execlists_active() is no longer protected by the engine->active.lock, we need to protect the request pointer with RCU to prevent it being freed as we evaluate whether or not we need to preempt. Fixes: df403069029d ("drm/i915/execlists: Lift process_csb() out of the irq-off spinlock") Fixes: 13ed13a4dcbf ("drm/i915: Don't set queue_priority_hint if we don't kick the submission") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191104090158.2959-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_scheduler.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index d2edb527dcb8..010d67f48ad9 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.c +++ b/drivers/gpu/drm/i915/i915_scheduler.c @@ -202,21 +202,26 @@ static void kick_submission(struct intel_engine_cs *engine, if (prio <= engine->execlists.queue_priority_hint) return; + rcu_read_lock(); + /* Nothing currently active? We're overdue for a submission! */ inflight = execlists_active(&engine->execlists); if (!inflight) - return; + goto unlock; /* * If we are already the currently executing context, don't * bother evaluating if we should preempt ourselves. */ if (inflight->hw_context == rq->hw_context) - return; + goto unlock; engine->execlists.queue_priority_hint = prio; if (need_preempt(prio, rq_prio(inflight))) tasklet_hi_schedule(&engine->execlists.tasklet); + +unlock: + rcu_read_unlock(); } static void __i915_schedule(struct i915_sched_node *node, -- cgit v1.2.3 From c4a774c4192c78200a3b6c564c7eeb993b98b225 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 1 Nov 2019 15:43:33 +0200 Subject: drm/i915: add for_each_port() and use it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add another for_each style macro to the pile of custom looping macros. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191101134333.11612-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_display.h | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 63c1bd4c2954..a03f56b7b4ef 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1246,7 +1246,7 @@ static enum port get_port_by_ddc_pin(struct drm_i915_private *i915, u8 ddc_pin) const struct ddi_vbt_port_info *info; enum port port; - for (port = PORT_A; port < I915_MAX_PORTS; port++) { + for_each_port(port) { info = &i915->vbt.ddi_port_info[port]; if (info->child && ddc_pin == info->alternate_ddc_pin) @@ -1297,7 +1297,7 @@ static enum port get_port_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch) const struct ddi_vbt_port_info *info; enum port port; - for (port = PORT_A; port < I915_MAX_PORTS; port++) { + for_each_port(port) { info = &i915->vbt.ddi_port_info[port]; if (info->child && aux_ch == info->alternate_aux_channel) @@ -1722,7 +1722,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) !HAS_PCH_SPLIT(dev_priv)); DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq); - for (port = PORT_A; port < I915_MAX_PORTS; port++) { + for_each_port(port) { struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; @@ -1736,7 +1736,7 @@ init_vbt_missing_defaults(struct drm_i915_private *dev_priv) { enum port port; - for (port = PORT_A; port < I915_MAX_PORTS; port++) { + for_each_port(port) { struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; enum phy phy = intel_port_to_phy(dev_priv, port); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 476bc71e6a83..397966147561 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -333,8 +333,11 @@ enum phy_fia { (__s) < RUNTIME_INFO(__dev_priv)->num_sprites[(__p)]; \ (__s)++) -#define for_each_port_masked(__port, __ports_mask) \ - for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++) \ +#define for_each_port(__port) \ + for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++) + +#define for_each_port_masked(__port, __ports_mask) \ + for_each_port(__port) \ for_each_if((__ports_mask) & BIT(__port)) #define for_each_phy_masked(__phy, __phys_mask) \ -- cgit v1.2.3 From 0a1f57b86c0b1bdc522ed5c96afdb67931e1d495 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Nov 2019 13:53:07 +0000 Subject: drm/i915/execlists: Reset CSB pointers by mmio as well Sometimes Icelake forgets to reset the CSB pointers on a GPU reset, leading to it carry on updating the old tail of the buffer. <0>[ 618.138490] i915_sel-5636 3d..1 673425465us : trace_ports: vecs0: submit { 14de2:504, 0:0 } <0>[ 618.138490] i915_sel-5636 3.... 673425493us : intel_engine_reset: vecs0 flags=100 <0>[ 618.138490] i915_sel-5636 3.... 673425493us : execlists_reset_prepare: vecs0: depth<-0 <0>[ 618.138490] i915_sel-5636 3.... 673425493us : intel_engine_stop_cs: vecs0 <0>[ 618.138490] i915_sel-5636 3.... 673425523us : __intel_gt_reset: engine_mask=40 <0>[ 618.138490] i915_sel-5636 3.... 673425568us : execlists_reset: vecs0 <0>[ 618.138490] i915_sel-5636 3d..1 673425568us : process_csb: vecs0 cs-irq head=1, tail=2 <0>[ 618.138490] i915_sel-5636 3d..1 673425568us : process_csb: vecs0 csb[2]: status=0x00000001:0x40000000 <0>[ 618.138490] i915_sel-5636 3d..1 673425569us : trace_ports: vecs0: promote { 14de2:504*, 0:0 } <0>[ 618.138490] i915_sel-5636 3d..1 673425570us : __i915_request_reset: vecs0 rq=14de2:504, guilty? yes <0>[ 618.138490] i915_sel-5636 3d..1 673425571us : __execlists_reset: vecs0 replay {head:2de0, tail:2e48} <0>[ 618.138490] i915_sel-5636 3d..1 673425572us : __i915_request_unsubmit: vecs0 fence 14de2:504, current 503 <0>[ 618.138490] i915_sel-5636 3.... 673435544us : intel_engine_cancel_stop_cs: vecs0 <0>[ 618.138490] i915_sel-5636 3.... 673435544us : process_csb: vecs0 cs-irq head=11, tail=11 <0>[ 618.138490] i915_sel-5636 3d..1 673435545us : __i915_request_submit: vecs0 fence 14de2:504, current 503 <0>[ 618.138490] i915_sel-5636 3d..1 673435546us : __execlists_submission_tasklet: vecs0: queue_priority_hint:-2147483648, submit:yes <0>[ 618.138490] i915_sel-5636 3d..1 673435548us : trace_ports: vecs0: submit { 14de2:504*, 0:0 } <0>[ 618.138490] i915_sel-5636 3.... 673435549us : execlists_reset_finish: vecs0: depth->0 <0>[ 618.138490] ksoftirq-21 2..s. 673435592us : process_csb: vecs0 cs-irq head=11, tail=3 <0>[ 618.138490] ksoftirq-21 2..s. 673435593us : process_csb: vecs0 csb[0]: status=0x00000001:0x40000000 <0>[ 618.138490] ksoftirq-21 2..s. 673435594us : trace_ports: vecs0: promote { 14de2:504*, 0:0 } <0>[ 618.138490] ksoftirq-21 2..s. 673435596us : process_csb: vecs0 csb[1]: status=0x00000018:0x40000040 <0>[ 618.138490] ksoftirq-21 2..s. 673435597us : trace_ports: vecs0: completed { 14de2:504*, 0:0 } <0>[ 618.138490] ksoftirq-21 2..s. 673435612us : process_csb: process_csb:2188 GEM_BUG_ON(!i915_request_completed(*execlists->active) && !reset_in_progress(execlists)) After the reset, we do another clflush before checking the CSB to be sure we see whatever was left in the CSB prior to the reset. So it is unlikely to be an incoherent view of the CSB, and more likely that Icelake didn't reset its pointers. References: 582a6f90aa0d ("drm/i915/execlists: Add a paranoid flush of the CSB pointers upon reset") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191104135307.21083-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 8d79a965f341..1975fe4775d2 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -2996,6 +2996,14 @@ static void reset_csb_pointers(struct intel_engine_cs *engine) WRITE_ONCE(*execlists->csb_write, reset_value); wmb(); /* Make sure this is visible to HW (paranoia?) */ + /* + * Sometimes Icelake forgets to reset its pointers on a GPU reset. + * Bludgeon them with a mmio update to be sure. + */ + ENGINE_WRITE(engine, RING_CONTEXT_STATUS_PTR, + reset_value << 8 | reset_value); + ENGINE_POSTING_READ(engine, RING_CONTEXT_STATUS_PTR); + invalidate_csb_entries(&execlists->csb_status[0], &execlists->csb_status[reset_value]); } -- cgit v1.2.3 From ffe0fd2404f794ad24f8a68b6778036a7f4309c1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 31 Oct 2019 18:56:46 +0200 Subject: drm/i915: Expose 10:10:10 XRGB formats on SNB-BDW sprites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SNB-BDW support 10:10:10 formats on the sprite planes. Let's expose them. v2: Rebase due to fp16 landing Signed-off-by: Ville Syrjälä Reviewed-by: Juha-Pekka Heikkila Reviewed-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20191031165652.10868-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_sprite.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 14b35678a363..21d6e2f2e514 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -1319,6 +1319,12 @@ static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, case DRM_FORMAT_XRGB8888: sprctl |= SPRITE_FORMAT_RGBX888; break; + case DRM_FORMAT_XBGR2101010: + sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX; + break; + case DRM_FORMAT_XRGB2101010: + sprctl |= SPRITE_FORMAT_RGBX101010; + break; case DRM_FORMAT_XBGR16161616F: sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX; break; @@ -1624,6 +1630,12 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, case DRM_FORMAT_XRGB8888: dvscntr |= DVS_FORMAT_RGBX888; break; + case DRM_FORMAT_XBGR2101010: + dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR; + break; + case DRM_FORMAT_XRGB2101010: + dvscntr |= DVS_FORMAT_RGBX101010; + break; case DRM_FORMAT_XBGR16161616F: dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR; break; @@ -2355,6 +2367,8 @@ static const u64 i9xx_plane_format_modifiers[] = { static const u32 snb_plane_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, DRM_FORMAT_XRGB16161616F, DRM_FORMAT_XBGR16161616F, DRM_FORMAT_YUYV, @@ -2573,6 +2587,8 @@ static bool snb_sprite_format_mod_supported(struct drm_plane *_plane, switch (format) { case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_XRGB16161616F: case DRM_FORMAT_XBGR16161616F: case DRM_FORMAT_YUYV: -- cgit v1.2.3 From 73263cb6e2fe77681e872f94999458db27d8d7bc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 31 Oct 2019 18:56:47 +0200 Subject: drm/i915: Expose alpha formats on VLV/CHV primary planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we expose VLV/CHV alpha blending only on the sprite planes, but the primary planes can do it as well. Let's flip it on. v2: Rebase due to fp16 landing Signed-off-by: Ville Syrjälä Reviewed-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20191031165652.10868-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 62 ++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c689cb5f94d3..983649c483a1 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -111,6 +111,21 @@ static const u32 i965_primary_formats[] = { DRM_FORMAT_XBGR16161616F, }; +/* Primary plane formats for vlv/chv */ +static const u32 vlv_primary_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_XBGR16161616F, +}; + static const u64 i9xx_format_modifiers[] = { I915_FORMAT_MOD_X_TILED, DRM_FORMAT_MOD_LINEAR, @@ -2971,6 +2986,8 @@ static int i9xx_format_to_fourcc(int format) switch (format) { case DISPPLANE_8BPP: return DRM_FORMAT_C8; + case DISPPLANE_BGRA555: + return DRM_FORMAT_ARGB1555; case DISPPLANE_BGRX555: return DRM_FORMAT_XRGB1555; case DISPPLANE_BGRX565: @@ -2980,10 +2997,18 @@ static int i9xx_format_to_fourcc(int format) return DRM_FORMAT_XRGB8888; case DISPPLANE_RGBX888: return DRM_FORMAT_XBGR8888; + case DISPPLANE_BGRA888: + return DRM_FORMAT_ARGB8888; + case DISPPLANE_RGBA888: + return DRM_FORMAT_ABGR8888; case DISPPLANE_BGRX101010: return DRM_FORMAT_XRGB2101010; case DISPPLANE_RGBX101010: return DRM_FORMAT_XBGR2101010; + case DISPPLANE_BGRA101010: + return DRM_FORMAT_ARGB2101010; + case DISPPLANE_RGBA101010: + return DRM_FORMAT_ABGR2101010; case DISPPLANE_RGBX161616: return DRM_FORMAT_XBGR16161616F; } @@ -3708,6 +3733,9 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, case DRM_FORMAT_XRGB1555: dspcntr |= DISPPLANE_BGRX555; break; + case DRM_FORMAT_ARGB1555: + dspcntr |= DISPPLANE_BGRA555; + break; case DRM_FORMAT_RGB565: dspcntr |= DISPPLANE_BGRX565; break; @@ -3717,12 +3745,24 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, case DRM_FORMAT_XBGR8888: dspcntr |= DISPPLANE_RGBX888; break; + case DRM_FORMAT_ARGB8888: + dspcntr |= DISPPLANE_BGRA888; + break; + case DRM_FORMAT_ABGR8888: + dspcntr |= DISPPLANE_RGBA888; + break; case DRM_FORMAT_XRGB2101010: dspcntr |= DISPPLANE_BGRX101010; break; case DRM_FORMAT_XBGR2101010: dspcntr |= DISPPLANE_RGBX101010; break; + case DRM_FORMAT_ARGB2101010: + dspcntr |= DISPPLANE_BGRA101010; + break; + case DRM_FORMAT_ABGR2101010: + dspcntr |= DISPPLANE_RGBA101010; + break; case DRM_FORMAT_XBGR16161616F: dspcntr |= DISPPLANE_RGBX161616; break; @@ -15294,8 +15334,12 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_RGB565: case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_XBGR16161616F: return modifier == DRM_FORMAT_MOD_LINEAR || modifier == I915_FORMAT_MOD_X_TILED; @@ -15517,7 +15561,20 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; } - if (INTEL_GEN(dev_priv) >= 4) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + formats = vlv_primary_formats; + num_formats = ARRAY_SIZE(vlv_primary_formats); + modifiers = i9xx_format_modifiers; + + plane->max_stride = i9xx_plane_max_stride; + plane->update_plane = i9xx_update_plane; + plane->disable_plane = i9xx_disable_plane; + plane->get_hw_state = i9xx_plane_get_hw_state; + plane->check_plane = i9xx_plane_check; + plane->min_cdclk = vlv_plane_min_cdclk; + + plane_funcs = &i965_plane_funcs; + } else if (INTEL_GEN(dev_priv) >= 4) { /* * WaFP16GammaEnabling:ivb * "Workaround : When using the 64-bit format, the plane @@ -15538,6 +15595,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) formats = i965_primary_formats; num_formats = ARRAY_SIZE(i965_primary_formats); } + modifiers = i9xx_format_modifiers; plane->max_stride = i9xx_plane_max_stride; @@ -15550,8 +15608,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->min_cdclk = hsw_plane_min_cdclk; else if (IS_IVYBRIDGE(dev_priv)) plane->min_cdclk = ivb_plane_min_cdclk; - else if (IS_CHERRYVIEW(dev_priv) || IS_VALLEYVIEW(dev_priv)) - plane->min_cdclk = vlv_plane_min_cdclk; else plane->min_cdclk = i9xx_plane_min_cdclk; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 53c280c4e741..b819392ba700 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6353,6 +6353,7 @@ enum { #define DISPPLANE_RGBX101010 (0x8 << 26) #define DISPPLANE_RGBA101010 (0x9 << 26) #define DISPPLANE_BGRX101010 (0xa << 26) +#define DISPPLANE_BGRA101010 (0xb << 26) #define DISPPLANE_RGBX161616 (0xc << 26) #define DISPPLANE_RGBX888 (0xe << 26) #define DISPPLANE_RGBA888 (0xf << 26) -- cgit v1.2.3 From d8aa1a487b3201a1586739d3e8a1aeceaf9111f7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 31 Oct 2019 18:56:48 +0200 Subject: drm/i915: Add missing 10bpc formats for pipe B sprites on CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CHV pipe B sprites gained support for the 10bpc X/ARGB pixel formats. On VLV and CHV pipe A/C these are only supported by the primary plane. Add the require bits to expose the new formats. v2: Reorder the formats for consistency Signed-off-by: Ville Syrjälä Reviewed-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20191031165652.10868-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_sprite.c | 33 +++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 14 ++++++------ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 21d6e2f2e514..8726e7f38a07 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -958,6 +958,12 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, case DRM_FORMAT_ABGR2101010: sprctl |= SP_FORMAT_RGBA1010102; break; + case DRM_FORMAT_XRGB2101010: + sprctl |= SP_FORMAT_BGRX1010102; + break; + case DRM_FORMAT_ARGB2101010: + sprctl |= SP_FORMAT_BGRA1010102; + break; case DRM_FORMAT_XBGR8888: sprctl |= SP_FORMAT_RGBX8888; break; @@ -2391,6 +2397,22 @@ static const u32 vlv_plane_formats[] = { DRM_FORMAT_VYUY, }; +static const u32 chv_pipe_b_sprite_formats[] = { + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, +}; + static const u32 skl_plane_formats[] = { DRM_FORMAT_C8, DRM_FORMAT_RGB565, @@ -2623,6 +2645,8 @@ static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: @@ -3019,8 +3043,13 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane->check_plane = vlv_sprite_check; plane->min_cdclk = vlv_plane_min_cdclk; - formats = vlv_plane_formats; - num_formats = ARRAY_SIZE(vlv_plane_formats); + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { + formats = chv_pipe_b_sprite_formats; + num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats); + } else { + formats = vlv_plane_formats; + num_formats = ARRAY_SIZE(vlv_plane_formats); + } modifiers = i9xx_plane_format_modifiers; plane_funcs = &vlv_sprite_funcs; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b819392ba700..78dfdcfc724a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6628,12 +6628,14 @@ enum { #define SP_ENABLE (1 << 31) #define SP_GAMMA_ENABLE (1 << 30) #define SP_PIXFORMAT_MASK (0xf << 26) -#define SP_FORMAT_YUV422 (0 << 26) -#define SP_FORMAT_BGR565 (5 << 26) -#define SP_FORMAT_BGRX8888 (6 << 26) -#define SP_FORMAT_BGRA8888 (7 << 26) -#define SP_FORMAT_RGBX1010102 (8 << 26) -#define SP_FORMAT_RGBA1010102 (9 << 26) +#define SP_FORMAT_YUV422 (0x0 << 26) +#define SP_FORMAT_BGR565 (0x5 << 26) +#define SP_FORMAT_BGRX8888 (0x6 << 26) +#define SP_FORMAT_BGRA8888 (0x7 << 26) +#define SP_FORMAT_RGBX1010102 (0x8 << 26) +#define SP_FORMAT_RGBA1010102 (0x9 << 26) +#define SP_FORMAT_BGRX1010102 (0xa << 26) /* CHV pipe B */ +#define SP_FORMAT_BGRA1010102 (0xb << 26) /* CHV pipe B */ #define SP_FORMAT_RGBX8888 (0xe << 26) #define SP_FORMAT_RGBA8888 (0xf << 26) #define SP_ALPHA_PREMULTIPLY (1 << 23) /* CHV pipe B */ -- cgit v1.2.3 From ed94034f3d6dc8c9fa1dae59f6058bbd06a97034 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 31 Oct 2019 18:56:49 +0200 Subject: drm/i915: Expose C8 on VLV/CHV sprite planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VLV/CHV sprite planes also support the C8 format. Let's expose that. Signed-off-by: Ville Syrjälä Reviewed-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20191031165652.10868-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_sprite.c | 6 ++++++ drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 8726e7f38a07..3364eeb0ea07 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -943,6 +943,9 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state, case DRM_FORMAT_VYUY: sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; break; + case DRM_FORMAT_C8: + sprctl |= SP_FORMAT_8BPP; + break; case DRM_FORMAT_RGB565: sprctl |= SP_FORMAT_BGR565; break; @@ -2384,6 +2387,7 @@ static const u32 snb_plane_formats[] = { }; static const u32 vlv_plane_formats[] = { + DRM_FORMAT_C8, DRM_FORMAT_RGB565, DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, @@ -2398,6 +2402,7 @@ static const u32 vlv_plane_formats[] = { }; static const u32 chv_pipe_b_sprite_formats[] = { + DRM_FORMAT_C8, DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, @@ -2638,6 +2643,7 @@ static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane, } switch (format) { + case DRM_FORMAT_C8: case DRM_FORMAT_RGB565: case DRM_FORMAT_ABGR8888: case DRM_FORMAT_ARGB8888: diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 78dfdcfc724a..a607ea520829 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6629,6 +6629,7 @@ enum { #define SP_GAMMA_ENABLE (1 << 30) #define SP_PIXFORMAT_MASK (0xf << 26) #define SP_FORMAT_YUV422 (0x0 << 26) +#define SP_FORMAT_8BPP (0x2 << 26) #define SP_FORMAT_BGR565 (0x5 << 26) #define SP_FORMAT_BGRX8888 (0x6 << 26) #define SP_FORMAT_BGRA8888 (0x7 << 26) -- cgit v1.2.3 From f9c43a313f5128a977a5f699a805c155990671fc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 31 Oct 2019 18:56:50 +0200 Subject: drm/i915: Add 10bpc formats with alpha for icl+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ICL+ again supports alpha blending with 10bpc pixel formats. Expose them. v2: Add all the stuff I missed earlier! Signed-off-by: Ville Syrjälä Reviewed-by: Juha-Pekka Heikkila Reviewed-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20191031165652.10868-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 19 +++++++++++++++---- drivers/gpu/drm/i915/display/intel_sprite.c | 10 ++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 983649c483a1..512c797bfc69 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3053,10 +3053,17 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) return DRM_FORMAT_XRGB8888; } case PLANE_CTL_FORMAT_XRGB_2101010: - if (rgb_order) - return DRM_FORMAT_XBGR2101010; - else - return DRM_FORMAT_XRGB2101010; + if (rgb_order) { + if (alpha) + return DRM_FORMAT_ABGR2101010; + else + return DRM_FORMAT_XBGR2101010; + } else { + if (alpha) + return DRM_FORMAT_ARGB2101010; + else + return DRM_FORMAT_XRGB2101010; + } case PLANE_CTL_FORMAT_XRGB_16161616F: if (rgb_order) { if (alpha) @@ -4102,8 +4109,10 @@ static u32 skl_plane_ctl_format(u32 pixel_format) case DRM_FORMAT_ARGB8888: return PLANE_CTL_FORMAT_XRGB_8888; case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ABGR2101010: return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX; case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_ARGB2101010: return PLANE_CTL_FORMAT_XRGB_2101010; case DRM_FORMAT_XBGR16161616F: case DRM_FORMAT_ABGR16161616F: @@ -5705,6 +5714,8 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, case DRM_FORMAT_ARGB8888: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 3364eeb0ea07..b30deef9e39d 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -2483,6 +2483,8 @@ static const u32 icl_sdr_y_plane_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, DRM_FORMAT_YUYV, DRM_FORMAT_YVYU, DRM_FORMAT_UYVY, @@ -2504,6 +2506,8 @@ static const u32 icl_sdr_uv_plane_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, DRM_FORMAT_YUYV, DRM_FORMAT_YVYU, DRM_FORMAT_UYVY, @@ -2529,6 +2533,8 @@ static const u32 icl_hdr_plane_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, DRM_FORMAT_XRGB16161616F, DRM_FORMAT_XBGR16161616F, DRM_FORMAT_ARGB16161616F, @@ -2697,6 +2703,8 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_RGB565: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: @@ -2749,6 +2757,8 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_RGB565: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: -- cgit v1.2.3 From 12fef149d755e33230108b923fcb6216a8e1e2de Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 31 Oct 2019 18:56:51 +0200 Subject: drm/i915: Sort format arrays consistently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's try to keep the pixel format arrays somewhat sorted: 1. RGB before YUV 2. smaller bpp before larger bpp 3. X before A 4. RGB before BGR Signed-off-by: Ville Syrjälä Reviewed-by: Juha-Pekka Heikkila Reviewed-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20191031165652.10868-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_sprite.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 512c797bfc69..5f3b9b423e27 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -85,8 +85,8 @@ /* Primary plane formats for gen <= 3 */ static const u32 i8xx_primary_formats[] = { DRM_FORMAT_C8, - DRM_FORMAT_RGB565, DRM_FORMAT_XRGB1555, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, }; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index b30deef9e39d..d7f71fa90659 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -2389,10 +2389,10 @@ static const u32 snb_plane_formats[] = { static const u32 vlv_plane_formats[] = { DRM_FORMAT_C8, DRM_FORMAT_RGB565, - DRM_FORMAT_ABGR8888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR2101010, DRM_FORMAT_ABGR2101010, DRM_FORMAT_YUYV, -- cgit v1.2.3 From dbb1a6fbbb809fe364f51293026616c58916f330 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 31 Oct 2019 18:56:52 +0200 Subject: drm/i915: Eliminate redundancy in intel_primary_plane_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lots of redundant assignments inside intel_primary_plane_create(). Get rid of them. v2: Rebase due to fp16 landing Signed-off-by: Ville Syrjälä Reviewed-by: Juha-Pekka Heikkila Reviewed-by: Uma Shankar Link: https://patchwork.freedesktop.org/patch/msgid/20191031165652.10868-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 60 ++++++++++------------------ 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5f3b9b423e27..876fc25968bf 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15540,7 +15540,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) const struct drm_plane_funcs *plane_funcs; unsigned int supported_rotations; unsigned int possible_crtcs; - const u64 *modifiers; const u32 *formats; int num_formats; int ret, zpos; @@ -15575,16 +15574,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { formats = vlv_primary_formats; num_formats = ARRAY_SIZE(vlv_primary_formats); - modifiers = i9xx_format_modifiers; - - plane->max_stride = i9xx_plane_max_stride; - plane->update_plane = i9xx_update_plane; - plane->disable_plane = i9xx_disable_plane; - plane->get_hw_state = i9xx_plane_get_hw_state; - plane->check_plane = i9xx_plane_check; - plane->min_cdclk = vlv_plane_min_cdclk; - - plane_funcs = &i965_plane_funcs; } else if (INTEL_GEN(dev_priv) >= 4) { /* * WaFP16GammaEnabling:ivb @@ -15606,50 +15595,45 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) formats = i965_primary_formats; num_formats = ARRAY_SIZE(i965_primary_formats); } - - modifiers = i9xx_format_modifiers; - - plane->max_stride = i9xx_plane_max_stride; - plane->update_plane = i9xx_update_plane; - plane->disable_plane = i9xx_disable_plane; - plane->get_hw_state = i9xx_plane_get_hw_state; - plane->check_plane = i9xx_plane_check; - - if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) - plane->min_cdclk = hsw_plane_min_cdclk; - else if (IS_IVYBRIDGE(dev_priv)) - plane->min_cdclk = ivb_plane_min_cdclk; - else - plane->min_cdclk = i9xx_plane_min_cdclk; - - plane_funcs = &i965_plane_funcs; } else { formats = i8xx_primary_formats; num_formats = ARRAY_SIZE(i8xx_primary_formats); - modifiers = i9xx_format_modifiers; + } - plane->max_stride = i9xx_plane_max_stride; - plane->update_plane = i9xx_update_plane; - plane->disable_plane = i9xx_disable_plane; - plane->get_hw_state = i9xx_plane_get_hw_state; - plane->check_plane = i9xx_plane_check; + if (INTEL_GEN(dev_priv) >= 4) + plane_funcs = &i965_plane_funcs; + else + plane_funcs = &i8xx_plane_funcs; + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + plane->min_cdclk = vlv_plane_min_cdclk; + else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) + plane->min_cdclk = hsw_plane_min_cdclk; + else if (IS_IVYBRIDGE(dev_priv)) + plane->min_cdclk = ivb_plane_min_cdclk; + else plane->min_cdclk = i9xx_plane_min_cdclk; - plane_funcs = &i8xx_plane_funcs; - } + plane->max_stride = i9xx_plane_max_stride; + plane->update_plane = i9xx_update_plane; + plane->disable_plane = i9xx_disable_plane; + plane->get_hw_state = i9xx_plane_get_hw_state; + plane->check_plane = i9xx_plane_check; possible_crtcs = BIT(pipe); if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, possible_crtcs, plane_funcs, - formats, num_formats, modifiers, + formats, num_formats, + i9xx_format_modifiers, DRM_PLANE_TYPE_PRIMARY, "primary %c", pipe_name(pipe)); else ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, possible_crtcs, plane_funcs, - formats, num_formats, modifiers, + formats, num_formats, + i9xx_format_modifiers, DRM_PLANE_TYPE_PRIMARY, "plane %c", plane_name(plane->i9xx_plane)); -- cgit v1.2.3 From 74e8cd5ba4a2c0bc9c1130542296ea2f83c6a13a Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Tue, 29 Oct 2019 18:24:44 -0700 Subject: drm/i915: Add for_each_new_intel_connector_in_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same macro as for_each_new_connector_in_state() but it uses intel/i915 types instead of the drm ones. Signed-off-by: José Roberto de Souza Reviewed-by: Mika Kahola Reviewed-by: Lucas De Marchi Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20190823082055.5992-11-lucas.demarchi@intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20191030012448.14937-2-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_display.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 397966147561..4dc490760fbc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -455,6 +455,14 @@ enum phy_fia { for_each_if ((plane_state = \ to_intel_plane_state(__drm_atomic_get_current_plane_state((crtc_state)->uapi.state, &plane->base)))) +#define for_each_new_intel_connector_in_state(__state, connector, new_connector_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->base.num_connector; \ + (__i)++) \ + for_each_if ((__state)->base.connectors[__i].ptr && \ + ((connector) = to_intel_connector((__state)->base.connectors[__i].ptr), \ + (new_connector_state) = to_intel_digital_connector_state((__state)->base.connectors[__i].new_state), 1)) + void intel_link_compute_m_n(u16 bpp, int nlanes, int pixel_clock, int link_clock, struct intel_link_m_n *m_n, -- cgit v1.2.3 From 142110c4ef6d2dfaf109ad60a3a2bcbc9bec0cd1 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 29 Oct 2019 18:24:45 -0700 Subject: drm/i915: add wrappers to get intel connector state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrap drm_atomic_get_old_connector_state so we can get the intel_digital_connector_state and make it easier to migrate to intel types. Signed-off-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191030012448.14937-3-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_display_types.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 764a715c5d1c..fadd9853f966 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1570,6 +1570,24 @@ intel_atomic_get_new_crtc_state(struct intel_atomic_state *state, &crtc->base)); } +static inline struct intel_digital_connector_state * +intel_atomic_get_new_connector_state(struct intel_atomic_state *state, + struct intel_connector *connector) +{ + return to_intel_digital_connector_state( + drm_atomic_get_new_connector_state(&state->base, + &connector->base)); +} + +static inline struct intel_digital_connector_state * +intel_atomic_get_old_connector_state(struct intel_atomic_state *state, + struct intel_connector *connector) +{ + return to_intel_digital_connector_state( + drm_atomic_get_old_connector_state(&state->base, + &connector->base)); +} + /* intel_display.c */ static inline bool intel_crtc_has_type(const struct intel_crtc_state *crtc_state, -- cgit v1.2.3 From a687b4ef6e2825162fb58bffaf1556ca68705393 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 29 Oct 2019 18:24:46 -0700 Subject: drm/i915/tgl: do not enable transcoder clock twice on MST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For MST on Tiger Lake there are different moments when we need to configure the transcoder clock select. For the first link this is in step 7.a of the spec, before training the link. For additional streams this should be done as part of step 8.b after programming receiver VC Payload ID. Bspec: 49190 Signed-off-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191030012448.14937-4-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 7 ++++--- drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 7deae472be5f..2f05110191a0 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3462,9 +3462,10 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, icl_program_mg_dp_mode(dig_port, crtc_state); /* - * 7.a - Steps in this function should only be executed over MST - * master, what will be taken in care by MST hook - * intel_mst_pre_enable_dp() + * 7.a - single stream or multi-stream master transcoder: Configure + * Transcoder Clock Select. For additional MST streams this will be done + * by intel_mst_pre_enable_dp() after programming VC Payload ID through + * AUX. */ intel_ddi_enable_pipe_clock(crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 5b2ca81f5cd6..27494aa48b0b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -303,21 +303,23 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, to_intel_connector(conn_state->connector); int ret; u32 temp; + bool first_mst_stream; /* MST encoders are bound to a crtc, not to a connector, * force the mapping here for get_hw_state. */ connector->encoder = encoder; intel_mst->connector = connector; + first_mst_stream = intel_dp->active_mst_links == 0; DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); - if (intel_dp->active_mst_links == 0) + if (first_mst_stream) intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true); - if (intel_dp->active_mst_links == 0) + if (first_mst_stream) intel_dig_port->base.pre_enable(&intel_dig_port->base, pipe_config, NULL); @@ -334,7 +336,15 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); - intel_ddi_enable_pipe_clock(pipe_config); + /* + * Before Gen 12 this is not done as part of + * intel_dig_port->base.pre_enable() and should be done here. For + * Gen 12+ the step in which this should be done is different for the + * first MST stream, so it's done on the DDI for the first stream and + * here for the following ones. + */ + if (INTEL_GEN(dev_priv) < 12 || !first_mst_stream) + intel_ddi_enable_pipe_clock(pipe_config); } static void intel_mst_enable_dp(struct intel_encoder *encoder, -- cgit v1.2.3 From 35ac28a88223d64a996535c58b8f0112118a989c Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 29 Oct 2019 18:24:47 -0700 Subject: drm/i915: avoid reading DP_TP_CTL twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just avoid the additional read in case DP_TP_CTL is enabled: read it once and save the value. Signed-off-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191030012448.14937-5-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 33 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 2f05110191a0..c91521bcf06a 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4148,37 +4148,38 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); enum port port = intel_dig_port->base.port; - u32 val; + u32 dp_tp_ctl, ddi_buf_ctl; bool wait = false; - if (I915_READ(intel_dp->regs.dp_tp_ctl) & DP_TP_CTL_ENABLE) { - val = I915_READ(DDI_BUF_CTL(port)); - if (val & DDI_BUF_CTL_ENABLE) { - val &= ~DDI_BUF_CTL_ENABLE; - I915_WRITE(DDI_BUF_CTL(port), val); + dp_tp_ctl = I915_READ(intel_dp->regs.dp_tp_ctl); + + if (dp_tp_ctl & DP_TP_CTL_ENABLE) { + ddi_buf_ctl = I915_READ(DDI_BUF_CTL(port)); + if (ddi_buf_ctl & DDI_BUF_CTL_ENABLE) { + I915_WRITE(DDI_BUF_CTL(port), + ddi_buf_ctl & ~DDI_BUF_CTL_ENABLE); wait = true; } - val = I915_READ(intel_dp->regs.dp_tp_ctl); - val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); - val |= DP_TP_CTL_LINK_TRAIN_PAT1; - I915_WRITE(intel_dp->regs.dp_tp_ctl, val); + dp_tp_ctl &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK); + dp_tp_ctl |= DP_TP_CTL_LINK_TRAIN_PAT1; + I915_WRITE(intel_dp->regs.dp_tp_ctl, dp_tp_ctl); POSTING_READ(intel_dp->regs.dp_tp_ctl); if (wait) intel_wait_ddi_buf_idle(dev_priv, port); } - val = DP_TP_CTL_ENABLE | - DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; + dp_tp_ctl = DP_TP_CTL_ENABLE | + DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; if (intel_dp->link_mst) - val |= DP_TP_CTL_MODE_MST; + dp_tp_ctl |= DP_TP_CTL_MODE_MST; else { - val |= DP_TP_CTL_MODE_SST; + dp_tp_ctl |= DP_TP_CTL_MODE_SST; if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) - val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; + dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; } - I915_WRITE(intel_dp->regs.dp_tp_ctl, val); + I915_WRITE(intel_dp->regs.dp_tp_ctl, dp_tp_ctl); POSTING_READ(intel_dp->regs.dp_tp_ctl); intel_dp->DP |= DDI_BUF_CTL_ENABLE; -- cgit v1.2.3 From 59ed05ccdded5eb18ce012eff3d01798ac8535fa Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 1 Nov 2019 16:20:24 +0200 Subject: drm/i915: update rawclk also on resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since CNP it's possible for rawclk to have two different values, 19.2 and 24 MHz. If the value indicated by SFUSE_STRAP register is different from the power on default for PCH_RAWCLK_FREQ, we'll end up having a mismatch between the rawclk hardware and software states after suspend/resume. On previous platforms this used to work by accident, because the power on defaults worked just fine. Update the rawclk also on resume. The natural place to do this would be intel_modeset_init_hw(), however VLV/CHV need it done before intel_power_domains_init_hw(). Thus put it there even if it feels slightly out of place. v2: Call intel_update_rawclck() in intel_power_domains_init_hw() for all platforms (Ville). Reported-by: Shawn Lee Cc: Shawn Lee Cc: Ville Syrjala Reviewed-by: Ville Syrjälä Tested-by: Shawn Lee Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191101142024.13877-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 3 +++ drivers/gpu/drm/i915/i915_drv.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 707ac110e271..ce1b64f4dd44 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5015,6 +5015,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume) power_domains->initializing = true; + /* Must happen before power domain init on VLV/CHV */ + intel_update_rawclk(i915); + if (INTEL_GEN(i915) >= 11) { icl_display_core_init(i915, resume); } else if (IS_CANNONLAKE(i915)) { diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ccb5b566795f..82e4e6bf08c3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -296,9 +296,6 @@ static int i915_driver_modeset_probe(struct drm_i915_private *i915) if (ret) goto cleanup_vga_client; - /* must happen before intel_power_domains_init_hw() on VLV/CHV */ - intel_update_rawclk(i915); - intel_power_domains_init_hw(i915, false); intel_csr_ucode_init(i915); -- cgit v1.2.3 From 074f51574e7ae81b91b2ac4182c2425087cb8356 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 4 Nov 2019 16:14:36 +0200 Subject: drm/i915/dsc: make parameter arrays const No need for them to be mutable. Cc: Manasi Navare Reviewed-by: Manasi Navare Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191104141439.26312-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 9cb36f855f07..763f1d7208e9 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -33,7 +33,7 @@ enum COLUMN_INDEX_BPC { #define DSC_SUPPORTED_VERSION_MIN 1 /* From DSC_v1.11 spec, rc_parameter_Set syntax element typically constant */ -static u16 rc_buf_thresh[] = { +static const u16 rc_buf_thresh[] = { 896, 1792, 2688, 3584, 4480, 5376, 6272, 6720, 7168, 7616, 7744, 7872, 8000, 8064 }; @@ -53,7 +53,7 @@ struct rc_parameters { * Selected Rate Control Related Parameter Recommended Values * from DSC_v1.11 spec & C Model release: DSC_model_20161212 */ -static struct rc_parameters rc_params[][MAX_COLUMN_INDEX] = { +static const struct rc_parameters rc_params[][MAX_COLUMN_INDEX] = { { /* 6BPP/8BPC */ { 768, 15, 6144, 3, 13, 11, 11, { -- cgit v1.2.3 From 6aead5df0556e44338cf305988ddea7e5c3f2e33 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 4 Nov 2019 16:14:37 +0200 Subject: drm/i915/dsc: clean up rc parameter table access Use a simple pointer to the relevant element instead of duplicating the array subscription. No functional changes. Cc: Manasi Navare Reviewed-by: Manasi Navare Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191104141439.26312-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 55 +++++++++++++++++-------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 763f1d7208e9..f1df654369a7 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -53,7 +53,7 @@ struct rc_parameters { * Selected Rate Control Related Parameter Recommended Values * from DSC_v1.11 spec & C Model release: DSC_model_20161212 */ -static const struct rc_parameters rc_params[][MAX_COLUMN_INDEX] = { +static const struct rc_parameters rc_parameters[][MAX_COLUMN_INDEX] = { { /* 6BPP/8BPC */ { 768, 15, 6144, 3, 13, 11, 11, { @@ -319,14 +319,29 @@ static int get_column_index_for_rc_params(u8 bits_per_component) } } +static const struct rc_parameters *get_rc_params(u16 compressed_bpp, + u8 bits_per_component) +{ + int row_index, column_index; + + row_index = get_row_index_for_rc_params(compressed_bpp); + if (row_index < 0) + return NULL; + + column_index = get_column_index_for_rc_params(bits_per_component); + if (column_index < 0) + return NULL; + + return &rc_parameters[row_index][column_index]; +} + int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config) { struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config; u16 compressed_bpp = pipe_config->dsc.compressed_bpp; + const struct rc_parameters *rc_params; u8 i = 0; - int row_index = 0; - int column_index = 0; u8 line_buf_depth = 0; vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay; @@ -399,39 +414,29 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, vdsc_cfg->rc_buf_thresh[13] = 0x7D; } - row_index = get_row_index_for_rc_params(compressed_bpp); - column_index = - get_column_index_for_rc_params(vdsc_cfg->bits_per_component); - - if (row_index < 0 || column_index < 0) + rc_params = get_rc_params(compressed_bpp, vdsc_cfg->bits_per_component); + if (!rc_params) return -EINVAL; - vdsc_cfg->first_line_bpg_offset = - rc_params[row_index][column_index].first_line_bpg_offset; - vdsc_cfg->initial_xmit_delay = - rc_params[row_index][column_index].initial_xmit_delay; - vdsc_cfg->initial_offset = - rc_params[row_index][column_index].initial_offset; - vdsc_cfg->flatness_min_qp = - rc_params[row_index][column_index].flatness_min_qp; - vdsc_cfg->flatness_max_qp = - rc_params[row_index][column_index].flatness_max_qp; - vdsc_cfg->rc_quant_incr_limit0 = - rc_params[row_index][column_index].rc_quant_incr_limit0; - vdsc_cfg->rc_quant_incr_limit1 = - rc_params[row_index][column_index].rc_quant_incr_limit1; + vdsc_cfg->first_line_bpg_offset = rc_params->first_line_bpg_offset; + vdsc_cfg->initial_xmit_delay = rc_params->initial_xmit_delay; + vdsc_cfg->initial_offset = rc_params->initial_offset; + vdsc_cfg->flatness_min_qp = rc_params->flatness_min_qp; + vdsc_cfg->flatness_max_qp = rc_params->flatness_max_qp; + vdsc_cfg->rc_quant_incr_limit0 = rc_params->rc_quant_incr_limit0; + vdsc_cfg->rc_quant_incr_limit1 = rc_params->rc_quant_incr_limit1; for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { vdsc_cfg->rc_range_params[i].range_min_qp = - rc_params[row_index][column_index].rc_range_params[i].range_min_qp; + rc_params->rc_range_params[i].range_min_qp; vdsc_cfg->rc_range_params[i].range_max_qp = - rc_params[row_index][column_index].rc_range_params[i].range_max_qp; + rc_params->rc_range_params[i].range_max_qp; /* * Range BPG Offset uses 2's complement and is only a 6 bits. So * mask it to get only 6 bits. */ vdsc_cfg->rc_range_params[i].range_bpg_offset = - rc_params[row_index][column_index].rc_range_params[i].range_bpg_offset & + rc_params->rc_range_params[i].range_bpg_offset & DSC_RANGE_BPG_OFFSET_MASK; } -- cgit v1.2.3 From b0ab655c87167563ce336a896bfeeaa51d41dcc8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 4 Nov 2019 16:14:38 +0200 Subject: drm/i915/dsc: split out encoder specific parts from DSC compute params Split out the DP specific parts, making it easier to add DSI specific configuration. Also move the encoder specific parts towards the end, to allow overriding generic configuration if needed. This also improves clarity by making it clear the encoder independent configuration does not depend on the encoder specific parts. v2: Rebase Cc: Manasi Navare Reviewed-by: Manasi Navare Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191104141439.26312-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_vdsc.c | 68 +++++++++++++++++++------------ drivers/gpu/drm/i915/display/intel_vdsc.h | 5 +-- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index b03696944c16..8c6c3690e929 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2132,7 +2132,7 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, } } - ret = intel_dp_compute_dsc_params(intel_dp, pipe_config); + ret = intel_dsc_compute_params(&dig_port->base, pipe_config); if (ret < 0) { DRM_DEBUG_KMS("Cannot compute valid DSC parameters for Input Bpp = %d " "Compressed BPP = %d\n", diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index f1df654369a7..ac10736a076a 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -335,32 +335,14 @@ static const struct rc_parameters *get_rc_params(u16 compressed_bpp, return &rc_parameters[row_index][column_index]; } -int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config) +/* Values filled from DSC Sink DPCD */ +static int intel_dsc_dp_compute_params(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) { + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config; - u16 compressed_bpp = pipe_config->dsc.compressed_bpp; - const struct rc_parameters *rc_params; - u8 i = 0; - u8 line_buf_depth = 0; + u8 line_buf_depth; - vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay; - vdsc_cfg->pic_height = pipe_config->hw.adjusted_mode.crtc_vdisplay; - vdsc_cfg->slice_width = DIV_ROUND_UP(vdsc_cfg->pic_width, - pipe_config->dsc.slice_count); - /* - * Slice Height of 8 works for all currently available panels. So start - * with that if pic_height is an integral multiple of 8. - * Eventually add logic to try multiple slice heights. - */ - if (vdsc_cfg->pic_height % 8 == 0) - vdsc_cfg->slice_height = 8; - else if (vdsc_cfg->pic_height % 4 == 0) - vdsc_cfg->slice_height = 4; - else - vdsc_cfg->slice_height = 2; - - /* Values filled from DSC Sink DPCD */ vdsc_cfg->dsc_version_major = (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT; @@ -377,6 +359,7 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, DRM_DEBUG_KMS("DSC Sink Line Buffer Depth invalid\n"); return -EINVAL; } + if (vdsc_cfg->dsc_version_minor == 2) vdsc_cfg->line_buf_depth = (line_buf_depth == DSC_1_2_MAX_LINEBUF_DEPTH_BITS) ? DSC_1_2_MAX_LINEBUF_DEPTH_VAL : line_buf_depth; @@ -384,13 +367,42 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, vdsc_cfg->line_buf_depth = (line_buf_depth > DSC_1_1_MAX_LINEBUF_DEPTH_BITS) ? DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth; + vdsc_cfg->block_pred_enable = + intel_dp->dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & + DP_DSC_BLK_PREDICTION_IS_SUPPORTED; + + return 0; +} + +int intel_dsc_compute_params(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) +{ + struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config; + u16 compressed_bpp = pipe_config->dsc.compressed_bpp; + const struct rc_parameters *rc_params; + u8 i = 0; + int ret; + + vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay; + vdsc_cfg->pic_height = pipe_config->hw.adjusted_mode.crtc_vdisplay; + vdsc_cfg->slice_width = DIV_ROUND_UP(vdsc_cfg->pic_width, + pipe_config->dsc.slice_count); + /* + * Slice Height of 8 works for all currently available panels. So start + * with that if pic_height is an integral multiple of 8. + * Eventually add logic to try multiple slice heights. + */ + if (vdsc_cfg->pic_height % 8 == 0) + vdsc_cfg->slice_height = 8; + else if (vdsc_cfg->pic_height % 4 == 0) + vdsc_cfg->slice_height = 4; + else + vdsc_cfg->slice_height = 2; + /* Gen 11 does not support YCbCr */ vdsc_cfg->simple_422 = false; /* Gen 11 does not support VBR */ vdsc_cfg->vbr_enable = false; - vdsc_cfg->block_pred_enable = - intel_dp->dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & - DP_DSC_BLK_PREDICTION_IS_SUPPORTED; /* Gen 11 only supports integral values of bpp */ vdsc_cfg->bits_per_pixel = compressed_bpp << 4; @@ -458,6 +470,10 @@ int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, vdsc_cfg->initial_scale_value = (vdsc_cfg->rc_model_size << 3) / (vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset); + ret = intel_dsc_dp_compute_params(encoder, pipe_config); + if (ret) + return ret; + return drm_dsc_compute_rc_parameters(vdsc_cfg); } diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h index 90d3f6017fcb..4ed2256750c3 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc.h @@ -8,13 +8,12 @@ struct intel_encoder; struct intel_crtc_state; -struct intel_dp; void intel_dsc_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_dsc_disable(const struct intel_crtc_state *crtc_state); -int intel_dp_compute_dsc_params(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config); +int intel_dsc_compute_params(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config); enum intel_display_power_domain intel_dsc_power_domain(const struct intel_crtc_state *crtc_state); -- cgit v1.2.3 From 75217f8d029b237ce3fdc9238edce01dcd4c9b86 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 4 Nov 2019 16:14:39 +0200 Subject: drm/i915/dsc: rename functions for consistency Use intel_dsc_ prefix. No functional changes. Cc: Manasi Navare Reviewed-by: Manasi Navare Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191104141439.26312-4-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index ac10736a076a..b23ba8d108db 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -501,8 +501,8 @@ intel_dsc_power_domain(const struct intel_crtc_state *crtc_state) return POWER_DOMAIN_TRANSCODER(cpu_transcoder); } -static void intel_configure_pps_for_dsc_encoder(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +static void intel_dsc_pps_configure(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -901,8 +901,8 @@ static void intel_configure_pps_for_dsc_encoder(struct intel_encoder *encoder, } } -static void intel_dp_write_dsc_pps_sdp(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +static void intel_dsc_dp_pps_write(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); @@ -937,9 +937,9 @@ void intel_dsc_enable(struct intel_encoder *encoder, intel_display_power_get(dev_priv, intel_dsc_power_domain(crtc_state)); - intel_configure_pps_for_dsc_encoder(encoder, crtc_state); + intel_dsc_pps_configure(encoder, crtc_state); - intel_dp_write_dsc_pps_sdp(encoder, crtc_state); + intel_dsc_dp_pps_write(encoder, crtc_state); if (crtc_state->cpu_transcoder == TRANSCODER_EDP) { dss_ctl1_reg = DSS_CTL1; -- cgit v1.2.3 From a096883dda2cfa52c19e2ab4121b64efe8cf95a6 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 17 Oct 2019 16:58:10 +0100 Subject: drm/i915/dsb: Remove PIN_MAPPABLE from the DSB object VMA It sounds like the hardware only needs the DSB object to be in global GTT and not in the mappable region. Signed-off-by: Tvrtko Ursulin Cc: Animesh Manna Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20191017155810.21654-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index bb5a0e91b370..d8ad5fe1efef 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -119,7 +119,7 @@ intel_dsb_get(struct intel_crtc *crtc) goto err; } - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE); + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); if (IS_ERR(vma)) { DRM_ERROR("Vma creation failed\n"); i915_gem_object_put(obj); -- cgit v1.2.3 From bee0a70a9eab27061dd0346dd0df09e6c2e8caa2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 5 Nov 2019 14:53:05 +0000 Subject: drm/i915/gem: Early rejection of no-aperture map_ggtt If the device does not have an aperture through which we can indirectly access and detile the buffers, simply reject the ioctl. Later we can extend the ioctl to support different modes, but as an extension the user must opt in and explicitly control the mmap type (viz MMAP_OFFSET_IOCTL). Signed-off-by: Chris Wilson Cc: Abdiel Janulgue Cc: Matthew Auld Cc: Joonas Lahtinen Reviewed-by: Abdiel Janulgue Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191105145305.14314-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index e3002849844b..d60973603cc1 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -450,6 +450,9 @@ i915_gem_mmap_gtt(struct drm_file *file, struct drm_i915_gem_object *obj; int ret; + if (!i915_ggtt_has_aperture(&to_i915(dev)->ggtt)) + return -ENODEV; + obj = i915_gem_object_lookup(file, handle); if (!obj) return -ENOENT; -- cgit v1.2.3 From 1e460bf9eaa59047183689ac28a772147eb747c9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 Nov 2019 19:14:46 +0200 Subject: drm/i915: Frob the correct crtc state in intel_crtc_disable_noatomic() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The uapi vs. hw state split introduced a bug in intel_crtc_disable_noatomic() where it's now frobbing an already freed temp crtc state instead of adjusting the crtc state we are really left with. Fix that by making a cleaner separation beteen the two. This causes explosions on any machine that boots up with pipes already running but not hooked up to any encoder (typical behaviour for gen2-4 VBIOS). Cc: Maarten Lankhorst Fixes: 58d124ea2739 ("drm/i915: Complete crtc hw/uapi split, v6.") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191105171447.22111-1-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_display.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 876fc25968bf..1f93860fb897 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7191,11 +7191,13 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct intel_bw_state *bw_state = to_intel_bw_state(dev_priv->bw_obj.state); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->state); enum intel_display_power_domain domain; struct intel_plane *plane; u64 domains; struct drm_atomic_state *state; - struct intel_crtc_state *crtc_state; + struct intel_crtc_state *temp_crtc_state; int ret; if (!intel_crtc->active) @@ -7219,12 +7221,12 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, state->acquire_ctx = ctx; /* Everything's already locked, -EDEADLK can't happen. */ - crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); + temp_crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); ret = drm_atomic_add_affected_connectors(state, crtc); - WARN_ON(IS_ERR(crtc_state) || ret); + WARN_ON(IS_ERR(temp_crtc_state) || ret); - dev_priv->display.crtc_disable(crtc_state, to_intel_atomic_state(state)); + dev_priv->display.crtc_disable(temp_crtc_state, to_intel_atomic_state(state)); drm_atomic_state_put(state); -- cgit v1.2.3 From cddb85dc1eca10300eb23873f6d9e84267aabd9d Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 6 Nov 2019 12:31:35 +0000 Subject: drm/i915/lmem: fixup fake lmem teardown We should not be unconditionally calling release_fake_lmem_bar. Signed-off-by: Matthew Auld Cc: Lucas De Marchi Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191106123135.12441-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/intel_region_lmem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_region_lmem.c b/drivers/gpu/drm/i915/intel_region_lmem.c index 583118095635..eddb392917aa 100644 --- a/drivers/gpu/drm/i915/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/intel_region_lmem.c @@ -51,8 +51,10 @@ static int init_fake_lmem_bar(struct intel_memory_region *mem) static void release_fake_lmem_bar(struct intel_memory_region *mem) { - if (drm_mm_node_allocated(&mem->fake_mappable)) - drm_mm_remove_node(&mem->fake_mappable); + if (!drm_mm_node_allocated(&mem->fake_mappable)) + return; + + drm_mm_remove_node(&mem->fake_mappable); dma_unmap_resource(&mem->i915->drm.pdev->dev, mem->remap_addr, -- cgit v1.2.3 From 841e86728615baa77b0ea9d8b357e66052c75fe5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 Nov 2019 13:31:29 +0000 Subject: drm/i915/gt: Only drop heartbeat.systole if the sole owner Mika spotted that only using cancel_delayed_work() could mean that we attempted to clear the heartbeat.systole while the worker was still running. Rectify the situation by only touching the systole from outside the worker if we suceeded in cancelling the worker before it could run. The worker is expected to clean up by itself upon idling. Reported-by: Mika Kuoppala Fixes: 058179e72e09 ("drm/i915/gt: Replace hangcheck by heartbeats") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191106133129.17732-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c index 5051f304705b..06aa14c7aa8c 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c @@ -141,8 +141,8 @@ void intel_engine_unpark_heartbeat(struct intel_engine_cs *engine) void intel_engine_park_heartbeat(struct intel_engine_cs *engine) { - cancel_delayed_work(&engine->heartbeat.work); - i915_request_put(fetch_and_zero(&engine->heartbeat.systole)); + if (cancel_delayed_work(&engine->heartbeat.work)) + i915_request_put(fetch_and_zero(&engine->heartbeat.systole)); } void intel_engine_init_heartbeat(struct intel_engine_cs *engine) -- cgit v1.2.3 From feba2b8146633390f8df44946eceb4274f7377ed Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 Nov 2019 14:41:55 +0000 Subject: drm/i915/gem: Fix error path to unlock if the GEM context is closed When inside the lock, remember to unlock even if you want to leave early. Reported-by: Dan Carpenter Fixes: a4e7ccdac38e ("drm/i915: Move context management under GEM") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191106144155.25727-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index de6e55af82cf..d49869b1aa10 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1136,7 +1136,7 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv, if (i915_gem_context_is_closed(ctx)) { err = -ENOENT; - goto out; + goto unlock; } if (vm == rcu_access_pointer(ctx->vm)) -- cgit v1.2.3 From 4b4069985658e8d1932884aa379b0a69c31a9137 Mon Sep 17 00:00:00 2001 From: Niranjana Vishwanathapura Date: Wed, 6 Nov 2019 17:24:16 +0000 Subject: drm/i915: Remove unwanted rcu_read_lock/unlock We don't need rcu read side critical section to call pid_nr(), remove it. Signed-off-by: Niranjana Vishwanathapura Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191106172416.17188-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gpu_error.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index e8b67f5e521d..1f2f266f26af 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1230,10 +1230,7 @@ static void record_request(const struct i915_request *request, erq->start = i915_ggtt_offset(request->ring->vma); erq->head = request->head; erq->tail = request->tail; - - rcu_read_lock(); erq->pid = ctx->pid ? pid_nr(ctx->pid) : 0; - rcu_read_unlock(); } static void engine_record_requests(struct intel_engine_cs *engine, -- cgit v1.2.3 From 6cf6e590ea2e45db1fcf3ef006d5adbd7f7c06ab Mon Sep 17 00:00:00 2001 From: James Ausmus Date: Tue, 5 Nov 2019 16:55:26 -0800 Subject: drm/i915/tgl: Add second TGL PCH ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Another TGP ID has shown up, so let's add it to avoid South Display breakage on systems that have this ID. Cc: Lucas De Marchi Cc: José Roberto de Souza Signed-off-by: James Ausmus Reviewed-by: José Roberto de Souza Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20191106005526.1500-1-james.ausmus@intel.com --- drivers/gpu/drm/i915/intel_pch.c | 1 + drivers/gpu/drm/i915/intel_pch.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c index 000ba43e2c02..fd22355b9a96 100644 --- a/drivers/gpu/drm/i915/intel_pch.c +++ b/drivers/gpu/drm/i915/intel_pch.c @@ -85,6 +85,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) WARN_ON(!IS_ELKHARTLAKE(dev_priv)); return PCH_MCC; case INTEL_PCH_TGP_DEVICE_ID_TYPE: + case INTEL_PCH_TGP2_DEVICE_ID_TYPE: DRM_DEBUG_KMS("Found Tiger Lake LP PCH\n"); WARN_ON(!IS_TIGERLAKE(dev_priv)); return PCH_TGP; diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h index 1115c6a0522c..52d145dcdb15 100644 --- a/drivers/gpu/drm/i915/intel_pch.h +++ b/drivers/gpu/drm/i915/intel_pch.h @@ -47,6 +47,7 @@ enum intel_pch { #define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480 #define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00 #define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080 +#define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380 #define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80 #define INTEL_PCH_JSP2_DEVICE_ID_TYPE 0x3880 #define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100 -- cgit v1.2.3 From 70dfbc29ab9b39b34b4713fb6bacc05d8109968b Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 5 Nov 2019 23:17:17 -0800 Subject: drm/i915: switch intel_ddi_init() to intel types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer using intel_encoder and pass the base where needed rather than keeping both encoder and intel_encoder variables around. v2: actually add all changes to the patch Signed-off-by: Lucas De Marchi Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191106071715.10613-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 56 ++++++++++++++++---------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index c91521bcf06a..398c6f054a6e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4687,8 +4687,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) struct ddi_vbt_port_info *port_info = &dev_priv->vbt.ddi_port_info[port]; struct intel_digital_port *intel_dig_port; - struct intel_encoder *intel_encoder; - struct drm_encoder *encoder; + struct intel_encoder *encoder; bool init_hdmi, init_dp, init_lspcon = false; enum phy phy = intel_port_to_phy(dev_priv, port); @@ -4717,31 +4716,31 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) if (!intel_dig_port) return; - intel_encoder = &intel_dig_port->base; - encoder = &intel_encoder->base; + encoder = &intel_dig_port->base; - drm_encoder_init(&dev_priv->drm, encoder, &intel_ddi_funcs, + drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port)); - intel_encoder->hotplug = intel_ddi_hotplug; - intel_encoder->compute_output_type = intel_ddi_compute_output_type; - intel_encoder->compute_config = intel_ddi_compute_config; - intel_encoder->enable = intel_enable_ddi; - intel_encoder->pre_pll_enable = intel_ddi_pre_pll_enable; - intel_encoder->post_pll_disable = intel_ddi_post_pll_disable; - intel_encoder->pre_enable = intel_ddi_pre_enable; - intel_encoder->disable = intel_disable_ddi; - intel_encoder->post_disable = intel_ddi_post_disable; - intel_encoder->update_pipe = intel_ddi_update_pipe; - intel_encoder->get_hw_state = intel_ddi_get_hw_state; - intel_encoder->get_config = intel_ddi_get_config; - intel_encoder->suspend = intel_dp_encoder_suspend; - intel_encoder->get_power_domains = intel_ddi_get_power_domains; - intel_encoder->type = INTEL_OUTPUT_DDI; - intel_encoder->power_domain = intel_port_to_power_domain(port); - intel_encoder->port = port; - intel_encoder->cloneable = 0; - intel_encoder->pipe_mask = ~0; + encoder->hotplug = intel_ddi_hotplug; + encoder->compute_output_type = intel_ddi_compute_output_type; + encoder->compute_config = intel_ddi_compute_config; + encoder->enable = intel_enable_ddi; + encoder->pre_pll_enable = intel_ddi_pre_pll_enable; + encoder->post_pll_disable = intel_ddi_post_pll_disable; + encoder->pre_enable = intel_ddi_pre_enable; + encoder->disable = intel_disable_ddi; + encoder->post_disable = intel_ddi_post_disable; + encoder->update_pipe = intel_ddi_update_pipe; + encoder->get_hw_state = intel_ddi_get_hw_state; + encoder->get_config = intel_ddi_get_config; + encoder->suspend = intel_dp_encoder_suspend; + encoder->get_power_domains = intel_ddi_get_power_domains; + + encoder->type = INTEL_OUTPUT_DDI; + encoder->power_domain = intel_port_to_power_domain(port); + encoder->port = port; + encoder->cloneable = 0; + encoder->pipe_mask = ~0; if (INTEL_GEN(dev_priv) >= 11) intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & @@ -4749,6 +4748,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) else intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); + intel_dig_port->dp.output_reg = INVALID_MMIO_REG; intel_dig_port->max_lanes = intel_ddi_max_lanes(intel_dig_port); intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); @@ -4759,8 +4759,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) intel_tc_port_init(intel_dig_port, is_legacy); - intel_encoder->update_prepare = intel_ddi_update_prepare; - intel_encoder->update_complete = intel_ddi_update_complete; + encoder->update_prepare = intel_ddi_update_prepare; + encoder->update_complete = intel_ddi_update_complete; } WARN_ON(port > PORT_I); @@ -4776,7 +4776,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) /* In theory we don't need the encoder->type check, but leave it just in * case we have some really bad VBTs... */ - if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) { + if (encoder->type != INTEL_OUTPUT_EDP && init_hdmi) { if (!intel_ddi_init_hdmi_connector(intel_dig_port)) goto err; } @@ -4800,6 +4800,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) return; err: - drm_encoder_cleanup(encoder); + drm_encoder_cleanup(&encoder->base); kfree(intel_dig_port); } -- cgit v1.2.3 From 3466a3def2c01e0ee3e2035f2dc988816cfab460 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 Nov 2019 22:34:10 +0000 Subject: drm/i915/gt: Cleanup heartbeat systole first Before we grab the engine wakeref, tidy up the previous heartbeat request. If we then abort because the engine powerwell is off, we ensure the request is freed as we know we will not have freed it when cancelling the work (as the work is running!). Fixes: 841e86728615 ("drm/i915/gt: Only drop heartbeat.systole if the sole owner") References: 058179e72e09 ("drm/i915/gt: Replace hangcheck by heartbeats") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191106223410.30334-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c index 06aa14c7aa8c..c91fd4e4af29 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c @@ -63,15 +63,15 @@ static void heartbeat(struct work_struct *wrk) struct intel_context *ce = engine->kernel_context; struct i915_request *rq; - if (!intel_engine_pm_get_if_awake(engine)) - return; - rq = engine->heartbeat.systole; if (rq && i915_request_completed(rq)) { i915_request_put(rq); engine->heartbeat.systole = NULL; } + if (!intel_engine_pm_get_if_awake(engine)) + return; + if (intel_gt_is_wedged(engine->gt)) goto out; -- cgit v1.2.3 From f86dbacb30029f4e0396e8b18b0ca60fabaec6c4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 5 Nov 2019 10:01:48 +0100 Subject: drm/i915: Switch obj->mm.lock lockdep annotations on its head The trouble with having a plain nesting flag for locks which do not naturally nest (unlike block devices and their partitions, which is the original motivation for nesting levels) is that lockdep will never spot a true deadlock if you screw up. This patch is an attempt at trying better, by highlighting a bit more of the actual nature of the nesting that's going on. Essentially we have two kinds of objects: - objects without pages allocated, which cannot be on any lru and are hence inaccessible to the shrinker. - objects which have pages allocated, which are on an lru, and which the shrinker can decide to throw out. For the former type of object, memory allocations while holding obj->mm.lock are permissible. For the latter they are not. And get/put_pages transitions between the two types of objects. This is still not entirely fool-proof since the rules might change. But as long as we run such a code ever at runtime lockdep should be able to observe the inconsistency and complain (like with any other lockdep class that we've split up in multiple classes). But there are a few clear benefits: - We can drop the nesting flag parameter from __i915_gem_object_put_pages, because that function by definition is never going allocate memory, and calling it on an object which doesn't have its pages allocated would be a bug. - We strictly catch more bugs, since there's not only one place in the entire tree which is annotated with the special class. All the other places that had explicit lockdep nesting annotations we're now going to leave up to lockdep again. - Specifically this catches stuff like calling get_pages from put_pages (which isn't really a good idea, if we can call get_pages so could the shrinker). I've seen patches do exactly that. Of course I fully expect CI will show me for the fool I am with this one here :-) v2: There can only be one (lockdep only has a cache for the first subclass, not for deeper ones, and we don't want to make these locks even slower). Still separate enums for better documentation. Real fix: don't forget about phys objs and pin_map(), and fix the shrinker to have the right annotations ... silly me. v3: Forgot usertptr too ... v4: Improve comment for pages_pin_count, drop the IMPORTANT comment and instead prime lockdep (Chris). v5: Appease checkpatch, no double empty lines (Chris) v6: More rebasing over selftest changes. Also somehow I forgot to push this patch :-/ Also format comments consistently while at it. v7: Fix typo in commit message (Joonas) Also drop the priming, with the lmem merge we now have allocations while holding the lmem lock, which wreaks the generic priming I've done in earlier patches. Should probably be resurrected when lmem is fixed. See commit 232a6ebae419193f5b8da4fa869ae5089ab105c2 Author: Matthew Auld Date: Tue Oct 8 17:01:14 2019 +0100 drm/i915: introduce intel_memory_region I'm keeping the priming patch locally so it wont get lost. Cc: Matthew Auld Cc: Chris Wilson Cc: "Tang, CQ" Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Reviewed-by: Chris Wilson (v5) Reviewed-by: Joonas Lahtinen (v6) Signed-off-by: Daniel Vetter Signed-off-by: Daniel Vetter Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20191105090148.30269-1-daniel.vetter@ffwll.ch [mlankhorst: Fix commit typos pointed out by Michael Ruhl] --- drivers/gpu/drm/i915/gem/i915_gem_object.c | 4 +++- drivers/gpu/drm/i915/gem/i915_gem_object.h | 17 ++++++++++++++--- drivers/gpu/drm/i915/gem/i915_gem_object_types.h | 6 +++++- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 9 ++++----- drivers/gpu/drm/i915/gem/i915_gem_phys.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_shrinker.c | 5 ++--- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 4 ++-- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 14 +++++++------- drivers/gpu/drm/i915/selftests/intel_memory_region.c | 4 ++-- 9 files changed, 40 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index a50296cce0d8..db103d3c8760 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -22,6 +22,8 @@ * */ +#include + #include "display/intel_frontbuffer.h" #include "gt/intel_gt.h" #include "i915_drv.h" @@ -186,7 +188,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, GEM_BUG_ON(!list_empty(&obj->lut_list)); atomic_set(&obj->mm.pages_pin_count, 0); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); GEM_BUG_ON(i915_gem_object_has_pages(obj)); bitmap_free(obj->bit_17); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 458cd51331f1..edaf7126a84d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -319,11 +319,22 @@ i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock/struct_mutex */ I915_MM_NORMAL = 0, - I915_MM_SHRINKER /* called "recursively" from direct-reclaim-esque */ + /* + * Only used by struct_mutex, when called "recursively" from + * direct-reclaim-esque. Safe because there is only every one + * struct_mutex in the entire system. + */ + I915_MM_SHRINKER = 1, + /* + * Used for obj->mm.lock when allocating pages. Safe because the object + * isn't yet on any LRU, and therefore the shrinker can't deadlock on + * it. As soon as the object has pages, obj->mm.lock nests within + * fs_reclaim. + */ + I915_MM_GET_PAGES = 1, }; -int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, - enum i915_mm_subclass subclass); +int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj); void i915_gem_object_truncate(struct drm_i915_gem_object *obj); void i915_gem_object_writeback(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 96008374a412..15f8297dc34e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -162,7 +162,11 @@ struct drm_i915_gem_object { atomic_t bind_count; struct { - struct mutex lock; /* protects the pages and their use */ + /* + * Protects the pages and their use. Do not use directly, but + * instead go through the pin/unpin interfaces. + */ + struct mutex lock; atomic_t pages_pin_count; atomic_t shrink_pin; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 29f4c2850745..f402c2c415c2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -106,7 +106,7 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj) { int err; - err = mutex_lock_interruptible(&obj->mm.lock); + err = mutex_lock_interruptible_nested(&obj->mm.lock, I915_MM_GET_PAGES); if (err) return err; @@ -190,8 +190,7 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) return pages; } -int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, - enum i915_mm_subclass subclass) +int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) { struct sg_table *pages; int err; @@ -202,7 +201,7 @@ int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, GEM_BUG_ON(atomic_read(&obj->bind_count)); /* May be called by shrinker from within get_pages() (on another bo) */ - mutex_lock_nested(&obj->mm.lock, subclass); + mutex_lock(&obj->mm.lock); if (unlikely(atomic_read(&obj->mm.pages_pin_count))) { err = -EBUSY; goto unlock; @@ -308,7 +307,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, if (!i915_gem_object_type_has(obj, flags)) return ERR_PTR(-ENXIO); - err = mutex_lock_interruptible(&obj->mm.lock); + err = mutex_lock_interruptible_nested(&obj->mm.lock, I915_MM_GET_PAGES); if (err) return ERR_PTR(err); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c index 8043ff63d73f..b1b7c1b3038a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c @@ -164,7 +164,7 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align) if (err) return err; - mutex_lock(&obj->mm.lock); + mutex_lock_nested(&obj->mm.lock, I915_MM_GET_PAGES); if (obj->mm.madv != I915_MADV_WILLNEED) { err = -EFAULT; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c index fd3ce6da8497..066b3df677e8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c @@ -57,7 +57,7 @@ static bool unsafe_drop_pages(struct drm_i915_gem_object *obj, flags = I915_GEM_OBJECT_UNBIND_ACTIVE; if (i915_gem_object_unbind(obj, flags) == 0) - __i915_gem_object_put_pages(obj, I915_MM_SHRINKER); + __i915_gem_object_put_pages(obj); return !i915_gem_object_has_pages(obj); } @@ -209,8 +209,7 @@ i915_gem_shrink(struct drm_i915_private *i915, if (unsafe_drop_pages(obj, shrink)) { /* May arrive from get_pages on another bo */ - mutex_lock_nested(&obj->mm.lock, - I915_MM_SHRINKER); + mutex_lock(&obj->mm.lock); if (!i915_gem_object_has_pages(obj)) { try_to_writeback(obj, shrink); count += obj->base.size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index 1e045c337044..ee65c6acf0e2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -131,7 +131,7 @@ userptr_mn_invalidate_range_start(struct mmu_notifier *_mn, ret = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE); if (ret == 0) - ret = __i915_gem_object_put_pages(obj, I915_MM_SHRINKER); + ret = __i915_gem_object_put_pages(obj); i915_gem_object_put(obj); if (ret) return ret; @@ -483,7 +483,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) } } - mutex_lock(&obj->mm.lock); + mutex_lock_nested(&obj->mm.lock, I915_MM_GET_PAGES); if (obj->userptr.work == &work->work) { struct sg_table *pages = ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 688c49a24f32..5c9583349077 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -517,7 +517,7 @@ static int igt_mock_memory_region_huge_pages(void *arg) i915_vma_unpin(vma); i915_vma_close(vma); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); i915_gem_object_put(obj); } } @@ -650,7 +650,7 @@ static int igt_mock_ppgtt_misaligned_dma(void *arg) i915_vma_close(vma); i915_gem_object_unpin_pages(obj); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); i915_gem_object_put(obj); } @@ -678,7 +678,7 @@ static void close_object_list(struct list_head *objects, list_del(&obj->st_link); i915_gem_object_unpin_pages(obj); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); i915_gem_object_put(obj); } } @@ -948,7 +948,7 @@ static int igt_mock_ppgtt_64K(void *arg) i915_vma_close(vma); i915_gem_object_unpin_pages(obj); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); i915_gem_object_put(obj); } } @@ -1301,7 +1301,7 @@ static int igt_ppgtt_exhaust_huge(void *arg) } i915_gem_object_unpin_pages(obj); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); i915_gem_object_put(obj); } } @@ -1442,7 +1442,7 @@ try_again: } out_unpin: i915_gem_object_unpin_pages(obj); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); out_put: i915_gem_object_put(obj); @@ -1530,7 +1530,7 @@ static int igt_ppgtt_sanity_check(void *arg) err = igt_write_huge(ctx, obj); i915_gem_object_unpin_pages(obj); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); i915_gem_object_put(obj); if (err) { diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 19e1cca8f143..95d609abd39b 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -32,7 +32,7 @@ static void close_objects(struct intel_memory_region *mem, if (i915_gem_object_has_pinned_pages(obj)) i915_gem_object_unpin_pages(obj); /* No polluting the memory region between tests */ - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); list_del(&obj->st_link); i915_gem_object_put(obj); } @@ -122,7 +122,7 @@ put: static void igt_object_release(struct drm_i915_gem_object *obj) { i915_gem_object_unpin_pages(obj); - __i915_gem_object_put_pages(obj, I915_MM_NORMAL); + __i915_gem_object_put_pages(obj); list_del(&obj->st_link); i915_gem_object_put(obj); } -- cgit v1.2.3 From e692b4021a2e48745d4bdac2b2775bdc8f03b433 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Nov 2019 18:37:19 +0100 Subject: lockdep: add might_lock_nested() Necessary to annotate functions where we might acquire a mutex_lock_nested() or similar. Needed by i915. Acked-by: Peter Zijlstra (Intel) Signed-off-by: Daniel Vetter Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: linux-kernel@vger.kernel.org Signed-off-by: Daniel Vetter Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20191104173720.2696-2-daniel.vetter@ffwll.ch --- include/linux/lockdep.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index b8a835fd611b..827722c21797 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -628,6 +628,13 @@ do { \ lock_acquire(&(lock)->dep_map, 0, 0, 1, 1, NULL, _THIS_IP_); \ lock_release(&(lock)->dep_map, 0, _THIS_IP_); \ } while (0) +# define might_lock_nested(lock, subclass) \ +do { \ + typecheck(struct lockdep_map *, &(lock)->dep_map); \ + lock_acquire(&(lock)->dep_map, subclass, 0, 1, 1, NULL, \ + _THIS_IP_); \ + lock_release(&(lock)->dep_map, 0, _THIS_IP_); \ +} while (0) #define lockdep_assert_irqs_enabled() do { \ WARN_ONCE(debug_locks && !current->lockdep_recursion && \ @@ -650,6 +657,7 @@ do { \ #else # define might_lock(lock) do { } while (0) # define might_lock_read(lock) do { } while (0) +# define might_lock_nested(lock, subclass) do { } while (0) # define lockdep_assert_irqs_enabled() do { } while (0) # define lockdep_assert_irqs_disabled() do { } while (0) # define lockdep_assert_in_irq() do { } while (0) -- cgit v1.2.3 From 74ceefd10b1f40b0b4bc71bcf6fe14d4df66c163 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 4 Nov 2019 18:37:20 +0100 Subject: drm/i915: use might_lock_nested in get_pages annotation So strictly speaking the existing annotation is also ok, because we have a chain of obj->mm.lock#I915_MM_GET_PAGES -> fs_reclaim -> obj->mm.lock (the shrinker cannot get at an object while we're in get_pages, hence this is safe). But it's confusing, so try to take the right subclass of the lock. This does a bit reduce our lockdep based checking, but then it's also less fragile, in case we ever change the nesting around. Signed-off-by: Daniel Vetter Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: linux-kernel@vger.kernel.org Signed-off-by: Daniel Vetter Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20191104173720.2696-3-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/gem/i915_gem_object.h | 36 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index edaf7126a84d..e5750d506cc9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -271,10 +271,27 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj); int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj); +enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock/struct_mutex */ + I915_MM_NORMAL = 0, + /* + * Only used by struct_mutex, when called "recursively" from + * direct-reclaim-esque. Safe because there is only every one + * struct_mutex in the entire system. + */ + I915_MM_SHRINKER = 1, + /* + * Used for obj->mm.lock when allocating pages. Safe because the object + * isn't yet on any LRU, and therefore the shrinker can't deadlock on + * it. As soon as the object has pages, obj->mm.lock nests within + * fs_reclaim. + */ + I915_MM_GET_PAGES = 1, +}; + static inline int __must_check i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { - might_lock(&obj->mm.lock); + might_lock_nested(&obj->mm.lock, I915_MM_GET_PAGES); if (atomic_inc_not_zero(&obj->mm.pages_pin_count)) return 0; @@ -317,23 +334,6 @@ i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) __i915_gem_object_unpin_pages(obj); } -enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock/struct_mutex */ - I915_MM_NORMAL = 0, - /* - * Only used by struct_mutex, when called "recursively" from - * direct-reclaim-esque. Safe because there is only every one - * struct_mutex in the entire system. - */ - I915_MM_SHRINKER = 1, - /* - * Used for obj->mm.lock when allocating pages. Safe because the object - * isn't yet on any LRU, and therefore the shrinker can't deadlock on - * it. As soon as the object has pages, obj->mm.lock nests within - * fs_reclaim. - */ - I915_MM_GET_PAGES = 1, -}; - int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj); void i915_gem_object_truncate(struct drm_i915_gem_object *obj); void i915_gem_object_writeback(struct drm_i915_gem_object *obj); -- cgit v1.2.3 From 3c954c418eb363343ff515756e440aa1dc216e0b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 29 Oct 2019 12:39:47 +0200 Subject: drm/i915/display: only include intel_dp_link_training.h where needed The intel_dp_link_training.h include has no need or place in intel_display.h. Include it in intel_display.c instead. Cc: Manasi Navare Fixes: eadf6f9170d5 ("drm/i915/display/icl: Enable master-slaves in trans port sync") Reviewed-by: Manasi Navare Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191029103947.7535-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_display.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1f93860fb897..8e14e5b0507c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -66,6 +66,7 @@ #include "intel_cdclk.h" #include "intel_color.h" #include "intel_display_types.h" +#include "intel_dp_link_training.h" #include "intel_fbc.h" #include "intel_fbdev.h" #include "intel_fifo_underrun.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 4dc490760fbc..a5ec5eeff056 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -27,7 +27,6 @@ #include #include -#include "intel_dp_link_training.h" enum link_m_n_set; struct dpll; -- cgit v1.2.3 From 2b0a4fc25ad8e3da4a156995a513dca6abf247de Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 Nov 2019 22:12:23 +0000 Subject: drm/i915: Leave the aliasing-ppgtt size alone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hidden aliasing-ppgtt's size is never revealed, as we only inspect the front GTT when engaged. However, we were "fixing" the hidden ppgtt to match, with the net result that we ended up leaking the unused portion on Braswell were we preallocated the entire set of top level PDP, see gen8_preallocate_top_level_pdp(). [ 26.025364] DMA-API: pci 0000:00:02.0: device driver has pending DMA allocations while released from device [count=2] [ 26.025364] One of leaked entries details: [device address=0x0000000230778000] [size=4096 bytes] [mapped with DMA_BIDIRECTIONAL] [mapped as single] [ 26.025683] WARNING: CPU: 0 PID: 415 at kernel/dma/debug.c:894 dma_debug_device_change+0x1a4/0x1f0 [ 26.025905] Modules linked in: i915(E-) intel_powerclamp(E) nls_ascii(E) nls_cp437(E) crct10dif_pclmul(E) crc32_pclmul(E) vfat(E) crc32c_intel(E) fat(E) ghash_clmulni_intel(E) prime_numbers(E) intel_gtt(E) i2c_algo_bit(E) efi_pstore(E) drm_kms_helper(E) syscopyarea(E) sysfillrect(E) sysimgblt(E) fb_sys_fops(E) evdev(E) drm(E) aesni_intel(E) glue_helper(E) crypto_simd(E) cryptd(E) intel_cstate(E) sg(E) efivars(E) pcspkr(E) video(E) button(E) efivarfs(E) ip_tables(E) x_tables(E) autofs4(E) sd_mod(E) lpc_ich(E) ahci(E) mfd_core(E) i2c_i801(E) libahci(E) i2c_designware_pci(E) i2c_designware_core(E) [ 26.026613] CPU: 0 PID: 415 Comm: rmmod Tainted: G E 5.4.0-rc6+ #25 [ 26.026837] Hardware name: /, BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015 [ 26.027080] RIP: 0010:dma_debug_device_change+0x1a4/0x1f0 [ 26.027319] Code: 89 54 24 08 e8 ad 60 62 00 48 8b 54 24 08 48 89 c6 41 57 4d 89 e9 49 89 d8 44 89 f1 41 54 48 c7 c7 e0 61 06 82 e8 c1 aa f5 ff <0f> 0b 5a 59 48 83 3c 24 00 0f 85 97 26 00 00 8b 05 77 47 92 01 85 [ 26.027600] RSP: 0018:ffff888228d2fcc8 EFLAGS: 00010282 [ 26.027831] RAX: 0000000000000000 RBX: 0000000230778000 RCX: 0000000000000000 [ 26.028053] RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffffed10451a5f8f [ 26.028279] RBP: ffff88823480c0b0 R08: 0000000000000001 R09: ffffed1046e83eb1 [ 26.028500] R10: ffffed1046e83eb0 R11: ffff88823741f587 R12: ffffffff82067340 [ 26.028725] R13: 0000000000001000 R14: 0000000000000002 R15: ffffffff82067480 [ 26.028952] FS: 00007fdf3ed174c0(0000) GS:ffff888237400000(0000) knlGS:0000000000000000 [ 26.029185] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 26.029405] CR2: 000055e211109030 CR3: 0000000230139000 CR4: 00000000001006f0 [ 26.029622] Call Trace: [ 26.029846] notifier_call_chain+0x67/0xa0 [ 26.030076] blocking_notifier_call_chain+0x5a/0x80 [ 26.030305] device_release_driver_internal+0x20d/0x260 [ 26.030535] driver_detach+0x7b/0xe1 [ 26.030761] bus_remove_driver+0x8c/0x153 [ 26.030993] pci_unregister_driver+0x2d/0xf0 [ 26.032603] i915_exit+0x16/0x1c [i915] Reported-by: Ville Syrjälä Fixes: 1eda701eace2 ("drm/i915/gtt: Recursive cleanup for gen8") References: c082afac86cb ("drm/i915: Move aliasing_ppgtt underneath its i915_ggtt") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191106221223.7437-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 88179202c556..6239a9adbf14 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2609,8 +2609,6 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) GEM_BUG_ON(ggtt->vm.vma_ops.unbind_vma != ggtt_unbind_vma); ggtt->vm.vma_ops.unbind_vma = aliasing_gtt_unbind_vma; - ppgtt->vm.total = ggtt->vm.total; - return 0; err_ppgtt: -- cgit v1.2.3 From 9e678fc9baaab1428ae6abe27d88381b011d31cb Mon Sep 17 00:00:00 2001 From: Ramalingam C Date: Tue, 5 Nov 2019 20:14:14 +0530 Subject: drm/i915: FB backing gem obj should reside in LMEM If Local memory is supported by hardware, we want framebuffer backing gem objects from local memory. if the backing obj is not from LMEM, pin_to_display is failed. v2: memory regions are correctly assigned to obj->memory_regions [tvrtko] migration failure is reported as debug log [Tvrtko] v3: Migration is dropped. only error is reported [Daniel] mem region check is move to pin_to_display [Chris] v4: s/dev_priv/i915 [chris] v5: i915_gem_object_is_lmem is used for detecting the obj mem type. [Matt] cc: Matthew Auld Signed-off-by: Ramalingam C Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191105144414.30470-1-ramalingam.c@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 9937b4c341f1..e2af63af67ad 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -12,6 +12,7 @@ #include "i915_gem_ioctls.h" #include "i915_gem_object.h" #include "i915_vma.h" +#include "i915_gem_lmem.h" static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj) { @@ -419,11 +420,16 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view, unsigned int flags) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); struct i915_vma *vma; int ret; assert_object_held(obj); + /* Frame buffer must be in LMEM (no migration yet) */ + if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj)) + return ERR_PTR(-EINVAL); + /* * The display engine is not coherent with the LLC cache on gen6. As * a result, we make sure that the pinning that is about to occur is @@ -435,7 +441,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, * with that bit in the PTE to main memory with just one PIPE_CONTROL. */ ret = i915_gem_object_set_cache_level(obj, - HAS_WT(to_i915(obj->base.dev)) ? + HAS_WT(i915) ? I915_CACHE_WT : I915_CACHE_NONE); if (ret) return ERR_PTR(ret); -- cgit v1.2.3 From 0ccc42a2fd5107a7f58e62c8b35b61de9a70ce82 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 30 Oct 2019 21:08:15 +0200 Subject: drm/i915: Preload LUTs if the hw isn't currently using them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The LUTs are single buffered so in order to program them without tearing we'd have to do it during vblank (actually to be 100% effective it has to happen between start of vblank and frame start). We have no proper mechanism for that at the moment so we just defer loading them after the vblank waits have happened. That is not quite sufficient (especially when committing multiple pipes whose vblanks don't line up) so the LUT load will often leak into the following frame causing tearing. However in case the hardware wasn't previously using the LUT we can preload it before setting the enable bit (which is double buffered so won't tear). Let's determine if we can do such preloading and make it happen. Slight variation between the hardware requires some platforms specifics in the checks. Hans is seeing ugly colored flash on VLV/CHV macchines (GPD win and Asus T100HA) when the gamma LUT gets loaded for the first time as the BIOS has left some junk in the LUT memory. v2: Deal with uapi vs. hw crtc state split s/GCM/CGM/ typo fix Cc: Hans de Goede Fixes: 051a6d8d3ca0 ("drm/i915: Move LUT programming to happen after vblank waits") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191030190815.7359-1-ville.syrjala@linux.intel.com Tested-by: Hans de Goede Reviewed-by: Hans de Goede --- drivers/gpu/drm/i915/display/intel_atomic.c | 1 + drivers/gpu/drm/i915/display/intel_color.c | 61 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_display.c | 6 +++ drivers/gpu/drm/i915/display/intel_display_types.h | 1 + 4 files changed, 69 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index ea24a45dab86..fd0026fc3618 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -209,6 +209,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->update_wm_pre = false; crtc_state->update_wm_post = false; crtc_state->fifo_changed = false; + crtc_state->preload_luts = false; crtc_state->wm.need_postvbl_update = false; crtc_state->fb_bits = 0; crtc_state->update_planes = 0; diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 5008a3fca484..3980e8b50c28 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1022,6 +1022,55 @@ void intel_color_commit(const struct intel_crtc_state *crtc_state) dev_priv->display.color_commit(crtc_state); } +static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + struct intel_atomic_state *state = + to_intel_atomic_state(new_crtc_state->uapi.state); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + + return !old_crtc_state->hw.gamma_lut && + !old_crtc_state->hw.degamma_lut; +} + +static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + struct intel_atomic_state *state = + to_intel_atomic_state(new_crtc_state->uapi.state); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + + /* + * CGM_PIPE_MODE is itself single buffered. We'd have to + * somehow split it out from chv_load_luts() if we wanted + * the ability to preload the CGM LUTs/CSC without tearing. + */ + if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode) + return false; + + return !old_crtc_state->hw.gamma_lut; +} + +static bool glk_can_preload_luts(const struct intel_crtc_state *new_crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + struct intel_atomic_state *state = + to_intel_atomic_state(new_crtc_state->uapi.state); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + + /* + * The hardware degamma is active whenever the pipe + * CSC is active. Thus even if the old state has no + * software degamma we need to avoid clobbering the + * linear hardware degamma mid scanout. + */ + return !old_crtc_state->csc_enable && + !old_crtc_state->hw.gamma_lut; +} + int intel_color_check(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); @@ -1165,6 +1214,8 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + return 0; } @@ -1217,6 +1268,8 @@ static int chv_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + crtc_state->preload_luts = chv_can_preload_luts(crtc_state); + return 0; } @@ -1271,6 +1324,8 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + return 0; } @@ -1328,6 +1383,8 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + return 0; } @@ -1366,6 +1423,8 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) if (ret) return ret; + crtc_state->preload_luts = glk_can_preload_luts(crtc_state); + return 0; } @@ -1415,6 +1474,8 @@ static int icl_color_check(struct intel_crtc_state *crtc_state) crtc_state->csc_mode = icl_csc_mode(crtc_state); + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); + return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8e14e5b0507c..551de2baa569 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14329,6 +14329,11 @@ static void intel_update_crtc(struct intel_crtc *crtc, /* vblanks work again, re-enable pipe CRC. */ intel_crtc_enable_pipe_crc(crtc); } else { + if (new_crtc_state->preload_luts && + (new_crtc_state->uapi.color_mgmt_changed || + new_crtc_state->update_pipe)) + intel_color_load_luts(new_crtc_state); + intel_pre_plane_update(old_crtc_state, new_crtc_state); if (new_crtc_state->update_pipe) @@ -14842,6 +14847,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->hw.active && !needs_modeset(new_crtc_state) && + !new_crtc_state->preload_luts && (new_crtc_state->uapi.color_mgmt_changed || new_crtc_state->update_pipe)) intel_color_load_luts(new_crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index fadd9853f966..83ea04149b77 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -821,6 +821,7 @@ struct intel_crtc_state { bool disable_cxsr; bool update_wm_pre, update_wm_post; /* watermarks are updated */ bool fifo_changed; /* FIFO split is changed */ + bool preload_luts; /* Pipe source size (ie. panel fitter input size) * All planes will be positioned inside this space, -- cgit v1.2.3 From 7caaed94eade788e79618685a52e223f23786e0d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Nov 2019 08:12:41 +0000 Subject: drm/i915/gt: Defer engine registration until fully initialised MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only add the engine to the available set of uabi engines once it has been fully initialised and we know we want it in the public set. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Michał Wajdeczko Cc: Andi Shyti Acked-by: Andi Shyti Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191107081252.10542-17-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index f8113bc756c6..bf20305a1083 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -344,7 +344,6 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id) gt->engine_class[info->class][info->instance] = engine; gt->engine[id] = engine; - intel_engine_add_user(engine); gt->i915->engine[id] = engine; return 0; @@ -481,6 +480,8 @@ int intel_engines_init(struct intel_gt *gt) err = init(engine); if (err) goto cleanup; + + intel_engine_add_user(engine); } return 0; -- cgit v1.2.3 From 27dbae8f36c1c25008b7885fc07c57054b7dfba3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 Nov 2019 09:13:12 +0000 Subject: drm/i915/gem: Safely acquire the ctx->vm when copying As we read the ctx->vm unlocked before cloning/exporting, we should validate our reference is correct before returning it. We already do for clone_vm() but were not so strict around get_ppgtt(). Signed-off-by: Chris Wilson Reviewed-by: Niranjana Vishwanathapura Link: https://patchwork.freedesktop.org/patch/msgid/20191106091312.12921-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 86 ++++++++++++++++------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index d49869b1aa10..94b51b13ef17 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -169,6 +169,44 @@ lookup_user_engine(struct i915_gem_context *ctx, return i915_gem_context_get_engine(ctx, idx); } +static struct i915_address_space * +context_get_vm_rcu(struct i915_gem_context *ctx) +{ + GEM_BUG_ON(!rcu_access_pointer(ctx->vm)); + + do { + struct i915_address_space *vm; + + /* + * We do not allow downgrading from full-ppgtt [to a shared + * global gtt], so ctx->vm cannot become NULL. + */ + vm = rcu_dereference(ctx->vm); + if (!kref_get_unless_zero(&vm->ref)) + continue; + + /* + * This ppgtt may have be reallocated between + * the read and the kref, and reassigned to a third + * context. In order to avoid inadvertent sharing + * of this ppgtt with that third context (and not + * src), we have to confirm that we have the same + * ppgtt after passing through the strong memory + * barrier implied by a successful + * kref_get_unless_zero(). + * + * Once we have acquired the current ppgtt of ctx, + * we no longer care if it is released from ctx, as + * it cannot be reallocated elsewhere. + */ + + if (vm == rcu_access_pointer(ctx->vm)) + return rcu_pointer_handoff(vm); + + i915_vm_put(vm); + } while (1); +} + static void __free_engines(struct i915_gem_engines *e, unsigned int count) { while (count--) { @@ -1006,7 +1044,7 @@ static int get_ppgtt(struct drm_i915_file_private *file_priv, return -ENODEV; rcu_read_lock(); - vm = i915_vm_get(ctx->vm); + vm = context_get_vm_rcu(ctx); rcu_read_unlock(); ret = mutex_lock_interruptible(&file_priv->vm_idr_lock); @@ -2035,47 +2073,21 @@ static int clone_vm(struct i915_gem_context *dst, struct i915_address_space *vm; int err = 0; - rcu_read_lock(); - do { - vm = rcu_dereference(src->vm); - if (!vm) - break; - - if (!kref_get_unless_zero(&vm->ref)) - continue; - - /* - * This ppgtt may have be reallocated between - * the read and the kref, and reassigned to a third - * context. In order to avoid inadvertent sharing - * of this ppgtt with that third context (and not - * src), we have to confirm that we have the same - * ppgtt after passing through the strong memory - * barrier implied by a successful - * kref_get_unless_zero(). - * - * Once we have acquired the current ppgtt of src, - * we no longer care if it is released from src, as - * it cannot be reallocated elsewhere. - */ - - if (vm == rcu_access_pointer(src->vm)) - break; + if (!rcu_access_pointer(src->vm)) + return 0; - i915_vm_put(vm); - } while (1); + rcu_read_lock(); + vm = context_get_vm_rcu(src); rcu_read_unlock(); - if (vm) { - if (!mutex_lock_interruptible(&dst->mutex)) { - __assign_ppgtt(dst, vm); - mutex_unlock(&dst->mutex); - } else { - err = -EINTR; - } - i915_vm_put(vm); + if (!mutex_lock_interruptible(&dst->mutex)) { + __assign_ppgtt(dst, vm); + mutex_unlock(&dst->mutex); + } else { + err = -EINTR; } + i915_vm_put(vm); return err; } -- cgit v1.2.3 From 6349120ddcbf6267cc4467ee01f852f7bd0cdd42 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Nov 2019 18:05:57 +0000 Subject: drm: Move EXPORT_SYMBOL_FOR_TESTS_ONLY under a separate Kconfig Currently, we only export symbols for drm-selftests which are either compiled as modules or into the main drm builtin. However, if we want to export symbols from drm.ko for the drivers' selftests, we require a means of controlling that export separately. So we add a new Kconfig to determine whether or not the EXPORT_SYMBOL_FOR_TESTS_ONLY() takes effect. Signed-off-by: Chris Wilson Cc: Daniel Vetter Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191107180601.30815-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/Kconfig | 4 ++++ include/drm/drm_util.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index caeef11976e8..e4bf9f8e2430 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -54,6 +54,9 @@ config DRM_DEBUG_MM If in doubt, say "N". +config DRM_EXPORT_FOR_TESTS + bool + config DRM_DEBUG_SELFTEST tristate "kselftests for DRM" depends on DRM @@ -61,6 +64,7 @@ config DRM_DEBUG_SELFTEST select PRIME_NUMBERS select DRM_LIB_RANDOM select DRM_KMS_HELPER + select DRM_EXPORT_FOR_TESTS if m default n help This option provides kernel modules that can be used to run diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h index 07b8e9f04599..79952d8c4bba 100644 --- a/include/drm/drm_util.h +++ b/include/drm/drm_util.h @@ -41,7 +41,7 @@ * Use EXPORT_SYMBOL_FOR_TESTS_ONLY() for functions that shall * only be visible for drmselftests. */ -#if defined(CONFIG_DRM_DEBUG_SELFTEST_MODULE) +#if defined(CONFIG_DRM_EXPORT_FOR_TESTS) #define EXPORT_SYMBOL_FOR_TESTS_ONLY(x) EXPORT_SYMBOL(x) #else #define EXPORT_SYMBOL_FOR_TESTS_ONLY(x) -- cgit v1.2.3 From 4748aa16d5273bf4b42d3581e5e33da1faa69722 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Nov 2019 18:05:58 +0000 Subject: drm: Expose a method for creating anonymous struct file around drm_minor Sometimes we need to create a struct file to wrap a drm_device, as it the user were to have opened /dev/dri/card0 but to do so anonymously (i.e. for internal use). Provide a utility method to create a struct file with the drm_device->driver.fops, that wrap the drm_device. v2: Restrict usage to selftests Signed-off-by: Chris Wilson Cc: Daniel Vetter Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191107180601.30815-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_file.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_file.h | 3 +++ 2 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index ea34bc991858..4d9385d1bf2d 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -31,7 +31,9 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include +#include #include #include #include @@ -754,3 +756,43 @@ void drm_send_event(struct drm_device *dev, struct drm_pending_event *e) spin_unlock_irqrestore(&dev->event_lock, irqflags); } EXPORT_SYMBOL(drm_send_event); + +/** + * mock_drm_getfile - Create a new struct file for the drm device + * @minor: drm minor to wrap (e.g. #drm_device.primary) + * @flags: file creation mode (O_RDWR etc) + * + * This create a new struct file that wraps a DRM file context around a + * DRM minor. This mimicks userspace opening e.g. /dev/dri/card0, but without + * invoking userspace. The struct file may be operated on using its f_op + * (the drm_device.driver.fops) to mimick userspace operations, or be supplied + * to userspace facing functions as an internal/anonymous client. + * + * RETURNS: + * Pointer to newly created struct file, ERR_PTR on failure. + */ +struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags) +{ + struct drm_device *dev = minor->dev; + struct drm_file *priv; + struct file *file; + + priv = drm_file_alloc(minor); + if (IS_ERR(priv)) + return ERR_CAST(priv); + + file = anon_inode_getfile("drm", dev->driver->fops, priv, flags); + if (IS_ERR(file)) { + drm_file_free(priv); + return file; + } + + /* Everyone shares a single global address space */ + file->f_mapping = dev->anon_inode->i_mapping; + + drm_dev_get(dev); + priv->filp = file; + + return file; +} +EXPORT_SYMBOL_FOR_TESTS_ONLY(mock_drm_getfile); diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 67af60bb527a..8b099b347817 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -42,6 +42,7 @@ struct dma_fence; struct drm_file; struct drm_device; struct device; +struct file; /* * FIXME: Not sure we want to have drm_minor here in the end, but to avoid @@ -387,4 +388,6 @@ void drm_event_cancel_free(struct drm_device *dev, void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e); void drm_send_event(struct drm_device *dev, struct drm_pending_event *e); +struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags); + #endif /* _DRM_FILE_H_ */ -- cgit v1.2.3 From 85ca528ed79ca8e8c6d0505dceaa081768dce300 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Nov 2019 18:05:59 +0000 Subject: drm/i915/selftests: Replace mock_file hackery with drm's true fake As drm now exports a method to create an anonymous struct file around a drm_device for internal use, make use of it to avoid our horrible hacks. Danial suggested that the mock_file_put() wrapper was suitable for drm-core, along with the mock_drm_getfile() [and that the vestigal mock_drm_file() in this patch should perhaps be the drm interface itself]. However, the eventual goal is to remove the mock_drm_file() and use the struct file and fput() directly, in this patch we take a simple transition in that direction. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191107180601.30815-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Kconfig.debug | 2 + drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 12 +++--- .../drm/i915/gem/selftests/i915_gem_object_blt.c | 4 +- drivers/gpu/drm/i915/gt/selftest_context.c | 4 +- drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 8 ++-- drivers/gpu/drm/i915/gt/selftest_workarounds.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem.c | 4 +- drivers/gpu/drm/i915/selftests/i915_gem_evict.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 4 +- drivers/gpu/drm/i915/selftests/i915_request.c | 2 +- .../gpu/drm/i915/selftests/intel_memory_region.c | 2 +- drivers/gpu/drm/i915/selftests/mock_drm.c | 49 ++++------------------ drivers/gpu/drm/i915/selftests/mock_drm.h | 8 +++- 14 files changed, 39 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 80815a5229a1..e28face9fd9f 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -29,6 +29,7 @@ config DRM_I915_DEBUG select X86_MSR # used by igt/pm_rpm select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks) select DRM_DEBUG_MM if DRM=y + select DRM_EXPORT_FOR_TESTS if m select DRM_DEBUG_SELFTEST select DMABUF_SELFTESTS select SW_SYNC # signaling validation framework (igt/syncobj*) @@ -152,6 +153,7 @@ config DRM_I915_SELFTEST bool "Enable selftests upon driver load" depends on DRM_I915 default n + select DRM_EXPORT_FOR_TESTS if m select FAULT_INJECTION select PRIME_NUMBERS help diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 5c9583349077..2310ed9b8f89 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1944,6 +1944,6 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915) err = i915_subtests(tests, ctx); out_file: - mock_file_free(i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 62fabc023a83..47890c92534c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -149,7 +149,7 @@ static int live_nop_switch(void *arg) } out_file: - mock_file_free(i915, file); + mock_file_put(file); return err; } @@ -377,7 +377,7 @@ out: } kfree(data); out_file: - mock_file_free(i915, file); + mock_file_put(file); return err; } @@ -716,7 +716,7 @@ out_file: if (igt_live_test_end(&t)) err = -EIO; - mock_file_free(i915, file); + mock_file_put(file); if (err) return err; @@ -854,7 +854,7 @@ out_test: if (igt_live_test_end(&t)) err = -EIO; out_file: - mock_file_free(i915, file); + mock_file_put(file); return err; } @@ -1426,7 +1426,7 @@ out_file: if (igt_live_test_end(&t)) err = -EIO; - mock_file_free(i915, file); + mock_file_put(file); return err; } @@ -1750,7 +1750,7 @@ static int igt_vm_isolation(void *arg) out_file: if (igt_live_test_end(&t)) err = -EIO; - mock_file_free(i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c index e8132aca0bb6..d9fdfddb7091 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c @@ -301,7 +301,7 @@ err_flush: intel_context_put(ce); out_file: - mock_file_free(i915, file); + mock_file_put(file); return err; } @@ -432,7 +432,7 @@ err_flush: intel_context_put(ce); out_file: - mock_file_free(i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index bc720defc6b8..a5688f7d9073 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -313,7 +313,7 @@ static int live_active_context(void *arg) } out_file: - mock_file_free(gt->i915, file); + mock_file_put(file); return err; } @@ -423,7 +423,7 @@ static int live_remote_context(void *arg) } out_file: - mock_file_free(gt->i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c index 85e9ccf5c304..cdaaee4432b2 100644 --- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c @@ -439,7 +439,7 @@ static int igt_reset_nop(void *arg) err = igt_flush_test(gt->i915); out: - mock_file_free(gt->i915, file); + mock_file_put(file); if (intel_gt_is_wedged(gt)) err = -EIO; return err; @@ -535,7 +535,7 @@ static int igt_reset_nop_engine(void *arg) err = igt_flush_test(gt->i915); out: - mock_file_free(gt->i915, file); + mock_file_put(file); if (intel_gt_is_wedged(gt)) err = -EIO; return err; @@ -752,7 +752,7 @@ static int active_engine(void *data) } err_file: - mock_file_free(engine->i915, file); + mock_file_put(file); return err; } @@ -1325,7 +1325,7 @@ static int igt_reset_evict_ppgtt(void *arg) i915_vm_put(vm); out: - mock_file_free(gt->i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c index abce6e4ec9c0..5c69ec5c5ef9 100644 --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c @@ -739,7 +739,7 @@ static int live_dirty_whitelist(void *arg) } out_file: - mock_file_free(gt->i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index d83f6bf6d9d4..aa6282adfd09 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -163,7 +163,7 @@ static int igt_gem_suspend(void *arg) err = switch_to_context(ctx); out: - mock_file_free(i915, file); + mock_file_put(file); return err; } @@ -198,7 +198,7 @@ static int igt_gem_hibernate(void *arg) err = switch_to_context(ctx); out: - mock_file_free(i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c index 42e948144f1b..41092dcea5b1 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c @@ -515,7 +515,7 @@ static int igt_evict_contexts(void *arg) pr_info("Submitted %lu contexts/requests on %s\n", count, engine->name); - mock_file_free(i915, file); + mock_file_put(file); if (err) break; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 3f7e80fb3bbd..c3e0d63c4d0c 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -1026,7 +1026,7 @@ static int exercise_ppgtt(struct drm_i915_private *dev_priv, i915_vm_put(&ppgtt->vm); out_free: - mock_file_free(dev_priv, file); + mock_file_put(file); return err; } @@ -2022,7 +2022,7 @@ out_put_bbe: out_vm: i915_vm_put(vm); out_unlock: - mock_file_free(i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 9e6d3159cd80..7c56ee38cc5b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -1430,7 +1430,7 @@ out_threads: out_smoke: kfree(smoke); out_file: - mock_file_free(i915, file); + mock_file_put(file); out_rpm: intel_runtime_pm_put(&i915->runtime_pm, wakeref); diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 95d609abd39b..f8497ad90f53 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -439,7 +439,7 @@ static int igt_lmem_write_gpu(void *arg) out_put: i915_gem_object_put(obj); out_file: - mock_file_free(i915, file); + mock_file_put(file); return err; } diff --git a/drivers/gpu/drm/i915/selftests/mock_drm.c b/drivers/gpu/drm/i915/selftests/mock_drm.c index 09c704153456..c100c3efe239 100644 --- a/drivers/gpu/drm/i915/selftests/mock_drm.c +++ b/drivers/gpu/drm/i915/selftests/mock_drm.c @@ -22,52 +22,17 @@ * */ +#include + #include "mock_drm.h" struct drm_file *mock_file(struct drm_i915_private *i915) { - struct file *filp; - struct inode *inode; - struct drm_file *file; - int err; - - inode = kzalloc(sizeof(*inode), GFP_KERNEL); - if (!inode) { - err = -ENOMEM; - goto err; - } - - inode->i_rdev = i915->drm.primary->index; - - filp = kzalloc(sizeof(*filp), GFP_KERNEL); - if (!filp) { - err = -ENOMEM; - goto err_inode; - } - - err = drm_open(inode, filp); - if (err) - goto err_filp; + struct file *file; - file = filp->private_data; - memset(&file->filp, POISON_INUSE, sizeof(file->filp)); - file->authenticated = true; - - kfree(filp); - kfree(inode); - return file; - -err_filp: - kfree(filp); -err_inode: - kfree(inode); -err: - return ERR_PTR(err); -} - -void mock_file_free(struct drm_i915_private *i915, struct drm_file *file) -{ - struct file filp = { .private_data = file }; + file = mock_drm_getfile(i915->drm.primary, O_RDWR); + if (IS_ERR(file)) + return ERR_CAST(file); - drm_release(NULL, &filp); + return file->private_data; } diff --git a/drivers/gpu/drm/i915/selftests/mock_drm.h b/drivers/gpu/drm/i915/selftests/mock_drm.h index b39beee9f8f6..dc4190bd3f5a 100644 --- a/drivers/gpu/drm/i915/selftests/mock_drm.h +++ b/drivers/gpu/drm/i915/selftests/mock_drm.h @@ -25,7 +25,13 @@ #ifndef __MOCK_DRM_H #define __MOCK_DRM_H +struct drm_file; +struct drm_i915_private; + struct drm_file *mock_file(struct drm_i915_private *i915); -void mock_file_free(struct drm_i915_private *i915, struct drm_file *file); +static inline void mock_file_put(struct drm_file *file) +{ + fput(file->filp); +} #endif /* !__MOCK_DRM_H */ -- cgit v1.2.3 From 6fedafacae1b951af104d862888a446b6c3f3a39 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Nov 2019 18:06:00 +0000 Subject: drm/i915/selftests: Wrap vm_mmap() around GEM objects Provide a utility function to create a vma corresponding to an mmap() of our device. And use it to exercise the equivalent of userspace performing a GTT mmap of our objects. Signed-off-by: Chris Wilson Cc: Abdiel Janulgue Reviewed-by: Abdiel Janulgue Link: https://patchwork.freedesktop.org/patch/msgid/20191107180601.30815-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 100 +++++++++++++++++++++ drivers/gpu/drm/i915/selftests/igt_mmap.c | 39 ++++++++ drivers/gpu/drm/i915/selftests/igt_mmap.h | 19 ++++ 4 files changed, 159 insertions(+) create mode 100644 drivers/gpu/drm/i915/selftests/igt_mmap.c create mode 100644 drivers/gpu/drm/i915/selftests/igt_mmap.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 90dcf09f52cc..e0fd10c0cfb8 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -259,6 +259,7 @@ i915-$(CONFIG_DRM_I915_SELFTEST) += \ selftests/i915_selftest.o \ selftests/igt_flush_test.o \ selftests/igt_live_test.o \ + selftests/igt_mmap.o \ selftests/igt_reset.o \ selftests/igt_spinner.o diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 29b2077b73d2..e04d0815b84f 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -12,6 +12,7 @@ #include "i915_selftest.h" #include "selftests/i915_random.h" #include "selftests/igt_flush_test.h" +#include "selftests/igt_mmap.h" struct tile { unsigned int width; @@ -694,12 +695,111 @@ err_obj: goto out; } +#define expand32(x) (((x) << 0) | ((x) << 8) | ((x) << 16) | ((x) << 24)) +static int igt_mmap_gtt(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj; + struct vm_area_struct *area; + unsigned long addr; + void *vaddr; + int err, i; + + if (!i915_ggtt_has_aperture(&i915->ggtt)) + return 0; + + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(vaddr)) { + err = PTR_ERR(vaddr); + goto out; + } + memset(vaddr, POISON_INUSE, PAGE_SIZE); + i915_gem_object_flush_map(obj); + i915_gem_object_unpin_map(obj); + + err = create_mmap_offset(obj); + if (err) + goto out; + + addr = igt_mmap_node(i915, &obj->base.vma_node, + 0, PROT_WRITE, MAP_SHARED); + if (IS_ERR_VALUE(addr)) { + err = addr; + goto out; + } + + pr_debug("igt_mmap(obj:gtt) @ %lx\n", addr); + + area = find_vma(current->mm, addr); + if (!area) { + pr_err("Did not create a vm_area_struct for the mmap\n"); + err = -EINVAL; + goto out_unmap; + } + + if (area->vm_private_data != obj) { + pr_err("vm_area_struct did not point back to our object!\n"); + err = -EINVAL; + goto out_unmap; + } + + for (i = 0; i < PAGE_SIZE / sizeof(u32); i++) { + u32 __user *ux = u64_to_user_ptr((u64)(addr + i * sizeof(*ux))); + u32 x; + + if (get_user(x, ux)) { + pr_err("Unable to read from GTT mmap, offset:%zd\n", + i * sizeof(x)); + err = -EFAULT; + break; + } + + if (x != expand32(POISON_INUSE)) { + pr_err("Read incorrect value from GTT mmap, offset:%zd, found:%x, expected:%x\n", + i * sizeof(x), x, expand32(POISON_INUSE)); + err = -EINVAL; + break; + } + + x = expand32(POISON_FREE); + if (put_user(x, ux)) { + pr_err("Unable to write to GTT mmap, offset:%zd\n", + i * sizeof(x)); + err = -EFAULT; + break; + } + } + +out_unmap: + vm_munmap(addr, PAGE_SIZE); + + vaddr = i915_gem_object_pin_map(obj, I915_MAP_FORCE_WC); + if (IS_ERR(vaddr)) { + err = PTR_ERR(vaddr); + goto out; + } + if (err == 0 && memchr_inv(vaddr, POISON_FREE, PAGE_SIZE)) { + pr_err("Write via GGTT mmap did not land in backing store\n"); + err = -EINVAL; + } + i915_gem_object_unpin_map(obj); + +out: + i915_gem_object_put(obj); + return err; +} + int i915_gem_mman_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { SUBTEST(igt_partial_tiling), SUBTEST(igt_smoke_tiling), SUBTEST(igt_mmap_offset_exhaustion), + SUBTEST(igt_mmap_gtt), }; return i915_subtests(tests, i915); diff --git a/drivers/gpu/drm/i915/selftests/igt_mmap.c b/drivers/gpu/drm/i915/selftests/igt_mmap.c new file mode 100644 index 000000000000..583a4ff8b8c9 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/igt_mmap.c @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2019 Intel Corporation + */ + +#include + +#include "i915_drv.h" +#include "igt_mmap.h" + +unsigned long igt_mmap_node(struct drm_i915_private *i915, + struct drm_vma_offset_node *node, + unsigned long addr, + unsigned long prot, + unsigned long flags) +{ + struct file *file; + int err; + + /* Pretend to open("/dev/dri/card0") */ + file = mock_drm_getfile(i915->drm.primary, O_RDWR); + if (IS_ERR(file)) + return PTR_ERR(file); + + err = drm_vma_node_allow(node, file->private_data); + if (err) { + addr = err; + goto out_file; + } + + addr = vm_mmap(file, addr, drm_vma_node_size(node) << PAGE_SHIFT, + prot, flags, drm_vma_node_offset_addr(node)); + + drm_vma_node_revoke(node, file->private_data); +out_file: + fput(file); + return addr; +} diff --git a/drivers/gpu/drm/i915/selftests/igt_mmap.h b/drivers/gpu/drm/i915/selftests/igt_mmap.h new file mode 100644 index 000000000000..6e716cb59d7e --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/igt_mmap.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2019 Intel Corporation + */ + +#ifndef IGT_MMAP_H +#define IGT_MMAP_H + +struct drm_i915_private; +struct drm_vma_offset_node; + +unsigned long igt_mmap_node(struct drm_i915_private *i915, + struct drm_vma_offset_node *node, + unsigned long addr, + unsigned long prot, + unsigned long flags); + +#endif /* IGT_MMAP_H */ -- cgit v1.2.3 From 1d1d0af67939c0a99dbf352628db0016924f8613 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Nov 2019 18:06:01 +0000 Subject: drm/i915/selftests: Verify mmap_gtt revocation on unbinding Whenever, we unbind (or change fence registers) on an object, we must revoke any and all mmap_gtt using the previous bindings. Those user PTEs point at the GGTT which know points into a new object, the wrong object. Ergo, those PTEs must be cleared so that any user access provokes a new page fault. Signed-off-by: Chris Wilson Cc: Abdiel Janulgue Reviewed-by: Abdiel Janulgue Link: https://patchwork.freedesktop.org/patch/msgid/20191107180601.30815-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 111 +++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index e04d0815b84f..cabf45b1403f 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -793,6 +793,116 @@ out: return err; } +static int check_present_pte(pte_t *pte, unsigned long addr, void *data) +{ + if (!pte_present(*pte) || pte_none(*pte)) { + pr_err("missing PTE:%lx\n", + (addr - (unsigned long)data) >> PAGE_SHIFT); + return -EINVAL; + } + + return 0; +} + +static int check_absent_pte(pte_t *pte, unsigned long addr, void *data) +{ + if (pte_present(*pte) && !pte_none(*pte)) { + pr_err("present PTE:%lx; expected to be revoked\n", + (addr - (unsigned long)data) >> PAGE_SHIFT); + return -EINVAL; + } + + return 0; +} + +static int check_present(unsigned long addr, unsigned long len) +{ + return apply_to_page_range(current->mm, addr, len, + check_present_pte, (void *)addr); +} + +static int check_absent(unsigned long addr, unsigned long len) +{ + return apply_to_page_range(current->mm, addr, len, + check_absent_pte, (void *)addr); +} + +static int prefault_range(u64 start, u64 len) +{ + const char __user *addr, *end; + char __maybe_unused c; + int err; + + addr = u64_to_user_ptr(start); + end = addr + len; + + for (; addr < end; addr += PAGE_SIZE) { + err = __get_user(c, addr); + if (err) + return err; + } + + return __get_user(c, end - 1); +} + +static int igt_mmap_gtt_revoke(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj; + unsigned long addr; + int err; + + if (!i915_ggtt_has_aperture(&i915->ggtt)) + return 0; + + obj = i915_gem_object_create_internal(i915, SZ_4M); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + err = create_mmap_offset(obj); + if (err) + goto out; + + addr = igt_mmap_node(i915, &obj->base.vma_node, + 0, PROT_WRITE, MAP_SHARED); + if (IS_ERR_VALUE(addr)) { + err = addr; + goto out; + } + + err = prefault_range(addr, obj->base.size); + if (err) + goto out_unmap; + + GEM_BUG_ON(!atomic_read(&obj->bind_count)); + + err = check_present(addr, obj->base.size); + if (err) + goto out_unmap; + + /* + * After unbinding the object from the GGTT, its address may be reused + * for other objects. Ergo we have to revoke the previous mmap PTE + * access as it no longer points to the same object. + */ + err = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE); + if (err) { + pr_err("Failed to unbind object!\n"); + goto out_unmap; + } + GEM_BUG_ON(atomic_read(&obj->bind_count)); + + err = check_absent(addr, obj->base.size); + if (err) + goto out_unmap; + +out_unmap: + vm_munmap(addr, obj->base.size); +out: + i915_gem_object_put(obj); + return err; +} + int i915_gem_mman_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { @@ -800,6 +910,7 @@ int i915_gem_mman_live_selftests(struct drm_i915_private *i915) SUBTEST(igt_smoke_tiling), SUBTEST(igt_mmap_offset_exhaustion), SUBTEST(igt_mmap_gtt), + SUBTEST(igt_mmap_gtt_revoke), }; return i915_subtests(tests, i915); -- cgit v1.2.3 From 5e19c0b062b43511ac84931b9f61327c638a82f9 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 7 Nov 2019 09:45:27 -0800 Subject: drm/i915: Expand documentation for gen12 DP pre-enable sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than just specifying the bullet numbers from the bspec (e.g., "4.b") actually include the description of what the bspec wants us to do. Steps can be renumbered or moved so including the description will help us match the code up to the spec. Plus if we add support for new platforms, some of the steps may be added/removed so more descriptive comments will be useful for ensuring all of the bspec requirements are met. Cc: José Roberto de Souza Cc: Lucas De Marchi Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191107174527.11165-1-matthew.d.roper@intel.com Reviewed-by: Lucas De Marchi Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 92 +++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 398c6f054a6e..092f0341d8d4 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3438,48 +3438,86 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, intel_dp->regs.dp_tp_ctl = TGL_DP_TP_CTL(transcoder); intel_dp->regs.dp_tp_status = TGL_DP_TP_STATUS(transcoder); - /* 1.a got on intel_atomic_commit_tail() */ + /* + * 1. Enable Power Wells + * + * This was handled at the beginning of intel_atomic_commit_tail(), + * before we called down into this function. + */ - /* 2. */ + /* 2. Enable Panel Power if PPS is required */ intel_edp_panel_on(intel_dp); /* - * 1.b, 3. and 4.a is done before tgl_ddi_pre_enable_dp() by: - * haswell_crtc_enable()->intel_encoders_pre_pll_enable() and - * haswell_crtc_enable()->intel_enable_shared_dpll() + * 3. For non-TBT Type-C ports, set FIA lane count + * (DFLEXDPSP.DPX4TXLATC) + * + * This was done before tgl_ddi_pre_enable_dp by + * haswell_crtc_enable()->intel_encoders_pre_pll_enable(). */ - /* 4.b */ + /* + * 4. Enable the port PLL. + * + * The PLL enabling itself was already done before this function by + * haswell_crtc_enable()->intel_enable_shared_dpll(). We need only + * configure the PLL to port mapping here. + */ intel_ddi_clk_select(encoder, crtc_state); - /* 5. */ + /* 5. If IO power is controlled through PWR_WELL_CTL, Enable IO Power */ if (!intel_phy_is_tc(dev_priv, phy) || dig_port->tc_mode != TC_PORT_TBT_ALT) intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); - /* 6. */ + /* 6. Program DP_MODE */ icl_program_mg_dp_mode(dig_port, crtc_state); /* - * 7.a - single stream or multi-stream master transcoder: Configure - * Transcoder Clock Select. For additional MST streams this will be done - * by intel_mst_pre_enable_dp() after programming VC Payload ID through - * AUX. + * 7. The rest of the below are substeps under the bspec's "Enable and + * Train Display Port" step. Note that steps that are specific to + * MST will be handled by intel_mst_pre_enable_dp() before/after it + * calls into this function. Also intel_mst_pre_enable_dp() only calls + * us when active_mst_links==0, so any steps designated for "single + * stream or multi-stream master transcoder" can just be performed + * unconditionally here. + */ + + /* + * 7.a Configure Transcoder Clock Select to direct the Port clock to the + * Transcoder. */ intel_ddi_enable_pipe_clock(crtc_state); - /* 7.b */ + /* + * 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST + * Transport Select + */ intel_ddi_config_transcoder_func(crtc_state); - /* 7.d */ + /* + * 7.c Configure & enable DP_TP_CTL with link training pattern 1 + * selected + * + * This will be handled by the intel_dp_start_link_train() farther + * down this function. + */ + + /* + * 7.d Type C with DP alternate or fixed/legacy/static connection - + * Disable PHY clock gating per Type-C DDI Buffer page + */ icl_phy_set_clock_gating(dig_port, false); - /* 7.e */ + /* 7.e Configure voltage swing and related IO settings */ tgl_ddi_vswing_sequence(encoder, crtc_state->port_clock, level, encoder->type); - /* 7.f */ + /* + * 7.f Combo PHY: Configure PORT_CL_DW10 Static Power Down to power up + * the used lanes of the DDI. + */ if (intel_phy_is_combo(dev_priv, phy)) { bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; @@ -3489,7 +3527,14 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, lane_reversal); } - /* 7.g */ + /* + * 7.g Configure and enable DDI_BUF_CTL + * 7.h Wait for DDI_BUF_CTL DDI Idle Status = 0b (Not Idle), timeout + * after 500 us. + * + * We only configure what the register value will be here. Actual + * enabling happens during link training farther down. + */ intel_ddi_init_dp_buf_reg(encoder); if (!is_mst) @@ -3502,10 +3547,17 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, * training */ intel_dp_sink_set_fec_ready(intel_dp, crtc_state); - /* 7.c, 7.h, 7.i, 7.j */ + + /* + * 7.i Follow DisplayPort specification training sequence (see notes for + * failure handling) + * 7.j If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle + * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent) + * (timeout after 800 us) + */ intel_dp_start_link_train(intel_dp); - /* 7.k */ + /* 7.k Set DP_TP_CTL link training to Normal */ if (!is_trans_port_sync_mode(crtc_state)) intel_dp_stop_link_train(intel_dp); @@ -3518,7 +3570,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder, * so not enabling it for now. */ - /* 7.l */ + /* 7.l Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); intel_dsc_enable(encoder, crtc_state); } -- cgit v1.2.3 From 080f1288483bb6d78b474ac8038f0d6745eb71c1 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 8 Nov 2019 14:13:55 +0900 Subject: drm/i915: change to_mock() to an inline function Since this function is defined in a header file, it should be 'static inline' instead of 'static'. Signed-off-by: Masahiro Yamada Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191108051356.29980-1-yamada.masahiro@socionext.com --- drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.h b/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.h index f0f8bbd82dfc..22818bbb139d 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.h +++ b/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.h @@ -14,7 +14,7 @@ struct mock_dmabuf { struct page *pages[]; }; -static struct mock_dmabuf *to_mock(struct dma_buf *buf) +static inline struct mock_dmabuf *to_mock(struct dma_buf *buf) { return buf->priv; } -- cgit v1.2.3 From ab11a9270a91c833b9b4e3975443f529d1c7cf17 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 8 Nov 2019 18:41:42 +0900 Subject: drm/i915: make more headers self-contained The headers in the gem/selftests/, gt/selftests, gvt/, selftests/ directories have never been compile-tested, but it would be possible to make them self-contained. This commit only addresses missing and forward struct declarations. Signed-off-by: Masahiro Yamada Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191108094142.25942-1-yamada.masahiro@socionext.com --- drivers/gpu/drm/i915/gem/selftests/mock_context.h | 3 +++ drivers/gpu/drm/i915/gt/selftests/mock_timeline.h | 2 ++ drivers/gpu/drm/i915/gvt/cmd_parser.h | 4 ++++ drivers/gpu/drm/i915/gvt/display.h | 5 +++++ drivers/gpu/drm/i915/gvt/edid.h | 4 ++++ drivers/gpu/drm/i915/gvt/execlist.h | 2 ++ drivers/gpu/drm/i915/gvt/fb_decoder.h | 2 ++ drivers/gpu/drm/i915/gvt/hypercall.h | 4 ++++ drivers/gpu/drm/i915/gvt/interrupt.h | 3 +++ drivers/gpu/drm/i915/gvt/mmio.h | 2 ++ drivers/gpu/drm/i915/gvt/page_track.h | 3 +++ drivers/gpu/drm/i915/gvt/sched_policy.h | 3 +++ drivers/gpu/drm/i915/selftests/mock_gtt.h | 3 +++ drivers/gpu/drm/i915/selftests/mock_region.h | 5 +++++ drivers/gpu/drm/i915/selftests/mock_uncore.h | 3 +++ 15 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.h b/drivers/gpu/drm/i915/gem/selftests/mock_context.h index 0b926653914f..45de09ec28d1 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.h +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.h @@ -7,6 +7,9 @@ #ifndef __MOCK_CONTEXT_H #define __MOCK_CONTEXT_H +struct drm_file; +struct drm_i915_private; + void mock_init_contexts(struct drm_i915_private *i915); struct i915_gem_context * diff --git a/drivers/gpu/drm/i915/gt/selftests/mock_timeline.h b/drivers/gpu/drm/i915/gt/selftests/mock_timeline.h index 689efc66c908..d2bcc3df6183 100644 --- a/drivers/gpu/drm/i915/gt/selftests/mock_timeline.h +++ b/drivers/gpu/drm/i915/gt/selftests/mock_timeline.h @@ -7,6 +7,8 @@ #ifndef __MOCK_TIMELINE__ #define __MOCK_TIMELINE__ +#include + struct intel_timeline; void mock_timeline_init(struct intel_timeline *timeline, u64 context); diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.h b/drivers/gpu/drm/i915/gvt/cmd_parser.h index 286703643002..ab25d151932a 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.h +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.h @@ -38,6 +38,10 @@ #define GVT_CMD_HASH_BITS 7 +struct intel_gvt; +struct intel_shadow_wa_ctx; +struct intel_vgpu_workload; + void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt); int intel_gvt_init_cmd_parser(struct intel_gvt *gvt); diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h index a87f33e6a23c..b59b34046e1e 100644 --- a/drivers/gpu/drm/i915/gvt/display.h +++ b/drivers/gpu/drm/i915/gvt/display.h @@ -35,6 +35,11 @@ #ifndef _GVT_DISPLAY_H_ #define _GVT_DISPLAY_H_ +#include + +struct intel_gvt; +struct intel_vgpu; + #define SBI_REG_MAX 20 #define DPCD_SIZE 0x700 diff --git a/drivers/gpu/drm/i915/gvt/edid.h b/drivers/gpu/drm/i915/gvt/edid.h index f6dfc8b795ec..dfe0cbc6aad8 100644 --- a/drivers/gpu/drm/i915/gvt/edid.h +++ b/drivers/gpu/drm/i915/gvt/edid.h @@ -35,6 +35,10 @@ #ifndef _GVT_EDID_H_ #define _GVT_EDID_H_ +#include + +struct intel_vgpu; + #define EDID_SIZE 128 #define EDID_ADDR 0x50 /* Linux hvm EDID addr */ diff --git a/drivers/gpu/drm/i915/gvt/execlist.h b/drivers/gpu/drm/i915/gvt/execlist.h index 5ccc2c695848..5c0c1fd30c83 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.h +++ b/drivers/gpu/drm/i915/gvt/execlist.h @@ -35,6 +35,8 @@ #ifndef _GVT_EXECLIST_H_ #define _GVT_EXECLIST_H_ +#include + struct execlist_ctx_descriptor_format { union { u32 ldw; diff --git a/drivers/gpu/drm/i915/gvt/fb_decoder.h b/drivers/gpu/drm/i915/gvt/fb_decoder.h index 60c155085029..67b6ede9e707 100644 --- a/drivers/gpu/drm/i915/gvt/fb_decoder.h +++ b/drivers/gpu/drm/i915/gvt/fb_decoder.h @@ -36,6 +36,8 @@ #ifndef _GVT_FB_DECODER_H_ #define _GVT_FB_DECODER_H_ +#include + #define _PLANE_CTL_FORMAT_SHIFT 24 #define _PLANE_CTL_TILED_SHIFT 10 #define _PIPE_V_SRCSZ_SHIFT 0 diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index 4862fb12778e..9599c0a762b2 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -33,6 +33,10 @@ #ifndef _GVT_HYPERCALL_H_ #define _GVT_HYPERCALL_H_ +#include + +struct device; + enum hypervisor_type { INTEL_GVT_HYPERVISOR_XEN = 0, INTEL_GVT_HYPERVISOR_KVM, diff --git a/drivers/gpu/drm/i915/gvt/interrupt.h b/drivers/gpu/drm/i915/gvt/interrupt.h index 5313fb1b33e1..fcd663811d37 100644 --- a/drivers/gpu/drm/i915/gvt/interrupt.h +++ b/drivers/gpu/drm/i915/gvt/interrupt.h @@ -32,6 +32,8 @@ #ifndef _GVT_INTERRUPT_H_ #define _GVT_INTERRUPT_H_ +#include + enum intel_gvt_event_type { RCS_MI_USER_INTERRUPT = 0, RCS_DEBUG, @@ -135,6 +137,7 @@ enum intel_gvt_event_type { struct intel_gvt_irq; struct intel_gvt; +struct intel_vgpu; typedef void (*gvt_event_virt_handler_t)(struct intel_gvt_irq *irq, enum intel_gvt_event_type event, struct intel_vgpu *vgpu); diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index 5874f1cb4306..2e68f4b02c94 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h @@ -36,6 +36,8 @@ #ifndef _GVT_MMIO_H_ #define _GVT_MMIO_H_ +#include + struct intel_gvt; struct intel_vgpu; diff --git a/drivers/gpu/drm/i915/gvt/page_track.h b/drivers/gpu/drm/i915/gvt/page_track.h index fa607a71c3c0..f6eb7135583c 100644 --- a/drivers/gpu/drm/i915/gvt/page_track.h +++ b/drivers/gpu/drm/i915/gvt/page_track.h @@ -25,6 +25,9 @@ #ifndef _GVT_PAGE_TRACK_H_ #define _GVT_PAGE_TRACK_H_ +#include + +struct intel_vgpu; struct intel_vgpu_page_track; typedef int (*gvt_page_track_handler_t)( diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.h b/drivers/gpu/drm/i915/gvt/sched_policy.h index 7b59e3e88b8b..3dacdad5f529 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.h +++ b/drivers/gpu/drm/i915/gvt/sched_policy.h @@ -34,6 +34,9 @@ #ifndef __GVT_SCHED_POLICY__ #define __GVT_SCHED_POLICY__ +struct intel_gvt; +struct intel_vgpu; + struct intel_gvt_sched_policy_ops { int (*init)(struct intel_gvt *gvt); void (*clean)(struct intel_gvt *gvt); diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.h b/drivers/gpu/drm/i915/selftests/mock_gtt.h index 3387393286de..e3f224f43beb 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.h +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.h @@ -25,6 +25,9 @@ #ifndef __MOCK_GTT_H #define __MOCK_GTT_H +struct drm_i915_private; +struct i915_ggtt; + void mock_init_ggtt(struct drm_i915_private *i915, struct i915_ggtt *ggtt); void mock_fini_ggtt(struct i915_ggtt *ggtt); diff --git a/drivers/gpu/drm/i915/selftests/mock_region.h b/drivers/gpu/drm/i915/selftests/mock_region.h index 24608089d833..329bf74dfaca 100644 --- a/drivers/gpu/drm/i915/selftests/mock_region.h +++ b/drivers/gpu/drm/i915/selftests/mock_region.h @@ -6,6 +6,11 @@ #ifndef __MOCK_REGION_H #define __MOCK_REGION_H +#include + +struct drm_i915_private; +struct intel_memory_region; + struct intel_memory_region * mock_region_create(struct drm_i915_private *i915, resource_size_t start, diff --git a/drivers/gpu/drm/i915/selftests/mock_uncore.h b/drivers/gpu/drm/i915/selftests/mock_uncore.h index 8a2cc553f466..7acf1ef4d488 100644 --- a/drivers/gpu/drm/i915/selftests/mock_uncore.h +++ b/drivers/gpu/drm/i915/selftests/mock_uncore.h @@ -25,6 +25,9 @@ #ifndef __MOCK_UNCORE_H #define __MOCK_UNCORE_H +struct drm_i915_private; +struct intel_uncore; + void mock_uncore_init(struct intel_uncore *uncore, struct drm_i915_private *i915); -- cgit v1.2.3 From a8c9a7f52ec5a4b36ce183efd5fda4e4fd90ec45 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Nov 2019 21:39:29 +0000 Subject: drm/i915/selftests: Complete transition to a real struct file mock Since drm provided us with a real struct file we can use for our anonymous internal clients (mock_file), complete our transition to using that as the primary interface (and not the mocked up struct drm_file we previous were using). Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191107213929.23286-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 4 +-- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 34 +++++++++---------- .../drm/i915/gem/selftests/i915_gem_object_blt.c | 8 ++--- drivers/gpu/drm/i915/gem/selftests/mock_context.c | 5 +-- drivers/gpu/drm/i915/gem/selftests/mock_context.h | 2 +- drivers/gpu/drm/i915/gt/selftest_context.c | 8 ++--- drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 16 ++++----- drivers/gpu/drm/i915/gt/selftest_workarounds.c | 4 +-- drivers/gpu/drm/i915/i915_drv.c | 4 --- drivers/gpu/drm/i915/selftests/i915_gem.c | 8 ++--- drivers/gpu/drm/i915/selftests/i915_gem_evict.c | 4 +-- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 8 ++--- drivers/gpu/drm/i915/selftests/i915_request.c | 4 +-- .../gpu/drm/i915/selftests/intel_memory_region.c | 4 +-- drivers/gpu/drm/i915/selftests/mock_drm.c | 38 ---------------------- drivers/gpu/drm/i915/selftests/mock_drm.h | 15 ++++++--- 16 files changed, 66 insertions(+), 100 deletions(-) delete mode 100644 drivers/gpu/drm/i915/selftests/mock_drm.c diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 2310ed9b8f89..3f992491f537 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1912,9 +1912,9 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915) SUBTEST(igt_ppgtt_smoke_huge), SUBTEST(igt_ppgtt_sanity_check), }; - struct drm_file *file; struct i915_gem_context *ctx; struct i915_address_space *vm; + struct file *file; int err; if (!HAS_PPGTT(i915)) { @@ -1944,6 +1944,6 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915) err = i915_subtests(tests, ctx); out_file: - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 47890c92534c..896f47d80a1c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -33,7 +33,7 @@ static int live_nop_switch(void *arg) struct intel_engine_cs *engine; struct i915_gem_context **ctx; struct igt_live_test t; - struct drm_file *file; + struct file *file; unsigned long n; int err = -ENODEV; @@ -149,7 +149,7 @@ static int live_nop_switch(void *arg) } out_file: - mock_file_put(file); + fput(file); return err; } @@ -255,7 +255,7 @@ static int live_parallel_switch(void *arg) int (* const *fn)(void *arg); struct i915_gem_context *ctx; struct intel_context *ce; - struct drm_file *file; + struct file *file; int n, m, count; int err = 0; @@ -377,7 +377,7 @@ out: } kfree(data); out_file: - mock_file_put(file); + fput(file); return err; } @@ -502,17 +502,17 @@ out_unmap: return err; } -static int file_add_object(struct drm_file *file, - struct drm_i915_gem_object *obj) +static int file_add_object(struct file *file, struct drm_i915_gem_object *obj) { int err; GEM_BUG_ON(obj->base.handle_count); /* tie the object to the drm_file for easy reaping */ - err = idr_alloc(&file->object_idr, &obj->base, 1, 0, GFP_KERNEL); + err = idr_alloc(&to_drm_file(file)->object_idr, + &obj->base, 1, 0, GFP_KERNEL); if (err < 0) - return err; + return err; i915_gem_object_get(obj); obj->base.handle_count++; @@ -521,7 +521,7 @@ static int file_add_object(struct drm_file *file, static struct drm_i915_gem_object * create_test_object(struct i915_address_space *vm, - struct drm_file *file, + struct file *file, struct list_head *objects) { struct drm_i915_gem_object *obj; @@ -621,9 +621,9 @@ static int igt_ctx_exec(void *arg) unsigned long ncontexts, ndwords, dw; struct i915_request *tq[5] = {}; struct igt_live_test t; - struct drm_file *file; IGT_TIMEOUT(end_time); LIST_HEAD(objects); + struct file *file; if (!intel_engine_can_store_dword(engine)) continue; @@ -716,7 +716,7 @@ out_file: if (igt_live_test_end(&t)) err = -EIO; - mock_file_put(file); + fput(file); if (err) return err; @@ -733,7 +733,7 @@ static int igt_shared_ctx_exec(void *arg) struct i915_gem_context *parent; struct intel_engine_cs *engine; struct igt_live_test t; - struct drm_file *file; + struct file *file; int err = 0; /* @@ -854,7 +854,7 @@ out_test: if (igt_live_test_end(&t)) err = -EIO; out_file: - mock_file_put(file); + fput(file); return err; } @@ -1317,10 +1317,10 @@ static int igt_ctx_readonly(void *arg) struct i915_gem_context *ctx; unsigned long idx, ndwords, dw; struct igt_live_test t; - struct drm_file *file; I915_RND_STATE(prng); IGT_TIMEOUT(end_time); LIST_HEAD(objects); + struct file *file; int err = -ENODEV; /* @@ -1426,7 +1426,7 @@ out_file: if (igt_live_test_end(&t)) err = -EIO; - mock_file_put(file); + fput(file); return err; } @@ -1663,9 +1663,9 @@ static int igt_vm_isolation(void *arg) struct i915_gem_context *ctx_a, *ctx_b; struct intel_engine_cs *engine; struct igt_live_test t; - struct drm_file *file; I915_RND_STATE(prng); unsigned long count; + struct file *file; u64 vm_total; int err; @@ -1750,7 +1750,7 @@ static int igt_vm_isolation(void *arg) out_file: if (igt_live_test_end(&t)) err = -EIO; - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c index d9fdfddb7091..dd43ea0c9025 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c @@ -198,7 +198,7 @@ static int igt_fill_blt_thread(void *arg) struct drm_i915_gem_object *obj; struct i915_gem_context *ctx; struct intel_context *ce; - struct drm_file *file; + struct file *file; unsigned int prio; IGT_TIMEOUT(end); int err; @@ -301,7 +301,7 @@ err_flush: intel_context_put(ce); out_file: - mock_file_put(file); + fput(file); return err; } @@ -313,7 +313,7 @@ static int igt_copy_blt_thread(void *arg) struct drm_i915_gem_object *src, *dst; struct i915_gem_context *ctx; struct intel_context *ce; - struct drm_file *file; + struct file *file; unsigned int prio; IGT_TIMEOUT(end); int err; @@ -432,7 +432,7 @@ err_flush: intel_context_put(ce); out_file: - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.c b/drivers/gpu/drm/i915/gem/selftests/mock_context.c index 29b8984f0e47..cdcb006321a7 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.c @@ -5,6 +5,7 @@ */ #include "mock_context.h" +#include "selftests/mock_drm.h" #include "selftests/mock_gtt.h" struct i915_gem_context * @@ -74,7 +75,7 @@ void mock_init_contexts(struct drm_i915_private *i915) } struct i915_gem_context * -live_context(struct drm_i915_private *i915, struct drm_file *file) +live_context(struct drm_i915_private *i915, struct file *file) { struct i915_gem_context *ctx; int err; @@ -83,7 +84,7 @@ live_context(struct drm_i915_private *i915, struct drm_file *file) if (IS_ERR(ctx)) return ctx; - err = gem_context_register(ctx, file->driver_priv); + err = gem_context_register(ctx, to_drm_file(file)->driver_priv); if (err < 0) goto err_ctx; diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.h b/drivers/gpu/drm/i915/gem/selftests/mock_context.h index 45de09ec28d1..c858db2362f1 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.h +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.h @@ -19,7 +19,7 @@ mock_context(struct drm_i915_private *i915, void mock_context_close(struct i915_gem_context *ctx); struct i915_gem_context * -live_context(struct drm_i915_private *i915, struct drm_file *file); +live_context(struct drm_i915_private *i915, struct file *file); struct i915_gem_context *kernel_context(struct drm_i915_private *i915); void kernel_context_close(struct i915_gem_context *ctx); diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index a5688f7d9073..14ba6ceb9177 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -289,7 +289,7 @@ static int live_active_context(void *arg) struct intel_engine_cs *engine; struct i915_gem_context *fixme; enum intel_engine_id id; - struct drm_file *file; + struct file *file; int err = 0; file = mock_file(gt->i915); @@ -313,7 +313,7 @@ static int live_active_context(void *arg) } out_file: - mock_file_put(file); + fput(file); return err; } @@ -399,7 +399,7 @@ static int live_remote_context(void *arg) struct intel_engine_cs *engine; struct i915_gem_context *fixme; enum intel_engine_id id; - struct drm_file *file; + struct file *file; int err = 0; file = mock_file(gt->i915); @@ -423,7 +423,7 @@ static int live_remote_context(void *arg) } out_file: - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c index cdaaee4432b2..d155c9374453 100644 --- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c @@ -380,8 +380,8 @@ static int igt_reset_nop(void *arg) struct i915_gem_context *ctx; unsigned int reset_count, count; enum intel_engine_id id; - struct drm_file *file; IGT_TIMEOUT(end_time); + struct file *file; int err = 0; /* Check that we can reset during non-user portions of requests */ @@ -439,7 +439,7 @@ static int igt_reset_nop(void *arg) err = igt_flush_test(gt->i915); out: - mock_file_put(file); + fput(file); if (intel_gt_is_wedged(gt)) err = -EIO; return err; @@ -452,7 +452,7 @@ static int igt_reset_nop_engine(void *arg) struct intel_engine_cs *engine; struct i915_gem_context *ctx; enum intel_engine_id id; - struct drm_file *file; + struct file *file; int err = 0; /* Check that we can engine-reset during non-user portions */ @@ -535,7 +535,7 @@ static int igt_reset_nop_engine(void *arg) err = igt_flush_test(gt->i915); out: - mock_file_put(file); + fput(file); if (intel_gt_is_wedged(gt)) err = -EIO; return err; @@ -700,8 +700,8 @@ static int active_engine(void *data) struct intel_engine_cs *engine = arg->engine; struct i915_request *rq[8] = {}; struct i915_gem_context *ctx[ARRAY_SIZE(rq)]; - struct drm_file *file; unsigned long count = 0; + struct file *file; int err = 0; file = mock_file(engine->i915); @@ -752,7 +752,7 @@ static int active_engine(void *data) } err_file: - mock_file_put(file); + fput(file); return err; } @@ -1302,7 +1302,7 @@ static int igt_reset_evict_ppgtt(void *arg) struct intel_gt *gt = arg; struct i915_gem_context *ctx; struct i915_address_space *vm; - struct drm_file *file; + struct file *file; int err; file = mock_file(gt->i915); @@ -1325,7 +1325,7 @@ static int igt_reset_evict_ppgtt(void *arg) i915_vm_put(vm); out: - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c index 5c69ec5c5ef9..d5d1e1a32187 100644 --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c @@ -711,7 +711,7 @@ static int live_dirty_whitelist(void *arg) struct intel_engine_cs *engine; struct i915_gem_context *ctx; enum intel_engine_id id; - struct drm_file *file; + struct file *file; int err = 0; /* Can the user write to the whitelisted registers? */ @@ -739,7 +739,7 @@ static int live_dirty_whitelist(void *arg) } out_file: - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 82e4e6bf08c3..64f8ba3449ed 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2781,7 +2781,3 @@ static struct drm_driver driver = { .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, }; - -#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) -#include "selftests/mock_drm.c" -#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index aa6282adfd09..657e23a8dd11 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -136,7 +136,7 @@ static int igt_gem_suspend(void *arg) { struct drm_i915_private *i915 = arg; struct i915_gem_context *ctx; - struct drm_file *file; + struct file *file; int err; file = mock_file(i915); @@ -163,7 +163,7 @@ static int igt_gem_suspend(void *arg) err = switch_to_context(ctx); out: - mock_file_put(file); + fput(file); return err; } @@ -171,7 +171,7 @@ static int igt_gem_hibernate(void *arg) { struct drm_i915_private *i915 = arg; struct i915_gem_context *ctx; - struct drm_file *file; + struct file *file; int err; file = mock_file(i915); @@ -198,7 +198,7 @@ static int igt_gem_hibernate(void *arg) err = switch_to_context(ctx); out: - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c index 41092dcea5b1..5f133d177212 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c @@ -466,7 +466,7 @@ static int igt_evict_contexts(void *arg) /* Overfill the GGTT with context objects and so try to evict one. */ for_each_engine(engine, gt, id) { struct i915_sw_fence fence; - struct drm_file *file; + struct file *file; file = mock_file(i915); if (IS_ERR(file)) { @@ -515,7 +515,7 @@ static int igt_evict_contexts(void *arg) pr_info("Submitted %lu contexts/requests on %s\n", count, engine->name); - mock_file_put(file); + fput(file); if (err) break; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index c3e0d63c4d0c..d94db487c4dd 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -1001,9 +1001,9 @@ static int exercise_ppgtt(struct drm_i915_private *dev_priv, u64 hole_start, u64 hole_end, unsigned long end_time)) { - struct drm_file *file; struct i915_ppgtt *ppgtt; IGT_TIMEOUT(end_time); + struct file *file; int err; if (!HAS_FULL_PPGTT(dev_priv)) @@ -1026,7 +1026,7 @@ static int exercise_ppgtt(struct drm_i915_private *dev_priv, i915_vm_put(&ppgtt->vm); out_free: - mock_file_put(file); + fput(file); return err; } @@ -1782,9 +1782,9 @@ static int igt_cs_tlb(void *arg) struct i915_address_space *vm; struct i915_gem_context *ctx; struct intel_context *ce; - struct drm_file *file; struct i915_vma *vma; I915_RND_STATE(prng); + struct file *file; unsigned int i; u32 *result; u32 *batch; @@ -2022,7 +2022,7 @@ out_put_bbe: out_vm: i915_vm_put(vm); out_unlock: - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 7c56ee38cc5b..50cc7ca9afba 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -1306,9 +1306,9 @@ static int live_breadcrumbs_smoketest(void *arg) struct task_struct **threads; struct igt_live_test live; intel_wakeref_t wakeref; - struct drm_file *file; struct smoketest *smoke; unsigned int n, idx; + struct file *file; int ret = 0; /* @@ -1430,7 +1430,7 @@ out_threads: out_smoke: kfree(smoke); out_file: - mock_file_put(file); + fput(file); out_rpm: intel_runtime_pm_put(&i915->runtime_pm, wakeref); diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index f8497ad90f53..b60916561462 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -404,7 +404,7 @@ static int igt_lmem_write_gpu(void *arg) struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; struct i915_gem_context *ctx; - struct drm_file *file; + struct file *file; I915_RND_STATE(prng); u32 sz; int err; @@ -439,7 +439,7 @@ static int igt_lmem_write_gpu(void *arg) out_put: i915_gem_object_put(obj); out_file: - mock_file_put(file); + fput(file); return err; } diff --git a/drivers/gpu/drm/i915/selftests/mock_drm.c b/drivers/gpu/drm/i915/selftests/mock_drm.c deleted file mode 100644 index c100c3efe239..000000000000 --- a/drivers/gpu/drm/i915/selftests/mock_drm.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright © 2017 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 "mock_drm.h" - -struct drm_file *mock_file(struct drm_i915_private *i915) -{ - struct file *file; - - file = mock_drm_getfile(i915->drm.primary, O_RDWR); - if (IS_ERR(file)) - return ERR_CAST(file); - - return file->private_data; -} diff --git a/drivers/gpu/drm/i915/selftests/mock_drm.h b/drivers/gpu/drm/i915/selftests/mock_drm.h index dc4190bd3f5a..d7f49e149f0c 100644 --- a/drivers/gpu/drm/i915/selftests/mock_drm.h +++ b/drivers/gpu/drm/i915/selftests/mock_drm.h @@ -25,13 +25,20 @@ #ifndef __MOCK_DRM_H #define __MOCK_DRM_H -struct drm_file; +#include + struct drm_i915_private; +struct drm_file; +struct file; + +static inline struct file *mock_file(struct drm_i915_private *i915) +{ + return mock_drm_getfile(i915->drm.primary, O_RDWR); +} -struct drm_file *mock_file(struct drm_i915_private *i915); -static inline void mock_file_put(struct drm_file *file) +static inline struct drm_file *to_drm_file(struct file *f) { - fput(file->filp); + return f->private_data; } #endif /* !__MOCK_DRM_H */ -- cgit v1.2.3 From b5572d312d5925ff05b46c42ccbad0e945dc813c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 7 Nov 2019 22:12:01 +0000 Subject: drm/i915/selftests: Mark up sole accessor to ctx->vm as being protected In the selftests, where we are accessing a private ctx from within the confines of a single test, we know that the ctx->vm pointer is static and bounded by the lifetime of the test. We can use a simple helper to provide the RCU annotations to keep sparse happy. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191107221201.30497-1-chris@chris-wilson.co.uk --- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 896f47d80a1c..9a509c18b7c7 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -26,6 +26,12 @@ #define DW_PER_PAGE (PAGE_SIZE / sizeof(u32)) +static inline struct i915_address_space *ctx_vm(struct i915_gem_context *ctx) +{ + /* single threaded, private ctx */ + return rcu_dereference_protected(ctx->vm, true); +} + static int live_nop_switch(void *arg) { const unsigned int nctx = 1024; @@ -786,14 +792,15 @@ static int igt_shared_ctx_exec(void *arg) } mutex_lock(&ctx->mutex); - __assign_ppgtt(ctx, parent->vm); + __assign_ppgtt(ctx, ctx_vm(parent)); mutex_unlock(&ctx->mutex); ce = i915_gem_context_get_engine(ctx, engine->legacy_idx); GEM_BUG_ON(IS_ERR(ce)); if (!obj) { - obj = create_test_object(parent->vm, file, &objects); + obj = create_test_object(ctx_vm(parent), + file, &objects); if (IS_ERR(obj)) { err = PTR_ERR(obj); intel_context_put(ce); @@ -1343,14 +1350,11 @@ static int igt_ctx_readonly(void *arg) goto out_file; } - rcu_read_lock(); - vm = rcu_dereference(ctx->vm) ?: &i915->ggtt.alias->vm; + vm = ctx_vm(ctx) ?: &i915->ggtt.alias->vm; if (!vm || !vm->has_read_only) { - rcu_read_unlock(); err = 0; goto out_file; } - rcu_read_unlock(); ndwords = 0; dw = 0; @@ -1380,7 +1384,7 @@ static int igt_ctx_readonly(void *arg) pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n", ndwords, dw, max_dwords(obj), ce->engine->name, - yesno(!!rcu_access_pointer(ctx->vm)), + yesno(!!ctx_vm(ctx)), err); i915_gem_context_unlock_engines(ctx); goto out_file; @@ -1698,11 +1702,11 @@ static int igt_vm_isolation(void *arg) } /* We can only test vm isolation, if the vm are distinct */ - if (ctx_a->vm == ctx_b->vm) + if (ctx_vm(ctx_a) == ctx_vm(ctx_b)) goto out_file; - vm_total = ctx_a->vm->total; - GEM_BUG_ON(ctx_b->vm->total != vm_total); + vm_total = ctx_vm(ctx_a)->total; + GEM_BUG_ON(ctx_vm(ctx_b)->total != vm_total); vm_total -= I915_GTT_PAGE_SIZE; count = 0; -- cgit v1.2.3 From c1c82d267ae8b42de0802c31fabeb843189adb9d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 8 Nov 2019 10:35:10 +0000 Subject: drm/i915/pmu: Cheat when reading the actual frequency to avoid fw We want to avoid taking forcewake when querying the performance stats, as we wish to avoid perturbing the system under observation. (And with the forcewake being kept alive for 1ms after use, sampling the frequency from a 200Hz timer keeps forcewake 40% active.) Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191108103511.20951-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_pmu.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 05395015d1f2..8e74f40413b8 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -366,8 +366,21 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns) val = rps->cur_freq; if (intel_gt_pm_get_if_awake(gt)) { - val = intel_uncore_read_notrace(uncore, GEN6_RPSTAT1); - val = intel_get_cagf(rps, val); + u32 stat; + + /* + * We take a quick peek here without using forcewake + * so that we don't perturb the system under observation + * (forcewake => !rc6 => increased power use). We expect + * that if the read fails because it is outside of the + * mmio power well, then it will return 0 -- in which + * case we assume the system is running at the intended + * frequency. Fortunately, the read should rarely fail! + */ + stat = intel_uncore_read_fw(uncore, GEN6_RPSTAT1); + if (stat) + val = intel_get_cagf(rps, stat); + intel_gt_pm_put(gt); } -- cgit v1.2.3 From d79e1bd676f090f359a30e9fff4b992dcc071347 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 8 Nov 2019 10:35:11 +0000 Subject: drm/i915/pmu: Only use exclusive mmio access for gen7 On gen7, we have to avoid concurrent access to the same mmio cacheline, and so coordinate all mmio access with the uncore->lock. However, for pmu, we want to avoid perturbing the system and disabling interrupts unnecessarily, so restrict the w/a to gen7 where it is requied to prevent machine hangs. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191108103511.20951-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_pmu.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 8e74f40413b8..4804775644bf 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -292,6 +292,16 @@ add_sample(struct i915_pmu_sample *sample, u32 val) sample->cur += val; } +static bool exclusive_mmio_access(const struct drm_i915_private *i915) +{ + /* + * We have to avoid concurrent mmio cache line access on gen7 or + * risk a machine hang. For a fun history lesson dig out the old + * userspace intel_gpu_top and run it on Ivybridge or Haswell! + */ + return IS_GEN(i915, 7); +} + static void engines_sample(struct intel_gt *gt, unsigned int period_ns) { @@ -304,6 +314,7 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns) for_each_engine(engine, gt, id) { struct intel_engine_pmu *pmu = &engine->pmu; + spinlock_t *mmio_lock; unsigned long flags; bool busy; u32 val; @@ -311,7 +322,12 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns) if (!intel_engine_pm_get_if_awake(engine)) continue; - spin_lock_irqsave(&engine->uncore->lock, flags); + mmio_lock = NULL; + if (exclusive_mmio_access(i915)) + mmio_lock = &engine->uncore->lock; + + if (unlikely(mmio_lock)) + spin_lock_irqsave(mmio_lock, flags); val = ENGINE_READ_FW(engine, RING_CTL); if (val == 0) /* powerwell off => engine idle */ @@ -342,7 +358,8 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns) add_sample(&pmu->sample[I915_SAMPLE_BUSY], period_ns); skip: - spin_unlock_irqrestore(&engine->uncore->lock, flags); + if (unlikely(mmio_lock)) + spin_unlock_irqrestore(mmio_lock, flags); intel_engine_pm_put(engine); } } -- cgit v1.2.3 From baea9ffe64200033499a4955f431e315bb807899 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 6 Nov 2019 19:23:49 +0200 Subject: drm/i915: Don't oops in dumb_create ioctl if we have no crtcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we have a crtc before probing its primary plane's max stride. Initially I thought we can't get this far without crtcs, but looks like we can via the dumb_create ioctl. Not sure if we shouldn't disable dumb buffer support entirely when we have no crtcs, but that would require some amount of work as the only thing currently being checked is dev->driver->dumb_create which we'd have to convert to some device specific dynamic thing. Cc: stable@vger.kernel.org Reported-by: Mika Kuoppala Fixes: aa5ca8b7421c ("drm/i915: Align dumb buffer stride to 4k to allow for gtt remapping") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191106172349.11987-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/display/intel_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 551de2baa569..5f3340554149 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2544,6 +2544,9 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, * the highest stride limits of them all. */ crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A); + if (!crtc) + return 0; + plane = to_intel_plane(crtc->base.primary); return plane->max_stride(plane, pixel_format, modifier, -- cgit v1.2.3 From 0b0120d4c7b013eba59b33254febc0a6e4049e13 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Mon, 11 Nov 2019 11:53:08 +0200 Subject: drm/i915/perf: always consider holding preemption a privileged op The ordering of the checks in the existing code can lead to holding preemption not being considered as privileged op. Signed-off-by: Lionel Landwerlin Fixes: 9cd20ef7803c ("drm/i915/perf: allow holding preemption on filtered ctx") Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191111095308.2550-1-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 2c380aba1ce9..507236bd41ae 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -3312,15 +3312,6 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf, } } - if (props->hold_preemption) { - if (!props->single_context) { - DRM_DEBUG("preemption disable with no context\n"); - ret = -EINVAL; - goto err; - } - privileged_op = true; - } - /* * On Haswell the OA unit supports clock gating off for a specific * context and in this mode there's no visibility of metrics for the @@ -3340,12 +3331,21 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf, * doesn't request global stream access (i.e. query based sampling * using MI_RECORD_PERF_COUNT. */ - if (IS_HASWELL(perf->i915) && specific_ctx && !props->hold_preemption) + if (IS_HASWELL(perf->i915) && specific_ctx) privileged_op = false; else if (IS_GEN(perf->i915, 12) && specific_ctx && (props->sample_flags & SAMPLE_OA_REPORT) == 0) privileged_op = false; + if (props->hold_preemption) { + if (!props->single_context) { + DRM_DEBUG("preemption disable with no context\n"); + ret = -EINVAL; + goto err; + } + privileged_op = true; + } + /* Similar to perf's kernel.perf_paranoid_cpu sysctl option * we check a dev.i915.perf_stream_paranoid sysctl option * to determine if it's ok to access system wide OA counters -- cgit v1.2.3 From 028a7a989cb57790868df20e50dff682e73e33e6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 10 Nov 2019 18:57:50 +0000 Subject: drm/i915/icl: Refine PG_HYSTERESIS After doing some measuring, Icelake behaves on a par with Broadwell, and without having to compromise for low power cores with long latencies, we can reduce the powergating hysteresis so that the powersaving is enabled faster. No impact observed on client side throughput measures (so negligible increase in extra switching), and inspection from high frequency polling using igt/gem_exec_nop/sequential, provided an estimate for the upper bound before we can measure a substantial impact on latency. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191110185806.17413-9-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rc6.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 5ad4a92a9582..5e3ba034bd46 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -88,15 +88,12 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) * do not want the enable hysteresis to less than the wakeup latency. * * igt/gem_exec_nop/sequential provides a rough estimate for the - * service latency, and puts it around 10us for Broadwell (and other - * big core) and around 40us for Broxton (and other low power cores). - * [Note that for legacy ringbuffer submission, this is less than 1us!] - * However, the wakeup latency on Broxton is closer to 100us. To be - * conservative, we have to factor in a context switch on top (due - * to ksoftirqd). + * service latency, and puts it under 10us for Icelake, similar to + * Broadwell+, To be conservative, we want to factor in a context + * switch on top (due to ksoftirqd). */ - set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 250); - set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 250); + set(uncore, GEN9_MEDIA_PG_IDLE_HYSTERESIS, 60); + set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60); /* 3a: Enable RC6 */ set(uncore, GEN6_RC_CONTROL, -- cgit v1.2.3 From fecffa4668cf62e679aeea8caa9d0f241f822578 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 11:43:19 +0000 Subject: drm/i915: Protect context while grabbing its name for the request Inside print_request(), we query the context/timeline name. Nothing immediately protects the context from being freed if the request is complete -- we rely on serialisation by the caller to keep the name valid until they finish using it. Inside intel_engine_dump(), we generally only print the requests in the execution queue protected by the engine->active.lock, but we also show the pending execlists ports which are not protected and so require a rcu_read_lock to keep the pointer valid. [ 1695.700883] BUG: KASAN: use-after-free in i915_fence_get_timeline_name+0x53/0x90 [i915] [ 1695.700981] Read of size 8 at addr ffff8887344f4d50 by task gem_ctx_persist/2968 [ 1695.701068] [ 1695.701156] CPU: 1 PID: 2968 Comm: gem_ctx_persist Tainted: G U 5.4.0-rc6+ #331 [ 1695.701246] Hardware name: Intel Corporation NUC7i5BNK/NUC7i5BNB, BIOS BNKBL357.86A.0052.2017.0918.1346 09/18/2017 [ 1695.701334] Call Trace: [ 1695.701424] dump_stack+0x5b/0x90 [ 1695.701870] ? i915_fence_get_timeline_name+0x53/0x90 [i915] [ 1695.701964] print_address_description.constprop.7+0x36/0x50 [ 1695.702408] ? i915_fence_get_timeline_name+0x53/0x90 [i915] [ 1695.702856] ? i915_fence_get_timeline_name+0x53/0x90 [i915] [ 1695.702947] __kasan_report.cold.10+0x1a/0x3a [ 1695.703390] ? i915_fence_get_timeline_name+0x53/0x90 [i915] [ 1695.703836] i915_fence_get_timeline_name+0x53/0x90 [i915] [ 1695.704241] print_request+0x82/0x2e0 [i915] [ 1695.704638] ? fwtable_read32+0x133/0x360 [i915] [ 1695.705042] ? write_timestamp+0x110/0x110 [i915] [ 1695.705133] ? _raw_spin_lock_irqsave+0x79/0xc0 [ 1695.705221] ? refcount_inc_not_zero_checked+0x91/0x110 [ 1695.705306] ? refcount_dec_and_mutex_lock+0x50/0x50 [ 1695.705709] ? intel_engine_find_active_request+0x202/0x230 [i915] [ 1695.706115] intel_engine_dump+0x2c9/0x900 [i915] Fixes: c36eebd9ba5d ("drm/i915/gt: execlists->active is serialised by the tasklet") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191111114323.5833-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index bf20305a1083..b9613d044393 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1373,6 +1373,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine, } execlists_active_lock_bh(execlists); + rcu_read_lock(); for (port = execlists->active; (rq = *port); port++) { char hdr[80]; int len; @@ -1410,6 +1411,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine, if (tl) intel_timeline_put(tl); } + rcu_read_unlock(); execlists_active_unlock_bh(execlists); } else if (INTEL_GEN(dev_priv) > 6) { drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n", -- cgit v1.2.3 From fc4f125d958f4e8ce3477f990fb916fe1806daff Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 11:43:20 +0000 Subject: drm/i915/gem: Embed context/timeline name inside the GEM context Use a small char buffer inside the i915_gem_context to store the user friendly name so that ctx->name has the same lifetime as the RCU protected GEM context. That is, e.g. when using print_request() that prints the timeline name (ctx->name), the name will not be prematurely freed upon the context being closed and the last reference dropped. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Matthew Auld Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191111114323.5833-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 12 ++---------- drivers/gpu/drm/i915/gem/i915_gem_context_types.h | 18 +++++++++--------- drivers/gpu/drm/i915/gem/selftests/mock_context.c | 4 +--- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 94b51b13ef17..982770e8163d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -277,9 +277,7 @@ static void i915_gem_context_free(struct i915_gem_context *ctx) if (ctx->timeline) intel_timeline_put(ctx->timeline); - kfree(ctx->name); put_pid(ctx->pid); - mutex_destroy(&ctx->mutex); kfree_rcu(ctx, rcu); @@ -789,12 +787,8 @@ static int gem_context_register(struct i915_gem_context *ctx, mutex_unlock(&ctx->mutex); ctx->pid = get_task_pid(current, PIDTYPE_PID); - ctx->name = kasprintf(GFP_KERNEL, "%s[%d]", - current->comm, pid_nr(ctx->pid)); - if (!ctx->name) { - ret = -ENOMEM; - goto err_pid; - } + snprintf(ctx->name, sizeof(ctx->name), "%s[%d]", + current->comm, pid_nr(ctx->pid)); /* And finally expose ourselves to userspace via the idr */ mutex_lock(&fpriv->context_idr_lock); @@ -803,8 +797,6 @@ static int gem_context_register(struct i915_gem_context *ctx, if (ret >= 0) goto out; - kfree(fetch_and_zero(&ctx->name)); -err_pid: put_pid(fetch_and_zero(&ctx->pid)); out: return ret; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index 861d7d92fe9f..69df5459c350 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -100,15 +100,6 @@ struct i915_gem_context { */ struct pid *pid; - /** - * @name: arbitrary name - * - * A name is constructed for the context from the creator's process - * name, pid and user handle in order to uniquely identify the - * context in messages. - */ - const char *name; - /** link: place with &drm_i915_private.context_list */ struct list_head link; struct llist_node free_link; @@ -176,6 +167,15 @@ struct i915_gem_context { * per vm, which may be one per context or shared with the global GTT) */ struct radix_tree_root handles_vma; + + /** + * @name: arbitrary name, used for user debug + * + * A name is constructed for the context from the creator's process + * name, pid and user handle in order to uniquely identify the + * context in messages. + */ + char name[TASK_COMM_LEN + 8]; }; #endif /* __I915_GEM_CONTEXT_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.c b/drivers/gpu/drm/i915/gem/selftests/mock_context.c index cdcb006321a7..53e89efb09c0 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.c @@ -37,9 +37,7 @@ mock_context(struct drm_i915_private *i915, if (name) { struct i915_ppgtt *ppgtt; - ctx->name = kstrdup(name, GFP_KERNEL); - if (!ctx->name) - goto err_put; + strncpy(ctx->name, name, sizeof(ctx->name)); ppgtt = mock_ppgtt(i915, name); if (!ppgtt) -- cgit v1.2.3 From 267c012635c2a5cdeedf6ccf85b57add3f7826b3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 11:43:21 +0000 Subject: drm/i915/gem: Update context name on closing Update the context.name on closing so that the persistent requests are clear in debug prints. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191111114323.5833-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 982770e8163d..72d389afa28a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -461,11 +461,29 @@ static void kill_context(struct i915_gem_context *ctx) } } +static void set_closed_name(struct i915_gem_context *ctx) +{ + char *s; + + /* Replace '[]' with '<>' to indicate closed in debug prints */ + + s = strrchr(ctx->name, '['); + if (!s) + return; + + *s = '<'; + + s = strchr(s + 1, ']'); + if (s) + *s = '>'; +} + static void context_close(struct i915_gem_context *ctx) { struct i915_address_space *vm; i915_gem_context_set_closed(ctx); + set_closed_name(ctx); mutex_lock(&ctx->mutex); -- cgit v1.2.3 From dfd9c1b4eab124c16c3b59362c3640983bf79949 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 11:43:22 +0000 Subject: drm/i915: Show guilty context name on GPU reset We mention that we are resetting the GPU, and dump the device state for post mortem debugging. However, while that dump contains the active processes and the one flagged as causing the error, we do not always include that information in dmesg. Include the name of the guilty process in dmesg for reference. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191111114323.5833-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_reset.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index f03e000051c1..86d52383bf9d 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -87,6 +87,10 @@ static bool context_mark_guilty(struct i915_gem_context *ctx) if (!i915_gem_context_is_bannable(ctx)) return false; + dev_notice(ctx->i915->drm.dev, + "%s context reset due to GPU hang\n", + ctx->name); + /* Record the timestamp for the last N hangs */ prev_hang = ctx->hang_timestamp[0]; for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp) - 1; i++) -- cgit v1.2.3 From e8887bb3eb6f55401e0d0f9ee5739e5baca4a58c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 11:43:23 +0000 Subject: drm/i915: Cancel context if it hangs after it is closed If we detect a hang in a closed context, just flush all of its requests and cancel any remaining execution along the context. Note that after closing the context, the last reference to the context may be dropped, leaving it only valid under RCU. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191111114323.5833-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_reset.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 86d52383bf9d..b7007cd78c6f 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -81,6 +81,11 @@ static bool context_mark_guilty(struct i915_gem_context *ctx) bool banned; int i; + if (i915_gem_context_is_closed(ctx)) { + i915_gem_context_set_banned(ctx); + return true; + } + atomic_inc(&ctx->guilty_count); /* Cool contexts are too cool to be banned! (Used for reset testing.) */ @@ -128,6 +133,7 @@ void __i915_request_reset(struct i915_request *rq, bool guilty) GEM_BUG_ON(i915_request_completed(rq)); + rcu_read_lock(); /* protect the GEM context */ if (guilty) { i915_request_skip(rq, -EIO); if (context_mark_guilty(rq->gem_context)) @@ -136,6 +142,7 @@ void __i915_request_reset(struct i915_request *rq, bool guilty) dma_fence_set_error(&rq->fence, -EAGAIN); context_mark_innocent(rq->gem_context); } + rcu_read_unlock(); } static bool i915_in_reset(struct pci_dev *pdev) -- cgit v1.2.3 From e88866ef02851c88fe95a4bb97820b94b4d46f36 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 9 Nov 2019 10:53:56 +0000 Subject: drm/i915/pmu: "Frequency" is reported as accumulated cycles We report "frequencies" (actual-frequency, requested-frequency) as the number of accumulated cycles so that the average frequency over that period may be determined by the user. This means the units we report to the user are Mcycles (or just M), not MHz. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191109105356.5273-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_pmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 4804775644bf..9b02be0ad4e6 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -908,8 +908,8 @@ create_event_attributes(struct i915_pmu *pmu) const char *name; const char *unit; } events[] = { - __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "MHz"), - __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "MHz"), + __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "M"), + __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "M"), __event(I915_PMU_INTERRUPTS, "interrupts", NULL), __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"), }; -- cgit v1.2.3 From 34485832cb98727fb9ceaf68a51160ad2f942344 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 12:27:05 +0000 Subject: drm/i915/selftests: Exercise parallel blit operations on a single ctx Make sure that our code is robust enough to handle multiple threads trying to clear objects for a single client context. This brings the joy of a shared GGTT to all! References: https://bugs.freedesktop.org/show_bug.cgi?id=112176 Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191111122706.28292-1-chris@chris-wilson.co.uk --- .../drm/i915/gem/selftests/i915_gem_object_blt.c | 93 +++++++++++++--------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c index dd43ea0c9025..8a0fba7d5d4f 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c @@ -186,6 +186,8 @@ err_src: struct igt_thread_arg { struct drm_i915_private *i915; + struct i915_gem_context *ctx; + struct file *file; struct rnd_state prng; unsigned int n_cpus; }; @@ -198,24 +200,20 @@ static int igt_fill_blt_thread(void *arg) struct drm_i915_gem_object *obj; struct i915_gem_context *ctx; struct intel_context *ce; - struct file *file; unsigned int prio; IGT_TIMEOUT(end); int err; - file = mock_file(i915); - if (IS_ERR(file)) - return PTR_ERR(file); + ctx = thread->ctx; + if (!ctx) { + ctx = live_context(i915, thread->file); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); - ctx = live_context(i915, file); - if (IS_ERR(ctx)) { - err = PTR_ERR(ctx); - goto out_file; + prio = i915_prandom_u32_max_state(I915_PRIORITY_MAX, prng); + ctx->sched.priority = I915_USER_PRIORITY(prio); } - prio = i915_prandom_u32_max_state(I915_PRIORITY_MAX, prng); - ctx->sched.priority = I915_USER_PRIORITY(prio); - ce = i915_gem_context_get_engine(ctx, BCS0); GEM_BUG_ON(IS_ERR(ce)); @@ -300,8 +298,6 @@ err_flush: err = 0; intel_context_put(ce); -out_file: - fput(file); return err; } @@ -313,24 +309,20 @@ static int igt_copy_blt_thread(void *arg) struct drm_i915_gem_object *src, *dst; struct i915_gem_context *ctx; struct intel_context *ce; - struct file *file; unsigned int prio; IGT_TIMEOUT(end); int err; - file = mock_file(i915); - if (IS_ERR(file)) - return PTR_ERR(file); + ctx = thread->ctx; + if (!ctx) { + ctx = live_context(i915, thread->file); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); - ctx = live_context(i915, file); - if (IS_ERR(ctx)) { - err = PTR_ERR(ctx); - goto out_file; + prio = i915_prandom_u32_max_state(I915_PRIORITY_MAX, prng); + ctx->sched.priority = I915_USER_PRIORITY(prio); } - prio = i915_prandom_u32_max_state(I915_PRIORITY_MAX, prng); - ctx->sched.priority = I915_USER_PRIORITY(prio); - ce = i915_gem_context_get_engine(ctx, BCS0); GEM_BUG_ON(IS_ERR(ce)); @@ -431,19 +423,19 @@ err_flush: err = 0; intel_context_put(ce); -out_file: - fput(file); return err; } static int igt_threaded_blt(struct drm_i915_private *i915, - int (*blt_fn)(void *arg)) + int (*blt_fn)(void *arg), + unsigned int flags) +#define SINGLE_CTX BIT(0) { struct igt_thread_arg *thread; struct task_struct **tsk; + unsigned int n_cpus, i; I915_RND_STATE(prng); - unsigned int n_cpus; - unsigned int i; + struct file *file; int err = 0; n_cpus = num_online_cpus() + 1; @@ -453,13 +445,27 @@ static int igt_threaded_blt(struct drm_i915_private *i915, return 0; thread = kcalloc(n_cpus, sizeof(struct igt_thread_arg), GFP_KERNEL); - if (!thread) { - kfree(tsk); - return 0; + if (!thread) + goto out_tsk; + + thread[0].file = mock_file(i915); + if (IS_ERR(thread[0].file)) { + err = PTR_ERR(file); + goto out_thread; + } + + if (flags & SINGLE_CTX) { + thread[0].ctx = live_context(i915, thread[0].file); + if (IS_ERR(thread[0].ctx)) { + err = PTR_ERR(thread[0].ctx); + goto out_file; + } } for (i = 0; i < n_cpus; ++i) { thread[i].i915 = i915; + thread[i].file = thread[0].file; + thread[i].ctx = thread[0].ctx; thread[i].n_cpus = n_cpus; thread[i].prng = I915_RND_STATE_INITIALIZER(prandom_u32_state(&prng)); @@ -488,20 +494,33 @@ static int igt_threaded_blt(struct drm_i915_private *i915, put_task_struct(tsk[i]); } - kfree(tsk); +out_file: + fput(thread[0].file); +out_thread: kfree(thread); - +out_tsk: + kfree(tsk); return err; } static int igt_fill_blt(void *arg) { - return igt_threaded_blt(arg, igt_fill_blt_thread); + return igt_threaded_blt(arg, igt_fill_blt_thread, 0); +} + +static int igt_fill_blt_ctx0(void *arg) +{ + return igt_threaded_blt(arg, igt_fill_blt_thread, SINGLE_CTX); } static int igt_copy_blt(void *arg) { - return igt_threaded_blt(arg, igt_copy_blt_thread); + return igt_threaded_blt(arg, igt_copy_blt_thread, 0); +} + +static int igt_copy_blt_ctx0(void *arg) +{ + return igt_threaded_blt(arg, igt_copy_blt_thread, SINGLE_CTX); } int i915_gem_object_blt_live_selftests(struct drm_i915_private *i915) @@ -510,7 +529,9 @@ int i915_gem_object_blt_live_selftests(struct drm_i915_private *i915) SUBTEST(perf_fill_blt), SUBTEST(perf_copy_blt), SUBTEST(igt_fill_blt), + SUBTEST(igt_fill_blt_ctx0), SUBTEST(igt_copy_blt), + SUBTEST(igt_copy_blt_ctx0), }; if (intel_gt_is_wedged(&i915->gt)) -- cgit v1.2.3 From 1af65515e36306a3dbe935b46e1d970188b1e5e0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 12:27:06 +0000 Subject: drm/i915/selftests: Fill all the drm_vma_manager holes To test mmap_offset_exhaustion, we first have to fill the entire vma manager leaving a single page. Don't assume that the vma manager is not already fragment, and fill all the holes. Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191111122706.28292-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 51 +++++++++++++++++----- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index cabf45b1403f..9f1a69027a04 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -607,28 +607,49 @@ static int igt_mmap_offset_exhaustion(void *arg) struct drm_i915_private *i915 = arg; struct drm_mm *mm = &i915->drm.vma_offset_manager->vm_addr_space_mm; struct drm_i915_gem_object *obj; - struct drm_mm_node resv, *hole; - u64 hole_start, hole_end; + struct drm_mm_node *hole, *next; int loop, err; /* Disable background reaper */ disable_retire_worker(i915); GEM_BUG_ON(!i915->gt.awake); + intel_gt_retire_requests(&i915->gt); + i915_gem_drain_freed_objects(i915); /* Trim the device mmap space to only a page */ - memset(&resv, 0, sizeof(resv)); - drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { - resv.start = hole_start; - resv.size = hole_end - hole_start - 1; /* PAGE_SIZE units */ - mmap_offset_lock(i915); - err = drm_mm_reserve_node(mm, &resv); - mmap_offset_unlock(i915); + mmap_offset_lock(i915); + loop = 1; /* PAGE_SIZE units */ + list_for_each_entry_safe(hole, next, &mm->hole_stack, hole_stack) { + struct drm_mm_node *resv; + + resv = kzalloc(sizeof(*resv), GFP_NOWAIT); + if (!resv) { + err = -ENOMEM; + goto out_park; + } + + resv->start = drm_mm_hole_node_start(hole) + loop; + resv->size = hole->hole_size - loop; + resv->color = -1ul; + loop = 0; + + if (!resv->size) { + kfree(resv); + continue; + } + + pr_debug("Reserving hole [%llx + %llx]\n", + resv->start, resv->size); + + err = drm_mm_reserve_node(mm, resv); if (err) { pr_err("Failed to trim VMA manager, err=%d\n", err); + kfree(resv); goto out_park; } - break; } + GEM_BUG_ON(!list_is_singular(&mm->hole_stack)); + mmap_offset_unlock(i915); /* Just fits! */ if (!assert_mmap_offset(i915, PAGE_SIZE, 0)) { @@ -685,9 +706,15 @@ static int igt_mmap_offset_exhaustion(void *arg) out: mmap_offset_lock(i915); - drm_mm_remove_node(&resv); - mmap_offset_unlock(i915); out_park: + drm_mm_for_each_node_safe(hole, next, mm) { + if (hole->color != -1ul) + continue; + + drm_mm_remove_node(hole); + kfree(hole); + } + mmap_offset_unlock(i915); restore_retire_worker(i915); return err; err_obj: -- cgit v1.2.3 From 7a73e671acbaf00ad6aa4ee0e3f39e3c9a9ef563 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 10 Nov 2019 18:57:54 +0000 Subject: drm/i915: Taint the kernel on dumping the GEM ftrace buffer As the ftrace buffer is single shot, once dumped it will not update. As such, it only provides information for the first bug and all subsequent bugs are noise. The goal of CI is to have zero bugs, so taint the kernel causing CI to reboot the machine; fix the bug and move on. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191110185806.17413-13-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index f6f9675848b8..36a8c7673c4f 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -68,9 +68,10 @@ struct drm_i915_private; pr_err(__VA_ARGS__); \ trace_printk(__VA_ARGS__); \ } while (0) -#define GEM_TRACE_DUMP() ftrace_dump(DUMP_ALL) +#define GEM_TRACE_DUMP() \ + do { ftrace_dump(DUMP_ALL); add_taint_for_CI(TAINT_WARN); } while (0) #define GEM_TRACE_DUMP_ON(expr) \ - do { if (expr) ftrace_dump(DUMP_ALL); } while (0) + do { if (expr) GEM_TRACE_DUMP(); } while (0) #else #define GEM_TRACE(...) do { } while (0) #define GEM_TRACE_ERR(...) do { } while (0) -- cgit v1.2.3 From 69a48c1d28e05893607b89515442b993cd5326ed Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 10 Nov 2019 18:57:51 +0000 Subject: drm/i915/execlists: Reduce barrier on context switch to a wmb() Having been forced to reduce Braswell back to using the aliasing ppgtt, the coherency issue we previously observed cannot impact us. Reduce the performance penalty imposed on all platforms from using the mfence to a mere sfence. References: cf66b8a0ba14 ("drm/i915/execlists: Apply a full mb before execution for Braswell") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191110185806.17413-10-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 1975fe4775d2..e57345795c08 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1218,13 +1218,8 @@ static u64 execlists_update_context(const struct i915_request *rq) * may not be visible to the HW prior to the completion of the UC * register write and that we may begin execution from the context * before its image is complete leading to invalid PD chasing. - * - * Furthermore, Braswell, at least, wants a full mb to be sure that - * the writes are coherent in memory (visible to the GPU) prior to - * execution, and not just visible to other CPUs (as is the result of - * wmb). */ - mb(); + wmb(); desc = ce->lrc_desc; ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE; -- cgit v1.2.3 From bd8c9cca88765caee0dfa93967c6d8f16b4cbfb9 Mon Sep 17 00:00:00 2001 From: Gwan-gyeong Mun Date: Wed, 6 Nov 2019 23:26:36 +0200 Subject: drm/i915: Split a setting of MSA to MST and SST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The setting of MSA is done by the DDI .pre_enable() hook. And when we are using MST, the MSA is only set to first mst stream by calling of DDI .pre_eanble() hook. It raies issues to non-first mst streams. Wrong MSA or missed MSA packets might show scrambled screen or wrong screen. This splits a setting of MSA to MST and SST cases. And In the MST case it will call a setting of MSA after an allocating of Virtual Channel from MST encoder pre_enable callback. Cc: Ville Syrjälä Cc: Stanislav Lisovskiy Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112212 Fixes: 0c06fa156006 ("drm/i915/dp: Add support of BT.2020 Colorimetry to DP MSA") Fixes: d4a415dcda35 ("drm/i915: Fix MST oops due to MSA changes") Signed-off-by: Gwan-gyeong Mun Link: https://patchwork.freedesktop.org/patch/msgid/20191106212636.502471-1-gwan-gyeong.mun@intel.com Reviewed-by: Lucas De Marchi [vsyrjala: nuke spurious newline] Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_ddi.c | 10 ++++++---- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 092f0341d8d4..a387aea1c809 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1794,10 +1794,8 @@ void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state, * of Color Encoding Format and Content Color Gamut] while sending * YCBCR 420, HDR BT.2020 signals we should program MSA MISC1 fields * which indicate VSC SDP for the Pixel Encoding/Colorimetry Format. - * - * FIXME MST doesn't pass in the conn_state */ - if (conn_state && intel_dp_needs_vsc_sdp(crtc_state, conn_state)) + if (intel_dp_needs_vsc_sdp(crtc_state, conn_state)) temp |= DP_MSA_MISC_COLOR_VSC_SDP; I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp); @@ -3658,7 +3656,11 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, else hsw_ddi_pre_enable_dp(encoder, crtc_state, conn_state); - intel_ddi_set_dp_msa(crtc_state, conn_state); + /* MST will call a setting of MSA after an allocating of Virtual Channel + * from MST encoder pre_enable callback. + */ + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) + intel_ddi_set_dp_msa(crtc_state, conn_state); } static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 27494aa48b0b..21e81830d525 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -345,6 +345,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, */ if (INTEL_GEN(dev_priv) < 12 || !first_mst_stream) intel_ddi_enable_pipe_clock(pipe_config); + + intel_ddi_set_dp_msa(pipe_config, conn_state); } static void intel_mst_enable_dp(struct intel_encoder *encoder, -- cgit v1.2.3 From 0d4bbe3d407f79438dc4f87943db21f7134cfc65 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 13:32:03 +0000 Subject: drm/i915/userptr: Try to acquire the page lock around set_page_dirty() set_page_dirty says: For pages with a mapping this should be done under the page lock for the benefit of asynchronous memory errors who prefer a consistent dirty state. This rule can be broken in some special cases, but should be better not to. Under those rules, it is only safe for us to use the plain set_page_dirty calls for shmemfs/anonymous memory. Userptr may be used with real mappings and so needs to use the locked version (set_page_dirty_lock). However, following a try_to_unmap() we may want to remove the userptr and so call put_pages(). However, try_to_unmap() acquires the page lock and so we must avoid recursively locking the pages ourselves -- which means that we cannot safely acquire the lock around set_page_dirty(). Since we can't be sure of the lock, we have to risk skip dirtying the page, or else risk calling set_page_dirty() without a lock and so risk fs corruption. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203317 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112012 Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video memory (userptr) ioctl") References: cb6d7c7dc7ff ("drm/i915/userptr: Acquire the page lock around set_page_dirty()") References: 505a8ec7e11a ("Revert "drm/i915/userptr: Acquire the page lock around set_page_dirty()"") References: 6dcc693bc57f ("ext4: warn when page is dirtied without buffers") Signed-off-by: Chris Wilson Cc: Lionel Landwerlin Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191111133205.11590-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index ee65c6acf0e2..dd104b0e2071 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -646,8 +646,28 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj, obj->mm.dirty = false; for_each_sgt_page(page, sgt_iter, pages) { - if (obj->mm.dirty) + if (obj->mm.dirty && trylock_page(page)) { + /* + * As this may not be anonymous memory (e.g. shmem) + * but exist on a real mapping, we have to lock + * the page in order to dirty it -- holding + * the page reference is not sufficient to + * prevent the inode from being truncated. + * Play safe and take the lock. + * + * However...! + * + * The mmu-notifier can be invalidated for a + * migrate_page, that is alreadying holding the lock + * on the page. Such a try_to_unmap() will result + * in us calling put_pages() and so recursively try + * to lock the page. We avoid that deadlock with + * a trylock_page() and in exchange we risk missing + * some page dirtying. + */ set_page_dirty(page); + unlock_page(page); + } mark_page_accessed(page); put_page(page); -- cgit v1.2.3 From d323c9b88260bc2cf3e3ed4bc741ab69643e0233 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 13:32:04 +0000 Subject: drm/i915/userptr: Handle unlocked gup retries Enable gup to retry and fault the pages outside of the mmap_sem lock in our worker. As we are inside our worker, outside of any critical path, we can allow the mmap_sem lock to be dropped in order to service a page fault; this in turn allows the mm to populate the page using a slow fault handler. References: 5b56d49fc31d ("mm: add locked parameter to get_user_pages_remote()") Testcase: igt/gem_userptr/userfault Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191111133205.11590-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index dd104b0e2071..54ebc7ab71bc 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -459,26 +459,31 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) if (pvec != NULL) { struct mm_struct *mm = obj->userptr.mm->mm; unsigned int flags = 0; + int locked = 0; if (!i915_gem_object_is_readonly(obj)) flags |= FOLL_WRITE; ret = -EFAULT; if (mmget_not_zero(mm)) { - down_read(&mm->mmap_sem); while (pinned < npages) { + if (!locked) { + down_read(&mm->mmap_sem); + locked = 1; + } ret = get_user_pages_remote (work->task, mm, obj->userptr.ptr + pinned * PAGE_SIZE, npages - pinned, flags, - pvec + pinned, NULL, NULL); + pvec + pinned, NULL, &locked); if (ret < 0) break; pinned += ret; } - up_read(&mm->mmap_sem); + if (locked) + up_read(&mm->mmap_sem); mmput(mm); } } -- cgit v1.2.3 From 31b61f0ef9af62b6404d8df5dcd2cf58f80c9f53 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 13:32:05 +0000 Subject: drm/i915/execlists: Move reset_active() from schedule-out to schedule-in The gem_ctx_persistence/smoketest was detecting an odd coherency issue inside the LRC context image; that the address of the ring buffer did not match our associated struct intel_ring. As we set the address into the context image when we pin the ring buffer into place before the context is active, that leaves the question of where did it get overwritten. Either the HW context save occurred after our pin which would imply that our idle barriers are broken, or we overwrote the context image ourselves. It is only in reset_active() where we dabble inside the context image outside of a serialised path from schedule-out; but we could equally perform the operation inside schedule-in which is then fully serialised with the context pin -- and remains serialised by the engine pulse with kill_context(). (The only downside, aside from doing more work inside the engine->active.lock, was the plan to merge all the reset paths into doing their context scrubbing on schedule-out needs more thought.) Fixes: d12acee84ffb ("drm/i915/execlists: Cancel banned contexts on schedule-out") Testcase: igt/gem_ctx_persistence/smoketest Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191111133205.11590-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 120 +++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index e57345795c08..33ce258d484f 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1042,6 +1042,59 @@ execlists_check_context(const struct intel_context *ce, WARN_ONCE(!valid, "Invalid lrc state found before submission\n"); } +static void restore_default_state(struct intel_context *ce, + struct intel_engine_cs *engine) +{ + u32 *regs = ce->lrc_reg_state; + + if (engine->pinned_default_state) + memcpy(regs, /* skip restoring the vanilla PPHWSP */ + engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE, + engine->context_size - PAGE_SIZE); + + execlists_init_reg_state(regs, ce, engine, ce->ring, false); +} + +static void reset_active(struct i915_request *rq, + struct intel_engine_cs *engine) +{ + struct intel_context * const ce = rq->hw_context; + u32 head; + + /* + * The executing context has been cancelled. We want to prevent + * further execution along this context and propagate the error on + * to anything depending on its results. + * + * In __i915_request_submit(), we apply the -EIO and remove the + * requests' payloads for any banned requests. But first, we must + * rewind the context back to the start of the incomplete request so + * that we do not jump back into the middle of the batch. + * + * We preserve the breadcrumbs and semaphores of the incomplete + * requests so that inter-timeline dependencies (i.e other timelines) + * remain correctly ordered. And we defer to __i915_request_submit() + * so that all asynchronous waits are correctly handled. + */ + GEM_TRACE("%s(%s): { rq=%llx:%lld }\n", + __func__, engine->name, rq->fence.context, rq->fence.seqno); + + /* On resubmission of the active request, payload will be scrubbed */ + if (i915_request_completed(rq)) + head = rq->tail; + else + head = active_request(ce->timeline, rq)->head; + ce->ring->head = intel_ring_wrap(ce->ring, head); + intel_ring_update_space(ce->ring); + + /* Scrub the context image to prevent replaying the previous batch */ + restore_default_state(ce, engine); + __execlists_update_reg_state(ce, engine); + + /* We've switched away, so this should be a no-op, but intent matters */ + ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; +} + static inline struct intel_engine_cs * __execlists_schedule_in(struct i915_request *rq) { @@ -1050,8 +1103,11 @@ __execlists_schedule_in(struct i915_request *rq) intel_context_get(ce); + if (unlikely(i915_gem_context_is_banned(ce->gem_context))) + reset_active(rq, engine); + if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) - execlists_check_context(ce, rq->engine); + execlists_check_context(ce, engine); if (ce->tag) { /* Use a fixed tag for OA and friends */ @@ -1102,72 +1158,22 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce) tasklet_schedule(&ve->base.execlists.tasklet); } -static void restore_default_state(struct intel_context *ce, - struct intel_engine_cs *engine) -{ - u32 *regs = ce->lrc_reg_state; - - if (engine->pinned_default_state) - memcpy(regs, /* skip restoring the vanilla PPHWSP */ - engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE, - engine->context_size - PAGE_SIZE); - - execlists_init_reg_state(regs, ce, engine, ce->ring, false); -} - -static void reset_active(struct i915_request *rq, - struct intel_engine_cs *engine) -{ - struct intel_context * const ce = rq->hw_context; - u32 head; - - /* - * The executing context has been cancelled. We want to prevent - * further execution along this context and propagate the error on - * to anything depending on its results. - * - * In __i915_request_submit(), we apply the -EIO and remove the - * requests' payloads for any banned requests. But first, we must - * rewind the context back to the start of the incomplete request so - * that we do not jump back into the middle of the batch. - * - * We preserve the breadcrumbs and semaphores of the incomplete - * requests so that inter-timeline dependencies (i.e other timelines) - * remain correctly ordered. And we defer to __i915_request_submit() - * so that all asynchronous waits are correctly handled. - */ - GEM_TRACE("%s(%s): { rq=%llx:%lld }\n", - __func__, engine->name, rq->fence.context, rq->fence.seqno); - - /* On resubmission of the active request, payload will be scrubbed */ - if (i915_request_completed(rq)) - head = rq->tail; - else - head = active_request(ce->timeline, rq)->head; - ce->ring->head = intel_ring_wrap(ce->ring, head); - intel_ring_update_space(ce->ring); - - /* Scrub the context image to prevent replaying the previous batch */ - restore_default_state(ce, engine); - __execlists_update_reg_state(ce, engine); - - /* We've switched away, so this should be a no-op, but intent matters */ - ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; -} - static inline void __execlists_schedule_out(struct i915_request *rq, struct intel_engine_cs * const engine) { struct intel_context * const ce = rq->hw_context; + /* + * NB process_csb() is not under the engine->active.lock and hence + * schedule_out can race with schedule_in meaning that we should + * refrain from doing non-trivial work here. + */ + intel_engine_context_out(engine); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); intel_gt_pm_put(engine->gt); - if (unlikely(i915_gem_context_is_banned(ce->gem_context))) - reset_active(rq, engine); - /* * If this is part of a virtual engine, its next request may * have been blocked waiting for access to the active context. -- cgit v1.2.3 From 3c7a44bbbfa7896df0aa08a77a15ddcf21d59498 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 17:27:16 +0000 Subject: drm/i915/selftests: Perform some basic cycle counting of MI ops Some basic information that is useful to know, such as how many cycles is a MI_NOOP. v2: Keep volatile pages pinned at all times! (Matthew) Signed-off-by: Chris Wilson Cc: Anna Karas Cc: Tvrtko Ursulin Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191111172716.23733-1-chris@chris-wilson.co.uk --- .../drm/i915/gem/selftests/i915_gem_object_blt.c | 15 +- drivers/gpu/drm/i915/gt/selftest_engine_cs.c | 348 ++++++++++++++++++++- drivers/gpu/drm/i915/i915_pci.c | 6 + drivers/gpu/drm/i915/i915_selftest.h | 4 + .../gpu/drm/i915/selftests/i915_perf_selftests.h | 13 + drivers/gpu/drm/i915/selftests/i915_selftest.c | 43 +++ 6 files changed, 426 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/i915/selftests/i915_perf_selftests.h diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c index 8a0fba7d5d4f..c8a8c07e07ab 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c @@ -526,8 +526,6 @@ static int igt_copy_blt_ctx0(void *arg) int i915_gem_object_blt_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { - SUBTEST(perf_fill_blt), - SUBTEST(perf_copy_blt), SUBTEST(igt_fill_blt), SUBTEST(igt_fill_blt_ctx0), SUBTEST(igt_copy_blt), @@ -542,3 +540,16 @@ int i915_gem_object_blt_live_selftests(struct drm_i915_private *i915) return i915_live_subtests(tests, i915); } + +int i915_gem_object_blt_perf_selftests(struct drm_i915_private *i915) +{ + static const struct i915_subtest tests[] = { + SUBTEST(perf_fill_blt), + SUBTEST(perf_copy_blt), + }; + + if (intel_gt_is_wedged(&i915->gt)) + return 0; + + return i915_live_subtests(tests, i915); +} diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c index 3880f07c29b8..5981a7b71ec9 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c @@ -4,7 +4,353 @@ * Copyright © 2018 Intel Corporation */ -#include "../i915_selftest.h" +#include + +#include "intel_gt_pm.h" +#include "intel_rps.h" + +#include "i915_selftest.h" +#include "selftests/igt_flush_test.h" + +#define COUNT 5 + +static int cmp_u32(const void *A, const void *B) +{ + const u32 *a = A, *b = B; + + return *a - *b; +} + +static void perf_begin(struct intel_gt *gt) +{ + intel_gt_pm_get(gt); + + /* Boost gpufreq to max [waitboost] and keep it fixed */ + atomic_inc(>->rps.num_waiters); + schedule_work(>->rps.work); + flush_work(>->rps.work); +} + +static int perf_end(struct intel_gt *gt) +{ + atomic_dec(>->rps.num_waiters); + intel_gt_pm_put(gt); + + return igt_flush_test(gt->i915); +} + +static int write_timestamp(struct i915_request *rq, int slot) +{ + u32 cmd; + u32 *cs; + + cs = intel_ring_begin(rq, 4); + if (IS_ERR(cs)) + return PTR_ERR(cs); + + cmd = MI_STORE_REGISTER_MEM | MI_USE_GGTT; + if (INTEL_GEN(rq->i915) >= 8) + cmd++; + *cs++ = cmd; + *cs++ = i915_mmio_reg_offset(RING_TIMESTAMP(rq->engine->mmio_base)); + *cs++ = i915_request_timeline(rq)->hwsp_offset + slot * sizeof(u32); + *cs++ = 0; + + intel_ring_advance(rq, cs); + + return 0; +} + +static struct i915_vma *create_empty_batch(struct intel_context *ce) +{ + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + u32 *cs; + int err; + + obj = i915_gem_object_create_internal(ce->engine->i915, PAGE_SIZE); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + cs = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(cs)) { + err = PTR_ERR(cs); + goto err_put; + } + + cs[0] = MI_BATCH_BUFFER_END; + + i915_gem_object_flush_map(obj); + + vma = i915_vma_instance(obj, ce->vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err_unpin; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + goto err_unpin; + + i915_gem_object_unpin_map(obj); + return vma; + +err_unpin: + i915_gem_object_unpin_map(obj); +err_put: + i915_gem_object_put(obj); + return ERR_PTR(err); +} + +static u32 trifilter(u32 *a) +{ + u64 sum; + + sort(a, COUNT, sizeof(*a), cmp_u32, NULL); + + sum += mul_u32_u32(a[2], 2); + sum += a[1]; + sum += a[3]; + + return sum >> 2; +} + +static int perf_mi_bb_start(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_engine_cs *engine; + enum intel_engine_id id; + int err = 0; + + if (INTEL_GEN(gt->i915) < 7) /* for per-engine CS_TIMESTAMP */ + return 0; + + perf_begin(gt); + for_each_engine(engine, gt, id) { + struct intel_context *ce = engine->kernel_context; + struct i915_vma *batch; + u32 cycles[COUNT]; + int i; + + batch = create_empty_batch(ce); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + break; + } + + err = i915_vma_sync(batch); + if (err) { + i915_vma_put(batch); + break; + } + + for (i = 0; i < ARRAY_SIZE(cycles); i++) { + struct i915_request *rq; + + rq = i915_request_create(ce); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + break; + } + + err = write_timestamp(rq, 2); + if (err) + goto out; + + err = rq->engine->emit_bb_start(rq, + batch->node.start, 8, + 0); + if (err) + goto out; + + err = write_timestamp(rq, 3); + if (err) + goto out; + +out: + i915_request_get(rq); + i915_request_add(rq); + + if (i915_request_wait(rq, 0, HZ / 5) < 0) + err = -EIO; + i915_request_put(rq); + if (err) + break; + + cycles[i] = rq->hwsp_seqno[3] - rq->hwsp_seqno[2]; + } + i915_vma_put(batch); + if (err) + break; + + pr_info("%s: MI_BB_START cycles: %u\n", + engine->name, trifilter(cycles)); + } + if (perf_end(gt)) + err = -EIO; + + return err; +} + +static struct i915_vma *create_nop_batch(struct intel_context *ce) +{ + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + u32 *cs; + int err; + + obj = i915_gem_object_create_internal(ce->engine->i915, SZ_64K); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + cs = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(cs)) { + err = PTR_ERR(cs); + goto err_put; + } + + memset(cs, 0, SZ_64K); + cs[SZ_64K / sizeof(*cs) - 1] = MI_BATCH_BUFFER_END; + + i915_gem_object_flush_map(obj); + + vma = i915_vma_instance(obj, ce->vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err_unpin; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + goto err_unpin; + + i915_gem_object_unpin_map(obj); + return vma; + +err_unpin: + i915_gem_object_unpin_map(obj); +err_put: + i915_gem_object_put(obj); + return ERR_PTR(err); +} + +static int perf_mi_noop(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_engine_cs *engine; + enum intel_engine_id id; + int err = 0; + + if (INTEL_GEN(gt->i915) < 7) /* for per-engine CS_TIMESTAMP */ + return 0; + + perf_begin(gt); + for_each_engine(engine, gt, id) { + struct intel_context *ce = engine->kernel_context; + struct i915_vma *base, *nop; + u32 cycles[COUNT]; + int i; + + base = create_empty_batch(ce); + if (IS_ERR(base)) { + err = PTR_ERR(base); + break; + } + + err = i915_vma_sync(base); + if (err) { + i915_vma_put(base); + break; + } + + nop = create_nop_batch(ce); + if (IS_ERR(nop)) { + err = PTR_ERR(nop); + i915_vma_put(base); + break; + } + + err = i915_vma_sync(nop); + if (err) { + i915_vma_put(nop); + i915_vma_put(base); + break; + } + + for (i = 0; i < ARRAY_SIZE(cycles); i++) { + struct i915_request *rq; + + rq = i915_request_create(ce); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + break; + } + + err = write_timestamp(rq, 2); + if (err) + goto out; + + err = rq->engine->emit_bb_start(rq, + base->node.start, 8, + 0); + if (err) + goto out; + + err = write_timestamp(rq, 3); + if (err) + goto out; + + err = rq->engine->emit_bb_start(rq, + nop->node.start, + nop->node.size, + 0); + if (err) + goto out; + + err = write_timestamp(rq, 4); + if (err) + goto out; + +out: + i915_request_get(rq); + i915_request_add(rq); + + if (i915_request_wait(rq, 0, HZ / 5) < 0) + err = -EIO; + i915_request_put(rq); + if (err) + break; + + cycles[i] = + (rq->hwsp_seqno[4] - rq->hwsp_seqno[3]) - + (rq->hwsp_seqno[3] - rq->hwsp_seqno[2]); + } + i915_vma_put(nop); + i915_vma_put(base); + if (err) + break; + + pr_info("%s: 16K MI_NOOP cycles: %u\n", + engine->name, trifilter(cycles)); + } + if (perf_end(gt)) + err = -EIO; + + return err; +} + +int intel_engine_cs_perf_selftests(struct drm_i915_private *i915) +{ + static const struct i915_subtest tests[] = { + SUBTEST(perf_mi_bb_start), + SUBTEST(perf_mi_noop), + }; + + if (intel_gt_is_wedged(&i915->gt)) + return 0; + + return intel_gt_live_subtests(tests, &i915->gt); +} static int intel_mmio_bases_check(void *arg) { diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 1bb701d32a5d..da3e9b5752ac 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1003,6 +1003,12 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err > 0 ? -ENOTTY : err; } + err = i915_perf_selftests(pdev); + if (err) { + i915_pci_remove(pdev); + return err > 0 ? -ENOTTY : err; + } + return 0; } diff --git a/drivers/gpu/drm/i915/i915_selftest.h b/drivers/gpu/drm/i915/i915_selftest.h index 4d88205de51b..98bcb6fa0ab4 100644 --- a/drivers/gpu/drm/i915/i915_selftest.h +++ b/drivers/gpu/drm/i915/i915_selftest.h @@ -36,6 +36,7 @@ struct i915_selftest { char *filter; int mock; int live; + int perf; }; #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) @@ -45,6 +46,7 @@ extern struct i915_selftest i915_selftest; int i915_mock_selftests(void); int i915_live_selftests(struct pci_dev *pdev); +int i915_perf_selftests(struct pci_dev *pdev); /* We extract the function declarations from i915_mock_selftests.h and * i915_live_selftests.h Add your unit test declarations there! @@ -61,6 +63,7 @@ int i915_live_selftests(struct pci_dev *pdev); #undef selftest #define selftest(name, func) int func(struct drm_i915_private *i915); #include "selftests/i915_live_selftests.h" +#include "selftests/i915_perf_selftests.h" #undef selftest struct i915_subtest { @@ -109,6 +112,7 @@ int __i915_subtests(const char *caller, static inline int i915_mock_selftests(void) { return 0; } static inline int i915_live_selftests(struct pci_dev *pdev) { return 0; } +static inline int i915_perf_selftests(struct pci_dev *pdev) { return 0; } #define I915_SELFTEST_DECLARE(x) #define I915_SELFTEST_ONLY(x) 0 diff --git a/drivers/gpu/drm/i915/selftests/i915_perf_selftests.h b/drivers/gpu/drm/i915/selftests/i915_perf_selftests.h new file mode 100644 index 000000000000..f7129a243daa --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_perf_selftests.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* List each unit test as selftest(name, function) + * + * The name is used as both an enum and expanded as subtest__name to create + * a module parameter. It must be unique and legal for a C identifier. + * + * The function should be of type int function(void). It may be conditionally + * compiled using #if IS_ENABLED(DRM_I915_SELFTEST). + * + * Tests are executed in order by igt/i915_selftest + */ +selftest(engine_cs, intel_engine_cs_perf_selftests) +selftest(blt, i915_gem_object_blt_perf_selftests) diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c index a6cca4ad96f6..d3bf9eefb682 100644 --- a/drivers/gpu/drm/i915/selftests/i915_selftest.c +++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c @@ -57,6 +57,12 @@ enum { #undef selftest }; +enum { +#define selftest(name, func) perf_##name, +#include "i915_perf_selftests.h" +#undef selftest +}; + struct selftest { bool enabled; const char *name; @@ -78,6 +84,12 @@ static struct selftest live_selftests[] = { }; #undef selftest +#define selftest(n, f) [perf_##n] = { .name = #n, { .live = f } }, +static struct selftest perf_selftests[] = { +#include "i915_perf_selftests.h" +}; +#undef selftest + /* Embed the line number into the parameter name so that we can order tests */ #define selftest(n, func) selftest_0(n, func, param(n)) #define param(n) __PASTE(igt__, __PASTE(__LINE__, __mock_##n)) @@ -93,6 +105,13 @@ module_param_named(id, live_selftests[live_##n].enabled, bool, 0400); #include "i915_live_selftests.h" #undef selftest_0 #undef param + +#define param(n) __PASTE(igt__, __PASTE(__LINE__, __perf_##n)) +#define selftest_0(n, func, id) \ +module_param_named(id, perf_selftests[perf_##n].enabled, bool, 0400); +#include "i915_perf_selftests.h" +#undef selftest_0 +#undef param #undef selftest static void set_default_test_all(struct selftest *st, unsigned int count) @@ -200,6 +219,27 @@ int i915_live_selftests(struct pci_dev *pdev) return 0; } +int i915_perf_selftests(struct pci_dev *pdev) +{ + int err; + + if (!i915_selftest.perf) + return 0; + + err = run_selftests(perf, pdev_to_i915(pdev)); + if (err) { + i915_selftest.perf = err; + return err; + } + + if (i915_selftest.perf < 0) { + i915_selftest.perf = -ENOTTY; + return 1; + } + + return 0; +} + static bool apply_subtest_filter(const char *caller, const char *name) { char *filter, *sep, *tok; @@ -365,3 +405,6 @@ MODULE_PARM_DESC(mock_selftests, "Run selftests before loading, using mock hardw module_param_named_unsafe(live_selftests, i915_selftest.live, int, 0400); MODULE_PARM_DESC(live_selftests, "Run selftests after driver initialisation on the live system (0:disabled [default], 1:run tests then continue, -1:run tests then exit module)"); + +module_param_named_unsafe(perf_selftests, i915_selftest.perf, int, 0400); +MODULE_PARM_DESC(perf_selftests, "Run performance orientated selftests after driver initialisation on the live system (0:disabled [default], 1:run tests then continue, -1:run tests then exit module)"); -- cgit v1.2.3 From bdce2bea0f5e6bd3e3fa85278cc2fb8632f71572 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 18:21:42 +0000 Subject: drm/i915/gem: Replace implicit dev_priv->uncore for stolen init Pass around the intended intel_uncore for mmio access during stolen setup, and avoid relying on the implicit magic I915_READ() macros. Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191111182143.23479-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 207 +++++++++++++++-------------- 1 file changed, 109 insertions(+), 98 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index a2d49c04e6a4..55422fec7422 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -26,48 +26,49 @@ * for is a boon. */ -int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, +int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *i915, struct drm_mm_node *node, u64 size, unsigned alignment, u64 start, u64 end) { int ret; - if (!drm_mm_initialized(&dev_priv->mm.stolen)) + if (!drm_mm_initialized(&i915->mm.stolen)) return -ENODEV; /* WaSkipStolenMemoryFirstPage:bdw+ */ - if (INTEL_GEN(dev_priv) >= 8 && start < 4096) + if (INTEL_GEN(i915) >= 8 && start < 4096) start = 4096; - mutex_lock(&dev_priv->mm.stolen_lock); - ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node, + mutex_lock(&i915->mm.stolen_lock); + ret = drm_mm_insert_node_in_range(&i915->mm.stolen, node, size, alignment, 0, start, end, DRM_MM_INSERT_BEST); - mutex_unlock(&dev_priv->mm.stolen_lock); + mutex_unlock(&i915->mm.stolen_lock); return ret; } -int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, +int i915_gem_stolen_insert_node(struct drm_i915_private *i915, struct drm_mm_node *node, u64 size, unsigned alignment) { - return i915_gem_stolen_insert_node_in_range(dev_priv, node, size, + return i915_gem_stolen_insert_node_in_range(i915, node, size, alignment, 0, U64_MAX); } -void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, +void i915_gem_stolen_remove_node(struct drm_i915_private *i915, struct drm_mm_node *node) { - mutex_lock(&dev_priv->mm.stolen_lock); + mutex_lock(&i915->mm.stolen_lock); drm_mm_remove_node(node); - mutex_unlock(&dev_priv->mm.stolen_lock); + mutex_unlock(&i915->mm.stolen_lock); } -static int i915_adjust_stolen(struct drm_i915_private *dev_priv, +static int i915_adjust_stolen(struct drm_i915_private *i915, struct resource *dsm) { - struct i915_ggtt *ggtt = &dev_priv->ggtt; + struct i915_ggtt *ggtt = &i915->ggtt; + struct intel_uncore *uncore = ggtt->vm.gt->uncore; struct resource *r; if (dsm->start == 0 || dsm->end <= dsm->start) @@ -79,14 +80,14 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv, */ /* Make sure we don't clobber the GTT if it's within stolen memory */ - if (INTEL_GEN(dev_priv) <= 4 && - !IS_G33(dev_priv) && !IS_PINEVIEW(dev_priv) && !IS_G4X(dev_priv)) { + if (INTEL_GEN(i915) <= 4 && + !IS_G33(i915) && !IS_PINEVIEW(i915) && !IS_G4X(i915)) { struct resource stolen[2] = {*dsm, *dsm}; struct resource ggtt_res; resource_size_t ggtt_start; - ggtt_start = I915_READ(PGTBL_CTL); - if (IS_GEN(dev_priv, 4)) + ggtt_start = intel_uncore_read(uncore, PGTBL_CTL); + if (IS_GEN(i915, 4)) ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) | (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28; else @@ -120,7 +121,7 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv, * kernel. So if the region is already marked as busy, something * is seriously wrong. */ - r = devm_request_mem_region(dev_priv->drm.dev, dsm->start, + r = devm_request_mem_region(i915->drm.dev, dsm->start, resource_size(dsm), "Graphics Stolen Memory"); if (r == NULL) { @@ -133,14 +134,14 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv, * reservation starting from 1 instead of 0. * There's also BIOS with off-by-one on the other end. */ - r = devm_request_mem_region(dev_priv->drm.dev, dsm->start + 1, + r = devm_request_mem_region(i915->drm.dev, dsm->start + 1, resource_size(dsm) - 2, "Graphics Stolen Memory"); /* * GEN3 firmware likes to smash pci bridges into the stolen * range. Apparently this works. */ - if (r == NULL && !IS_GEN(dev_priv, 3)) { + if (!r && !IS_GEN(i915, 3)) { DRM_ERROR("conflict detected with stolen region: %pR\n", dsm); @@ -151,25 +152,27 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv, return 0; } -static void i915_gem_cleanup_stolen(struct drm_i915_private *dev_priv) +static void i915_gem_cleanup_stolen(struct drm_i915_private *i915) { - if (!drm_mm_initialized(&dev_priv->mm.stolen)) + if (!drm_mm_initialized(&i915->mm.stolen)) return; - drm_mm_takedown(&dev_priv->mm.stolen); + drm_mm_takedown(&i915->mm.stolen); } -static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, +static void g4x_get_stolen_reserved(struct drm_i915_private *i915, + struct intel_uncore *uncore, resource_size_t *base, resource_size_t *size) { - u32 reg_val = I915_READ(IS_GM45(dev_priv) ? - CTG_STOLEN_RESERVED : - ELK_STOLEN_RESERVED); - resource_size_t stolen_top = dev_priv->dsm.end + 1; + u32 reg_val = intel_uncore_read(uncore, + IS_GM45(i915) ? + CTG_STOLEN_RESERVED : + ELK_STOLEN_RESERVED); + resource_size_t stolen_top = i915->dsm.end + 1; DRM_DEBUG_DRIVER("%s_STOLEN_RESERVED = %08x\n", - IS_GM45(dev_priv) ? "CTG" : "ELK", reg_val); + IS_GM45(i915) ? "CTG" : "ELK", reg_val); if ((reg_val & G4X_STOLEN_RESERVED_ENABLE) == 0) return; @@ -178,7 +181,7 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, * Whether ILK really reuses the ELK register for this is unclear. * Let's see if we catch anyone with this supposedly enabled on ILK. */ - WARN(IS_GEN(dev_priv, 5), "ILK stolen reserved found? 0x%08x\n", + WARN(IS_GEN(i915, 5), "ILK stolen reserved found? 0x%08x\n", reg_val); if (!(reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK)) @@ -190,11 +193,12 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, *size = stolen_top - *base; } -static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, +static void gen6_get_stolen_reserved(struct drm_i915_private *i915, + struct intel_uncore *uncore, resource_size_t *base, resource_size_t *size) { - u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); + u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -222,12 +226,13 @@ static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, } } -static void vlv_get_stolen_reserved(struct drm_i915_private *dev_priv, +static void vlv_get_stolen_reserved(struct drm_i915_private *i915, + struct intel_uncore *uncore, resource_size_t *base, resource_size_t *size) { - u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); - resource_size_t stolen_top = dev_priv->dsm.end + 1; + u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); + resource_size_t stolen_top = i915->dsm.end + 1; DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -250,11 +255,12 @@ static void vlv_get_stolen_reserved(struct drm_i915_private *dev_priv, *base = stolen_top - *size; } -static void gen7_get_stolen_reserved(struct drm_i915_private *dev_priv, +static void gen7_get_stolen_reserved(struct drm_i915_private *i915, + struct intel_uncore *uncore, resource_size_t *base, resource_size_t *size) { - u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); + u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -276,11 +282,12 @@ static void gen7_get_stolen_reserved(struct drm_i915_private *dev_priv, } } -static void chv_get_stolen_reserved(struct drm_i915_private *dev_priv, +static void chv_get_stolen_reserved(struct drm_i915_private *i915, + struct intel_uncore *uncore, resource_size_t *base, resource_size_t *size) { - u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); + u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -308,12 +315,13 @@ static void chv_get_stolen_reserved(struct drm_i915_private *dev_priv, } } -static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, +static void bdw_get_stolen_reserved(struct drm_i915_private *i915, + struct intel_uncore *uncore, resource_size_t *base, resource_size_t *size) { - u32 reg_val = I915_READ(GEN6_STOLEN_RESERVED); - resource_size_t stolen_top = dev_priv->dsm.end + 1; + u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); + resource_size_t stolen_top = i915->dsm.end + 1; DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -328,10 +336,11 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, } static void icl_get_stolen_reserved(struct drm_i915_private *i915, + struct intel_uncore *uncore, resource_size_t *base, resource_size_t *size) { - u64 reg_val = intel_uncore_read64(&i915->uncore, GEN6_STOLEN_RESERVED); + u64 reg_val = intel_uncore_read64(uncore, GEN6_STOLEN_RESERVED); DRM_DEBUG_DRIVER("GEN6_STOLEN_RESERVED = 0x%016llx\n", reg_val); @@ -356,22 +365,23 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915, } } -static int i915_gem_init_stolen(struct drm_i915_private *dev_priv) +static int i915_gem_init_stolen(struct drm_i915_private *i915) { + struct intel_uncore *uncore = &i915->uncore; resource_size_t reserved_base, stolen_top; resource_size_t reserved_total, reserved_size; - mutex_init(&dev_priv->mm.stolen_lock); + mutex_init(&i915->mm.stolen_lock); - if (intel_vgpu_active(dev_priv)) { - dev_notice(dev_priv->drm.dev, + if (intel_vgpu_active(i915)) { + dev_notice(i915->drm.dev, "%s, disabling use of stolen memory\n", "iGVT-g active"); return 0; } - if (intel_vtd_active() && INTEL_GEN(dev_priv) < 8) { - dev_notice(dev_priv->drm.dev, + if (intel_vtd_active() && INTEL_GEN(i915) < 8) { + dev_notice(i915->drm.dev, "%s, disabling use of stolen memory\n", "DMAR active"); return 0; @@ -380,58 +390,59 @@ static int i915_gem_init_stolen(struct drm_i915_private *dev_priv) if (resource_size(&intel_graphics_stolen_res) == 0) return 0; - dev_priv->dsm = intel_graphics_stolen_res; + i915->dsm = intel_graphics_stolen_res; - if (i915_adjust_stolen(dev_priv, &dev_priv->dsm)) + if (i915_adjust_stolen(i915, &i915->dsm)) return 0; - GEM_BUG_ON(dev_priv->dsm.start == 0); - GEM_BUG_ON(dev_priv->dsm.end <= dev_priv->dsm.start); + GEM_BUG_ON(i915->dsm.start == 0); + GEM_BUG_ON(i915->dsm.end <= i915->dsm.start); - stolen_top = dev_priv->dsm.end + 1; + stolen_top = i915->dsm.end + 1; reserved_base = stolen_top; reserved_size = 0; - switch (INTEL_GEN(dev_priv)) { + switch (INTEL_GEN(i915)) { case 2: case 3: break; case 4: - if (!IS_G4X(dev_priv)) + if (!IS_G4X(i915)) break; /* fall through */ case 5: - g4x_get_stolen_reserved(dev_priv, + g4x_get_stolen_reserved(i915, uncore, &reserved_base, &reserved_size); break; case 6: - gen6_get_stolen_reserved(dev_priv, + gen6_get_stolen_reserved(i915, uncore, &reserved_base, &reserved_size); break; case 7: - if (IS_VALLEYVIEW(dev_priv)) - vlv_get_stolen_reserved(dev_priv, + if (IS_VALLEYVIEW(i915)) + vlv_get_stolen_reserved(i915, uncore, &reserved_base, &reserved_size); else - gen7_get_stolen_reserved(dev_priv, + gen7_get_stolen_reserved(i915, uncore, &reserved_base, &reserved_size); break; case 8: case 9: case 10: - if (IS_LP(dev_priv)) - chv_get_stolen_reserved(dev_priv, + if (IS_LP(i915)) + chv_get_stolen_reserved(i915, uncore, &reserved_base, &reserved_size); else - bdw_get_stolen_reserved(dev_priv, + bdw_get_stolen_reserved(i915, uncore, &reserved_base, &reserved_size); break; default: - MISSING_CASE(INTEL_GEN(dev_priv)); + MISSING_CASE(INTEL_GEN(i915)); /* fall-through */ case 11: case 12: - icl_get_stolen_reserved(dev_priv, &reserved_base, + icl_get_stolen_reserved(i915, uncore, + &reserved_base, &reserved_size); break; } @@ -448,12 +459,12 @@ static int i915_gem_init_stolen(struct drm_i915_private *dev_priv) reserved_size = 0; } - dev_priv->dsm_reserved = - (struct resource) DEFINE_RES_MEM(reserved_base, reserved_size); + i915->dsm_reserved = + (struct resource)DEFINE_RES_MEM(reserved_base, reserved_size); - if (!resource_contains(&dev_priv->dsm, &dev_priv->dsm_reserved)) { + if (!resource_contains(&i915->dsm, &i915->dsm_reserved)) { DRM_ERROR("Stolen reserved area %pR outside stolen memory %pR\n", - &dev_priv->dsm_reserved, &dev_priv->dsm); + &i915->dsm_reserved, &i915->dsm); return 0; } @@ -462,14 +473,14 @@ static int i915_gem_init_stolen(struct drm_i915_private *dev_priv) reserved_total = stolen_top - reserved_base; DRM_DEBUG_DRIVER("Memory reserved for graphics device: %lluK, usable: %lluK\n", - (u64)resource_size(&dev_priv->dsm) >> 10, - ((u64)resource_size(&dev_priv->dsm) - reserved_total) >> 10); + (u64)resource_size(&i915->dsm) >> 10, + ((u64)resource_size(&i915->dsm) - reserved_total) >> 10); - dev_priv->stolen_usable_size = - resource_size(&dev_priv->dsm) - reserved_total; + i915->stolen_usable_size = + resource_size(&i915->dsm) - reserved_total; /* Basic memrange allocator for stolen space. */ - drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->stolen_usable_size); + drm_mm_init(&i915->mm.stolen, 0, i915->stolen_usable_size); return 0; } @@ -478,11 +489,11 @@ static struct sg_table * i915_pages_create_for_stolen(struct drm_device *dev, resource_size_t offset, resource_size_t size) { - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(dev); struct sg_table *st; struct scatterlist *sg; - GEM_BUG_ON(range_overflows(offset, size, resource_size(&dev_priv->dsm))); + GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm))); /* We hide that we have no struct page backing our stolen object * by wrapping the contiguous physical allocation with a fake @@ -502,7 +513,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, sg->offset = 0; sg->length = size; - sg_dma_address(sg) = (dma_addr_t)dev_priv->dsm.start + offset; + sg_dma_address(sg) = (dma_addr_t)i915->dsm.start + offset; sg_dma_len(sg) = size; return st; @@ -533,12 +544,12 @@ static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj, static void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj) { - struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct drm_i915_private *i915 = to_i915(obj->base.dev); struct drm_mm_node *stolen = fetch_and_zero(&obj->stolen); GEM_BUG_ON(!stolen); - i915_gem_stolen_remove_node(dev_priv, stolen); + i915_gem_stolen_remove_node(i915, stolen); kfree(stolen); if (obj->mm.region) @@ -552,7 +563,7 @@ static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = { }; static struct drm_i915_gem_object * -__i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, +__i915_gem_object_create_stolen(struct drm_i915_private *i915, struct drm_mm_node *stolen, struct intel_memory_region *mem) { @@ -565,12 +576,12 @@ __i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, if (!obj) goto err; - drm_gem_private_object_init(&dev_priv->drm, &obj->base, stolen->size); + drm_gem_private_object_init(&i915->drm, &obj->base, stolen->size); i915_gem_object_init(obj, &i915_gem_object_stolen_ops, &lock_class); obj->stolen = stolen; obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; - cache_level = HAS_LLC(dev_priv) ? I915_CACHE_LLC : I915_CACHE_NONE; + cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; i915_gem_object_set_cache_coherency(obj, cache_level); err = i915_gem_object_pin_pages(obj); @@ -593,12 +604,12 @@ _i915_gem_object_create_stolen(struct intel_memory_region *mem, resource_size_t size, unsigned int flags) { - struct drm_i915_private *dev_priv = mem->i915; + struct drm_i915_private *i915 = mem->i915; struct drm_i915_gem_object *obj; struct drm_mm_node *stolen; int ret; - if (!drm_mm_initialized(&dev_priv->mm.stolen)) + if (!drm_mm_initialized(&i915->mm.stolen)) return ERR_PTR(-ENODEV); if (size == 0) @@ -608,30 +619,30 @@ _i915_gem_object_create_stolen(struct intel_memory_region *mem, if (!stolen) return ERR_PTR(-ENOMEM); - ret = i915_gem_stolen_insert_node(dev_priv, stolen, size, 4096); + ret = i915_gem_stolen_insert_node(i915, stolen, size, 4096); if (ret) { obj = ERR_PTR(ret); goto err_free; } - obj = __i915_gem_object_create_stolen(dev_priv, stolen, mem); + obj = __i915_gem_object_create_stolen(i915, stolen, mem); if (IS_ERR(obj)) goto err_remove; return obj; err_remove: - i915_gem_stolen_remove_node(dev_priv, stolen); + i915_gem_stolen_remove_node(i915, stolen); err_free: kfree(stolen); return obj; } struct drm_i915_gem_object * -i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, +i915_gem_object_create_stolen(struct drm_i915_private *i915, resource_size_t size) { - return i915_gem_object_create_region(dev_priv->mm.regions[INTEL_REGION_STOLEN], + return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_STOLEN], size, I915_BO_ALLOC_CONTIGUOUS); } @@ -665,18 +676,18 @@ struct intel_memory_region *i915_gem_stolen_setup(struct drm_i915_private *i915) } struct drm_i915_gem_object * -i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv, +i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915, resource_size_t stolen_offset, resource_size_t gtt_offset, resource_size_t size) { - struct i915_ggtt *ggtt = &dev_priv->ggtt; + struct i915_ggtt *ggtt = &i915->ggtt; struct drm_i915_gem_object *obj; struct drm_mm_node *stolen; struct i915_vma *vma; int ret; - if (!drm_mm_initialized(&dev_priv->mm.stolen)) + if (!drm_mm_initialized(&i915->mm.stolen)) return ERR_PTR(-ENODEV); DRM_DEBUG_DRIVER("creating preallocated stolen object: stolen_offset=%pa, gtt_offset=%pa, size=%pa\n", @@ -694,19 +705,19 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv stolen->start = stolen_offset; stolen->size = size; - mutex_lock(&dev_priv->mm.stolen_lock); - ret = drm_mm_reserve_node(&dev_priv->mm.stolen, stolen); - mutex_unlock(&dev_priv->mm.stolen_lock); + mutex_lock(&i915->mm.stolen_lock); + ret = drm_mm_reserve_node(&i915->mm.stolen, stolen); + mutex_unlock(&i915->mm.stolen_lock); if (ret) { DRM_DEBUG_DRIVER("failed to allocate stolen space\n"); kfree(stolen); return ERR_PTR(ret); } - obj = __i915_gem_object_create_stolen(dev_priv, stolen, NULL); + obj = __i915_gem_object_create_stolen(i915, stolen, NULL); if (IS_ERR(obj)) { DRM_DEBUG_DRIVER("failed to allocate stolen object\n"); - i915_gem_stolen_remove_node(dev_priv, stolen); + i915_gem_stolen_remove_node(i915, stolen); kfree(stolen); return obj; } -- cgit v1.2.3 From 1e50787273539dd930ef73319f519837e9748347 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 18:21:43 +0000 Subject: drm/i915/gem: Pass mem region to preallocated stolen As the memory regions are setup early, we can rely on its existence as we takeover the HW settings from BIOS. Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191111182143.23479-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index 55422fec7422..afb08a1704a2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -549,11 +549,10 @@ i915_gem_object_release_stolen(struct drm_i915_gem_object *obj) GEM_BUG_ON(!stolen); + i915_gem_object_release_memory_region(obj); + i915_gem_stolen_remove_node(i915, stolen); kfree(stolen); - - if (obj->mm.region) - i915_gem_object_release_memory_region(obj); } static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = { @@ -563,9 +562,8 @@ static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = { }; static struct drm_i915_gem_object * -__i915_gem_object_create_stolen(struct drm_i915_private *i915, - struct drm_mm_node *stolen, - struct intel_memory_region *mem) +__i915_gem_object_create_stolen(struct intel_memory_region *mem, + struct drm_mm_node *stolen) { static struct lock_class_key lock_class; struct drm_i915_gem_object *obj; @@ -576,20 +574,19 @@ __i915_gem_object_create_stolen(struct drm_i915_private *i915, if (!obj) goto err; - drm_gem_private_object_init(&i915->drm, &obj->base, stolen->size); + drm_gem_private_object_init(&mem->i915->drm, &obj->base, stolen->size); i915_gem_object_init(obj, &i915_gem_object_stolen_ops, &lock_class); obj->stolen = stolen; obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; - cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; + cache_level = HAS_LLC(mem->i915) ? I915_CACHE_LLC : I915_CACHE_NONE; i915_gem_object_set_cache_coherency(obj, cache_level); err = i915_gem_object_pin_pages(obj); if (err) goto cleanup; - if (mem) - i915_gem_object_init_memory_region(obj, mem, 0); + i915_gem_object_init_memory_region(obj, mem, 0); return obj; @@ -625,7 +622,7 @@ _i915_gem_object_create_stolen(struct intel_memory_region *mem, goto err_free; } - obj = __i915_gem_object_create_stolen(i915, stolen, mem); + obj = __i915_gem_object_create_stolen(mem, stolen); if (IS_ERR(obj)) goto err_remove; @@ -681,6 +678,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915, resource_size_t gtt_offset, resource_size_t size) { + struct intel_memory_region *mem = i915->mm.regions[INTEL_REGION_STOLEN]; struct i915_ggtt *ggtt = &i915->ggtt; struct drm_i915_gem_object *obj; struct drm_mm_node *stolen; @@ -714,7 +712,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915, return ERR_PTR(ret); } - obj = __i915_gem_object_create_stolen(i915, stolen, NULL); + obj = __i915_gem_object_create_stolen(mem, stolen); if (IS_ERR(obj)) { DRM_DEBUG_DRIVER("failed to allocate stolen object\n"); i915_gem_stolen_remove_node(i915, stolen); -- cgit v1.2.3 From b5b61cb4b1bf8bd01daab17910c6dab0ded63068 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Nov 2019 11:34:34 +0000 Subject: drm/i915: Remove leftover gem.pm_notifier member Since we removed the pm hookup from the GT, the hook in drm_i915_private.gem is unused. Remove it. References: 18f3b2727fc3 ("drm/i915: Remove pm park/unpark notifications") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191112113434.31088-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7e0f67babe20..b82ff0bc6d0c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1252,8 +1252,6 @@ struct drm_i915_private { struct intel_gt gt; struct { - struct notifier_block pm_notifier; - struct i915_gem_contexts { spinlock_t lock; /* locks list */ struct list_head list; -- cgit v1.2.3 From f9228f7658734fe16ef7eec554d187a3d9577be8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 11 Nov 2019 12:09:57 +0000 Subject: drm/i915/gt: Try an extra flush on the Haswell blitter On gen7, including Haswell, the MI_FLUSH_DW command is not synchronous with the command streamer nor is there an option to make it so. To hide this we add a large delay on the CS so that the breadcrumb should always be visible before the interrupt. However, that does not seem to be enough to ensure the memory is actually coherent with the read of the breadcrumb. The breadcrumb update is a post-sync op... Throw in a preliminary MI_FLUSH_DW before the breadcrumb update in the hope that helps. References: https://bugs.freedesktop.org/show_bug.cgi?id=112147 Testcase: igt/i915_selftest/live_blt Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191111120957.17732-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index a47d5a7c32c9..fc29df712810 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -454,6 +454,10 @@ static u32 *gen7_xcs_emit_breadcrumb(struct i915_request *rq, u32 *cs) GEM_BUG_ON(i915_request_active_timeline(rq)->hwsp_ggtt != rq->engine->status_page.vma); GEM_BUG_ON(offset_in_page(i915_request_active_timeline(rq)->hwsp_offset) != I915_GEM_HWS_SEQNO_ADDR); + *cs++ = MI_FLUSH_DW; + *cs++ = 0; + *cs++ = 0; + *cs++ = MI_FLUSH_DW | MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_DW_STORE_INDEX; *cs++ = I915_GEM_HWS_SEQNO_ADDR | MI_FLUSH_DW_USE_GTT; *cs++ = rq->fence.seqno; @@ -469,7 +473,6 @@ static u32 *gen7_xcs_emit_breadcrumb(struct i915_request *rq, u32 *cs) *cs++ = 0; *cs++ = MI_USER_INTERRUPT; - *cs++ = MI_NOOP; rq->tail = intel_ring_offset(rq, cs); assert_ring_tail_valid(rq->ring, rq->tail); -- cgit v1.2.3 From 7a0073d662db8712b1bc1dff2e430725dd9ceff8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2019 17:39:48 +0200 Subject: drm/i915/bios: use a flag for vbt hdmi level shift presence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pre-initialized magic value is a bit silly, switch to a flag instead. v2: Reduce paranoia to a single sanity check (Ville) Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/74fe24ab6d5f0ea2ff2059cdf044d6d3006080fc.1573227240.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 10 +--------- drivers/gpu/drm/i915/display/intel_ddi.c | 13 +++++++------ drivers/gpu/drm/i915/i915_drv.h | 8 ++------ 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index a03f56b7b4ef..c19b234bebe6 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1509,6 +1509,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, port_name(port), hdmi_level_shift); info->hdmi_level_shift = hdmi_level_shift; + info->hdmi_level_shift_set = true; } if (bdb_version >= 204) { @@ -1692,8 +1693,6 @@ parse_general_definitions(struct drm_i915_private *dev_priv, static void init_vbt_defaults(struct drm_i915_private *dev_priv) { - enum port port; - dev_priv->vbt.crt_ddc_pin = GMBUS_PIN_VGADDC; /* Default to having backlight */ @@ -1721,13 +1720,6 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev_priv, !HAS_PCH_SPLIT(dev_priv)); DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq); - - for_each_port(port) { - struct ddi_vbt_port_info *info = - &dev_priv->vbt.ddi_port_info[port]; - - info->hdmi_level_shift = HDMI_LEVEL_SHIFT_UNKNOWN; - } } /* Defaults to initialize only if there is no VBT. */ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index a387aea1c809..e56eb8a49cdd 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -888,11 +888,10 @@ icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, int type, int rate, static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) { + struct ddi_vbt_port_info *port_info = &dev_priv->vbt.ddi_port_info[port]; int n_entries, level, default_entry; enum phy phy = intel_port_to_phy(dev_priv, port); - level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; - if (INTEL_GEN(dev_priv) >= 12) { if (intel_phy_is_combo(dev_priv, phy)) icl_get_combo_buf_trans(dev_priv, INTEL_OUTPUT_HDMI, @@ -927,12 +926,14 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por return 0; } - /* Choose a good default if VBT is badly populated */ - if (level == HDMI_LEVEL_SHIFT_UNKNOWN || level >= n_entries) - level = default_entry; - if (WARN_ON_ONCE(n_entries == 0)) return 0; + + if (port_info->hdmi_level_shift_set) + level = port_info->hdmi_level_shift; + else + level = default_entry; + if (WARN_ON_ONCE(level >= n_entries)) level = n_entries - 1; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b82ff0bc6d0c..9d95125f1798 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -627,13 +627,9 @@ struct ddi_vbt_port_info { int max_tmds_clock; - /* - * This is an index in the HDMI/DVI DDI buffer translation table. - * The special value HDMI_LEVEL_SHIFT_UNKNOWN means the VBT didn't - * populate this field. - */ -#define HDMI_LEVEL_SHIFT_UNKNOWN 0xff + /* This is an index in the HDMI/DVI DDI buffer translation table. */ u8 hdmi_level_shift; + u8 hdmi_level_shift_set:1; u8 supports_dvi:1; u8 supports_hdmi:1; -- cgit v1.2.3 From 0d9ef19bddc88ec06ea1e32f0dda25cb82063386 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2019 17:39:49 +0200 Subject: drm/i915/bios: store child devices in a list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the array is getting clumsy. Make things a bit more dynamic. Remove early returns on not having child devices when the end result after "iterating" the empty list would be the same. v3: - use list_add_tail to not reverse the child device list (Ville) v2: - stick to previous naming of child devices (Ville) - use kzalloc, handle failure - initialize list head earlier to keep intel_bios_driver_remove() safe Cc: Ville Syrjala Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/3e72da0b412354ed8be6719df55b0e0cc4caa61a.1573227240.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 123 ++++++++++++++---------------- drivers/gpu/drm/i915/i915_drv.h | 3 +- 2 files changed, 58 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index c19b234bebe6..7c0ca733bef8 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -58,6 +58,12 @@ * that. */ +/* Wrapper for VBT child device config */ +struct display_device_data { + struct child_device_config child; + struct list_head node; +}; + #define SLAVE_ADDR1 0x70 #define SLAVE_ADDR2 0x72 @@ -449,8 +455,9 @@ static void parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, u8 bdb_version) { struct sdvo_device_mapping *mapping; + const struct display_device_data *devdata; const struct child_device_config *child; - int i, count = 0; + int count = 0; /* * Only parse SDVO mappings on gens that could have SDVO. This isn't @@ -461,8 +468,8 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, u8 bdb_version) return; } - for (i = 0, count = 0; i < dev_priv->vbt.child_dev_num; i++) { - child = dev_priv->vbt.child_dev + i; + list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) { + child = &devdata->child; if (child->slave_addr != SLAVE_ADDR1 && child->slave_addr != SLAVE_ADDR2) { @@ -1572,8 +1579,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, static void parse_ddi_ports(struct drm_i915_private *dev_priv, u8 bdb_version) { - const struct child_device_config *child; - int i; + const struct display_device_data *devdata; if (!HAS_DDI(dev_priv) && !IS_CHERRYVIEW(dev_priv)) return; @@ -1581,11 +1587,8 @@ static void parse_ddi_ports(struct drm_i915_private *dev_priv, u8 bdb_version) if (bdb_version < 155) return; - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - child = dev_priv->vbt.child_dev + i; - - parse_ddi_port(dev_priv, child, bdb_version); - } + list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) + parse_ddi_port(dev_priv, &devdata->child, bdb_version); } static void @@ -1593,8 +1596,9 @@ parse_general_definitions(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) { const struct bdb_general_definitions *defs; + struct display_device_data *devdata; const struct child_device_config *child; - int i, child_device_num, count; + int i, child_device_num; u8 expected_size; u16 block_size; int bus_pin; @@ -1650,26 +1654,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv, /* get the number of child device */ child_device_num = (block_size - sizeof(*defs)) / defs->child_dev_size; - count = 0; - /* get the number of child device that is present */ - for (i = 0; i < child_device_num; i++) { - child = child_device_ptr(defs, i); - if (!child->device_type) - continue; - count++; - } - if (!count) { - DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); - return; - } - dev_priv->vbt.child_dev = kcalloc(count, sizeof(*child), GFP_KERNEL); - if (!dev_priv->vbt.child_dev) { - DRM_DEBUG_KMS("No memory space for child device\n"); - return; - } - dev_priv->vbt.child_dev_num = count; - count = 0; for (i = 0; i < child_device_num; i++) { child = child_device_ptr(defs, i); if (!child->device_type) @@ -1678,15 +1663,23 @@ parse_general_definitions(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("Found VBT child device with type 0x%x\n", child->device_type); + devdata = kzalloc(sizeof(*devdata), GFP_KERNEL); + if (!devdata) + break; + /* * Copy as much as we know (sizeof) and is available - * (child_dev_size) of the child device. Accessing the data must - * depend on VBT version. + * (child_dev_size) of the child device config. Accessing the + * data must depend on VBT version. */ - memcpy(dev_priv->vbt.child_dev + count, child, + memcpy(&devdata->child, child, min_t(size_t, defs->child_dev_size, sizeof(*child))); - count++; + + list_add_tail(&devdata->node, &dev_priv->vbt.display_devices); } + + if (list_empty(&dev_priv->vbt.display_devices)) + DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); } /* Common defaults which may be overridden by VBT. */ @@ -1836,6 +1829,8 @@ void intel_bios_init(struct drm_i915_private *dev_priv) const struct bdb_header *bdb; u8 __iomem *bios = NULL; + INIT_LIST_HEAD(&dev_priv->vbt.display_devices); + if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv)) { DRM_DEBUG_KMS("Skipping VBT init due to disabled display.\n"); return; @@ -1895,9 +1890,13 @@ out: */ void intel_bios_driver_remove(struct drm_i915_private *dev_priv) { - kfree(dev_priv->vbt.child_dev); - dev_priv->vbt.child_dev = NULL; - dev_priv->vbt.child_dev_num = 0; + struct display_device_data *devdata, *n; + + list_for_each_entry_safe(devdata, n, &dev_priv->vbt.display_devices, node) { + list_del(&devdata->node); + kfree(devdata); + } + kfree(dev_priv->vbt.sdvo_lvds_vbt_mode); dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; kfree(dev_priv->vbt.lfp_lvds_vbt_mode); @@ -1921,17 +1920,18 @@ void intel_bios_driver_remove(struct drm_i915_private *dev_priv) */ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv) { + const struct display_device_data *devdata; const struct child_device_config *child; - int i; if (!dev_priv->vbt.int_tv_support) return false; - if (!dev_priv->vbt.child_dev_num) + if (list_empty(&dev_priv->vbt.display_devices)) return true; - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - child = dev_priv->vbt.child_dev + i; + list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) { + child = &devdata->child; + /* * If the device type is not TV, continue. */ @@ -1963,14 +1963,14 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv) */ bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin) { + const struct display_device_data *devdata; const struct child_device_config *child; - int i; - if (!dev_priv->vbt.child_dev_num) + if (list_empty(&dev_priv->vbt.display_devices)) return true; - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - child = dev_priv->vbt.child_dev + i; + list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) { + child = &devdata->child; /* If the device type is not LFP, continue. * We have to check both the new identifiers as well as the @@ -2012,6 +2012,7 @@ bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin) */ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port) { + const struct display_device_data *devdata; const struct child_device_config *child; static const struct { u16 dp, hdmi; @@ -2022,7 +2023,6 @@ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port por [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, }; - int i; if (HAS_DDI(dev_priv)) { const struct ddi_vbt_port_info *port_info = @@ -2037,11 +2037,8 @@ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port por if (WARN_ON(port == PORT_A) || port >= ARRAY_SIZE(port_mapping)) return false; - if (!dev_priv->vbt.child_dev_num) - return false; - - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - child = dev_priv->vbt.child_dev + i; + list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) { + child = &devdata->child; if ((child->dvo_port == port_mapping[port].dp || child->dvo_port == port_mapping[port].hdmi) && @@ -2062,6 +2059,7 @@ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port por */ bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port) { + const struct display_device_data *devdata; const struct child_device_config *child; static const short port_mapping[] = { [PORT_B] = DVO_PORT_DPB, @@ -2070,16 +2068,12 @@ bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port) [PORT_E] = DVO_PORT_DPE, [PORT_F] = DVO_PORT_DPF, }; - int i; if (HAS_DDI(dev_priv)) return dev_priv->vbt.ddi_port_info[port].supports_edp; - if (!dev_priv->vbt.child_dev_num) - return false; - - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - child = dev_priv->vbt.child_dev + i; + list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) { + child = &devdata->child; if (child->dvo_port == port_mapping[port] && (child->device_type & DEVICE_TYPE_eDP_BITS) == @@ -2128,13 +2122,10 @@ static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port) { - const struct child_device_config *child; - int i; + const struct display_device_data *devdata; - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - child = dev_priv->vbt.child_dev + i; - - if (child_dev_is_dp_dual_mode(child, port)) + list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) { + if (child_dev_is_dp_dual_mode(&devdata->child, port)) return true; } @@ -2151,12 +2142,12 @@ bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port) { + const struct display_device_data *devdata; const struct child_device_config *child; u8 dvo_port; - int i; - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - child = dev_priv->vbt.child_dev + i; + list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) { + child = &devdata->child; if (!(child->device_type & DEVICE_TYPE_MIPI_OUTPUT)) continue; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9d95125f1798..50809ffdc6b2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -720,8 +720,7 @@ struct intel_vbt_data { int crt_ddc_pin; - int child_dev_num; - struct child_device_config *child_dev; + struct list_head display_devices; struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS]; struct sdvo_device_mapping sdvo_mappings[2]; -- cgit v1.2.3 From 5f00cac921b1219bc9daf00d169385b4cb3916ce Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Nov 2019 15:00:51 +0000 Subject: drm/i915: Flush context free work on cleanup Throw in a flush_work() to specifically flush the context cleanup work before the module is unloaded. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112248 Fixes: a4e7ccdac38e ("drm/i915: Move context management under GEM") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191112150051.1603-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 72d389afa28a..17f395672e5e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -776,6 +776,7 @@ int i915_gem_init_contexts(struct drm_i915_private *i915) void i915_gem_driver_release__contexts(struct drm_i915_private *i915) { destroy_kernel_context(&i915->kernel_context); + flush_work(&i915->gem.contexts.free_work); } static int context_idr_cleanup(int id, void *p, void *data) -- cgit v1.2.3 From 64ad532a43de7027cf45e45102f5083ec2b88434 Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Mon, 11 Nov 2019 16:40:21 +0530 Subject: drm/i915/dsi: Define command mode registers Adding all the register definitions needed for mipi dsi command mode. Signed-off-by: Madhav Chauhan Signed-off-by: Vandita Kulkarni Reviewed-by: Jani Nikula Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191111111029.9126-2-vandita.kulkarni@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 78 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a607ea520829..2ffcc21670b7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5036,14 +5036,20 @@ enum { #define BLM_PCH_POLARITY (1 << 29) #define BLC_PWM_PCH_CTL2 _MMIO(0xc8254) -#define UTIL_PIN_CTL _MMIO(0x48400) -#define UTIL_PIN_ENABLE (1 << 31) - -#define UTIL_PIN_PIPE(x) ((x) << 29) -#define UTIL_PIN_PIPE_MASK (3 << 29) -#define UTIL_PIN_MODE_PWM (1 << 24) -#define UTIL_PIN_MODE_MASK (0xf << 24) -#define UTIL_PIN_POLARITY (1 << 22) +#define UTIL_PIN_CTL _MMIO(0x48400) +#define UTIL_PIN_ENABLE (1 << 31) +#define UTIL_PIN_PIPE_MASK (3 << 29) +#define UTIL_PIN_PIPE(x) ((x) << 29) +#define UTIL_PIN_MODE_MASK (0xf << 24) +#define UTIL_PIN_MODE_DATA (0 << 24) +#define UTIL_PIN_MODE_PWM (1 << 24) +#define UTIL_PIN_MODE_VBLANK (4 << 24) +#define UTIL_PIN_MODE_VSYNC (5 << 24) +#define UTIL_PIN_MODE_EYE_LEVEL (8 << 24) +#define UTIL_PIN_OUTPUT_DATA (1 << 23) +#define UTIL_PIN_POLARITY (1 << 22) +#define UTIL_PIN_DIRECTION_INPUT (1 << 19) +#define UTIL_PIN_INPUT_DATA (1 << 16) /* BXT backlight register definition. */ #define _BXT_BLC_PWM_CTL1 0xC8250 @@ -7500,11 +7506,15 @@ enum { #define GEN8_DE_PORT_IMR _MMIO(0x44444) #define GEN8_DE_PORT_IIR _MMIO(0x44448) #define GEN8_DE_PORT_IER _MMIO(0x4444c) +#define DSI1_NON_TE (1 << 31) +#define DSI0_NON_TE (1 << 30) #define ICL_AUX_CHANNEL_E (1 << 29) #define CNL_AUX_CHANNEL_F (1 << 28) #define GEN9_AUX_CHANNEL_D (1 << 27) #define GEN9_AUX_CHANNEL_C (1 << 26) #define GEN9_AUX_CHANNEL_B (1 << 25) +#define DSI1_TE (1 << 24) +#define DSI0_TE (1 << 23) #define BXT_DE_PORT_HP_DDIC (1 << 5) #define BXT_DE_PORT_HP_DDIB (1 << 4) #define BXT_DE_PORT_HP_DDIA (1 << 3) @@ -10770,6 +10780,57 @@ enum skl_power_gate { #define ICL_ESC_CLK_DIV_SHIFT 0 #define DSI_MAX_ESC_CLK 20000 /* in KHz */ +#define _DSI_CMD_FRMCTL_0 0x6b034 +#define _DSI_CMD_FRMCTL_1 0x6b834 +#define DSI_CMD_FRMCTL(port) _MMIO_PORT(port, \ + _DSI_CMD_FRMCTL_0,\ + _DSI_CMD_FRMCTL_1) +#define DSI_FRAME_UPDATE_REQUEST (1 << 31) +#define DSI_PERIODIC_FRAME_UPDATE_ENABLE (1 << 29) +#define DSI_NULL_PACKET_ENABLE (1 << 28) +#define DSI_FRAME_IN_PROGRESS (1 << 0) + +#define _DSI_INTR_MASK_REG_0 0x6b070 +#define _DSI_INTR_MASK_REG_1 0x6b870 +#define DSI_INTR_MASK_REG(port) _MMIO_PORT(port, \ + _DSI_INTR_MASK_REG_0,\ + _DSI_INTR_MASK_REG_1) + +#define _DSI_INTR_IDENT_REG_0 0x6b074 +#define _DSI_INTR_IDENT_REG_1 0x6b874 +#define DSI_INTR_IDENT_REG(port) _MMIO_PORT(port, \ + _DSI_INTR_IDENT_REG_0,\ + _DSI_INTR_IDENT_REG_1) +#define DSI_TE_EVENT (1 << 31) +#define DSI_RX_DATA_OR_BTA_TERMINATED (1 << 30) +#define DSI_TX_DATA (1 << 29) +#define DSI_ULPS_ENTRY_DONE (1 << 28) +#define DSI_NON_TE_TRIGGER_RECEIVED (1 << 27) +#define DSI_HOST_CHKSUM_ERROR (1 << 26) +#define DSI_HOST_MULTI_ECC_ERROR (1 << 25) +#define DSI_HOST_SINGL_ECC_ERROR (1 << 24) +#define DSI_HOST_CONTENTION_DETECTED (1 << 23) +#define DSI_HOST_FALSE_CONTROL_ERROR (1 << 22) +#define DSI_HOST_TIMEOUT_ERROR (1 << 21) +#define DSI_HOST_LOW_POWER_TX_SYNC_ERROR (1 << 20) +#define DSI_HOST_ESCAPE_MODE_ENTRY_ERROR (1 << 19) +#define DSI_FRAME_UPDATE_DONE (1 << 16) +#define DSI_PROTOCOL_VIOLATION_REPORTED (1 << 15) +#define DSI_INVALID_TX_LENGTH (1 << 13) +#define DSI_INVALID_VC (1 << 12) +#define DSI_INVALID_DATA_TYPE (1 << 11) +#define DSI_PERIPHERAL_CHKSUM_ERROR (1 << 10) +#define DSI_PERIPHERAL_MULTI_ECC_ERROR (1 << 9) +#define DSI_PERIPHERAL_SINGLE_ECC_ERROR (1 << 8) +#define DSI_PERIPHERAL_CONTENTION_DETECTED (1 << 7) +#define DSI_PERIPHERAL_FALSE_CTRL_ERROR (1 << 6) +#define DSI_PERIPHERAL_TIMEOUT_ERROR (1 << 5) +#define DSI_PERIPHERAL_LP_TX_SYNC_ERROR (1 << 4) +#define DSI_PERIPHERAL_ESC_MODE_ENTRY_CMD_ERR (1 << 3) +#define DSI_EOT_SYNC_ERROR (1 << 2) +#define DSI_SOT_SYNC_ERROR (1 << 1) +#define DSI_SOT_ERROR (1 << 0) + /* Gen4+ Timestamp and Pipe Frame time stamp registers */ #define GEN4_TIMESTAMP _MMIO(0x2358) #define ILK_TIMESTAMP_HI _MMIO(0x70070) @@ -11374,6 +11435,7 @@ enum skl_power_gate { #define CMD_MODE_TE_GATE (0x1 << 28) #define VIDEO_MODE_SYNC_EVENT (0x2 << 28) #define VIDEO_MODE_SYNC_PULSE (0x3 << 28) +#define TE_SOURCE_GPIO (1 << 27) #define LINK_READY (1 << 20) #define PIX_FMT_MASK (0x3 << 16) #define PIX_FMT_SHIFT 16 -- cgit v1.2.3 From 8c388ac8f1866e61a811a81eb8bff429f3865512 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Nov 2019 16:36:43 +0000 Subject: drm/i915/selftests: Remove unused local variable 'file' drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c:453 igt_threaded_blt() error: uninitialized symbol 'file'. Fixes: 34485832cb98 ("drm/i915/selftests: Exercise parallel blit operations on a single ctx") Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191112163643.3527-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c index c8a8c07e07ab..675c1a20a2f1 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c @@ -435,7 +435,6 @@ static int igt_threaded_blt(struct drm_i915_private *i915, struct task_struct **tsk; unsigned int n_cpus, i; I915_RND_STATE(prng); - struct file *file; int err = 0; n_cpus = num_online_cpus() + 1; @@ -450,7 +449,7 @@ static int igt_threaded_blt(struct drm_i915_private *i915, thread[0].file = mock_file(i915); if (IS_ERR(thread[0].file)) { - err = PTR_ERR(file); + err = PTR_ERR(thread[0].file); goto out_thread; } -- cgit v1.2.3 From 860afa0868419fcf33a7160f3b48ff57e15a6e34 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Nov 2019 16:09:41 +0000 Subject: drm/i915/gt: Flush gen7 even harder live_blt is still failing on hsw, showing the hallmark of incoherency. Since we are fairly certain that the interrupt is after the seqno is visible, the other possibility is that the seqno is before the writes to memory are flushed. Throw in an TLB invalidate before the breadcrumb as we are reasonably confident that forces a CS stall. References: f9228f765873 ("drm/i915/gt: Try an extra flush on the Haswell blitter") References: https://bugs.freedesktop.org/show_bug.cgi?id=112147 Testcase: igt/i915_selftest/live_blt Signed-off-by: Chris Wilson Cc: Mika Kuoppala Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191112160941.23969-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index fc29df712810..e8bee44add34 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -454,8 +454,9 @@ static u32 *gen7_xcs_emit_breadcrumb(struct i915_request *rq, u32 *cs) GEM_BUG_ON(i915_request_active_timeline(rq)->hwsp_ggtt != rq->engine->status_page.vma); GEM_BUG_ON(offset_in_page(i915_request_active_timeline(rq)->hwsp_offset) != I915_GEM_HWS_SEQNO_ADDR); - *cs++ = MI_FLUSH_DW; - *cs++ = 0; + *cs++ = (MI_FLUSH_DW | MI_INVALIDATE_TLB | + MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW); + *cs++ = I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; *cs++ = 0; *cs++ = MI_FLUSH_DW | MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_DW_STORE_INDEX; -- cgit v1.2.3 From d670719467ecb3ab6bf39c97e01657a82d458fde Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 8 Nov 2019 13:42:51 -0800 Subject: drm/i915: do not warn late about hdmi on port A The warning should be just a warning. Where it is currently is wrong since we already registered the connector on drm, meaning it dies later on a NULL pointer deref if the VBT-overriding we have is removed. Move the warning up. Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191108214251.79305-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_hdmi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index e084c2f75379..ed4a68fb351f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -3140,6 +3140,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, DRM_DEBUG_KMS("Adding HDMI connector on [ENCODER:%d:%s]\n", intel_encoder->base.base.id, intel_encoder->base.name); + if (WARN_ON(port == PORT_A)) + return; + if (WARN(intel_dig_port->max_lanes < 4, "Not enough lanes (%d) for HDMI on [ENCODER:%d:%s]\n", intel_dig_port->max_lanes, intel_encoder->base.base.id, @@ -3159,8 +3162,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port); - if (WARN_ON(port == PORT_A)) - return; intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); if (HAS_DDI(dev_priv)) -- cgit v1.2.3 From 50a5065f4474c2dbc1f7462b45a32d33d7b48d88 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 12 Nov 2019 12:46:08 +0200 Subject: drm/i915: Fix detection for a CMP-V PCH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to internal documents I found for CMP PCHs the PCI ID 0xA3C1 belongs to a CMP-V chipset. Based on the same docs the programming of the PCH is compatible with that of KBP. Fix up my previous wrong assumption accordingly using the SPT programming which in turn is the basis for KBP. The original bug reporter verified that this is the correct PCH identification (the only way we'll program valid DDC pin-pair values to the GMBUS register) and the Windows team uses the same identification (that is using the KBP programming model for this PCH). I filed the necessary Bspec update requests (BSpec/33734). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112051 Fixes: 37c92dc303dd ("drm/i915: Add new CNL PCH ID seen on a CML platform") Reported-and-tested-by: Cyrus Cc: Cyrus Cc: Timo Aaltonen Cc: José Roberto de Souza Signed-off-by: Imre Deak Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191112104608.24587-1-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_pch.c | 6 +++++- drivers/gpu/drm/i915/intel_pch.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c index fd22355b9a96..43b68b5fc562 100644 --- a/drivers/gpu/drm/i915/intel_pch.c +++ b/drivers/gpu/drm/i915/intel_pch.c @@ -62,7 +62,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) /* KBP is SPT compatible */ return PCH_SPT; case INTEL_PCH_CNP_DEVICE_ID_TYPE: - case INTEL_PCH_CNP2_DEVICE_ID_TYPE: DRM_DEBUG_KMS("Found Cannon Lake PCH (CNP)\n"); WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); return PCH_CNP; @@ -76,6 +75,11 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) WARN_ON(!IS_COFFEELAKE(dev_priv)); /* CometPoint is CNP Compatible */ return PCH_CNP; + case INTEL_PCH_CMP_V_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Comet Lake V PCH (CMP-V)\n"); + WARN_ON(!IS_COFFEELAKE(dev_priv)); + /* Comet Lake V PCH is based on KBP, which is SPT compatible */ + return PCH_SPT; case INTEL_PCH_ICP_DEVICE_ID_TYPE: DRM_DEBUG_KMS("Found Ice Lake PCH\n"); WARN_ON(!IS_ICELAKE(dev_priv)); diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h index 52d145dcdb15..3053d1ce398b 100644 --- a/drivers/gpu/drm/i915/intel_pch.h +++ b/drivers/gpu/drm/i915/intel_pch.h @@ -40,10 +40,10 @@ enum intel_pch { #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00 #define INTEL_PCH_KBP_DEVICE_ID_TYPE 0xA280 #define INTEL_PCH_CNP_DEVICE_ID_TYPE 0xA300 -#define INTEL_PCH_CNP2_DEVICE_ID_TYPE 0xA380 #define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE 0x9D80 #define INTEL_PCH_CMP_DEVICE_ID_TYPE 0x0280 #define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680 +#define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380 #define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480 #define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00 #define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080 -- cgit v1.2.3 From 046091758b50a5fff79726a31c1391614a3d84c8 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 12 Nov 2019 14:47:56 -0800 Subject: Revert "drm/i915/ehl: Update MOCS table for EHL" This reverts commit f4071997f1de016780ec6b79c63d90cd5886ee83. These extra EHL entries won't behave as expected without a bit more work on the kernel side so let's drop them until that kernel work has had a chance to land. Userspace trying to use these new entries won't get the advantage of the new functionality these entries are meant to provide, but at least it won't misbehave. When we do add these back in the future, we'll probably want to explicitly use separate tables for ICL and EHL so that userspace software that mistakenly uses these entries (which are undefined on ICL) sees the same behavior it sees with all the other undefined entries. Cc: Francisco Jerez Cc: Jon Bloomfield Cc: Lucas De Marchi Cc: # v5.3+ Fixes: f4071997f1de ("drm/i915/ehl: Update MOCS table for EHL") Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191112224757.25116-1-matthew.d.roper@intel.com Reviewed-by: Francisco Jerez --- drivers/gpu/drm/i915/gt/intel_mocs.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index 6e881c735b20..06e2adbf27be 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -200,14 +200,6 @@ static const struct drm_i915_mocs_entry broxton_mocs_table[] = { MOCS_ENTRY(15, \ LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1), \ L3_3_WB), \ - /* Bypass LLC - Uncached (EHL+) */ \ - MOCS_ENTRY(16, \ - LE_1_UC | LE_TC_1_LLC | LE_SCF(1), \ - L3_1_UC), \ - /* Bypass LLC - L3 (Read-Only) (EHL+) */ \ - MOCS_ENTRY(17, \ - LE_1_UC | LE_TC_1_LLC | LE_SCF(1), \ - L3_3_WB), \ /* Self-Snoop - L3 + LLC */ \ MOCS_ENTRY(18, \ LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SSE(3), \ -- cgit v1.2.3 From bfb0e8e63d865559cc97af235aea583b7dcc235f Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 12 Nov 2019 14:47:57 -0800 Subject: drm/i915/tgl: MOCS table update The bspec was just updated with a minor correction to entry 61 (it shouldn't have had the SCF bit set). v2: - Add a MOCS_ENTRY_UNUSED() and use it to declare the explicitly-reserved MOCS entries. (Lucas) - Move the warning suppression from the Makefile to a #pragma that only affects the TGL table. (Lucas) v3: - Entries 16 and 17 are identical to ICL now, so no need to explicitly adjust them (or mess with compiler warning overrides). Bspec: 45101 Fixes: 2ddf992179c4 ("drm/i915/tgl: Define MOCS entries for Tigerlake") Cc: Tomasz Lis Cc: Lucas De Marchi Cc: Francisco Jerez Cc: Jon Bloomfield Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191112224757.25116-2-matthew.d.roper@intel.com Reviewed-by: Francisco Jerez Reviewed-by: Lucas De Marchi Reviewed-by: Tomasz Lis --- drivers/gpu/drm/i915/gt/intel_mocs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index 06e2adbf27be..2b977991b785 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -263,7 +263,7 @@ static const struct drm_i915_mocs_entry tigerlake_mocs_table[] = { L3_1_UC), /* HW Special Case (Displayable) */ MOCS_ENTRY(61, - LE_1_UC | LE_TC_1_LLC | LE_SCF(1), + LE_1_UC | LE_TC_1_LLC, L3_3_WB), }; -- cgit v1.2.3 From 9381e2bee8d2199501855a5d5f8dab016d6fb9e5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Nov 2019 15:19:56 +0000 Subject: drm/i915/gt: Invalidate as we write the gen7 breadcrumb Still the saga of the hsw live_blt incoherency continues. While it did seem that the invalidate before the breadcrumb had improved the mtbf, nevertheless live_blt still failed. Mika's next idea was to pull the invalidate-stall into the breadcrumb write itself. References: 860afa086841 ("drm/i915/gt: Flush gen7 even harder") References: https://bugs.freedesktop.org/show_bug.cgi?id=112147 Testcase: igt/i915_selftest/live_blt Signed-off-by: Chris Wilson Cc: Mika Kuoppala Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191113151956.32242-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index e8bee44add34..f25ceccb335e 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -454,12 +454,8 @@ static u32 *gen7_xcs_emit_breadcrumb(struct i915_request *rq, u32 *cs) GEM_BUG_ON(i915_request_active_timeline(rq)->hwsp_ggtt != rq->engine->status_page.vma); GEM_BUG_ON(offset_in_page(i915_request_active_timeline(rq)->hwsp_offset) != I915_GEM_HWS_SEQNO_ADDR); - *cs++ = (MI_FLUSH_DW | MI_INVALIDATE_TLB | - MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW); - *cs++ = I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; - *cs++ = 0; - - *cs++ = MI_FLUSH_DW | MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_DW_STORE_INDEX; + *cs++ = MI_FLUSH_DW | MI_INVALIDATE_TLB | + MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_DW_STORE_INDEX; *cs++ = I915_GEM_HWS_SEQNO_ADDR | MI_FLUSH_DW_USE_GTT; *cs++ = rq->fence.seqno; @@ -474,6 +470,7 @@ static u32 *gen7_xcs_emit_breadcrumb(struct i915_request *rq, u32 *cs) *cs++ = 0; *cs++ = MI_USER_INTERRUPT; + *cs++ = MI_NOOP; rq->tail = intel_ring_offset(rq, cs); assert_ring_tail_valid(rq->ring, rq->tail); -- cgit v1.2.3 From 496f50a601d5b3bbaad7188c2884c5bdcc8ec1aa Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 8 Nov 2019 13:13:51 -0800 Subject: drm/i915/bios: rename bios to oprom when mapping pci rom oprom is actually a better name to use when using pci_map_rom(). "bios" is way too generic and confusing. Signed-off-by: Lucas De Marchi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191108003602.33526-2-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 7c0ca733bef8..5042d71b3004 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1789,7 +1789,7 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) return vbt; } -static const struct vbt_header *find_vbt(void __iomem *bios, size_t size) +static const struct vbt_header *find_vbt(void __iomem *oprom, size_t size) { size_t i; @@ -1797,14 +1797,14 @@ static const struct vbt_header *find_vbt(void __iomem *bios, size_t size) for (i = 0; i + 4 < size; i++) { void *vbt; - if (ioread32(bios + i) != *((const u32 *) "$VBT")) + if (ioread32(oprom + i) != *((const u32 *)"$VBT")) continue; /* * This is the one place where we explicitly discard the address * space (__iomem) of the BIOS/VBT. */ - vbt = (void __force *) bios + i; + vbt = (void __force *)oprom + i; if (intel_bios_is_valid_vbt(vbt, size - i)) return vbt; @@ -1827,7 +1827,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv) struct pci_dev *pdev = dev_priv->drm.pdev; const struct vbt_header *vbt = dev_priv->opregion.vbt; const struct bdb_header *bdb; - u8 __iomem *bios = NULL; + u8 __iomem *oprom = NULL; INIT_LIST_HEAD(&dev_priv->vbt.display_devices); @@ -1842,11 +1842,11 @@ void intel_bios_init(struct drm_i915_private *dev_priv) if (!vbt) { size_t size; - bios = pci_map_rom(pdev, &size); - if (!bios) + oprom = pci_map_rom(pdev, &size); + if (!oprom) goto out; - vbt = find_vbt(bios, size); + vbt = find_vbt(oprom, size); if (!vbt) goto out; @@ -1880,8 +1880,8 @@ out: init_vbt_missing_defaults(dev_priv); } - if (bios) - pci_unmap_rom(pdev, bios); + if (oprom) + pci_unmap_rom(pdev, oprom); } /** -- cgit v1.2.3 From ff00ff96a56383166da41f8eb57ff6c39d55673a Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 8 Nov 2019 13:13:52 -0800 Subject: drm/i915/bios: make sure to check vbt size When we call intel_bios_is_valid_vbt(), size may not actually be the size of the VBT, but rather the size of the blob the VBT is contained in. For example, when mapping the PCI oprom, size will be the entire oprom size. We don't want to read beyond what is reported to be the VBT. So make sure we vbt->vbt_size makes sense and use that for the latter checks. v2: check for vbt_size after checking for vbt signature and give it a more meaningful error message (from Jani) Signed-off-by: Lucas De Marchi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191108003602.33526-3-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 5042d71b3004..f345f8d900d2 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1772,6 +1772,13 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) return false; } + if (vbt->vbt_size > size) { + DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n"); + return false; + } + + size = vbt->vbt_size; + if (range_overflows_t(size_t, vbt->bdb_offset, sizeof(struct bdb_header), -- cgit v1.2.3 From bb747fa5a9cbf561e5a30649f360feb9e6855645 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 7 Nov 2019 13:45:57 -0800 Subject: drm/i915/display: Fix TRANS_DDI_MST_TRANSPORT_SELECT definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TRANS_DDI_MST_TRANSPORT_SELECT is 2 bits wide not 3, it was taking one bit from EDP/DSI Input Select. Fixes: b3545e086877 ("drm/i915/tgl: add support to one DP-MST stream") Cc: Lucas De Marchi Signed-off-by: José Roberto de Souza Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20191107214559.77087-1-jose.souza@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2ffcc21670b7..585750676c81 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9675,7 +9675,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_A_ONOFF (4 << 12) #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) -#define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(12, 10) +#define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) #define TRANS_DDI_HDCP_SIGNALLING (1 << 9) -- cgit v1.2.3 From 4d89adc7b56faf56df032912f838c3cf8084492b Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 7 Nov 2019 13:45:58 -0800 Subject: drm/i915/display/dsi: Add support to pipe D MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding pipe D support to DSI transcoder. Not adding it for EDP transcoder code paths as only TGL has 4 pipes and it do not have a EDP transcoder. Reviewed-by: Lucas De Marchi Cc: Lucas De Marchi Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191107214559.77087-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 6 ++++++ drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 8eb2d7f29c82..f688207932e0 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -745,6 +745,9 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, case PIPE_C: tmp |= TRANS_DDI_EDP_INPUT_C_ONOFF; break; + case PIPE_D: + tmp |= TRANS_DDI_EDP_INPUT_D_ONOFF; + break; } /* enable DDI buffer */ @@ -1325,6 +1328,9 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder, case TRANS_DDI_EDP_INPUT_C_ONOFF: *pipe = PIPE_C; break; + case TRANS_DDI_EDP_INPUT_D_ONOFF: + *pipe = PIPE_D; + break; default: DRM_ERROR("Invalid PIPE input\n"); goto out; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 585750676c81..526fb0b208a8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9675,6 +9675,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_A_ONOFF (4 << 12) #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) +#define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) #define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) -- cgit v1.2.3 From ff15e5a068eeea1e4647fda407b5aa2fb76fb2a5 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 7 Nov 2019 13:45:59 -0800 Subject: drm/i915/display/mst: Enable virtual channel payload allocation earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This register was being enabled after enable TRANS_DDI_FUNC_CTL and PIPECONF/TRANS_CONF while BSpec states that it should be set when enabling TRANS_DDI_FUNC_CTL. BSpec: 49190 BSpec: 22243 Reviewed-by: Lucas De Marchi Cc: Lucas De Marchi Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191107214559.77087-3-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 18 ++---------------- drivers/gpu/drm/i915/display/intel_display.c | 6 ------ 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index e56eb8a49cdd..8f817de34460 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1802,22 +1802,6 @@ void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state, I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp); } -void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state, - bool state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 temp; - - temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); - if (state == true) - temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC; - else - temp &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC; - I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); -} - /* * Returns the TRANS_DDI_FUNC_CTL value based on CRTC state. * @@ -1923,6 +1907,8 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state) u32 temp; temp = intel_ddi_transcoder_func_reg_val_get(crtc_state); + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) + temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC; I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp); } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5f3340554149..c382498f081e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6673,9 +6673,6 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (pipe_config->has_pch_encoder) lpt_pch_enable(state, pipe_config); - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) - intel_ddi_set_vc_payload_alloc(pipe_config, true); - assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); @@ -6786,9 +6783,6 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, if (!transcoder_is_dsi(cpu_transcoder)) intel_disable_pipe(old_crtc_state); - if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) - intel_ddi_set_vc_payload_alloc(old_crtc_state, false); - if (INTEL_GEN(dev_priv) >= 11) icl_disable_transcoder_port_sync(old_crtc_state); -- cgit v1.2.3 From 523e0cc89b83c4caa98e2955762e35f1688e11ed Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 12 Nov 2019 18:19:35 -0800 Subject: drm/i915/tgl: allow DVI/HDMI on port A Tiger Lake supports HDMI on port A. For other platforms we ignore what the VBT says regarding HDMI to workaround broken VBTs, see commit 2ba7d7e04371 ("drm/i915/bios: ignore HDMI on port A"). Make this apply gen12+ so they inherit the TGL behavior. Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191113021935.41547-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index f345f8d900d2..6d7b1a83cb07 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1450,7 +1450,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, 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) { + if (port == PORT_A && is_dvi && INTEL_GEN(dev_priv) < 12) { DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n", is_hdmi ? "/HDMI" : ""); is_dvi = false; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index ed4a68fb351f..659a03b08849 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -3140,7 +3140,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, DRM_DEBUG_KMS("Adding HDMI connector on [ENCODER:%d:%s]\n", intel_encoder->base.base.id, intel_encoder->base.name); - if (WARN_ON(port == PORT_A)) + if (INTEL_GEN(dev_priv) < 12 && WARN_ON(port == PORT_A)) return; if (WARN(intel_dig_port->max_lanes < 4, -- cgit v1.2.3 From 48715f7001742e0d1cb20cffab1a0d75f5f7ad72 Mon Sep 17 00:00:00 2001 From: Bruce Chang Date: Wed, 13 Nov 2019 15:11:04 -0800 Subject: drm/i915: Avoid atomic context for error capture io_mapping_map_atomic/kmap_atomic are occasionally taken in error capture (if there is no aperture preallocated for the use of error capture), but the error capture and compression routines are now run in normal context: <3> [113.316247] BUG: sleeping function called from invalid context at mm/page_alloc.c:4653 <3> [113.318190] in_atomic(): 1, irqs_disabled(): 0, pid: 678, name: debugfs_test <4> [113.319900] no locks held by debugfs_test/678. <3> [113.321002] Preemption disabled at: <4> [113.321130] [] i915_error_object_create+0x494/0x610 [i915] <4> [113.327259] Call Trace: <4> [113.327871] dump_stack+0x67/0x9b <4> [113.328683] ___might_sleep+0x167/0x250 <4> [113.329618] __alloc_pages_nodemask+0x26b/0x1110 <4> [113.334614] pool_alloc.constprop.19+0x14/0x60 [i915] <4> [113.335951] compress_page+0x7c/0x100 [i915] <4> [113.337110] i915_error_object_create+0x4bd/0x610 [i915] <4> [113.338515] i915_capture_gpu_state+0x384/0x1680 [i915] However, it is not a good idea to run the slow compression inside atomic context, so we choose not to. Fixes: 895d8ebeaa924 ("drm/i915: error capture with no ggtt slot") Signed-off-by: Bruce Chang Reviewed-by: Brian Welty Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191113231104.24208-1-yu.bruce.chang@intel.com --- drivers/gpu/drm/i915/i915_gpu_error.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 1f2f266f26af..7118ecb7f144 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1029,9 +1029,9 @@ i915_error_object_create(struct drm_i915_private *i915, for_each_sgt_daddr(dma, iter, vma->pages) { void __iomem *s; - s = io_mapping_map_atomic_wc(&mem->iomap, dma); + s = io_mapping_map_wc(&mem->iomap, dma, PAGE_SIZE); ret = compress_page(compress, (void __force *)s, dst); - io_mapping_unmap_atomic(s); + io_mapping_unmap(s); if (ret) break; } @@ -1043,9 +1043,9 @@ i915_error_object_create(struct drm_i915_private *i915, drm_clflush_pages(&page, 1); - s = kmap_atomic(page); + s = kmap(page); ret = compress_page(compress, s, dst); - kunmap_atomic(s); + kunmap(s); drm_clflush_pages(&page, 1); -- cgit v1.2.3 From 5ba2bb587d89f0d44fbe4b74492c20dbf840cbfe Mon Sep 17 00:00:00 2001 From: Radhakrishna Sripada Date: Wed, 13 Nov 2019 15:19:53 -0800 Subject: drm/i915/tgl: Wa_1606679103 Extend disabling SAMPLER_STATE prefetch workaround to gen12. v2: Limit the WA to TGL A0 and update the WA no(Chris) BSpec: 52890 Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Radhakrishna Sripada Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191113231953.24853-1-radhakrishna.sripada@intel.com --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index e4bccc14602f..399acae2f33f 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -1315,6 +1315,14 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) GEN6_RC_SLEEP_PSMI_CONTROL, GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE | GEN8_RC_SEMA_IDLE_MSG_DISABLE); + + /* + * Wa_1606679103:tgl + * (see also Wa_1606682166:icl) + */ + wa_write_or(wal, + GEN7_SARCHKMD, + GEN7_DISABLE_SAMPLER_PREFETCH); } if (IS_GEN(i915, 11)) { -- cgit v1.2.3 From 93937659dc644f708def8fa58cb63c5c9f499f26 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Wed, 13 Nov 2019 17:46:39 +0200 Subject: drm/i915/perf: don't forget noa wait after oa config I'm observing incoherence metric values, changing from run to run. It appears the patches introducing noa wait & reconfiguration from command stream switched places in the series multiple times during the review. This lead to the dependency of one onto the order to go missing... Signed-off-by: Lionel Landwerlin Fixes: 15d0ace1f876 ("drm/i915/perf: execute OA configuration from command stream") Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191113154639.27144-1-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 507236bd41ae..31e47ee23357 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1870,7 +1870,7 @@ alloc_oa_config_buffer(struct i915_perf_stream *stream, config_length += num_lri_dwords(oa_config->mux_regs_len); config_length += num_lri_dwords(oa_config->b_counter_regs_len); config_length += num_lri_dwords(oa_config->flex_regs_len); - config_length++; /* MI_BATCH_BUFFER_END */ + config_length += 3; /* MI_BATCH_BUFFER_START */ config_length = ALIGN(sizeof(u32) * config_length, I915_GTT_PAGE_SIZE); obj = i915_gem_object_create_shmem(stream->perf->i915, config_length); @@ -1895,7 +1895,12 @@ alloc_oa_config_buffer(struct i915_perf_stream *stream, oa_config->flex_regs, oa_config->flex_regs_len); - *cs++ = MI_BATCH_BUFFER_END; + /* Jump into the active wait. */ + *cs++ = (INTEL_GEN(stream->perf->i915) < 8 ? + MI_BATCH_BUFFER_START : + MI_BATCH_BUFFER_START_GEN8); + *cs++ = i915_ggtt_offset(stream->noa_wait); + *cs++ = 0; i915_gem_object_flush_map(obj); i915_gem_object_unpin_map(obj); -- cgit v1.2.3 From abc5520704ab438099fe352636b30b05c1253bea Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 13 Nov 2019 18:06:33 +0000 Subject: drm/i915/fbdev: Restore physical addresses for fb_mmap() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fbdev uses the physical address of our framebuffer for its fb_mmap() routine. While we need to adapt this address for the new io BAR, we have to fix v5.4 first! The simplest fix is to restore the smem back to v5.3 and we will then probably have to implement our fbops->fb_mmap() callback to handle local memory. Reported-by: Neil MacLeod Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112256 Fixes: 5f889b9a61dd ("drm/i915: Disregard drm_mode_config.fb_base") Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Tested-by: Neil MacLeod Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191113180633.3947-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/display/intel_fbdev.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 3d1061470e76..48c960ca12fb 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -234,6 +234,11 @@ static int intelfb_create(struct drm_fb_helper *helper, info->apertures->ranges[0].base = ggtt->gmadr.start; info->apertures->ranges[0].size = ggtt->mappable_end; + /* Our framebuffer is the entirety of fbdev's system memory */ + info->fix.smem_start = + (unsigned long)(ggtt->gmadr.start + vma->node.start); + info->fix.smem_len = vma->node.size; + vaddr = i915_vma_pin_iomap(vma); if (IS_ERR(vaddr)) { DRM_ERROR("Failed to remap framebuffer into virtual memory\n"); @@ -243,10 +248,6 @@ static int intelfb_create(struct drm_fb_helper *helper, info->screen_base = vaddr; info->screen_size = vma->node.size; - /* Our framebuffer is the entirety of fbdev's system memory */ - info->fix.smem_start = (unsigned long)info->screen_base; - info->fix.smem_len = info->screen_size; - drm_fb_helper_fill_info(info, &ifbdev->helper, sizes); /* If the object is shmemfs backed, it will have given us zeroed pages. -- cgit v1.2.3 From 93975d613ec0731ce3148b543cbf675b3251bfff Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Nov 2019 22:35:57 +0000 Subject: drm/i915/gt: Set unused mocs entry to follow PTE on tgl as on all others Be consistent in our mocs setup on Tigerlake and set the unused control value to follow the PTE entry as we previously have done. The unused values are beyond the defines of the ABI, the consistency simplifies our checking. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191112223600.30993-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_mocs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index 2b977991b785..603263310c37 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -481,7 +481,7 @@ static void intel_mocs_init_global(struct intel_gt *gt) for (; index < table.n_entries; index++) intel_uncore_write(uncore, GEN12_GLOBAL_MOCS(index), - table.table[0].control_value); + table.table[I915_MOCS_PTE].control_value); } void intel_mocs_init(struct intel_gt *gt) -- cgit v1.2.3 From f616de0e24d344f98bc0b0bacd3236d65e2efab9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Nov 2019 22:35:58 +0000 Subject: drm/i915/gt: Tidy up debug-warns for the mocs control table As we always run new platforms through CI, we only need the debug code compiled in during CI runs. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191112223600.30993-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_mocs.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index 603263310c37..dfc3eda87a0c 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -283,44 +283,42 @@ static const struct drm_i915_mocs_entry icelake_mocs_table[] = { static bool get_mocs_settings(const struct drm_i915_private *i915, struct drm_i915_mocs_table *table) { - bool result = false; - if (INTEL_GEN(i915) >= 12) { table->size = ARRAY_SIZE(tigerlake_mocs_table); table->table = tigerlake_mocs_table; table->n_entries = GEN11_NUM_MOCS_ENTRIES; - result = true; } else if (IS_GEN(i915, 11)) { table->size = ARRAY_SIZE(icelake_mocs_table); table->table = icelake_mocs_table; table->n_entries = GEN11_NUM_MOCS_ENTRIES; - result = true; } else if (IS_GEN9_BC(i915) || IS_CANNONLAKE(i915)) { table->size = ARRAY_SIZE(skylake_mocs_table); table->n_entries = GEN9_NUM_MOCS_ENTRIES; table->table = skylake_mocs_table; - result = true; } else if (IS_GEN9_LP(i915)) { table->size = ARRAY_SIZE(broxton_mocs_table); table->n_entries = GEN9_NUM_MOCS_ENTRIES; table->table = broxton_mocs_table; - result = true; } else { WARN_ONCE(INTEL_GEN(i915) >= 9, "Platform that should have a MOCS table does not.\n"); + return false; } + if (GEM_DEBUG_WARN_ON(table->size > table->n_entries)) + return false; + /* WaDisableSkipCaching:skl,bxt,kbl,glk */ if (IS_GEN(i915, 9)) { int i; for (i = 0; i < table->size; i++) - if (WARN_ON(table->table[i].l3cc_value & - (L3_ESC(1) | L3_SCC(0x7)))) + if (GEM_DEBUG_WARN_ON(table->table[i].l3cc_value & + (L3_ESC(1) | L3_SCC(0x7)))) return false; } - return result; + return true; } static i915_reg_t mocs_register(const struct intel_engine_cs *engine, int index) @@ -389,9 +387,7 @@ static u16 get_entry_l3cc(const struct drm_i915_mocs_table *table, return table->table[I915_MOCS_PTE].l3cc_value; } -static inline u32 l3cc_combine(const struct drm_i915_mocs_table *table, - u16 low, - u16 high) +static inline u32 l3cc_combine(u16 low, u16 high) { return low | (u32)high << 16; } @@ -409,7 +405,7 @@ static void init_l3cc_table(struct intel_engine_cs *engine, intel_uncore_write(uncore, GEN9_LNCFCMOCS(i), - l3cc_combine(table, low, high)); + l3cc_combine(low, high)); } /* Odd table size - 1 left over */ @@ -418,7 +414,7 @@ static void init_l3cc_table(struct intel_engine_cs *engine, intel_uncore_write(uncore, GEN9_LNCFCMOCS(i), - l3cc_combine(table, low, unused_value)); + l3cc_combine(low, unused_value)); i++; } @@ -426,8 +422,7 @@ static void init_l3cc_table(struct intel_engine_cs *engine, for (; i < table->n_entries / 2; i++) intel_uncore_write(uncore, GEN9_LNCFCMOCS(i), - l3cc_combine(table, unused_value, - unused_value)); + l3cc_combine(unused_value, unused_value)); } void intel_mocs_init_engine(struct intel_engine_cs *engine) @@ -465,9 +460,6 @@ static void intel_mocs_init_global(struct intel_gt *gt) if (!get_mocs_settings(gt->i915, &table)) return; - if (GEM_DEBUG_WARN_ON(table.size > table.n_entries)) - return; - for (index = 0; index < table.size; index++) intel_uncore_write(uncore, GEN12_GLOBAL_MOCS(index), -- cgit v1.2.3 From f8a0c7a996ff17191973838e93f5be51c9828174 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Nov 2019 22:35:59 +0000 Subject: drm/i915/gt: Refactor mocs loops into single control macro We repeatedly (and more so in future) use the same looping construct over the mocs definition table to setup the register state. Refactor the loop construct into a reusable macro. add/remove: 2/1 grow/shrink: 1/2 up/down: 113/-330 (-217) Function old new delta intel_mocs_init_engine.cold - 71 +71 offset - 28 +28 __func__ 17273 17287 +14 intel_mocs_init 143 113 -30 mocs_register.isra 91 - -91 intel_mocs_init_engine 503 294 -209 Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191112223600.30993-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_mocs.c | 133 ++++++++++++++--------------------- drivers/gpu/drm/i915/i915_reg.h | 19 +++-- 2 files changed, 64 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index dfc3eda87a0c..f43466e776f4 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -321,27 +321,6 @@ static bool get_mocs_settings(const struct drm_i915_private *i915, return true; } -static i915_reg_t mocs_register(const struct intel_engine_cs *engine, int index) -{ - switch (engine->id) { - case RCS0: - return GEN9_GFX_MOCS(index); - case VCS0: - return GEN9_MFX0_MOCS(index); - case BCS0: - return GEN9_BLT_MOCS(index); - case VECS0: - return GEN9_VEBOX_MOCS(index); - case VCS1: - return GEN9_MFX1_MOCS(index); - case VCS2: - return GEN11_MFX2_MOCS(index); - default: - MISSING_CASE(engine->id); - return INVALID_MMIO_REG; - } -} - /* * Get control_value from MOCS entry taking into account when it's not used: * I915_MOCS_PTE's value is returned in this case. @@ -349,29 +328,47 @@ static i915_reg_t mocs_register(const struct intel_engine_cs *engine, int index) static u32 get_entry_control(const struct drm_i915_mocs_table *table, unsigned int index) { - if (table->table[index].used) + if (index < table->size && table->table[index].used) return table->table[index].control_value; return table->table[I915_MOCS_PTE].control_value; } -static void init_mocs_table(struct intel_engine_cs *engine, - const struct drm_i915_mocs_table *table) +#define for_each_mocs(mocs, t, i) \ + for (i = 0; \ + i < (t)->n_entries ? (mocs = get_entry_control((t), i)), 1 : 0;\ + i++) + +static void __init_mocs_table(struct intel_uncore *uncore, + const struct drm_i915_mocs_table *table, + u32 addr) { - struct intel_uncore *uncore = engine->uncore; - u32 unused_value = table->table[I915_MOCS_PTE].control_value; unsigned int i; + u32 mocs; - for (i = 0; i < table->size; i++) - intel_uncore_write_fw(uncore, - mocs_register(engine, i), - get_entry_control(table, i)); + for_each_mocs(mocs, table, i) + intel_uncore_write_fw(uncore, _MMIO(addr + i * 4), mocs); +} + +static u32 mocs_offset(const struct intel_engine_cs *engine) +{ + static const u32 offset[] = { + [RCS0] = __GEN9_RCS0_MOCS0, + [VCS0] = __GEN9_VCS0_MOCS0, + [VCS1] = __GEN9_VCS1_MOCS0, + [VECS0] = __GEN9_VECS0_MOCS0, + [BCS0] = __GEN9_BCS0_MOCS0, + [VCS2] = __GEN11_VCS2_MOCS0, + }; + + GEM_BUG_ON(engine->id >= ARRAY_SIZE(offset)); + return offset[engine->id]; +} - /* All remaining entries are unused */ - for (; i < table->n_entries; i++) - intel_uncore_write_fw(uncore, - mocs_register(engine, i), - unused_value); +static void init_mocs_table(struct intel_engine_cs *engine, + const struct drm_i915_mocs_table *table) +{ + __init_mocs_table(engine->uncore, table, mocs_offset(engine)); } /* @@ -381,7 +378,7 @@ static void init_mocs_table(struct intel_engine_cs *engine, static u16 get_entry_l3cc(const struct drm_i915_mocs_table *table, unsigned int index) { - if (table->table[index].used) + if (index < table->size && table->table[index].used) return table->table[index].l3cc_value; return table->table[I915_MOCS_PTE].l3cc_value; @@ -392,37 +389,23 @@ static inline u32 l3cc_combine(u16 low, u16 high) return low | (u32)high << 16; } +#define for_each_l3cc(l3cc, t, i) \ + for (i = 0; \ + i < ((t)->n_entries + 1) / 2 ? \ + (l3cc = l3cc_combine(get_entry_l3cc((t), 2 * i), \ + get_entry_l3cc((t), 2 * i + 1))), 1 : \ + 0; \ + i++) + static void init_l3cc_table(struct intel_engine_cs *engine, const struct drm_i915_mocs_table *table) { struct intel_uncore *uncore = engine->uncore; - u16 unused_value = table->table[I915_MOCS_PTE].l3cc_value; unsigned int i; + u32 l3cc; - for (i = 0; i < table->size / 2; i++) { - u16 low = get_entry_l3cc(table, 2 * i); - u16 high = get_entry_l3cc(table, 2 * i + 1); - - intel_uncore_write(uncore, - GEN9_LNCFCMOCS(i), - l3cc_combine(low, high)); - } - - /* Odd table size - 1 left over */ - if (table->size & 1) { - u16 low = get_entry_l3cc(table, 2 * i); - - intel_uncore_write(uncore, - GEN9_LNCFCMOCS(i), - l3cc_combine(low, unused_value)); - i++; - } - - /* All remaining entries are also unused */ - for (; i < table->n_entries / 2; i++) - intel_uncore_write(uncore, - GEN9_LNCFCMOCS(i), - l3cc_combine(unused_value, unused_value)); + for_each_l3cc(l3cc, table, i) + intel_uncore_write_fw(uncore, GEN9_LNCFCMOCS(i), l3cc); } void intel_mocs_init_engine(struct intel_engine_cs *engine) @@ -443,11 +426,14 @@ void intel_mocs_init_engine(struct intel_engine_cs *engine) init_l3cc_table(engine, &table); } -static void intel_mocs_init_global(struct intel_gt *gt) +static u32 global_mocs_offset(void) +{ + return i915_mmio_reg_offset(GEN12_GLOBAL_MOCS(0)); +} + +static void init_global_mocs(struct intel_gt *gt) { - struct intel_uncore *uncore = gt->uncore; struct drm_i915_mocs_table table; - unsigned int index; /* * LLC and eDRAM control values are not applicable to dgfx @@ -455,29 +441,14 @@ static void intel_mocs_init_global(struct intel_gt *gt) if (IS_DGFX(gt->i915)) return; - GEM_BUG_ON(!HAS_GLOBAL_MOCS_REGISTERS(gt->i915)); - if (!get_mocs_settings(gt->i915, &table)) return; - for (index = 0; index < table.size; index++) - intel_uncore_write(uncore, - GEN12_GLOBAL_MOCS(index), - table.table[index].control_value); - - /* - * Ok, now set the unused entries to the invalid entry (index 0). These - * entries are officially undefined and no contract for the contents and - * settings is given for these entries. - */ - for (; index < table.n_entries; index++) - intel_uncore_write(uncore, - GEN12_GLOBAL_MOCS(index), - table.table[I915_MOCS_PTE].control_value); + __init_mocs_table(gt->uncore, &table, global_mocs_offset()); } void intel_mocs_init(struct intel_gt *gt) { if (HAS_GLOBAL_MOCS_REGISTERS(gt->i915)) - intel_mocs_init_global(gt); + init_global_mocs(gt); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 526fb0b208a8..1cd07d789a17 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -11689,13 +11689,18 @@ enum skl_power_gate { /* MOCS (Memory Object Control State) registers */ #define GEN9_LNCFCMOCS(i) _MMIO(0xb020 + (i) * 4) /* L3 Cache Control */ -#define GEN9_GFX_MOCS(i) _MMIO(0xc800 + (i) * 4) /* Graphics MOCS registers */ -#define GEN9_MFX0_MOCS(i) _MMIO(0xc900 + (i) * 4) /* Media 0 MOCS registers */ -#define GEN9_MFX1_MOCS(i) _MMIO(0xca00 + (i) * 4) /* Media 1 MOCS registers */ -#define GEN9_VEBOX_MOCS(i) _MMIO(0xcb00 + (i) * 4) /* Video MOCS registers */ -#define GEN9_BLT_MOCS(i) _MMIO(0xcc00 + (i) * 4) /* Blitter MOCS registers */ -/* Media decoder 2 MOCS registers */ -#define GEN11_MFX2_MOCS(i) _MMIO(0x10000 + (i) * 4) +#define __GEN9_RCS0_MOCS0 0xc800 +#define GEN9_GFX_MOCS(i) _MMIO(__GEN9_RCS0_MOCS0 + (i) * 4) +#define __GEN9_VCS0_MOCS0 0xc900 +#define GEN9_MFX0_MOCS(i) _MMIO(__GEN9_VCS0_MOCS0 + (i) * 4) +#define __GEN9_VCS1_MOCS0 0xca00 +#define GEN9_MFX1_MOCS(i) _MMIO(__GEN9_VCS1_MOCS0 + (i) * 4) +#define __GEN9_VECS0_MOCS0 0xcb00 +#define GEN9_VEBOX_MOCS(i) _MMIO(__GEN9_VECS0_MOCS0 + (i) * 4) +#define __GEN9_BCS0_MOCS0 0xcc00 +#define GEN9_BLT_MOCS(i) _MMIO(__GEN9_BCS0_MOCS0 + (i) * 4) +#define __GEN11_VCS2_MOCS0 0x10000 +#define GEN11_MFX2_MOCS(i) _MMIO(__GEN11_VCS2_MOCS0 + (i) * 4) #define GEN10_SCRATCH_LNCF2 _MMIO(0xb0a0) #define PMFLUSHDONE_LNICRSDROP (1 << 20) -- cgit v1.2.3 From 3fb33cd32ffdf9da6ca53985c070e284e5acced9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 12 Nov 2019 22:36:00 +0000 Subject: drm/i915/selftests: Add coverage of mocs registers Probe the mocs registers for new contexts and across GPU resets. Similar to intel_workarounds, we have tables of what register values we expect to see, so verify that user contexts are affected by them. In the future, we should add tests similar to intel_sseu to cover dynamic reconfigurations. Signed-off-by: Chris Wilson Cc: Prathap Kumar Valsan Cc: Mika Kuoppala Reviewed-by: Prathap Kumar Valsan Link: https://patchwork.freedesktop.org/patch/msgid/20191112223600.30993-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_mocs.c | 4 + drivers/gpu/drm/i915/gt/selftest_mocs.c | 419 +++++++++++++++++++++ .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 + 3 files changed, 424 insertions(+) create mode 100644 drivers/gpu/drm/i915/gt/selftest_mocs.c diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index f43466e776f4..893249ea48d4 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -452,3 +452,7 @@ void intel_mocs_init(struct intel_gt *gt) if (HAS_GLOBAL_MOCS_REGISTERS(gt->i915)) init_global_mocs(gt); } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftest_mocs.c" +#endif diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c new file mode 100644 index 000000000000..a34d4fb52fa1 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c @@ -0,0 +1,419 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2019 Intel Corporation + */ + +#include "gt/intel_engine_pm.h" +#include "i915_selftest.h" + +#include "gem/selftests/mock_context.h" +#include "selftests/igt_reset.h" +#include "selftests/igt_spinner.h" + +struct live_mocs { + struct drm_i915_mocs_table table; + struct i915_vma *scratch; + void *vaddr; +}; + +static int request_add_sync(struct i915_request *rq, int err) +{ + i915_request_get(rq); + i915_request_add(rq); + if (i915_request_wait(rq, 0, HZ / 5) < 0) + err = -ETIME; + i915_request_put(rq); + + return err; +} + +static int request_add_spin(struct i915_request *rq, struct igt_spinner *spin) +{ + int err = 0; + + i915_request_get(rq); + i915_request_add(rq); + if (spin && !igt_wait_for_spinner(spin, rq)) + err = -ETIME; + i915_request_put(rq); + + return err; +} + +static struct i915_vma *create_scratch(struct intel_gt *gt) +{ + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + int err; + + obj = i915_gem_object_create_internal(gt->i915, PAGE_SIZE); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + i915_gem_object_set_cache_coherency(obj, I915_CACHING_CACHED); + + vma = i915_vma_instance(obj, >->ggtt->vm, NULL); + if (IS_ERR(vma)) { + i915_gem_object_put(obj); + return vma; + } + + err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL); + if (err) { + i915_gem_object_put(obj); + return ERR_PTR(err); + } + + return vma; +} + +static int live_mocs_init(struct live_mocs *arg, struct intel_gt *gt) +{ + int err; + + if (!get_mocs_settings(gt->i915, &arg->table)) + return -EINVAL; + + arg->scratch = create_scratch(gt); + if (IS_ERR(arg->scratch)) + return PTR_ERR(arg->scratch); + + arg->vaddr = i915_gem_object_pin_map(arg->scratch->obj, I915_MAP_WB); + if (IS_ERR(arg->vaddr)) { + err = PTR_ERR(arg->vaddr); + goto err_scratch; + } + + return 0; + +err_scratch: + i915_vma_unpin_and_release(&arg->scratch, 0); + return err; +} + +static void live_mocs_fini(struct live_mocs *arg) +{ + i915_vma_unpin_and_release(&arg->scratch, I915_VMA_RELEASE_MAP); +} + +static int read_regs(struct i915_request *rq, + u32 addr, unsigned int count, + uint32_t *offset) +{ + unsigned int i; + u32 *cs; + + GEM_BUG_ON(!IS_ALIGNED(*offset, sizeof(u32))); + + cs = intel_ring_begin(rq, 4 * count); + if (IS_ERR(cs)) + return PTR_ERR(cs); + + for (i = 0; i < count; i++) { + *cs++ = MI_STORE_REGISTER_MEM_GEN8 | MI_USE_GGTT; + *cs++ = addr; + *cs++ = *offset; + *cs++ = 0; + + addr += sizeof(u32); + *offset += sizeof(u32); + } + + intel_ring_advance(rq, cs); + + return 0; +} + +static int read_mocs_table(struct i915_request *rq, + const struct drm_i915_mocs_table *table, + uint32_t *offset) +{ + u32 addr; + + if (HAS_GLOBAL_MOCS_REGISTERS(rq->i915)) + addr = global_mocs_offset(); + else + addr = mocs_offset(rq->engine); + + return read_regs(rq, addr, table->n_entries, offset); +} + +static int read_l3cc_table(struct i915_request *rq, + const struct drm_i915_mocs_table *table, + uint32_t *offset) +{ + u32 addr = i915_mmio_reg_offset(GEN9_LNCFCMOCS(0)); + + return read_regs(rq, addr, (table->n_entries + 1) / 2, offset); +} + +static int check_mocs_table(struct intel_engine_cs *engine, + const struct drm_i915_mocs_table *table, + uint32_t **vaddr) +{ + unsigned int i; + u32 expect; + + for_each_mocs(expect, table, i) { + if (**vaddr != expect) { + pr_err("%s: Invalid MOCS[%d] entry, found %08x, expected %08x\n", + engine->name, i, **vaddr, expect); + return -EINVAL; + } + ++*vaddr; + } + + return 0; +} + +static bool mcr_range(struct drm_i915_private *i915, u32 offset) +{ + /* + * Registers in this range are affected by the MCR selector + * which only controls CPU initiated MMIO. Routing does not + * work for CS access so we cannot verify them on this path. + */ + return INTEL_GEN(i915) >= 8 && offset >= 0xb000 && offset <= 0xb4ff; +} + +static int check_l3cc_table(struct intel_engine_cs *engine, + const struct drm_i915_mocs_table *table, + uint32_t **vaddr) +{ + /* Can we read the MCR range 0xb00 directly? See intel_workarounds! */ + u32 reg = i915_mmio_reg_offset(GEN9_LNCFCMOCS(0)); + unsigned int i; + u32 expect; + + for_each_l3cc(expect, table, i) { + if (!mcr_range(engine->i915, reg) && **vaddr != expect) { + pr_err("%s: Invalid L3CC[%d] entry, found %08x, expected %08x\n", + engine->name, i, **vaddr, expect); + return -EINVAL; + } + ++*vaddr; + reg += 4; + } + + return 0; +} + +static int check_mocs_engine(struct live_mocs *arg, + struct intel_context *ce) +{ + struct i915_vma *vma = arg->scratch; + struct i915_request *rq; + u32 offset; + u32 *vaddr; + int err; + + memset32(arg->vaddr, STACK_MAGIC, PAGE_SIZE / sizeof(u32)); + + rq = intel_context_create_request(ce); + if (IS_ERR(rq)) + return PTR_ERR(rq); + + i915_vma_lock(vma); + err = i915_request_await_object(rq, vma->obj, true); + if (!err) + err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); + i915_vma_unlock(vma); + + /* Read the mocs tables back using SRM */ + offset = i915_ggtt_offset(vma); + if (!err) + err = read_mocs_table(rq, &arg->table, &offset); + if (!err && ce->engine->class == RENDER_CLASS) + err = read_l3cc_table(rq, &arg->table, &offset); + offset -= i915_ggtt_offset(vma); + GEM_BUG_ON(offset > PAGE_SIZE); + + err = request_add_sync(rq, err); + if (err) + return err; + + /* Compare the results against the expected tables */ + vaddr = arg->vaddr; + if (!err) + err = check_mocs_table(ce->engine, &arg->table, &vaddr); + if (!err && ce->engine->class == RENDER_CLASS) + err = check_l3cc_table(ce->engine, &arg->table, &vaddr); + if (err) + return err; + + GEM_BUG_ON(arg->vaddr + offset != vaddr); + return 0; +} + +static int live_mocs_kernel(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_engine_cs *engine; + enum intel_engine_id id; + struct live_mocs mocs; + int err; + + /* Basic check the system is configured with the expected mocs table */ + + err = live_mocs_init(&mocs, gt); + if (err) + return err; + + for_each_engine(engine, gt, id) { + err = check_mocs_engine(&mocs, engine->kernel_context); + if (err) + break; + } + + live_mocs_fini(&mocs); + return err; +} + +static int live_mocs_clean(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_engine_cs *engine; + enum intel_engine_id id; + struct live_mocs mocs; + int err; + + /* Every new context should see the same mocs table */ + + err = live_mocs_init(&mocs, gt); + if (err) + return err; + + for_each_engine(engine, gt, id) { + struct intel_context *ce; + + ce = intel_context_create(engine->kernel_context->gem_context, + engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + break; + } + + err = check_mocs_engine(&mocs, ce); + intel_context_put(ce); + if (err) + break; + } + + live_mocs_fini(&mocs); + return err; +} + +static int active_engine_reset(struct intel_context *ce, + const char *reason) +{ + struct igt_spinner spin; + struct i915_request *rq; + int err; + + err = igt_spinner_init(&spin, ce->engine->gt); + if (err) + return err; + + rq = igt_spinner_create_request(&spin, ce, MI_NOOP); + if (IS_ERR(rq)) { + igt_spinner_fini(&spin); + return PTR_ERR(rq); + } + + err = request_add_spin(rq, &spin); + if (err == 0) + err = intel_engine_reset(ce->engine, reason); + + igt_spinner_end(&spin); + igt_spinner_fini(&spin); + + return err; +} + +static int __live_mocs_reset(struct live_mocs *mocs, + struct intel_context *ce) +{ + int err; + + err = intel_engine_reset(ce->engine, "mocs"); + if (err) + return err; + + err = check_mocs_engine(mocs, ce); + if (err) + return err; + + err = active_engine_reset(ce, "mocs"); + if (err) + return err; + + err = check_mocs_engine(mocs, ce); + if (err) + return err; + + intel_gt_reset(ce->engine->gt, ce->engine->mask, "mocs"); + + err = check_mocs_engine(mocs, ce); + if (err) + return err; + + return 0; +} + +static int live_mocs_reset(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_engine_cs *engine; + enum intel_engine_id id; + struct live_mocs mocs; + int err = 0; + + /* Check the mocs setup is retained over per-engine and global resets */ + + if (!intel_has_reset_engine(gt)) + return 0; + + err = live_mocs_init(&mocs, gt); + if (err) + return err; + + igt_global_reset_lock(gt); + for_each_engine(engine, gt, id) { + struct intel_context *ce; + + ce = intel_context_create(engine->kernel_context->gem_context, + engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + break; + } + + intel_engine_pm_get(engine); + err = __live_mocs_reset(&mocs, ce); + intel_engine_pm_put(engine); + + intel_context_put(ce); + if (err) + break; + } + igt_global_reset_unlock(gt); + + live_mocs_fini(&mocs); + return err; +} + +int intel_mocs_live_selftests(struct drm_i915_private *i915) +{ + static const struct i915_subtest tests[] = { + SUBTEST(live_mocs_kernel), + SUBTEST(live_mocs_clean), + SUBTEST(live_mocs_reset), + }; + struct drm_i915_mocs_table table; + + if (!get_mocs_settings(i915, &table)) + return 0; + + return intel_gt_live_subtests(tests, &i915->gt); +} diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index 4b3cac73e291..11b40bc58e6d 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@ -16,6 +16,7 @@ selftest(gt_engines, intel_engine_live_selftests) selftest(gt_timelines, intel_timeline_live_selftests) selftest(gt_contexts, intel_context_live_selftests) selftest(gt_lrc, intel_lrc_live_selftests) +selftest(gt_mocs, intel_mocs_live_selftests) selftest(gt_pm, intel_gt_pm_live_selftests) selftest(gt_heartbeat, intel_heartbeat_live_selftests) selftest(requests, i915_request_live_selftests) -- cgit v1.2.3 From c9ad602feabe4271d2adf1bdae5d8b20c2dc84f1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 14 Nov 2019 17:25:35 +0000 Subject: drm/i915: Split i915_active.mutex into an irq-safe spinlock for the rbtree As we want to be able to run inside atomic context for retiring the i915_active, and we are no longer allowed to abuse mutex_trylock, split the tree management portion of i915_active.mutex into an irq-safe spinlock. References: a0855d24fc22d ("locking/mutex: Complain upon mutex API misuse in IRQ contexts") References: https://bugs.freedesktop.org/show_bug.cgi?id=111626 Fixes: 274cbf20fd10 ("drm/i915: Push the i915_active.retire into a worker") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Matthew Auld Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191114172535.1116-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_active.c | 57 ++++++++++++++-------------- drivers/gpu/drm/i915/i915_active_types.h | 1 + drivers/gpu/drm/i915/selftests/i915_active.c | 4 +- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 207383dda84d..5448f37c8102 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -91,14 +91,15 @@ static void debug_active_init(struct i915_active *ref) static void debug_active_activate(struct i915_active *ref) { - lockdep_assert_held(&ref->mutex); + spin_lock_irq(&ref->tree_lock); if (!atomic_read(&ref->count)) /* before the first inc */ debug_object_activate(ref, &active_debug_desc); + spin_unlock_irq(&ref->tree_lock); } static void debug_active_deactivate(struct i915_active *ref) { - lockdep_assert_held(&ref->mutex); + lockdep_assert_held(&ref->tree_lock); if (!atomic_read(&ref->count)) /* after the last dec */ debug_object_deactivate(ref, &active_debug_desc); } @@ -128,29 +129,22 @@ __active_retire(struct i915_active *ref) { struct active_node *it, *n; struct rb_root root; - bool retire = false; + unsigned long flags; - lockdep_assert_held(&ref->mutex); GEM_BUG_ON(i915_active_is_idle(ref)); /* return the unused nodes to our slabcache -- flushing the allocator */ - if (atomic_dec_and_test(&ref->count)) { - debug_active_deactivate(ref); - root = ref->tree; - ref->tree = RB_ROOT; - ref->cache = NULL; - retire = true; - } - - mutex_unlock(&ref->mutex); - if (!retire) + if (!atomic_dec_and_lock_irqsave(&ref->count, &ref->tree_lock, flags)) return; GEM_BUG_ON(rcu_access_pointer(ref->excl.fence)); - rbtree_postorder_for_each_entry_safe(it, n, &root, node) { - GEM_BUG_ON(i915_active_fence_isset(&it->base)); - kmem_cache_free(global.slab_cache, it); - } + debug_active_deactivate(ref); + + root = ref->tree; + ref->tree = RB_ROOT; + ref->cache = NULL; + + spin_unlock_irqrestore(&ref->tree_lock, flags); /* After the final retire, the entire struct may be freed */ if (ref->retire) @@ -158,6 +152,11 @@ __active_retire(struct i915_active *ref) /* ... except if you wait on it, you must manage your own references! */ wake_up_var(ref); + + rbtree_postorder_for_each_entry_safe(it, n, &root, node) { + GEM_BUG_ON(i915_active_fence_isset(&it->base)); + kmem_cache_free(global.slab_cache, it); + } } static void @@ -169,7 +168,6 @@ active_work(struct work_struct *wrk) if (atomic_add_unless(&ref->count, -1, 1)) return; - mutex_lock(&ref->mutex); __active_retire(ref); } @@ -180,9 +178,7 @@ active_retire(struct i915_active *ref) if (atomic_add_unless(&ref->count, -1, 1)) return; - /* If we are inside interrupt context (fence signaling), defer */ - if (ref->flags & I915_ACTIVE_RETIRE_SLEEPS || - !mutex_trylock(&ref->mutex)) { + if (ref->flags & I915_ACTIVE_RETIRE_SLEEPS) { queue_work(system_unbound_wq, &ref->work); return; } @@ -227,7 +223,7 @@ active_instance(struct i915_active *ref, struct intel_timeline *tl) if (!prealloc) return NULL; - mutex_lock(&ref->mutex); + spin_lock_irq(&ref->tree_lock); GEM_BUG_ON(i915_active_is_idle(ref)); parent = NULL; @@ -257,7 +253,7 @@ active_instance(struct i915_active *ref, struct intel_timeline *tl) out: ref->cache = node; - mutex_unlock(&ref->mutex); + spin_unlock_irq(&ref->tree_lock); BUILD_BUG_ON(offsetof(typeof(*node), base)); return &node->base; @@ -278,8 +274,10 @@ void __i915_active_init(struct i915_active *ref, if (bits & I915_ACTIVE_MAY_SLEEP) ref->flags |= I915_ACTIVE_RETIRE_SLEEPS; + spin_lock_init(&ref->tree_lock); ref->tree = RB_ROOT; ref->cache = NULL; + init_llist_head(&ref->preallocated_barriers); atomic_set(&ref->count, 0); __mutex_init(&ref->mutex, "i915_active", key); @@ -510,7 +508,7 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) if (RB_EMPTY_ROOT(&ref->tree)) return NULL; - mutex_lock(&ref->mutex); + spin_lock_irq(&ref->tree_lock); GEM_BUG_ON(i915_active_is_idle(ref)); /* @@ -575,7 +573,7 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) goto match; } - mutex_unlock(&ref->mutex); + spin_unlock_irq(&ref->tree_lock); return NULL; @@ -583,7 +581,7 @@ match: rb_erase(p, &ref->tree); /* Hide from waits and sibling allocations */ if (p == &ref->cache->node) ref->cache = NULL; - mutex_unlock(&ref->mutex); + spin_unlock_irq(&ref->tree_lock); return rb_entry(p, struct active_node, node); } @@ -664,6 +662,7 @@ unwind: void i915_active_acquire_barrier(struct i915_active *ref) { struct llist_node *pos, *next; + unsigned long flags; GEM_BUG_ON(i915_active_is_idle(ref)); @@ -673,7 +672,7 @@ void i915_active_acquire_barrier(struct i915_active *ref) * populated by i915_request_add_active_barriers() to point to the * request that will eventually release them. */ - mutex_lock_nested(&ref->mutex, SINGLE_DEPTH_NESTING); + spin_lock_irqsave_nested(&ref->tree_lock, flags, SINGLE_DEPTH_NESTING); llist_for_each_safe(pos, next, take_preallocated_barriers(ref)) { struct active_node *node = barrier_from_ll(pos); struct intel_engine_cs *engine = barrier_to_engine(node); @@ -699,7 +698,7 @@ void i915_active_acquire_barrier(struct i915_active *ref) llist_add(barrier_to_ll(node), &engine->barrier_tasks); intel_engine_pm_put(engine); } - mutex_unlock(&ref->mutex); + spin_unlock_irqrestore(&ref->tree_lock, flags); } void i915_request_add_active_barriers(struct i915_request *rq) diff --git a/drivers/gpu/drm/i915/i915_active_types.h b/drivers/gpu/drm/i915/i915_active_types.h index d89a74c142c6..96aed0ee700a 100644 --- a/drivers/gpu/drm/i915/i915_active_types.h +++ b/drivers/gpu/drm/i915/i915_active_types.h @@ -48,6 +48,7 @@ struct i915_active { atomic_t count; struct mutex mutex; + spinlock_t tree_lock; struct active_node *cache; struct rb_root tree; diff --git a/drivers/gpu/drm/i915/selftests/i915_active.c b/drivers/gpu/drm/i915/selftests/i915_active.c index f3fa05c78d78..60290f78750d 100644 --- a/drivers/gpu/drm/i915/selftests/i915_active.c +++ b/drivers/gpu/drm/i915/selftests/i915_active.c @@ -277,8 +277,8 @@ void i915_active_unlock_wait(struct i915_active *ref) } /* And wait for the retire callback */ - mutex_lock(&ref->mutex); - mutex_unlock(&ref->mutex); + spin_lock_irq(&ref->tree_lock); + spin_unlock_irq(&ref->tree_lock); /* ... which may have been on a thread instead */ flush_work(&ref->work); -- cgit v1.2.3 From c504f4dfaa68cf79385acc51262f241e94b1a32e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 20 Jun 2019 17:26:38 +0300 Subject: drm/i915: Do not override mode's aspect ratio with the prop value NONE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDMI_PICTURE_ASPECT_NONE means "Automatic" so when the user has that selected we should keep whatever aspect ratio the mode already has. Also no point in checking for connector->is_hdmi in the SDVO code since we only attach the property to HDMI connectors. Cc: Ilia Mirkin Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190620142639.17518-5-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_hdmi.c | 5 +++-- drivers/gpu/drm/i915/display/intel_sdvo.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 659a03b08849..315920c35cc0 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2451,8 +2451,9 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, if (ret) return ret; - /* Set user selected PAR to incoming mode's member */ - adjusted_mode->picture_aspect_ratio = conn_state->picture_aspect_ratio; + if (conn_state->picture_aspect_ratio) + adjusted_mode->picture_aspect_ratio = + conn_state->picture_aspect_ratio; pipe_config->lane_count = 4; diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index a4b1339fcc00..c9cae6a9e897 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -1349,9 +1349,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, if (IS_TV(intel_sdvo_connector)) i9xx_adjust_sdvo_tv_clock(pipe_config); - /* Set user selected PAR to incoming mode's member */ - if (intel_sdvo_connector->is_hdmi) - adjusted_mode->picture_aspect_ratio = conn_state->picture_aspect_ratio; + if (conn_state->picture_aspect_ratio) + adjusted_mode->picture_aspect_ratio = + conn_state->picture_aspect_ratio; if (!intel_sdvo_compute_avi_infoframe(intel_sdvo, pipe_config, conn_state)) { -- cgit v1.2.3 From e5436206f426463da1ac87ab367ef89a583742ca Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 20 Jun 2019 17:26:39 +0300 Subject: drm/i915: Drop redundant aspec ratio prop value initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDMI_PICTURE_ASPECT_NONE is zero and the connector state is kzalloc()'d so no need to initialize conn_state->picture_aspect_ratio with it. Cc: Ilia Mirkin Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190620142639.17518-6-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_hdmi.c | 1 - drivers/gpu/drm/i915/display/intel_sdvo.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 315920c35cc0..29a174af5314 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2876,7 +2876,6 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c intel_attach_colorspace_property(connector); drm_connector_attach_content_type_property(connector); - connector->state->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE; if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) drm_object_attach_property(&connector->base, diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index c9cae6a9e897..8758ee2a4442 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2654,7 +2654,6 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo, intel_attach_broadcast_rgb_property(&connector->base.base); } intel_attach_aspect_ratio_property(&connector->base.base); - connector->base.base.state->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE; } static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void) -- cgit v1.2.3 From 980f87a2edb3e7825949ebd0a7e63ab574c20816 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 14 Nov 2019 17:26:21 +0200 Subject: drm/i915: Restore GT coarse power gating workaround The workaround to disable coarse power gating is still needed on SKL GT3/GT4 machines and since the RC6 context corruption was discovered by the hardware team also on all GEN9 machines. Restore applying the workaround. Fixes: c113236718e8 ("drm/i915: Extract GT render sleep (rc6) management") Testcase: igt/intel_gt_pm_late_selftests/live_rc6_ctx Cc: Chris Wilson Cc: Andi Shyti Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191114152621.7235-1-imre.deak@intel.com --- drivers/gpu/drm/i915/gt/intel_rc6.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 5e3ba034bd46..7c0d9eb5c6fc 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -175,8 +175,13 @@ static void gen9_rc6_enable(struct intel_rc6 *rc6) GEN6_RC_CTL_RC6_ENABLE | rc6_mode); - set(uncore, GEN9_PG_ENABLE, - GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE); + /* + * WaRsDisableCoarsePowerGating:skl,cnl + * - Render/Media PG need to be disabled with RC6. + */ + if (!NEEDS_WaRsDisableCoarsePowerGating(rc6_to_i915(rc6))) + set(uncore, GEN9_PG_ENABLE, + GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE); } static void gen8_rc6_enable(struct intel_rc6 *rc6) -- cgit v1.2.3 From 1cdc2330e8d396c9cbebfc75fba4c94d34f80782 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Tue, 5 Nov 2019 14:53:21 -0800 Subject: drm/i915/guc: Properly capture & release GuC interrupts on Gen11+ With the new interrupt re-partitioning in Gen11, GuC controls by itself the interrupts it receives, so steering bits and registers have been defeatured. Being this the case, when the GuC is in control of submissions we won't know what to do with the ctx switch interrupt in the driver, so disable it. v2 (Daniele): replace the gen9 paths instead of keeping gen9 and gen11 functions since we won't support guc submission on any pre-gen11 platform. Signed-off-by: Oscar Mateo Signed-off-by: Michal Wajdeczko Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Cc: Matthew Brost Reviewed-by: John Harrison Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191105225321.26642-1-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/intel_rps.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 72 ++++------------------- 2 files changed, 14 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 20d6ee148afc..08a38a3b90b0 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1663,7 +1663,7 @@ void intel_rps_init(struct intel_rps *rps) if (INTEL_GEN(i915) <= 7) rps->pm_intrmsk_mbz |= GEN6_PM_RP_UP_EI_EXPIRED; - if (INTEL_GEN(i915) >= 8) + if (INTEL_GEN(i915) >= 8 && INTEL_GEN(i915) < 11) rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 2498c55e0ea5..902e25eb6b9d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1011,74 +1011,28 @@ void intel_guc_submission_fini(struct intel_guc *guc) static void guc_interrupts_capture(struct intel_gt *gt) { - struct intel_rps *rps = >->rps; struct intel_uncore *uncore = gt->uncore; - struct intel_engine_cs *engine; - enum intel_engine_id id; - int irqs; + u32 irqs = GT_CONTEXT_SWITCH_INTERRUPT; + u32 dmask = irqs << 16 | irqs; - /* tell all command streamers to forward interrupts (but not vblank) - * to GuC - */ - irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); - for_each_engine(engine, gt, id) - ENGINE_WRITE(engine, RING_MODE_GEN7, irqs); - - /* route USER_INTERRUPT to Host, all others are sent to GuC. */ - irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; - /* These three registers have the same bit definitions */ - intel_uncore_write(uncore, GUC_BCS_RCS_IER, ~irqs); - intel_uncore_write(uncore, GUC_VCS2_VCS1_IER, ~irqs); - intel_uncore_write(uncore, GUC_WD_VECS_IER, ~irqs); + GEM_BUG_ON(INTEL_GEN(gt->i915) < 11); - /* - * The REDIRECT_TO_GUC bit of the PMINTRMSK register directs all - * (unmasked) PM interrupts to the GuC. All other bits of this - * register *disable* generation of a specific interrupt. - * - * 'pm_intrmsk_mbz' indicates bits that are NOT to be set when - * writing to the PM interrupt mask register, i.e. interrupts - * that must not be disabled. - * - * If the GuC is handling these interrupts, then we must not let - * the PM code disable ANY interrupt that the GuC is expecting. - * So for each ENABLED (0) bit in this register, we must SET the - * bit in pm_intrmsk_mbz so that it's left enabled for the GuC. - * GuC needs ARAT expired interrupt unmasked hence it is set in - * pm_intrmsk_mbz. - * - * Here we CLEAR REDIRECT_TO_GUC bit in pm_intrmsk_mbz, which will - * result in the register bit being left SET! - */ - rps->pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK; - rps->pm_intrmsk_mbz &= ~GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; + /* Don't handle the ctx switch interrupt in GuC submission mode */ + intel_uncore_rmw(uncore, GEN11_RENDER_COPY_INTR_ENABLE, dmask, 0); + intel_uncore_rmw(uncore, GEN11_VCS_VECS_INTR_ENABLE, dmask, 0); } static void guc_interrupts_release(struct intel_gt *gt) { - struct intel_rps *rps = >->rps; struct intel_uncore *uncore = gt->uncore; - struct intel_engine_cs *engine; - enum intel_engine_id id; - int irqs; + u32 irqs = GT_CONTEXT_SWITCH_INTERRUPT; + u32 dmask = irqs << 16 | irqs; - /* - * tell all command streamers NOT to forward interrupts or vblank - * to GuC. - */ - irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); - irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); - for_each_engine(engine, gt, id) - ENGINE_WRITE(engine, RING_MODE_GEN7, irqs); - - /* route all GT interrupts to the host */ - intel_uncore_write(uncore, GUC_BCS_RCS_IER, 0); - intel_uncore_write(uncore, GUC_VCS2_VCS1_IER, 0); - intel_uncore_write(uncore, GUC_WD_VECS_IER, 0); - - rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; - rps->pm_intrmsk_mbz &= ~ARAT_EXPIRED_INTRMSK; + GEM_BUG_ON(INTEL_GEN(gt->i915) < 11); + + /* Handle ctx switch interrupts again */ + intel_uncore_rmw(uncore, GEN11_RENDER_COPY_INTR_ENABLE, 0, dmask); + intel_uncore_rmw(uncore, GEN11_VCS_VECS_INTR_ENABLE, 0, dmask); } static void guc_set_default_submission(struct intel_engine_cs *engine) -- cgit v1.2.3 From 7936a22dd4660d24b4ca0668c02b0372127cab44 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 14 Nov 2019 22:57:32 +0000 Subject: drm/i915/gt: Wait for new requests in intel_gt_retire_requests() Our callers fall into two categories, those passing timeout=0 who just want to flush request retirements and those passing a timeout that need to wait for submission completion (e.g. intel_gt_wait_for_idle()). Currently, we only wait for a snapshot of timelines at the start of the wait (but there was an expectation that new requests would cause timelines to appear at the end). However, our callers, such as intel_gt_wait_for_idle() before suspend, do require us to wait for the power management requests emitted by retirement as well. If we don't, then it takes an extra second or two for the background worker to flush the queue and mark the GT as idle. Fixes: 7e8057626640 ("drm/i915: Drop struct_mutex from around i915_retire_requests()") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191114225736.616885-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index b73229a84d85..ccbddddbbd52 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -33,7 +33,6 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) { struct intel_gt_timelines *timelines = >->timelines; struct intel_timeline *tl, *tn; - unsigned long active_count = 0; unsigned long flags; bool interruptible; LIST_HEAD(free); @@ -46,10 +45,8 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) spin_lock_irqsave(&timelines->lock, flags); list_for_each_entry_safe(tl, tn, &timelines->active_list, link) { - if (!mutex_trylock(&tl->mutex)) { - active_count++; /* report busy to caller, try again? */ + if (!mutex_trylock(&tl->mutex)) continue; - } intel_timeline_get(tl); GEM_BUG_ON(!tl->active_count); @@ -74,9 +71,7 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) /* Resume iteration after dropping lock */ list_safe_reset_next(tl, tn, link); - if (--tl->active_count) - active_count += !!rcu_access_pointer(tl->last_request.fence); - else + if (!--tl->active_count) list_del(&tl->link); mutex_unlock(&tl->mutex); @@ -92,7 +87,7 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) list_for_each_entry_safe(tl, tn, &free, link) __intel_timeline_free(&tl->kref); - return active_count ? timeout : 0; + return list_empty(&timelines->active_list) ? 0 : timeout; } int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout) -- cgit v1.2.3 From d96bb620fc8b8dd855fb5bea88644034371b64bb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 14 Nov 2019 22:57:36 +0000 Subject: drm/i915/gem: Silence sparse for RCU protection inside the constructor Inside the constructor, while cloning, we need to replace the dst->engines. Having forgotten that dst->engines is marked as RCU protected, we need to add the appropriate annotations to make sparse happy. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191114225736.616885-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 1284f47303fa..6f1e6181f67a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -2009,7 +2009,8 @@ static int clone_engines(struct i915_gem_context *dst, user_engines = i915_gem_context_user_engines(src); i915_gem_context_unlock_engines(src); - free_engines(dst->engines); + /* Serialised by constructor */ + free_engines(__context_engines_static(dst)); RCU_INIT_POINTER(dst->engines, clone); if (user_engines) i915_gem_context_set_user_engines(dst); @@ -2044,7 +2045,8 @@ static int clone_sseu(struct i915_gem_context *dst, unsigned long n; int err; - clone = dst->engines; /* no locking required; sole access */ + /* no locking required; sole access under constructor*/ + clone = __context_engines_static(dst); if (e->num_engines != clone->num_engines) { err = -EINVAL; goto unlock; -- cgit v1.2.3 From 90eb7d2aa3ce2d0c4d680ba53542317938f653b1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Nov 2019 12:27:55 +0000 Subject: drm/i915: Simplify NEEDS_WaRsDisableCoarsePowerGating It applies to all gen9 and gen10 now, so we can use a single test against the gen bitmask. Signed-off-by: Chris Wilson Cc: Imre Deak Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191115122755.830355-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1779f600fcfb..7bc1d8c102b2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1660,7 +1660,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, /* WaRsDisableCoarsePowerGating:skl,cnl */ #define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \ - (IS_CANNONLAKE(dev_priv) || IS_GEN(dev_priv, 9)) + IS_GEN_RANGE(dev_priv, 9, 10) #define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4) #define HAS_GMBUS_BURST_READ(dev_priv) (INTEL_GEN(dev_priv) >= 10 || \ -- cgit v1.2.3 From aeab92e264d4083864733e6013245257ac28aec1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Nov 2019 11:48:00 +0000 Subject: drm/i915/gt: Use gt locals for accessing rc6 RC6 is tracked underneath the intel_gt, so use our local pointers. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Andi Shyti Reviewed-by: Tvrtko Ursulin Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191115114800.725061-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 6187cdd06646..e61f752a3cd5 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -62,7 +62,7 @@ static int __gt_unpark(struct intel_wakeref *wf) GEM_BUG_ON(!gt->awake); if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) - intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL); + intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); intel_rps_unpark(>->rps); i915_pmu_gt_unparked(i915); @@ -90,8 +90,8 @@ static int __gt_park(struct intel_wakeref *wf) intel_synchronize_irq(i915); if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) { - intel_rc6_ctx_wa_check(&i915->gt.rc6); - intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL); + intel_rc6_ctx_wa_check(>->rc6); + intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); } GEM_BUG_ON(!wakeref); -- cgit v1.2.3 From dea397e818b18f688734802465e45a35a976d4df Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Nov 2019 15:08:39 +0000 Subject: drm/i915/gt: Flush retire.work timer object on unload We need to wait until the timer object is marked as deactivated before unloading, so follow up our gentle cancel_delayed_work() with the synchronous variant to ensure it is flushed off a remote cpu before we mark the memory as freed. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111994 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191115150841.880349-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt.c | 1 + drivers/gpu/drm/i915/gt/intel_gt_requests.c | 6 ++++++ drivers/gpu/drm/i915/gt/intel_gt_requests.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index c39b21c8d328..b5a9b87e4ec9 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -397,6 +397,7 @@ void intel_gt_driver_release(struct intel_gt *gt) void intel_gt_driver_late_release(struct intel_gt *gt) { intel_uc_driver_late_release(>->uc); + intel_gt_fini_requests(gt); intel_gt_fini_reset(gt); intel_gt_fini_timelines(gt); } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index ccbddddbbd52..a79e6efb31a2 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -130,3 +130,9 @@ void intel_gt_unpark_requests(struct intel_gt *gt) schedule_delayed_work(>->requests.retire_work, round_jiffies_up_relative(HZ)); } + +void intel_gt_fini_requests(struct intel_gt *gt) +{ + /* Wait until the work is marked as finished before unloading! */ + cancel_delayed_work_sync(>->requests.retire_work); +} diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.h b/drivers/gpu/drm/i915/gt/intel_gt_requests.h index bd31cbce47e0..fde546424c63 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.h @@ -20,5 +20,6 @@ int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout); void intel_gt_init_requests(struct intel_gt *gt); void intel_gt_park_requests(struct intel_gt *gt); void intel_gt_unpark_requests(struct intel_gt *gt); +void intel_gt_fini_requests(struct intel_gt *gt); #endif /* INTEL_GT_REQUESTS_H */ -- cgit v1.2.3 From dd590f680089af64b68282c7758177ec224f60d2 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 14 Nov 2019 16:02:24 +0200 Subject: drm/i915/perf: Add preemption check while waiting for OA While we're waiting for the OA configuration to apply, let's give a chance to other contexts that might need to run other workloads. Signed-off-by: Lionel Landwerlin Suggested-by: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191114140224.21818-1-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 31e47ee23357..608e6c3f3c1a 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1777,6 +1777,8 @@ static int alloc_noa_wait(struct i915_perf_stream *stream) *cs++ = MI_MATH_ADD; *cs++ = MI_MATH_STOREINV(MI_MATH_REG(JUMP_PREDICATE), MI_MATH_REG_CF); + *cs++ = MI_ARB_CHECK; + /* * Transfer the result into the predicate register to be used for the * predicated jump. -- cgit v1.2.3 From 2d19a71ce68f34e4f3570ca98d42912fbbd31f6c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 14 Nov 2019 22:57:35 +0000 Subject: drm/i915/selftests: Exercise long preemption chains Verify that we can execute a long chain of dependent requests from userspace, each one slightly more important than the last. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191114225736.616885-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/selftest_lrc.c | 196 +++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index d1ed3c0f851c..16ebe4d2308e 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -1915,6 +1915,201 @@ err_wedged: goto err_client_lo; } +static int create_gang(struct intel_engine_cs *engine, + struct i915_request **prev) +{ + struct drm_i915_gem_object *obj; + struct intel_context *ce; + struct i915_request *rq; + struct i915_vma *vma; + u32 *cs; + int err; + + ce = intel_context_create(engine->kernel_context->gem_context, engine); + if (IS_ERR(ce)) + return PTR_ERR(ce); + + obj = i915_gem_object_create_internal(engine->i915, 4096); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto err_ce; + } + + vma = i915_vma_instance(obj, ce->vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err_obj; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + goto err_obj; + + cs = i915_gem_object_pin_map(obj, I915_MAP_WC); + if (IS_ERR(cs)) + goto err_obj; + + /* Semaphore target: spin until zero */ + *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; + + *cs++ = MI_SEMAPHORE_WAIT | + MI_SEMAPHORE_POLL | + MI_SEMAPHORE_SAD_EQ_SDD; + *cs++ = 0; + *cs++ = lower_32_bits(vma->node.start); + *cs++ = upper_32_bits(vma->node.start); + + if (*prev) { + u64 offset = (*prev)->batch->node.start; + + /* Terminate the spinner in the next lower priority batch. */ + *cs++ = MI_STORE_DWORD_IMM_GEN4; + *cs++ = lower_32_bits(offset); + *cs++ = upper_32_bits(offset); + *cs++ = 0; + } + + *cs++ = MI_BATCH_BUFFER_END; + i915_gem_object_flush_map(obj); + i915_gem_object_unpin_map(obj); + + rq = intel_context_create_request(ce); + if (IS_ERR(rq)) + goto err_obj; + + rq->batch = vma; + i915_request_get(rq); + + i915_vma_lock(vma); + err = i915_request_await_object(rq, vma->obj, false); + if (!err) + err = i915_vma_move_to_active(vma, rq, 0); + if (!err) + err = rq->engine->emit_bb_start(rq, + vma->node.start, + PAGE_SIZE, 0); + i915_vma_unlock(vma); + i915_request_add(rq); + if (err) + goto err_rq; + + i915_gem_object_put(obj); + intel_context_put(ce); + + rq->client_link.next = &(*prev)->client_link; + *prev = rq; + return 0; + +err_rq: + i915_request_put(rq); +err_obj: + i915_gem_object_put(obj); +err_ce: + intel_context_put(ce); + return err; +} + +static int live_preempt_gang(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_engine_cs *engine; + enum intel_engine_id id; + + if (!HAS_LOGICAL_RING_PREEMPTION(gt->i915)) + return 0; + + /* + * Build as long a chain of preempters as we can, with each + * request higher priority than the last. Once we are ready, we release + * the last batch which then precolates down the chain, each releasing + * the next oldest in turn. The intent is to simply push as hard as we + * can with the number of preemptions, trying to exceed narrow HW + * limits. At a minimum, we insist that we can sort all the user + * high priority levels into execution order. + */ + + for_each_engine(engine, gt, id) { + struct i915_request *rq = NULL; + struct igt_live_test t; + IGT_TIMEOUT(end_time); + int prio = 0; + int err = 0; + u32 *cs; + + if (!intel_engine_has_preemption(engine)) + continue; + + if (igt_live_test_begin(&t, gt->i915, __func__, engine->name)) + return -EIO; + + do { + struct i915_sched_attr attr = { + .priority = I915_USER_PRIORITY(prio++), + }; + + err = create_gang(engine, &rq); + if (err) + break; + + /* Submit each spinner at increasing priority */ + engine->schedule(rq, &attr); + + if (prio <= I915_PRIORITY_MAX) + continue; + + if (prio > (INT_MAX >> I915_USER_PRIORITY_SHIFT)) + break; + + if (__igt_timeout(end_time, NULL)) + break; + } while (1); + pr_debug("%s: Preempt chain of %d requests\n", + engine->name, prio); + + /* + * Such that the last spinner is the highest priority and + * should execute first. When that spinner completes, + * it will terminate the next lowest spinner until there + * are no more spinners and the gang is complete. + */ + cs = i915_gem_object_pin_map(rq->batch->obj, I915_MAP_WC); + if (!IS_ERR(cs)) { + *cs = 0; + i915_gem_object_unpin_map(rq->batch->obj); + } else { + err = PTR_ERR(cs); + intel_gt_set_wedged(gt); + } + + while (rq) { /* wait for each rq from highest to lowest prio */ + struct i915_request *n = + list_next_entry(rq, client_link); + + if (err == 0 && i915_request_wait(rq, 0, HZ / 5) < 0) { + struct drm_printer p = + drm_info_printer(engine->i915->drm.dev); + + pr_err("Failed to flush chain of %d requests, at %d\n", + prio, rq_prio(rq) >> I915_USER_PRIORITY_SHIFT); + intel_engine_dump(engine, &p, + "%s\n", engine->name); + + err = -ETIME; + } + + i915_request_put(rq); + rq = n; + } + + if (igt_live_test_end(&t)) + err = -EIO; + if (err) + return err; + } + + return 0; +} + static int live_preempt_hang(void *arg) { struct intel_gt *gt = arg; @@ -3028,6 +3223,7 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915) SUBTEST(live_suppress_self_preempt), SUBTEST(live_suppress_wait_preempt), SUBTEST(live_chain_preempt), + SUBTEST(live_preempt_gang), SUBTEST(live_preempt_hang), SUBTEST(live_preempt_timeout), SUBTEST(live_preempt_smoke), -- cgit v1.2.3 From c212fbde20aca7a8180fe0d5770bc9cfa789e27d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Nov 2019 15:08:40 +0000 Subject: drm/i915/selftests: Disable heartbeat around context barrier tests As the heartbeat has the effect of flushing context barriers, this interferes with the context barrier tests that are trying to observe them directly. Disable the heartbeat so that the barriers are as predictable as the test demands. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191115150841.880349-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/selftest_context.c | 44 ++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index 14ba6ceb9177..3586af636304 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -5,6 +5,7 @@ */ #include "i915_selftest.h" +#include "intel_engine_heartbeat.h" #include "intel_engine_pm.h" #include "intel_gt.h" @@ -200,6 +201,7 @@ static int live_context_size(void *arg) static int __live_active_context(struct intel_engine_cs *engine, struct i915_gem_context *fixme) { + unsigned long saved_heartbeat; struct intel_context *ce; int pass; int err; @@ -227,36 +229,50 @@ static int __live_active_context(struct intel_engine_cs *engine, if (IS_ERR(ce)) return PTR_ERR(ce); + saved_heartbeat = engine->props.heartbeat_interval_ms; + engine->props.heartbeat_interval_ms = 0; + for (pass = 0; pass <= 2; pass++) { struct i915_request *rq; + intel_engine_pm_get(engine); + rq = intel_context_create_request(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto err; + goto out_engine; } err = request_sync(rq); if (err) - goto err; + goto out_engine; /* Context will be kept active until after an idle-barrier. */ if (i915_active_is_idle(&ce->active)) { pr_err("context is not active; expected idle-barrier (%s pass %d)\n", engine->name, pass); err = -EINVAL; - goto err; + goto out_engine; } if (!intel_engine_pm_is_awake(engine)) { pr_err("%s is asleep before idle-barrier\n", engine->name); err = -EINVAL; - goto err; + goto out_engine; } + +out_engine: + intel_engine_pm_put(engine); + if (err) + goto err; } /* Now make sure our idle-barriers are flushed */ + err = intel_engine_flush_barriers(engine); + if (err) + goto err; + err = context_sync(engine->kernel_context); if (err) goto err; @@ -270,8 +286,9 @@ static int __live_active_context(struct intel_engine_cs *engine, struct drm_printer p = drm_debug_printer(__func__); intel_engine_dump(engine, &p, - "%s is still awake after idle-barriers\n", - engine->name); + "%s is still awake:%d after idle-barriers\n", + engine->name, + atomic_read(&engine->wakeref.count)); GEM_TRACE_DUMP(); err = -EINVAL; @@ -279,6 +296,7 @@ static int __live_active_context(struct intel_engine_cs *engine, } err: + engine->props.heartbeat_interval_ms = saved_heartbeat; intel_context_put(ce); return err; } @@ -349,6 +367,7 @@ static int __live_remote_context(struct intel_engine_cs *engine, struct i915_gem_context *fixme) { struct intel_context *local, *remote; + unsigned long saved_heartbeat; int pass; int err; @@ -360,6 +379,12 @@ static int __live_remote_context(struct intel_engine_cs *engine, * clobber the idle-barrier. */ + if (intel_engine_pm_is_awake(engine)) { + pr_err("%s is awake before starting %s!\n", + engine->name, __func__); + return -EINVAL; + } + remote = intel_context_create(fixme, engine); if (IS_ERR(remote)) return PTR_ERR(remote); @@ -370,6 +395,10 @@ static int __live_remote_context(struct intel_engine_cs *engine, goto err_remote; } + saved_heartbeat = engine->props.heartbeat_interval_ms; + engine->props.heartbeat_interval_ms = 0; + intel_engine_pm_get(engine); + for (pass = 0; pass <= 2; pass++) { err = __remote_sync(local, remote); if (err) @@ -387,6 +416,9 @@ static int __live_remote_context(struct intel_engine_cs *engine, } } + intel_engine_pm_put(engine); + engine->props.heartbeat_interval_ms = saved_heartbeat; + intel_context_put(local); err_remote: intel_context_put(remote); -- cgit v1.2.3 From cc7a4cffea21954bc72bec8251719c3d6fcc322d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 24 Oct 2019 15:21:38 +0300 Subject: drm/i915: Fix frame start delay programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we're blindly poking at the frame start delay bits in PIPECONF when trying to sanitize the hardware state. Those bits decided to move elsewhere on HSW, so on many platforms we're not doing anything at all here. Also we're forgetting about the PCH transcoder entirely. Add all the bit definitions for the various homes these bits have had throughout the years, and reset them all to zero. However I'm not entirely sure this is a safe thing to do. If not I guess we'd want full readout+statecheck for this stuff. For now let's stick to the current logic and hope for the best. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191024122138.25065-3-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_display.c | 101 +++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 12 ++-- drivers/gpu/drm/i915/intel_pm.c | 1 - 3 files changed, 95 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c382498f081e..1558aefc2fd9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1674,11 +1674,16 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s assert_fdi_rx_enabled(dev_priv, pipe); if (HAS_PCH_CPT(dev_priv)) { - /* Workaround: Set the timing override bit before enabling the - * pch transcoder. */ reg = TRANS_CHICKEN2(pipe); val = I915_READ(reg); + /* + * Workaround: Set the timing override bit + * before enabling the pch transcoder. + */ val |= TRANS_CHICKEN2_TIMING_OVERRIDE; + /* Configure frame start delay to match the CPU */ + val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; + val |= TRANS_CHICKEN2_FRAME_START_DELAY(0); I915_WRITE(reg, val); } @@ -1687,6 +1692,10 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s pipeconf_val = I915_READ(PIPECONF(pipe)); if (HAS_PCH_IBX(dev_priv)) { + /* Configure frame start delay to match the CPU */ + val &= ~TRANS_FRAME_START_DELAY_MASK; + val |= TRANS_FRAME_START_DELAY(0); + /* * Make the BPC in transcoder be consistent with * that in pipeconf reg. For HDMI we must use 8bpc @@ -1724,9 +1733,12 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder); assert_fdi_rx_enabled(dev_priv, PIPE_A); - /* Workaround: set timing override bit. */ val = I915_READ(TRANS_CHICKEN2(PIPE_A)); + /* Workaround: set timing override bit. */ val |= TRANS_CHICKEN2_TIMING_OVERRIDE; + /* Configure frame start delay to match the CPU */ + val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; + val |= TRANS_CHICKEN2_FRAME_START_DELAY(0); I915_WRITE(TRANS_CHICKEN2(PIPE_A), val); val = TRANS_ENABLE; @@ -6583,6 +6595,19 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc) I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val); } +static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + i915_reg_t reg = CHICKEN_TRANS(crtc_state->cpu_transcoder); + u32 val; + + val = I915_READ(reg); + val &= ~HSW_FRAME_START_DELAY_MASK; + val |= HSW_FRAME_START_DELAY(0); + I915_WRITE(reg, val); +} + static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { @@ -6625,8 +6650,10 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, &pipe_config->fdi_m_n, NULL); } - if (!transcoder_is_dsi(cpu_transcoder)) + if (!transcoder_is_dsi(cpu_transcoder)) { + hsw_set_frame_start_delay(pipe_config); haswell_set_pipeconf(pipe_config); + } if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) bdw_set_pipemisc(pipe_config); @@ -8523,6 +8550,8 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); + pipeconf |= PIPECONF_FRAME_START_DELAY(0); + I915_WRITE(PIPECONF(crtc->pipe), pipeconf); POSTING_READ(PIPECONF(crtc->pipe)); } @@ -9604,6 +9633,8 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state) val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); + val |= PIPECONF_FRAME_START_DELAY(0); + I915_WRITE(PIPECONF(pipe), val); POSTING_READ(PIPECONF(pipe)); } @@ -17202,25 +17233,69 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv, (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A); } -static void intel_sanitize_crtc(struct intel_crtc *crtc, - struct drm_modeset_acquire_ctx *ctx) +static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc_state) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - /* Clear any frame start delays used for debugging left by the BIOS */ - if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) { + if (INTEL_GEN(dev_priv) >= 9 || + IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) { + i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder); + u32 val; + + if (transcoder_is_dsi(cpu_transcoder)) + return; + + val = I915_READ(reg); + val &= ~HSW_FRAME_START_DELAY_MASK; + val |= HSW_FRAME_START_DELAY(0); + I915_WRITE(reg, val); + } else { i915_reg_t reg = PIPECONF(cpu_transcoder); + u32 val; + + val = I915_READ(reg); + val &= ~PIPECONF_FRAME_START_DELAY_MASK; + val |= PIPECONF_FRAME_START_DELAY(0); + I915_WRITE(reg, val); + } + + if (!crtc_state->has_pch_encoder) + return; + + if (HAS_PCH_IBX(dev_priv)) { + i915_reg_t reg = PCH_TRANSCONF(crtc->pipe); + u32 val; + + val = I915_READ(reg); + val &= ~TRANS_FRAME_START_DELAY_MASK; + val |= TRANS_FRAME_START_DELAY(0); + I915_WRITE(reg, val); + } else { + i915_reg_t reg = TRANS_CHICKEN2(crtc->pipe); + u32 val; - I915_WRITE(reg, - I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); + val = I915_READ(reg); + val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; + val |= TRANS_CHICKEN2_FRAME_START_DELAY(0); + I915_WRITE(reg, val); } +} + +static void intel_sanitize_crtc(struct intel_crtc *crtc, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); if (crtc_state->hw.active) { struct intel_plane *plane; + /* Clear any frame start delays used for debugging left by the BIOS */ + intel_sanitize_frame_start_delay(crtc_state); + /* Disable everything but the primary plane */ for_each_intel_plane_on_crtc(dev, crtc, plane) { const struct intel_plane_state *plane_state = diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 478f5ff6c554..94d0f593eeb7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5757,7 +5757,8 @@ enum { #define PIPECONF_DOUBLE_WIDE (1 << 30) #define I965_PIPECONF_ACTIVE (1 << 30) #define PIPECONF_DSI_PLL_LOCKED (1 << 29) /* vlv & pipe A only */ -#define PIPECONF_FRAME_START_DELAY_MASK (3 << 27) +#define PIPECONF_FRAME_START_DELAY_MASK (3 << 27) /* pre-hsw */ +#define PIPECONF_FRAME_START_DELAY(x) ((x) << 27) /* pre-hsw: 0-3 */ #define PIPECONF_SINGLE_WIDE 0 #define PIPECONF_PIPE_UNLOCKED 0 #define PIPECONF_PIPE_LOCKED (1 << 25) @@ -7739,6 +7740,8 @@ enum { [TRANSCODER_B] = _CHICKEN_TRANS_B, \ [TRANSCODER_C] = _CHICKEN_TRANS_C, \ [TRANSCODER_D] = _CHICKEN_TRANS_D)) +#define HSW_FRAME_START_DELAY_MASK (3 << 27) +#define HSW_FRAME_START_DELAY(x) ((x) << 27) /* 0-3 */ #define VSC_DATA_SEL_SOFTWARE_CONTROL (1 << 25) /* GLK and CNL+ */ #define DDI_TRAINING_OVERRIDE_ENABLE (1 << 19) #define DDI_TRAINING_OVERRIDE_VALUE (1 << 18) @@ -8457,10 +8460,8 @@ enum { #define TRANS_STATE_MASK (1 << 30) #define TRANS_STATE_DISABLE (0 << 30) #define TRANS_STATE_ENABLE (1 << 30) -#define TRANS_FSYNC_DELAY_HB1 (0 << 27) -#define TRANS_FSYNC_DELAY_HB2 (1 << 27) -#define TRANS_FSYNC_DELAY_HB3 (2 << 27) -#define TRANS_FSYNC_DELAY_HB4 (3 << 27) +#define TRANS_FRAME_START_DELAY_MASK (3 << 27) /* ibx */ +#define TRANS_FRAME_START_DELAY(x) ((x) << 27) /* ibx: 0-3 */ #define TRANS_INTERLACE_MASK (7 << 21) #define TRANS_PROGRESSIVE (0 << 21) #define TRANS_INTERLACED (3 << 21) @@ -8481,6 +8482,7 @@ enum { #define TRANS_CHICKEN2_TIMING_OVERRIDE (1 << 31) #define TRANS_CHICKEN2_FDI_POLARITY_REVERSED (1 << 29) #define TRANS_CHICKEN2_FRAME_START_DELAY_MASK (3 << 27) +#define TRANS_CHICKEN2_FRAME_START_DELAY(x) ((x) << 27) /* 0-3 */ #define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER (1 << 26) #define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH (1 << 25) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 87f96157e156..4c6e70ed3d67 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6368,7 +6368,6 @@ static void cpt_init_clock_gating(struct drm_i915_private *dev_priv) val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED; if (dev_priv->vbt.fdi_rx_polarity_inverted) val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED; - val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER; val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH; I915_WRITE(TRANS_CHICKEN2(pipe), val); -- cgit v1.2.3 From 3c1fe1eb92f403d95aff35edb767c56e6be04ff1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Nov 2019 12:23:43 +0000 Subject: drm/i915/gt: Mention which device failed When telling the user that device power management is disabled, it is helpful to say which device that was. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Imre Deak Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20191115122343.821331-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rc6.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 602a02d01850..977a617a196d 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -540,7 +540,8 @@ void intel_rc6_ctx_wa_check(struct intel_rc6 *rc6) if (!intel_rc6_ctx_corrupted(rc6)) return; - DRM_NOTE("RC6 context corruption, disabling runtime power management\n"); + dev_notice(i915->drm.dev, + "RC6 context corruption, disabling runtime power management\n"); intel_rc6_disable(rc6); rc6->ctx_corrupted = true; -- cgit v1.2.3 From b291ce0a168b3403ac48228432abd9a58929da66 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Nov 2019 17:08:35 +0000 Subject: drm/i915/gem: Purge the sudden reappearance of i915_gem_object_pin() This died many years ago as we now use i915_vma first and foremost. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191115170835.1367869-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 36 +++++++++++++++--------- drivers/gpu/drm/i915/i915_drv.h | 8 ------ drivers/gpu/drm/i915/i915_gem.c | 38 +++++++++----------------- 3 files changed, 36 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index f0998f1225af..7a87e8270460 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1995,28 +1995,38 @@ static int i915_reset_gen7_sol_offsets(struct i915_request *rq) static struct i915_vma * shadow_batch_pin(struct i915_execbuffer *eb, struct drm_i915_gem_object *obj) { - struct drm_i915_private *dev_priv = eb->i915; - struct i915_vma * const vma = *eb->vma; struct i915_address_space *vm; + struct i915_vma *vma; u64 flags; + int err; /* * PPGTT backed shadow buffers must be mapped RO, to prevent * post-scan tampering */ - if (CMDPARSER_USES_GGTT(dev_priv)) { + if (CMDPARSER_USES_GGTT(eb->i915)) { + vm = &eb->engine->gt->ggtt->vm; flags = PIN_GLOBAL; - vm = &dev_priv->ggtt.vm; - } else if (vma->vm->has_read_only) { - flags = PIN_USER; - vm = vma->vm; - i915_gem_object_set_readonly(obj); } else { - DRM_DEBUG("Cannot prevent post-scan tampering without RO capable vm\n"); - return ERR_PTR(-EINVAL); + vm = eb->context->vm; + if (!vm->has_read_only) { + DRM_DEBUG("Cannot prevent post-scan tampering without RO capable vm\n"); + return ERR_PTR(-EINVAL); + } + + i915_gem_object_set_readonly(obj); + flags = PIN_USER; } - return i915_gem_object_pin(obj, vm, NULL, 0, 0, flags); + vma = i915_vma_instance(obj, vm, NULL); + if (IS_ERR(vma)) + return vma; + + err = i915_vma_pin(vma, 0, 0, flags); + if (err) + return ERR_PTR(err); + + return vma; } static struct i915_vma *eb_parse(struct i915_execbuffer *eb) @@ -2058,7 +2068,7 @@ static struct i915_vma *eb_parse(struct i915_execbuffer *eb) * For PPGTT backing however, we have no choice but to forcibly * reject unsafe buffers */ - if (CMDPARSER_USES_GGTT(eb->i915) && (err == -EACCES)) + if (i915_vma_is_ggtt(vma) && err == -EACCES) /* Execute original buffer non-secure */ vma = NULL; else @@ -2075,7 +2085,7 @@ static struct i915_vma *eb_parse(struct i915_execbuffer *eb) eb->batch_start_offset = 0; eb->batch = vma; - if (CMDPARSER_USES_GGTT(eb->i915)) + if (i915_vma_is_ggtt(vma)) eb->batch_flags |= I915_DISPATCH_SECURE; /* eb->batch_len unchanged */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7bc1d8c102b2..5fa38c55daa3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1842,14 +1842,6 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj, unsigned long flags); #define I915_GEM_OBJECT_UNBIND_ACTIVE BIT(0) -struct i915_vma * __must_check -i915_gem_object_pin(struct drm_i915_gem_object *obj, - struct i915_address_space *vm, - const struct i915_ggtt_view *view, - u64 size, - u64 alignment, - u64 flags); - void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv); static inline int __must_check diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 43c532756c7c..1ba5f26700b0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -891,22 +891,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, u64 alignment, u64 flags) { - struct drm_i915_private *dev_priv = to_i915(obj->base.dev); - struct i915_address_space *vm = &dev_priv->ggtt.vm; - - return i915_gem_object_pin(obj, vm, view, size, alignment, - flags | PIN_GLOBAL); -} - -struct i915_vma * -i915_gem_object_pin(struct drm_i915_gem_object *obj, - struct i915_address_space *vm, - const struct i915_ggtt_view *view, - u64 size, - u64 alignment, - u64 flags) -{ - struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct i915_ggtt *ggtt = &i915->ggtt; struct i915_vma *vma; int ret; @@ -915,17 +901,19 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, if (flags & PIN_MAPPABLE && (!view || view->type == I915_GGTT_VIEW_NORMAL)) { - /* If the required space is larger than the available + /* + * If the required space is larger than the available * aperture, we will not able to find a slot for the * object and unbinding the object now will be in * vain. Worse, doing so may cause us to ping-pong * the object in and out of the Global GTT and * waste a lot of cycles under the mutex. */ - if (obj->base.size > dev_priv->ggtt.mappable_end) + if (obj->base.size > ggtt->mappable_end) return ERR_PTR(-E2BIG); - /* If NONBLOCK is set the caller is optimistically + /* + * If NONBLOCK is set the caller is optimistically * trying to cache the full object within the mappable * aperture, and *must* have a fallback in place for * situations where we cannot bind the object. We @@ -941,11 +929,11 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, * we could try to minimise harm to others. */ if (flags & PIN_NONBLOCK && - obj->base.size > dev_priv->ggtt.mappable_end / 2) + obj->base.size > ggtt->mappable_end / 2) return ERR_PTR(-ENOSPC); } - vma = i915_vma_instance(obj, vm, view); + vma = i915_vma_instance(obj, &ggtt->vm, view); if (IS_ERR(vma)) return vma; @@ -955,7 +943,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, return ERR_PTR(-ENOSPC); if (flags & PIN_MAPPABLE && - vma->fence_size > dev_priv->ggtt.mappable_end / 2) + vma->fence_size > ggtt->mappable_end / 2) return ERR_PTR(-ENOSPC); } @@ -965,14 +953,14 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, } if (vma->fence && !i915_gem_object_is_tiled(obj)) { - mutex_lock(&vma->vm->mutex); + mutex_lock(&ggtt->vm.mutex); ret = i915_vma_revoke_fence(vma); - mutex_unlock(&vma->vm->mutex); + mutex_unlock(&ggtt->vm.mutex); if (ret) return ERR_PTR(ret); } - ret = i915_vma_pin(vma, size, alignment, flags); + ret = i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL); if (ret) return ERR_PTR(ret); -- cgit v1.2.3 From 82e0c5bbd6eb1d274b5a3e519ff0ab91f1f8e537 Mon Sep 17 00:00:00 2001 From: Don Hiatt Date: Fri, 15 Nov 2019 15:15:38 -0800 Subject: drm/i915/guc: Skip suspend/resume GuC action on platforms w/o GuC submission On some platforms (e.g. KBL) that do not support GuC submission, but the user enabled the GuC communication (e.g for HuC authentication) calling the GuC EXIT_S_STATE action results in lose of ability to enter RC6. We can remove the GuC suspend/resume entirely as we do not need to save the GuC submission status. Add intel_guc_submission_is_enabled() function to determine if GuC submission is active. v2: Do not suspend/resume the GuC on platforms that do not support Guc Submission. v3: Fix typo, move suspend logic to remove goto. v4: Use intel_guc_submission_is_enabled() to check GuC submission status. v5: No need to look at engine to determine if submission is enabled. Squash fix + intel_guc_submission_is_enabled() patch into one. v6: Move resume check into intel_guc_resume() for symmetry. Fix commit Fixes tag. Reported-by: KiteStramuort Reported-by: S. Zharkoff Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111594 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111623 Fixes: ffd5ce22faa4 ("drm/i915/guc: Updates for GuC 32.0.3 firmware") Cc: Michal Wajdeczko Cc: Daniele Ceralo Spurio Cc: Stuart Summers Cc: Chris Wilson Tested-by: Tomas Janousek Signed-off-by: Don Hiatt Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191115231538.1249-1-don.hiatt@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 15 +++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 019ae6486e8d..3ee4a4e7689d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -553,6 +553,13 @@ int intel_guc_suspend(struct intel_guc *guc) GUC_POWER_D1, /* any value greater than GUC_POWER_D0 */ }; + /* + * If GuC communication is enabled but submission is not supported, + * we do not need to suspend the GuC. + */ + if (!intel_guc_submission_is_enabled(guc)) + return 0; + /* * The ENTER_S_STATE action queues the save/restore operation in GuC FW * and then returns, so waiting on the H2G is not enough to guarantee @@ -610,6 +617,14 @@ int intel_guc_resume(struct intel_guc *guc) GUC_POWER_D0, }; + /* + * If GuC communication is enabled but submission is not supported, + * we do not need to resume the GuC but we do need to enable the + * GuC communication on resume (above). + */ + if (!intel_guc_submission_is_enabled(guc)) + return 0; + return intel_guc_send(guc, action, ARRAY_SIZE(action)); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5fa38c55daa3..bbf4dfdfa8ba 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2036,4 +2036,10 @@ i915_coherent_map_type(struct drm_i915_private *i915) return HAS_LLC(i915) ? I915_MAP_WB : I915_MAP_WC; } +static inline bool intel_guc_submission_is_enabled(struct intel_guc *guc) +{ + return intel_guc_is_submission_supported(guc) && + intel_guc_is_running(guc); +} + #endif -- cgit v1.2.3 From 48ea97fabe75c83adf4e6ff9262bbda229e6ee73 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 15 Nov 2019 14:04:40 +0200 Subject: drm/i915: fix accidental static variable use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's supposed to be just a const pointer. Fixes: 074c77e3ec63 ("drm/i915/tgl: Gen-12 display loses Yf tiling and legacy CCS support") Cc: Ville Syrjälä Cc: Dhinakaran Pandiyan Cc: Lucas De Marchi Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191115120440.17883-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_sprite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index d7f71fa90659..8394502b092d 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -2921,7 +2921,7 @@ struct intel_plane * skl_universal_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id) { - static const struct drm_plane_funcs *plane_funcs; + const struct drm_plane_funcs *plane_funcs; struct intel_plane *plane; enum drm_plane_type plane_type; unsigned int supported_rotations; -- cgit v1.2.3 From 8eed671415935215dd39569c4fe505a5d1d01014 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Nov 2019 09:43:42 +0000 Subject: drm/i915/selftests: Add intel_gt_driver_late_release for mock device Having called intel_gt_init_early() to setup the mock intel_gt, we need to call the corresponding intel_gt_driver_late_release() to clean up. References: dea397e818b1 ("drm/i915/gt: Flush retire.work timer object on unload") References: 24635c5152af ("drm/i915: Move intel_gt initialization to a separate file") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191118094342.2193485-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index e58b0bc9cdb6..d14ba8498f57 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -71,6 +71,7 @@ static void mock_device_release(struct drm_device *dev) mock_fini_ggtt(&i915->ggtt); destroy_workqueue(i915->wq); + intel_gt_driver_late_release(&i915->gt); intel_memory_regions_driver_release(i915); drm_mode_config_cleanup(&i915->drm); @@ -204,6 +205,7 @@ err_engine: err_unlock: destroy_workqueue(i915->wq); err_drv: + intel_gt_driver_late_release(&i915->gt); intel_memory_regions_driver_release(i915); drm_mode_config_cleanup(&i915->drm); drm_dev_fini(&i915->drm); -- cgit v1.2.3 From 9e7ecedf057f4cb7b69b948e90819e129a7fe168 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 15 Nov 2019 08:51:31 -0800 Subject: drm/i915/vbt: Parse panel options separately from timing data Newer VBT versions will add an alternate way to read panel DTD information, so let's split parsing of the general panel information from the timing data in preparation. Cc: Jani Nikula Signed-off-by: Matt Roper Reviewed-by: Jesse Barnes Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191115165132.9472-2-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 6d7b1a83cb07..d13ce0b7db8b 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -208,17 +208,12 @@ get_lvds_fp_timing(const struct bdb_header *bdb, return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs); } -/* Try to find integrated panel data */ +/* Parse general panel options */ static void -parse_lfp_panel_data(struct drm_i915_private *dev_priv, - const struct bdb_header *bdb) +parse_panel_options(struct drm_i915_private *dev_priv, + const struct bdb_header *bdb) { const struct bdb_lvds_options *lvds_options; - const struct bdb_lvds_lfp_data *lvds_lfp_data; - const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; - const struct lvds_dvo_timing *panel_dvo_timing; - const struct lvds_fp_timing *fp_timing; - struct drm_display_mode *panel_fixed_mode; int panel_type; int drrs_mode; int ret; @@ -267,6 +262,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("DRRS not supported (VBT input)\n"); break; } +} + +/* Try to find integrated panel timing data */ +static void +parse_lfp_panel_dtd(struct drm_i915_private *dev_priv, + const struct bdb_header *bdb) +{ + const struct bdb_lvds_lfp_data *lvds_lfp_data; + const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; + const struct lvds_dvo_timing *panel_dvo_timing; + const struct lvds_fp_timing *fp_timing; + struct drm_display_mode *panel_fixed_mode; + int panel_type = dev_priv->vbt.panel_type; lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); if (!lvds_lfp_data) @@ -1868,7 +1876,8 @@ void intel_bios_init(struct drm_i915_private *dev_priv) /* Grab useful general definitions */ parse_general_features(dev_priv, bdb); parse_general_definitions(dev_priv, bdb); - parse_lfp_panel_data(dev_priv, bdb); + parse_panel_options(dev_priv, bdb); + parse_lfp_panel_dtd(dev_priv, bdb); parse_lfp_backlight(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); parse_driver_features(dev_priv, bdb); -- cgit v1.2.3 From 33ef6d4fd8df78fbeccb0e3e97515bee8556b4af Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 15 Nov 2019 08:51:32 -0800 Subject: drm/i915/vbt: Handle generic DTD block VBT revision 229 adds a new "Generic DTD" block 58 and deprecates the old LFP panel mode data in block 42. Let's start parsing this block to fill in the panel fixed mode on devices with a >=229 VBT. v2: * Update according to the recent updates: - DTD size is now 16 bits instead of 24 - polarity is now just a single bit for hsync and vsync and is properly documented * Minor checkpatch fix v3: * Now that panel options are parsed separately from the previous patch, move generic DTD parsing into a function parallel to parse_lfp_panel_dtd. We'll still fall back to looking at the legacy LVDS timing block if the generic DTD fails. (Jani) * Don't forget to actually set lfp_lvds_vbt_mode! (Jani) * Drop "bdb_" prefix from dtd entry structure. (Jani) * Follow C99 standard for structure's flexible array member. (Jani) v4: * Add "positive" to polarity field names for clarity. (Jani) * Move VBT version check and fallback to legacy DTD parsing logic to a helper to keep top-level VBT parsing uncluttered. (Jani) * Restructure reserved bit packing at end of generic_dtd_entry from "u32 rsvd:24" to "u8 rsvd[3]" to prevent copy/paste mistakes in the future. (Jani) Bspec: 54751 Bspec: 20148 Cc: Jani Nikula Signed-off-by: Matt Roper Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191115165132.9472-3-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 96 ++++++++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_vbt_defs.h | 31 +++++++++ 2 files changed, 125 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index d13ce0b7db8b..f6a9a5ccb556 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -296,7 +296,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *dev_priv, dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; - DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n"); + DRM_DEBUG_KMS("Found panel mode in BIOS VBT legacy lfp table:\n"); drm_mode_debug_printmodeline(panel_fixed_mode); fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, @@ -313,6 +313,98 @@ parse_lfp_panel_dtd(struct drm_i915_private *dev_priv, } } +static void +parse_generic_dtd(struct drm_i915_private *dev_priv, + const struct bdb_header *bdb) +{ + const struct bdb_generic_dtd *generic_dtd; + const struct generic_dtd_entry *dtd; + struct drm_display_mode *panel_fixed_mode; + int num_dtd; + + generic_dtd = find_section(bdb, BDB_GENERIC_DTD); + if (!generic_dtd) + return; + + if (generic_dtd->gdtd_size < sizeof(struct generic_dtd_entry)) { + DRM_ERROR("GDTD size %u is too small.\n", + generic_dtd->gdtd_size); + return; + } else if (generic_dtd->gdtd_size != + sizeof(struct generic_dtd_entry)) { + DRM_ERROR("Unexpected GDTD size %u\n", generic_dtd->gdtd_size); + /* DTD has unknown fields, but keep going */ + } + + num_dtd = (get_blocksize(generic_dtd) - + sizeof(struct bdb_generic_dtd)) / generic_dtd->gdtd_size; + if (dev_priv->vbt.panel_type > num_dtd) { + DRM_ERROR("Panel type %d not found in table of %d DTD's\n", + dev_priv->vbt.panel_type, num_dtd); + return; + } + + dtd = &generic_dtd->dtd[dev_priv->vbt.panel_type]; + + panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); + if (!panel_fixed_mode) + return; + + panel_fixed_mode->hdisplay = dtd->hactive; + panel_fixed_mode->hsync_start = + panel_fixed_mode->hdisplay + dtd->hfront_porch; + panel_fixed_mode->hsync_end = + panel_fixed_mode->hsync_start + dtd->hsync; + panel_fixed_mode->htotal = panel_fixed_mode->hsync_end; + + panel_fixed_mode->vdisplay = dtd->vactive; + panel_fixed_mode->vsync_start = + panel_fixed_mode->vdisplay + dtd->vfront_porch; + panel_fixed_mode->vsync_end = + panel_fixed_mode->vsync_start + dtd->vsync; + panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end; + + panel_fixed_mode->clock = dtd->pixel_clock; + panel_fixed_mode->width_mm = dtd->width_mm; + panel_fixed_mode->height_mm = dtd->height_mm; + + panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; + drm_mode_set_name(panel_fixed_mode); + + if (dtd->hsync_positive_polarity) + panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC; + else + panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC; + + if (dtd->vsync_positive_polarity) + panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC; + else + panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC; + + DRM_DEBUG_KMS("Found panel mode in BIOS VBT generic dtd table:\n"); + drm_mode_debug_printmodeline(panel_fixed_mode); + + dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; +} + +static void +parse_panel_dtd(struct drm_i915_private *dev_priv, + const struct bdb_header *bdb) +{ + /* + * Older VBTs provided provided DTD information for internal displays + * through the "LFP panel DTD" block (42). As of VBT revision 229, + * that block is now deprecated and DTD information should be provided + * via a newer "generic DTD" block (58). Just to be safe, we'll + * try the new generic DTD block first on VBT >= 229, but still fall + * back to trying the old LFP block if that fails. + */ + if (bdb->version >= 229) + parse_generic_dtd(dev_priv, bdb); + if (!dev_priv->vbt.lfp_lvds_vbt_mode) + parse_lfp_panel_dtd(dev_priv, bdb); +} + static void parse_lfp_backlight(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) @@ -1877,7 +1969,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv) parse_general_features(dev_priv, bdb); parse_general_definitions(dev_priv, bdb); parse_panel_options(dev_priv, bdb); - parse_lfp_panel_dtd(dev_priv, bdb); + parse_panel_dtd(dev_priv, bdb); parse_lfp_backlight(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); parse_driver_features(dev_priv, bdb); diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index 69a7cb1fa121..f0338da3a82a 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -115,6 +115,7 @@ enum bdb_block_id { BDB_MIPI_CONFIG = 52, BDB_MIPI_SEQUENCE = 53, BDB_COMPRESSION_PARAMETERS = 56, + BDB_GENERIC_DTD = 58, BDB_SKIP = 254, /* VBIOS private block, ignore */ }; @@ -863,4 +864,34 @@ struct bdb_compression_parameters { struct dsc_compression_parameters_entry data[16]; } __packed; +/* + * Block 58 - Generic DTD Block + */ + +struct generic_dtd_entry { + u32 pixel_clock; + u16 hactive; + u16 hblank; + u16 hfront_porch; + u16 hsync; + u16 vactive; + u16 vblank; + u16 vfront_porch; + u16 vsync; + u16 width_mm; + u16 height_mm; + + /* Flags */ + u8 rsvd_flags:6; + u8 vsync_positive_polarity:1; + u8 hsync_positive_polarity:1; + + u8 rsvd[3]; +} __packed; + +struct bdb_generic_dtd { + u16 gdtd_size; + struct generic_dtd_entry dtd[]; /* up to 24 DTD's */ +} __packed; + #endif /* _INTEL_VBT_DEFS_H_ */ -- cgit v1.2.3 From c50bb4dd1fa52fb58274609afc415fcbd9ee6264 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Fri, 15 Nov 2019 12:04:30 -0800 Subject: drm/i915/mst: Check uapi enable not intel one during mst atomic check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the connector has VCPI allocated and is being moved to another pipe it causes drm_dp_atomic_release_vcpi_slots() and drm_dp_atomic_find_vcpi_slots() to be called in the same atomic check causing the error bellow. This happens because at this point Intel's hw.enable(and all other flags in the same struct) is not set but checking to on the uapi one it have the expected value. [ 580.804430] ------------[ cut here ]------------ [ 580.804436] WARNING: CPU: 0 PID: 1221 at drivers/gpu/drm/drm_dp_mst_topology.c:4094 drm_dp_atomic_find_vcpi_slots+0x157/0x180 [ 580.804439] Modules linked in: cdc_ether r8152 i915 prime_numbers snd_hda_codec_hdmi snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hwdep asix snd_hda_core x86_pkg_temp_thermal usbnet mei_hdcp coretemp mii mei_me crct10dif_pclmul snd_pcm crc32_pclmul mei ghash_clmulni_intel i2c_i801 [last unloaded: prime_numbers] [ 580.804462] CPU: 0 PID: 1221 Comm: kworker/0:0 Tainted: G W 5.4.0-rc7-zeh+ #1226 [ 580.804465] Hardware name: Intel Corporation Tiger Lake Client Platform/TigerLake U DDR4 SODIMM RVP, BIOS TGLSFWI1.D00.2321.A09.1909250226 09/25/2019 [ 580.804470] Workqueue: events output_poll_execute [ 580.804476] RIP: 0010:drm_dp_atomic_find_vcpi_slots+0x157/0x180 [ 580.804481] Code: 6a ff ff ff 49 89 6d 08 4c 89 6b 10 4c 89 63 18 49 89 6e 08 e9 55 ff ff ff 41 89 c7 5b 5d 44 89 f8 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 48 c7 c7 08 73 11 82 48 89 ee 41 bf ea ff ff ff e8 b2 e3 02 [ 580.804484] RSP: 0018:ffffc900009b7ab8 EFLAGS: 00010246 [ 580.804488] RAX: ffff88848c04ef50 RBX: ffff88848c04ef40 RCX: 0000000000000214 [ 580.804492] RDX: ffff88848c04f5e0 RSI: ffff888486eb2c68 RDI: ffff88848e518800 [ 580.804495] RBP: ffff88849d339000 R08: 00000000bc4e1092 R09: 0000000000000000 [ 580.804498] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88848c04e728 [ 580.804501] R13: 0000000000000214 R14: ffff88848c04e720 R15: ffff888486eb2c68 [ 580.804504] FS: 0000000000000000(0000) GS:ffff8884a0000000(0000) knlGS:0000000000000000 [ 580.804507] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 580.804510] CR2: 00007ff6bf1ba680 CR3: 0000000005210003 CR4: 0000000000760ef0 [ 580.804512] PKRU: 55555554 [ 580.804515] Call Trace: [ 580.804574] intel_dp_mst_compute_config+0x193/0x2b0 [i915] [ 580.804636] intel_atomic_check+0x10cc/0x20b0 [i915] [ 580.804644] ? drm_atomic_print_old_state+0xf1/0x130 [ 580.804655] drm_atomic_check_only+0x56a/0x810 [ 580.804663] drm_atomic_commit+0xe/0x50 [ 580.804668] drm_client_modeset_commit_atomic+0x18b/0x220 [ 580.804680] drm_client_modeset_commit_force+0x4d/0x180 [ 580.804685] drm_fb_helper_restore_fbdev_mode_unlocked+0x46/0xa0 [ 580.804689] drm_fb_helper_set_par+0x27/0x50 [ 580.804692] drm_fb_helper_hotplug_event.part.0+0xa7/0xc0 [ 580.804696] drm_kms_helper_hotplug_event+0x21/0x30 [ 580.804699] output_poll_execute+0x1a4/0x1c0 [ 580.804706] process_one_work+0x25b/0x5b0 [ 580.804713] worker_thread+0x4b/0x3b0 [ 580.804720] kthread+0x100/0x140 [ 580.804723] ? process_one_work+0x5b0/0x5b0 [ 580.804725] ? kthread_park+0x80/0x80 [ 580.804730] ret_from_fork+0x24/0x50 [ 580.804740] irq event stamp: 40988 [ 580.804743] hardirqs last enabled at (40987): [] console_unlock+0x437/0x590 [ 580.804746] hardirqs last disabled at (40988): [] trace_hardirqs_off_thunk+0x1a/0x20 [ 580.804749] softirqs last enabled at (40972): [] __do_softirq+0x389/0x47f [ 580.804752] softirqs last disabled at (40959): [] irq_exit+0xa9/0xc0 [ 580.804754] ---[ end trace 80052e0c60463c67 ]--- [ 580.804758] [drm:drm_dp_atomic_find_vcpi_slots] *ERROR* cannot allocate and release VCPI on [MST PORT:000000007880692e] in the same state [ 580.811370] [drm:intel_dp_hpd_pulse [i915]] got esi2 02 00 00 [ 580.817239] [drm:intel_dp_hpd_pulse [i915]] got esi 02 00 00 [ 580.817313] ------------[ cut here ]------------ [ 580.817318] WARNING: CPU: 0 PID: 1221 at drivers/gpu/drm/drm_dp_mst_topology.c:4094 drm_dp_atomic_find_vcpi_slots+0x157/0x180 [ 580.817321] Modules linked in: cdc_ether r8152 i915 prime_numbers snd_hda_codec_hdmi snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hwdep asix snd_hda_core x86_pkg_temp_thermal [ 580.817412] [drm:intel_dp_hpd_pulse [i915]] got hpd irq on [ENCODER:306:DDI E] - short [ 580.817413] usbnet mei_hdcp coretemp mii mei_me crct10dif_pclmul snd_pcm crc32_pclmul [ 580.817490] [drm:intel_dp_hpd_pulse [i915]] is_mst [ 580.817491] mei ghash_clmulni_intel i2c_i801 [last unloaded: prime_numbers] [ 580.817498] CPU: 0 PID: 1221 Comm: kworker/0:0 Tainted: G W 5.4.0-rc7-zeh+ #1226 [ 580.817503] Hardware name: Intel Corporation Tiger Lake Client Platform/TigerLake U DDR4 SODIMM RVP, BIOS TGLSFWI1.D00.2321.A09.1909250226 09/25/2019 [ 580.817506] Workqueue: events output_poll_execute [ 580.817511] RIP: 0010:drm_dp_atomic_find_vcpi_slots+0x157/0x180 [ 580.817514] Code: 6a ff ff ff 49 89 6d 08 4c 89 6b 10 4c 89 63 18 49 89 6e 08 e9 55 ff ff ff 41 89 c7 5b 5d 44 89 f8 41 5c 41 5d 41 5e 41 5f c3 <0f> 0b 48 c7 c7 08 73 11 82 48 89 ee 41 bf ea ff ff ff e8 b2 e3 02 [ 580.817516] RSP: 0018:ffffc900009b7ab8 EFLAGS: 00010246 [ 580.817519] RAX: ffff88848c04ef50 RBX: ffff88848c04ef40 RCX: 000000000000018f [ 580.817521] RDX: ffff88848c04f5e0 RSI: ffff888486eb2c68 RDI: ffff88848e518800 [ 580.817523] RBP: ffff88849d339000 R08: 00000000bc4e1092 R09: 0000000000000000 [ 580.817525] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88848c04e728 [ 580.817528] R13: 000000000000018f R14: ffff88848c04e720 R15: ffff888486eb2c68 [ 580.817532] FS: 0000000000000000(0000) GS:ffff8884a0000000(0000) knlGS:0000000000000000 [ 580.817534] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 580.817535] CR2: 00007ff6bf1ba680 CR3: 0000000005210003 CR4: 0000000000760ef0 [ 580.817537] PKRU: 55555554 [ 580.817538] Call Trace: [ 580.817620] intel_dp_mst_compute_config+0x193/0x2b0 [i915] [ 580.817690] intel_atomic_check+0x10cc/0x20b0 [i915] [ 580.817697] ? drm_atomic_print_old_state+0xf1/0x130 [ 580.817711] drm_atomic_check_only+0x56a/0x810 [ 580.817721] drm_atomic_commit+0xe/0x50 [ 580.817726] drm_client_modeset_commit_atomic+0x18b/0x220 [ 580.817744] drm_client_modeset_commit_force+0x4d/0x180 [ 580.817751] drm_fb_helper_restore_fbdev_mode_unlocked+0x46/0xa0 [ 580.817756] drm_fb_helper_set_par+0x27/0x50 [ 580.817762] drm_fb_helper_hotplug_event.part.0+0xa7/0xc0 [ 580.817767] drm_kms_helper_hotplug_event+0x21/0x30 [ 580.817771] output_poll_execute+0x1a4/0x1c0 [ 580.817780] process_one_work+0x25b/0x5b0 [ 580.817791] worker_thread+0x4b/0x3b0 [ 580.817800] kthread+0x100/0x140 [ 580.817804] ? process_one_work+0x5b0/0x5b0 [ 580.817807] ? kthread_park+0x80/0x80 [ 580.817813] ret_from_fork+0x24/0x50 [ 580.817832] irq event stamp: 41028 [ 580.817838] hardirqs last enabled at (41027): [] console_unlock+0x437/0x590 [ 580.817841] hardirqs last disabled at (41028): [] trace_hardirqs_off_thunk+0x1a/0x20 [ 580.817846] softirqs last enabled at (41022): [] __do_softirq+0x389/0x47f [ 580.817851] softirqs last disabled at (41013): [] irq_exit+0xa9/0xc0 [ 580.817854] ---[ end trace 80052e0c60463c68 ]--- [ 580.817858] [drm:drm_dp_atomic_find_vcpi_slots] *ERROR* cannot allocate and release VCPI on [MST PORT:000000007880692e] in the same state [ 580.830767] [drm:intel_dp_mst_compute_config [i915]] failed finding vcpi slots:-22 [ 580.830821] [drm:intel_atomic_check [i915]] Encoder config failure: -22 Cc: Lyude Paul Cc: Maarten Lankhorst Cc: Ville Syrjälä Cc: Lucas De Marchi Signed-off-by: José Roberto de Souza Reviewed-by: Lyude Paul Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191115200430.53146-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 9fc606c6dbee..f8a350359346 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -191,7 +191,7 @@ intel_dp_mst_atomic_check(struct drm_connector *connector, if (!crtc_state || !drm_atomic_crtc_needs_modeset(&crtc_state->uapi) || - crtc_state->hw.enable) + crtc_state->uapi.enable) return 0; } -- cgit v1.2.3 From ac4eead3796579bdadd12e2fa99c4ddc920eda30 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 15 Nov 2019 17:15:39 -0800 Subject: drm/i915/dsb: remove atomic operations The current dsb API is not really prepared to handle multithread access. I was debugging an issue that ended up fixed by commit a096883dda2c ("drm/i915/dsb: Remove PIN_MAPPABLE from the DSB object VMA") and was puzzled how these atomic operations were guaranteeing atomicity. if (atomic_add_return(1, &dsb->refcount) != 1) return dsb; Thread A could still be initializing dsb struct (and even fail in the middle) while thread B would take a reference and use it (even derefencing a NULL cmd_buf). I don't think the atomic operations here will help much if this were to support multithreaded scenario in future, so just remove them to avoid confusion. v2: Use refcount++ != 0 instead of ++refcount != 1 (from Ville) Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191111205024.22853-2-lucas.demarchi@intel.com Link: https://patchwork.freedesktop.org/patch/msgid/20191116011539.18230-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 10 +++++----- drivers/gpu/drm/i915/display/intel_dsb.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index d8ad5fe1efef..50c4d98c0020 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -107,7 +107,7 @@ intel_dsb_get(struct intel_crtc *crtc) if (!HAS_DSB(i915)) return dsb; - if (atomic_add_return(1, &dsb->refcount) != 1) + if (dsb->refcount++ != 0) return dsb; dsb->id = DSB1; @@ -123,7 +123,7 @@ intel_dsb_get(struct intel_crtc *crtc) if (IS_ERR(vma)) { DRM_ERROR("Vma creation failed\n"); i915_gem_object_put(obj); - atomic_dec(&dsb->refcount); + dsb->refcount--; goto err; } @@ -132,7 +132,7 @@ intel_dsb_get(struct intel_crtc *crtc) DRM_ERROR("Command buffer creation failed\n"); i915_vma_unpin_and_release(&vma, 0); dsb->cmd_buf = NULL; - atomic_dec(&dsb->refcount); + dsb->refcount--; goto err; } dsb->vma = vma; @@ -158,10 +158,10 @@ void intel_dsb_put(struct intel_dsb *dsb) if (!HAS_DSB(i915)) return; - if (WARN_ON(atomic_read(&dsb->refcount) == 0)) + if (WARN_ON(dsb->refcount == 0)) return; - if (atomic_dec_and_test(&dsb->refcount)) { + if (--dsb->refcount == 0) { i915_vma_unpin_and_release(&dsb->vma, I915_VMA_RELEASE_MAP); dsb->cmd_buf = NULL; dsb->free_pos = 0; diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 6f95c8e909e6..395ef9ce558e 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -22,7 +22,7 @@ enum dsb_id { }; struct intel_dsb { - atomic_t refcount; + long refcount; enum dsb_id id; u32 *cmd_buf; struct i915_vma *vma; -- cgit v1.2.3 From 03cea61076f00ec6514aae88ec56f01117824cb7 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 11 Nov 2019 12:50:25 -0800 Subject: drm/i915/dsb: fix extra warning on error path handling When we call intel_dsb_get(), the dsb initialization may fail for various reasons. We already log the error message in that path, making it unnecessary to trigger a warning that refcount == 0 when calling intel_dsb_put(). So here we simplify the logic and do lazy shutdown: leaving the extra refcount alive so when we call intel_dsb_put() we end up calling i915_vma_unpin_and_release(). Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191111205024.22853-3-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 50c4d98c0020..5bf67bdc8182 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -102,6 +102,7 @@ intel_dsb_get(struct intel_crtc *crtc) struct intel_dsb *dsb = &crtc->dsb; struct drm_i915_gem_object *obj; struct i915_vma *vma; + u32 *buf; intel_wakeref_t wakeref; if (!HAS_DSB(i915)) @@ -110,7 +111,6 @@ intel_dsb_get(struct intel_crtc *crtc) if (dsb->refcount++ != 0) return dsb; - dsb->id = DSB1; wakeref = intel_runtime_pm_get(&i915->runtime_pm); obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); @@ -123,22 +123,29 @@ intel_dsb_get(struct intel_crtc *crtc) if (IS_ERR(vma)) { DRM_ERROR("Vma creation failed\n"); i915_gem_object_put(obj); - dsb->refcount--; goto err; } - dsb->cmd_buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC); - if (IS_ERR(dsb->cmd_buf)) { + buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC); + if (IS_ERR(buf)) { DRM_ERROR("Command buffer creation failed\n"); - i915_vma_unpin_and_release(&vma, 0); - dsb->cmd_buf = NULL; - dsb->refcount--; goto err; } + + dsb->id = DSB1; dsb->vma = vma; + dsb->cmd_buf = buf; err: + /* + * Set cmd_buf to NULL so the writes pass-through, but leave the + * dangling refcount to be removed later by the corresponding + * intel_dsb_put(): the important error message will already be + * logged above. + */ + dsb->cmd_buf = NULL; intel_runtime_pm_put(&i915->runtime_pm, wakeref); + return dsb; } -- cgit v1.2.3 From d147483884ed08ee6bb618ef610ee0329a27fda7 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 18 Nov 2019 08:44:12 -0800 Subject: drm/i915/ehl: Update voltage level checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bspec was recently updated with new cdclk -> voltage level tables to accommodate the new 324/326.4 cdclk values. Bspec: 21809 Fixes: 63c9dae71dc5 ("drm/i915/ehl: Add voltage level requirement table") Cc: José Roberto de Souza Cc: Vivek Kasireddy Cc: Bob Paauwe Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191118164412.26216-1-matthew.d.roper@intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_cdclk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 8b702317557e..7d1ab1e5b7c3 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1273,7 +1273,9 @@ static u8 icl_calc_voltage_level(int cdclk) static u8 ehl_calc_voltage_level(int cdclk) { - if (cdclk > 312000) + if (cdclk > 326400) + return 3; + else if (cdclk > 312000) return 2; else if (cdclk > 180000) return 1; -- cgit v1.2.3 From b6422694c5853f7a4faf00431c9d7b5368138152 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Nov 2019 18:49:33 +0000 Subject: drm/i915/gt: Only wait for register chipset flush if active Only serialise with the chipset using an mmio if the chipset is currently active. We expect that any writes into the chipset range will simply be forgotten until it wakes up. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191118184943.2593048-8-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index b5a9b87e4ec9..c4fd8d65b8a3 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -304,7 +304,7 @@ void intel_gt_flush_ggtt_writes(struct intel_gt *gt) intel_gt_chipset_flush(gt); - with_intel_runtime_pm(uncore->rpm, wakeref) { + with_intel_runtime_pm_if_in_use(uncore->rpm, wakeref) { unsigned long flags; spin_lock_irqsave(&uncore->lock, flags); -- cgit v1.2.3 From a266bf42006004306dd48a9082c35dfbff153307 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Nov 2019 23:02:40 +0000 Subject: drm/i915/gt: Make intel_ring_unpin() safe for concurrent pint In order to avoid some nasty mutex inversions, commit 09c5ab384f6f ("drm/i915: Keep rings pinned while the context is active") allowed the intel_ring unpinning to be run concurrently with the next context pinning it. Thus each step in intel_ring_unpin() needed to be atomic and ordered in a nice onion with intel_ring_pin() so that the lifetimes overlapped and were always safe. Sadly, a few steps in intel_ring_unpin() were overlooked, such as closing the read/write pointers of the ring and discarding the intel_ring.vaddr, as these steps were not serialised with intel_ring_pin() and so could leave the ring in disarray. Fixes: 09c5ab384f6f ("drm/i915: Keep rings pinned while the context is active") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191118230254.2615942-6-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring.c b/drivers/gpu/drm/i915/gt/intel_ring.c index ece20504d240..374b28f13ca0 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring.c +++ b/drivers/gpu/drm/i915/gt/intel_ring.c @@ -57,9 +57,10 @@ int intel_ring_pin(struct intel_ring *ring) i915_vma_make_unshrinkable(vma); - GEM_BUG_ON(ring->vaddr); - ring->vaddr = addr; + /* Discard any unused bytes beyond that submitted to hw. */ + intel_ring_reset(ring, ring->emit); + ring->vaddr = addr; return 0; err_ring: @@ -85,20 +86,14 @@ void intel_ring_unpin(struct intel_ring *ring) if (!atomic_dec_and_test(&ring->pin_count)) return; - /* Discard any unused bytes beyond that submitted to hw. */ - intel_ring_reset(ring, ring->emit); - i915_vma_unset_ggtt_write(vma); if (i915_vma_is_map_and_fenceable(vma)) i915_vma_unpin_iomap(vma); else i915_gem_object_unpin_map(vma->obj); - GEM_BUG_ON(!ring->vaddr); - ring->vaddr = NULL; - - i915_vma_unpin(vma); i915_vma_make_purgeable(vma); + i915_vma_unpin(vma); } static struct i915_vma *create_ring_vma(struct i915_ggtt *ggtt, int size) -- cgit v1.2.3 From 42d70253c20920cf3affca4a6fc13cddbc71ee06 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Nov 2019 11:25:15 +0000 Subject: drm/i915/gem: Track ggtt writes from userspace on the bound vma When userspace writes into the GTT itself, it is supposed to call set-domain to let the kernel keep track and so manage the CPU/GPU caches. As we track writes on the individual i915_vma, we should also be sure to mark them as dirty. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191119112515.2766748-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index e2af63af67ad..9aebcf263191 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -149,9 +149,17 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); obj->read_domains |= I915_GEM_DOMAIN_GTT; if (write) { + struct i915_vma *vma; + obj->read_domains = I915_GEM_DOMAIN_GTT; obj->write_domain = I915_GEM_DOMAIN_GTT; obj->mm.dirty = true; + + spin_lock(&obj->vma.lock); + for_each_ggtt_vma(vma, obj) + if (i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND)) + i915_vma_set_ggtt_write(vma); + spin_unlock(&obj->vma.lock); } i915_gem_object_unpin_pages(obj); -- cgit v1.2.3 From 62d1c851466be84e725e1b7ca0662da5eea204e6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Nov 2019 10:09:18 +0000 Subject: drm/i915/gem: Merge GGTT vma flush into a single loop We only need the one loop to find the dirty vma flush them and their chipset. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191119100929.2628356-6-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_object.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index db103d3c8760..63bd3ff84f5e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -279,18 +279,12 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj, switch (obj->write_domain) { case I915_GEM_DOMAIN_GTT: - for_each_ggtt_vma(vma, obj) - intel_gt_flush_ggtt_writes(vma->vm->gt); - - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); - for_each_ggtt_vma(vma, obj) { - if (vma->iomap) - continue; - - i915_vma_unset_ggtt_write(vma); + if (i915_vma_unset_ggtt_write(vma)) + intel_gt_flush_ggtt_writes(vma->vm->gt); } + intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); break; case I915_GEM_DOMAIN_WC: -- cgit v1.2.3 From 530197795fac4e0cc0364a52c22791bfd03b625d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Nov 2019 10:09:20 +0000 Subject: drm/i915/gem: Protect the obj->vma.list during iteration Take the obj->vma.lock to prevent modifications to the list as we iterate, to avoid the dreaded NULL pointer. <1>[ 347.820823] BUG: kernel NULL pointer dereference, address: 0000000000000150 <1>[ 347.820856] #PF: supervisor read access in kernel mode <1>[ 347.820874] #PF: error_code(0x0000) - not-present page <6>[ 347.820892] PGD 0 P4D 0 <4>[ 347.820908] Oops: 0000 [#1] PREEMPT SMP NOPTI <4>[ 347.820926] CPU: 3 PID: 1303 Comm: gem_persistent_ Tainted: G U 5.4.0-rc7-CI-CI_DRM_7352+ #1 <4>[ 347.820956] Hardware name: /NUC6CAYB, BIOS AYAPLCEL.86A.0049.2018.0508.1356 05/08/2018 <4>[ 347.821132] RIP: 0010:i915_gem_object_flush_write_domain+0xd9/0x1d0 [i915] <4>[ 347.821157] Code: 0f 84 e9 00 00 00 48 8b 80 e0 fd ff ff f6 c4 40 75 11 e9 ed 00 00 00 48 8b 80 e0 fd ff ff f6 c4 40 74 26 48 8b 83 b0 00 00 00 <48> 8b b8 50 01 00 00 e8 fb 20 fb ff 48 8b 83 30 03 00 00 49 39 c4 <4>[ 347.821210] RSP: 0018:ffffc90000a1f8f8 EFLAGS: 00010202 <4>[ 347.821229] RAX: 0000000000000000 RBX: ffffc900008479a0 RCX: 0000000000000018 <4>[ 347.821252] RDX: 0000000000000000 RSI: 000000000000000d RDI: ffff888275a090b0 <4>[ 347.821274] RBP: ffff8882673c8040 R08: ffff88825991b8d0 R09: 0000000000000000 <4>[ 347.821297] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8882673c8280 <4>[ 347.821319] R13: ffff8882673c8368 R14: 0000000000000000 R15: ffff888266a54000 <4>[ 347.821343] FS: 00007f75865f4240(0000) GS:ffff888277b80000(0000) knlGS:0000000000000000 <4>[ 347.821368] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 347.821389] CR2: 0000000000000150 CR3: 000000025aee0000 CR4: 00000000003406e0 <4>[ 347.821411] Call Trace: <4>[ 347.821555] i915_gem_object_prepare_read+0xea/0x2a0 [i915] <4>[ 347.821706] intel_engine_cmd_parser+0x5ce/0xe90 [i915] <4>[ 347.821834] ? __i915_sw_fence_complete+0x1a0/0x250 [i915] <4>[ 347.821990] i915_gem_do_execbuffer+0xb4c/0x2550 [i915] Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191119100929.2628356-8-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_object.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 63bd3ff84f5e..458945e1823e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -279,10 +279,12 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj, switch (obj->write_domain) { case I915_GEM_DOMAIN_GTT: + spin_lock(&obj->vma.lock); for_each_ggtt_vma(vma, obj) { if (i915_vma_unset_ggtt_write(vma)) intel_gt_flush_ggtt_writes(vma->vm->gt); } + spin_unlock(&obj->vma.lock); intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); break; -- cgit v1.2.3 From 6d73af2767bb4855a3761a602c6cdde62640a185 Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Tue, 19 Nov 2019 12:50:04 +0530 Subject: drm/i915/dsi: Do not read the transcoder register. As per the Bspec, port mapping is fixed for mipi dsi. v2: Reuse the existing function (Jani) Signed-off-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191119072004.4093-1-vandita.kulkarni@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1558aefc2fd9..a7e55c9dc40e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10577,16 +10577,21 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; struct intel_shared_dpll *pll; enum port port; u32 tmp; - tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder)); - - if (INTEL_GEN(dev_priv) >= 12) - port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); - else - port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); + if (transcoder_is_dsi(cpu_transcoder)) { + port = (cpu_transcoder == TRANSCODER_DSI_A) ? + PORT_A : PORT_B; + } else { + tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); + if (INTEL_GEN(dev_priv) >= 12) + port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); + else + port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); + } if (INTEL_GEN(dev_priv) >= 11) icelake_get_ddi_pll(dev_priv, port, pipe_config); -- cgit v1.2.3 From 362bfb995b78394aefe61f7cc0511ef7c50bb11e Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 18 Nov 2019 10:02:19 -0800 Subject: drm/i915/tgl: Add DKL PHY vswing table for HDMI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bspec initially provided a single DKL PHY vswing table for both HDMI and DP, but was recently updated to include an independent table for HDMI. Bspec: 49292 Fixes: 978c3e539be2 ("drm/i915/tgl: Add dkl phy programming sequences") Cc: Clinton A Taylor Cc: Lucas De Marchi Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191118180219.9309-1-matthew.d.roper@intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 8f817de34460..a976606d21c7 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -593,7 +593,7 @@ struct tgl_dkl_phy_ddi_buf_trans { u32 dkl_de_emphasis_control; }; -static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_ddi_translations[] = { +static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_dp_ddi_trans[] = { /* VS pre-emp Non-trans mV Pre-emph dB */ { 0x7, 0x0, 0x00 }, /* 0 0 400mV 0 dB */ { 0x5, 0x0, 0x03 }, /* 0 1 400mV 3.5 dB */ @@ -607,6 +607,20 @@ static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_ddi_translations[] = { { 0x0, 0x0, 0x00 }, /* 3 0 1200mV 0 dB HDMI default */ }; +static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_hdmi_ddi_trans[] = { + /* HDMI Preset VS Pre-emph */ + { 0x7, 0x0, 0x0 }, /* 1 400mV 0dB */ + { 0x6, 0x0, 0x0 }, /* 2 500mV 0dB */ + { 0x4, 0x0, 0x0 }, /* 3 650mV 0dB */ + { 0x2, 0x0, 0x0 }, /* 4 800mV 0dB */ + { 0x0, 0x0, 0x0 }, /* 5 1000mV 0dB */ + { 0x0, 0x0, 0x5 }, /* 6 Full -1.5 dB */ + { 0x0, 0x0, 0x6 }, /* 7 Full -1.8 dB */ + { 0x0, 0x0, 0x7 }, /* 8 Full -2 dB */ + { 0x0, 0x0, 0x8 }, /* 9 Full -2.5 dB */ + { 0x0, 0x0, 0xA }, /* 10 Full -3 dB */ +}; + static const struct ddi_buf_trans * bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) { @@ -897,7 +911,7 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por icl_get_combo_buf_trans(dev_priv, INTEL_OUTPUT_HDMI, 0, &n_entries); else - n_entries = ARRAY_SIZE(tgl_dkl_phy_ddi_translations); + n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans); default_entry = n_entries - 1; } else if (INTEL_GEN(dev_priv) == 11) { if (intel_phy_is_combo(dev_priv, phy)) @@ -2358,7 +2372,7 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) icl_get_combo_buf_trans(dev_priv, encoder->type, intel_dp->link_rate, &n_entries); else - n_entries = ARRAY_SIZE(tgl_dkl_phy_ddi_translations); + n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans); } else if (INTEL_GEN(dev_priv) == 11) { if (intel_phy_is_combo(dev_priv, phy)) icl_get_combo_buf_trans(dev_priv, encoder->type, @@ -2810,8 +2824,13 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder, int link_clock, const struct tgl_dkl_phy_ddi_buf_trans *ddi_translations; u32 n_entries, val, ln, dpcnt_mask, dpcnt_val; - n_entries = ARRAY_SIZE(tgl_dkl_phy_ddi_translations); - ddi_translations = tgl_dkl_phy_ddi_translations; + if (encoder->type == INTEL_OUTPUT_HDMI) { + n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans); + ddi_translations = tgl_dkl_phy_hdmi_ddi_trans; + } else { + n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans); + ddi_translations = tgl_dkl_phy_dp_ddi_trans; + } if (level >= n_entries) level = n_entries - 1; -- cgit v1.2.3 From d18580b08b92ec4105eb0ede2d676e8b1f5a66c3 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 19 Nov 2019 15:01:54 +0000 Subject: drm/i915: make pool objects read-only For our current users we don't expect pool objects to be writable from the gpu. Signed-off-by: Matthew Auld Cc: Chris Wilson Fixes: 4f7af1948abc ("drm/i915: Support ro ppgtt mapped cmdparser shadow buffers") Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191119150154.18249-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_pool.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pool.c b/drivers/gpu/drm/i915/gt/intel_engine_pool.c index 3cdbd5f8b5be..397186818305 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pool.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pool.c @@ -104,6 +104,8 @@ node_create(struct intel_engine_pool *pool, size_t sz) return ERR_CAST(obj); } + i915_gem_object_set_readonly(obj); + node->obj = obj; return node; } -- cgit v1.2.3 From 1683d24c1470fb47716bd3ccd4e06547eb0ce0ed Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Nov 2019 16:25:58 +0000 Subject: drm/i915/gt: Move new timelines to the end of active_list When adding a new active timeline, place it at the end of the list. This allows for intel_gt_retire_requests() to pick up the newcomer more quickly and hopefully complete the retirement sooner. A miniscule optimisation. References: 7936a22dd466 ("drm/i915/gt: Wait for new requests in intel_gt_retire_requests()") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191119162559.3313003-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_timeline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 16a9e88d93de..0e277835aad0 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -342,7 +342,7 @@ void intel_timeline_enter(struct intel_timeline *tl) GEM_BUG_ON(!tl->active_count); /* overflow? */ spin_lock_irqsave(&timelines->lock, flags); - list_add(&tl->link, &timelines->active_list); + list_add_tail(&tl->link, &timelines->active_list); spin_unlock_irqrestore(&timelines->lock, flags); } -- cgit v1.2.3 From dcbebb11197cc7182fdbab61388939b8c323a08e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Nov 2019 16:25:59 +0000 Subject: drm/i915/gt: Schedule next retirement worker first As we may park the gt during request retirement, we may cancel the retirement worker only to then program the delayed worker once more. If we schedule the next delayed retirement worker first, if we then park the gt, the work will remain cancelled. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191119162559.3313003-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index a79e6efb31a2..25291e2af21e 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -110,9 +110,9 @@ static void retire_work_handler(struct work_struct *work) struct intel_gt *gt = container_of(work, typeof(*gt), requests.retire_work.work); - intel_gt_retire_requests(gt); schedule_delayed_work(>->requests.retire_work, round_jiffies_up_relative(HZ)); + intel_gt_retire_requests(gt); } void intel_gt_init_requests(struct intel_gt *gt) -- cgit v1.2.3 From 0cdfdf6fa9ee8babb72d3cb725c15a81dbc42bf1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Nov 2019 23:02:50 +0000 Subject: drm/i915/gt: Flush the requests after wedging on suspend Retire all requests if we resort to wedged the driver on suspend. They will now be idle, so we might as we free them before shutting down. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191118230254.2615942-16-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index e61f752a3cd5..470fbdc30e5a 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -257,6 +257,7 @@ static void wait_for_suspend(struct intel_gt *gt) * the gpu quiet. */ intel_gt_set_wedged(gt); + intel_gt_retire_requests(gt); } intel_gt_pm_wait_for_idle(gt); -- cgit v1.2.3 From 8ad305f1a29a8c06586aaef87443ce14936aac30 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Nov 2019 10:09:13 +0000 Subject: drm/i915/gem: Manually dump the debug trace on GEM_BUG_ON Since igt now defaults to not enabling ftrace-on-oops, we need to manually invoke GEM_TRACE_DUMP() to see the debug log prior to a GEM_BUG_ON panicking. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191119100929.2628356-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index 36a8c7673c4f..78a99d7c4e78 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -30,6 +30,8 @@ #include +#include "i915_utils.h" + struct drm_i915_private; #ifdef CONFIG_DRM_I915_DEBUG_GEM @@ -39,6 +41,7 @@ struct drm_i915_private; #define GEM_BUG_ON(condition) do { if (unlikely((condition))) { \ GEM_TRACE_ERR("%s:%d GEM_BUG_ON(%s)\n", \ __func__, __LINE__, __stringify(condition)); \ + GEM_TRACE_DUMP(); \ BUG(); \ } \ } while(0) -- cgit v1.2.3 From f4ba0707c825d60f1d0f5ce7bd3d875e68f3e204 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 18 Nov 2019 23:02:46 +0000 Subject: drm/i915: Wait until the intel_wakeref idle callback is complete When waiting for idle, serialise with any ongoing callback so that it will have completed before completing the wait. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191118230254.2615942-12-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_wakeref.c | 13 +++++++++++-- drivers/gpu/drm/i915/intel_wakeref.h | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c index 868cc78048d0..ad26d7f4ca3d 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.c +++ b/drivers/gpu/drm/i915/intel_wakeref.c @@ -109,8 +109,17 @@ void __intel_wakeref_init(struct intel_wakeref *wf, int intel_wakeref_wait_for_idle(struct intel_wakeref *wf) { - return wait_var_event_killable(&wf->wakeref, - !intel_wakeref_is_active(wf)); + int err; + + might_sleep(); + + err = wait_var_event_killable(&wf->wakeref, + !intel_wakeref_is_active(wf)); + if (err) + return err; + + intel_wakeref_unlock_wait(wf); + return 0; } static void wakeref_auto_timeout(struct timer_list *t) diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index 5f0c972a80fb..affe4de3746b 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -151,6 +151,21 @@ intel_wakeref_unlock(struct intel_wakeref *wf) mutex_unlock(&wf->mutex); } +/** + * intel_wakeref_unlock_wait: Wait until the active callback is complete + * @wf: the wakeref + * + * Waits for the active callback (under the @wf->mutex or another CPU) is + * complete. + */ +static inline void +intel_wakeref_unlock_wait(struct intel_wakeref *wf) +{ + mutex_lock(&wf->mutex); + mutex_unlock(&wf->mutex); + flush_work(&wf->work); +} + /** * intel_wakeref_is_active: Query whether the wakeref is currently held * @wf: the wakeref -- cgit v1.2.3 From ba446f746096f65e9ba80f80184441e708fba934 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 19 Nov 2019 15:47:23 +0000 Subject: drm/i915/selftests: Exercise rc6 w/a handling Reading from CTX_INFO upsets rc6, requiring us to detect and prevent possible rc6 context corruption. Poke at the bear! Signed-off-by: Chris Wilson Cc: Imre Deak Cc: Mika Kuoppala Reviewed-by: Andi Shyti Tested-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191119154723.3311814-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rc6.c | 4 + drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 18 +++ drivers/gpu/drm/i915/gt/selftest_rc6.c | 146 +++++++++++++++++++++ drivers/gpu/drm/i915/gt/selftest_rc6.h | 12 ++ .../gpu/drm/i915/selftests/i915_live_selftests.h | 2 + 5 files changed, 182 insertions(+) create mode 100644 drivers/gpu/drm/i915/gt/selftest_rc6.c create mode 100644 drivers/gpu/drm/i915/gt/selftest_rc6.h diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 977a617a196d..7a0bc6dde009 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -783,3 +783,7 @@ u64 intel_rc6_residency_us(struct intel_rc6 *rc6, i915_reg_t reg) { return DIV_ROUND_UP_ULL(intel_rc6_residency_ns(rc6, reg), 1000); } + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftest_rc6.c" +#endif diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c index d1752f15702a..5e563b877368 100644 --- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c @@ -6,6 +6,7 @@ */ #include "selftest_llc.h" +#include "selftest_rc6.h" static int live_gt_resume(void *arg) { @@ -58,3 +59,20 @@ int intel_gt_pm_live_selftests(struct drm_i915_private *i915) return intel_gt_live_subtests(tests, &i915->gt); } + +int intel_gt_pm_late_selftests(struct drm_i915_private *i915) +{ + static const struct i915_subtest tests[] = { + /* + * These tests may leave the system in an undesirable state. + * They are intended to be run last in CI and the system + * rebooted afterwards. + */ + SUBTEST(live_rc6_ctx_wa), + }; + + if (intel_gt_is_wedged(&i915->gt)) + return 0; + + return intel_gt_live_subtests(tests, &i915->gt); +} diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.c b/drivers/gpu/drm/i915/gt/selftest_rc6.c new file mode 100644 index 000000000000..67b7a6bc64f5 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.c @@ -0,0 +1,146 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2019 Intel Corporation + */ + +#include "intel_context.h" +#include "intel_engine_pm.h" +#include "intel_gt_requests.h" +#include "intel_ring.h" +#include "selftest_rc6.h" + +#include "selftests/i915_random.h" + +static const u32 *__live_rc6_ctx(struct intel_context *ce) +{ + struct i915_request *rq; + const u32 *result; + u32 cmd; + u32 *cs; + + rq = intel_context_create_request(ce); + if (IS_ERR(rq)) + return ERR_CAST(rq); + + cs = intel_ring_begin(rq, 4); + if (IS_ERR(cs)) { + i915_request_add(rq); + return cs; + } + + cmd = MI_STORE_REGISTER_MEM | MI_USE_GGTT; + if (INTEL_GEN(rq->i915) >= 8) + cmd++; + + *cs++ = cmd; + *cs++ = i915_mmio_reg_offset(GEN8_RC6_CTX_INFO); + *cs++ = ce->timeline->hwsp_offset + 8; + *cs++ = 0; + intel_ring_advance(rq, cs); + + result = rq->hwsp_seqno + 2; + i915_request_add(rq); + + return result; +} + +static struct intel_engine_cs ** +randomised_engines(struct intel_gt *gt, + struct rnd_state *prng, + unsigned int *count) +{ + struct intel_engine_cs *engine, **engines; + enum intel_engine_id id; + int n; + + n = 0; + for_each_engine(engine, gt, id) + n++; + if (!n) + return NULL; + + engines = kmalloc_array(n, sizeof(*engines), GFP_KERNEL); + if (!engines) + return NULL; + + n = 0; + for_each_engine(engine, gt, id) + engines[n++] = engine; + + i915_prandom_shuffle(engines, sizeof(*engines), n, prng); + + *count = n; + return engines; +} + +int live_rc6_ctx_wa(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_engine_cs **engines; + unsigned int n, count; + I915_RND_STATE(prng); + int err = 0; + + /* A read of CTX_INFO upsets rc6. Poke the bear! */ + if (INTEL_GEN(gt->i915) < 8) + return 0; + + engines = randomised_engines(gt, &prng, &count); + if (!engines) + return 0; + + for (n = 0; n < count; n++) { + struct intel_engine_cs *engine = engines[n]; + int pass; + + for (pass = 0; pass < 2; pass++) { + struct intel_context *ce; + unsigned int resets = + i915_reset_engine_count(>->i915->gpu_error, + engine); + const u32 *res; + + /* Use a sacrifical context */ + ce = intel_context_create(engine->kernel_context->gem_context, + engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + goto out; + } + + intel_engine_pm_get(engine); + res = __live_rc6_ctx(ce); + intel_engine_pm_put(engine); + intel_context_put(ce); + if (IS_ERR(res)) { + err = PTR_ERR(res); + goto out; + } + + if (intel_gt_wait_for_idle(gt, HZ / 5) == -ETIME) { + intel_gt_set_wedged(gt); + err = -ETIME; + goto out; + } + + intel_gt_pm_wait_for_idle(gt); + pr_debug("%s: CTX_INFO=%0x\n", + engine->name, READ_ONCE(*res)); + + if (resets != + i915_reset_engine_count(>->i915->gpu_error, + engine)) { + pr_err("%s: GPU reset required\n", + engine->name); + add_taint_for_CI(TAINT_WARN); + err = -EIO; + goto out; + } + } + } + +out: + kfree(engines); + return err; +} diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.h b/drivers/gpu/drm/i915/gt/selftest_rc6.h new file mode 100644 index 000000000000..f907e7b035ab --- /dev/null +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.h @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2019 Intel Corporation + */ + +#ifndef SELFTEST_RC6_H +#define SELFTEST_RC6_H + +int live_rc6_ctx_wa(void *arg); + +#endif /* SELFTEST_RC6_H */ diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index 11b40bc58e6d..c7c50aac8708 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@ -39,3 +39,5 @@ selftest(hangcheck, intel_hangcheck_live_selftests) selftest(execlists, intel_execlists_live_selftests) selftest(guc, intel_guc_live_selftest) selftest(perf, i915_perf_live_selftests) +/* Here be dragons: keep last to run last! */ +selftest(late_gt_pm, intel_gt_pm_late_selftests) -- cgit v1.2.3 From e668950149dedb873496a282eae3a8319713de76 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Nov 2019 09:33:01 +0000 Subject: drm/i915/selftests: Be explicit in ERR_PTR handling When setting up a full GGTT, we expect the next insert to fail with -ENOSPC. Simplify the use of ERR_PTR to not confuse either the reader or smatch. Reported-by: Dan Carpenter References: f40a7b7558ef ("drm/i915: Initial selftests for exercising eviction") Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191120093302.3723715-8-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/i915_gem_evict.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c index 5f133d177212..06ef88510209 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c @@ -198,8 +198,8 @@ static int igt_overcommit(void *arg) quirk_add(obj, &objects); vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); - if (!IS_ERR(vma) || PTR_ERR(vma) != -ENOSPC) { - pr_err("Failed to evict+insert, i915_gem_object_ggtt_pin returned err=%d\n", (int)PTR_ERR(vma)); + if (vma != ERR_PTR(-ENOSPC)) { + pr_err("Failed to evict+insert, i915_gem_object_ggtt_pin returned err=%d\n", (int)PTR_ERR_OR_ZERO(vma)); err = -EINVAL; goto cleanup; } -- cgit v1.2.3 From c53d13138da055646a197633c08b68969233e84b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Nov 2019 10:27:41 +0000 Subject: drm/i915/selftests: Take a ref to the request we wait upon i915_request_add() consumes the passed in reference to the i915_request, so if the selftest caller wishes to wait upon it afterwards, it needs to take a reference for itself. Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191120102741.3734346-1-chris@chris-wilson.co.uk --- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 39 +++++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 9a509c18b7c7..f1ce5f64b221 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -73,25 +73,34 @@ static int live_nop_switch(void *arg) } for_each_uabi_engine(engine, i915) { - struct i915_request *rq; + struct i915_request *rq = NULL; unsigned long end_time, prime; ktime_t times[2] = {}; times[0] = ktime_get_raw(); for (n = 0; n < nctx; n++) { - rq = igt_request_alloc(ctx[n], engine); - if (IS_ERR(rq)) { - err = PTR_ERR(rq); + struct i915_request *this; + + this = igt_request_alloc(ctx[n], engine); + if (IS_ERR(this)) { + err = PTR_ERR(this); goto out_file; } - i915_request_add(rq); + if (rq) { + i915_request_await_dma_fence(this, &rq->fence); + i915_request_put(rq); + } + rq = i915_request_get(this); + i915_request_add(this); } if (i915_request_wait(rq, 0, HZ / 5) < 0) { pr_err("Failed to populated %d contexts\n", nctx); intel_gt_set_wedged(&i915->gt); + i915_request_put(rq); err = -EIO; goto out_file; } + i915_request_put(rq); times[1] = ktime_get_raw(); @@ -106,13 +115,21 @@ static int live_nop_switch(void *arg) for_each_prime_number_from(prime, 2, 8192) { times[1] = ktime_get_raw(); + rq = NULL; for (n = 0; n < prime; n++) { - rq = igt_request_alloc(ctx[n % nctx], engine); - if (IS_ERR(rq)) { - err = PTR_ERR(rq); + struct i915_request *this; + + this = igt_request_alloc(ctx[n % nctx], engine); + if (IS_ERR(this)) { + err = PTR_ERR(this); goto out_file; } + if (rq) { /* Force submission order */ + i915_request_await_dma_fence(this, &rq->fence); + i915_request_put(rq); + } + /* * This space is left intentionally blank. * @@ -127,14 +144,18 @@ static int live_nop_switch(void *arg) * for latency. */ - i915_request_add(rq); + rq = i915_request_get(this); + i915_request_add(this); } + GEM_BUG_ON(!rq); if (i915_request_wait(rq, 0, HZ / 5) < 0) { pr_err("Switching between %ld contexts timed out\n", prime); intel_gt_set_wedged(&i915->gt); + i915_request_put(rq); break; } + i915_request_put(rq); times[1] = ktime_sub(ktime_get_raw(), times[1]); if (prime == 2) -- cgit v1.2.3 From 021ba10055697adb8b5e3e91852f290234597a75 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:21 +0200 Subject: drm/i915: Change intel_encoders_() calling convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just pass the atomic state and the crtc to intel_encoders_enable() & co. Make life simpler when you don't have to think which state (old vs. new) you have to pass in. Also constify the states while at it. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 101 ++++++++++++++------------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a7e55c9dc40e..56fac063f025 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6311,11 +6311,12 @@ static void intel_encoders_update_complete(struct intel_atomic_state *state) } } -static void intel_encoders_pre_pll_enable(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_atomic_state *state) +static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_connector_state *conn_state; + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct drm_connector_state *conn_state; struct drm_connector *conn; int i; @@ -6331,11 +6332,12 @@ static void intel_encoders_pre_pll_enable(struct intel_crtc *crtc, } } -static void intel_encoders_pre_enable(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_atomic_state *state) +static void intel_encoders_pre_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_connector_state *conn_state; + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct drm_connector_state *conn_state; struct drm_connector *conn; int i; @@ -6351,11 +6353,12 @@ static void intel_encoders_pre_enable(struct intel_crtc *crtc, } } -static void intel_encoders_enable(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_atomic_state *state) +static void intel_encoders_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_connector_state *conn_state; + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct drm_connector_state *conn_state; struct drm_connector *conn; int i; @@ -6372,11 +6375,12 @@ static void intel_encoders_enable(struct intel_crtc *crtc, } } -static void intel_encoders_disable(struct intel_crtc *crtc, - struct intel_crtc_state *old_crtc_state, - struct intel_atomic_state *state) +static void intel_encoders_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_connector_state *old_conn_state; + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct drm_connector_state *old_conn_state; struct drm_connector *conn; int i; @@ -6393,11 +6397,12 @@ static void intel_encoders_disable(struct intel_crtc *crtc, } } -static void intel_encoders_post_disable(struct intel_crtc *crtc, - struct intel_crtc_state *old_crtc_state, - struct intel_atomic_state *state) +static void intel_encoders_post_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_connector_state *old_conn_state; + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct drm_connector_state *old_conn_state; struct drm_connector *conn; int i; @@ -6413,11 +6418,12 @@ static void intel_encoders_post_disable(struct intel_crtc *crtc, } } -static void intel_encoders_post_pll_disable(struct intel_crtc *crtc, - struct intel_crtc_state *old_crtc_state, - struct intel_atomic_state *state) +static void intel_encoders_post_pll_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_connector_state *old_conn_state; + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct drm_connector_state *old_conn_state; struct drm_connector *conn; int i; @@ -6433,11 +6439,12 @@ static void intel_encoders_post_pll_disable(struct intel_crtc *crtc, } } -static void intel_encoders_update_pipe(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_atomic_state *state) +static void intel_encoders_update_pipe(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_connector_state *conn_state; + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct drm_connector_state *conn_state; struct drm_connector *conn; int i; @@ -6504,7 +6511,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc->active = true; - intel_encoders_pre_enable(intel_crtc, pipe_config, state); + intel_encoders_pre_enable(state, intel_crtc); if (pipe_config->has_pch_encoder) { /* Note: FDI PLL enabling _must_ be done before we enable the @@ -6537,7 +6544,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); - intel_encoders_enable(intel_crtc, pipe_config, state); + intel_encoders_enable(state, intel_crtc); if (HAS_PCH_CPT(dev_priv)) cpt_verify_modeset(dev, intel_crtc->pipe); @@ -6621,12 +6628,12 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (WARN_ON(intel_crtc->active)) return; - intel_encoders_pre_pll_enable(intel_crtc, pipe_config, state); + intel_encoders_pre_pll_enable(state, intel_crtc); if (pipe_config->shared_dpll) intel_enable_shared_dpll(pipe_config); - intel_encoders_pre_enable(intel_crtc, pipe_config, state); + intel_encoders_pre_enable(state, intel_crtc); if (intel_crtc_has_dp_encoder(pipe_config)) intel_dp_set_m_n(pipe_config, M1_N1); @@ -6703,7 +6710,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); - intel_encoders_enable(intel_crtc, pipe_config, state); + intel_encoders_enable(state, intel_crtc); if (psl_clkgate_wa) { intel_wait_for_vblank(dev_priv, pipe); @@ -6751,7 +6758,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); - intel_encoders_disable(intel_crtc, old_crtc_state, state); + intel_encoders_disable(state, intel_crtc); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -6763,7 +6770,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, if (old_crtc_state->has_pch_encoder) ironlake_fdi_disable(crtc); - intel_encoders_post_disable(intel_crtc, old_crtc_state, state); + intel_encoders_post_disable(state, intel_crtc); if (old_crtc_state->has_pch_encoder) { ironlake_disable_pch_transcoder(dev_priv, pipe); @@ -6801,7 +6808,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; - intel_encoders_disable(intel_crtc, old_crtc_state, state); + intel_encoders_disable(state, intel_crtc); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -6823,9 +6830,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, else ironlake_pfit_disable(old_crtc_state); - intel_encoders_post_disable(intel_crtc, old_crtc_state, state); + intel_encoders_post_disable(state, intel_crtc); - intel_encoders_post_pll_disable(intel_crtc, old_crtc_state, state); + intel_encoders_post_pll_disable(state, intel_crtc); } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) @@ -7056,7 +7063,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_encoders_pre_pll_enable(intel_crtc, pipe_config, state); + intel_encoders_pre_pll_enable(state, intel_crtc); if (IS_CHERRYVIEW(dev_priv)) { chv_prepare_pll(intel_crtc, pipe_config); @@ -7066,7 +7073,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, vlv_enable_pll(intel_crtc, pipe_config); } - intel_encoders_pre_enable(intel_crtc, pipe_config, state); + intel_encoders_pre_enable(state, intel_crtc); i9xx_pfit_enable(pipe_config); @@ -7081,7 +7088,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); - intel_encoders_enable(intel_crtc, pipe_config, state); + intel_encoders_enable(state, intel_crtc); } static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state) @@ -7120,7 +7127,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, if (!IS_GEN(dev_priv, 2)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_encoders_pre_enable(intel_crtc, pipe_config, state); + intel_encoders_pre_enable(state, intel_crtc); i9xx_enable_pll(intel_crtc, pipe_config); @@ -7141,7 +7148,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); - intel_encoders_enable(intel_crtc, pipe_config, state); + intel_encoders_enable(state, intel_crtc); } static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) @@ -7175,7 +7182,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, if (IS_GEN(dev_priv, 2)) intel_wait_for_vblank(dev_priv, pipe); - intel_encoders_disable(intel_crtc, old_crtc_state, state); + intel_encoders_disable(state, intel_crtc); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -7184,7 +7191,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, i9xx_pfit_disable(old_crtc_state); - intel_encoders_post_disable(intel_crtc, old_crtc_state, state); + intel_encoders_post_disable(state, intel_crtc); if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DSI)) { if (IS_CHERRYVIEW(dev_priv)) @@ -7195,7 +7202,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, i9xx_disable_pll(old_crtc_state); } - intel_encoders_post_pll_disable(intel_crtc, old_crtc_state, state); + intel_encoders_post_pll_disable(state, intel_crtc); if (!IS_GEN(dev_priv, 2)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); @@ -14370,7 +14377,7 @@ static void intel_update_crtc(struct intel_crtc *crtc, intel_pre_plane_update(old_crtc_state, new_crtc_state); if (new_crtc_state->update_pipe) - intel_encoders_update_pipe(crtc, new_crtc_state, state); + intel_encoders_update_pipe(state, crtc); } if (new_crtc_state->update_pipe && !new_crtc_state->enable_fbc) -- cgit v1.2.3 From d18b6bb80a5ae5d482ca84619f158400ea323b3c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:22 +0200 Subject: drm/i915: Add intel_crtc_vblank_off() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have intel_crtc_vblank_on(). Add a counterpart so we don't have to inline the disable+assert all over. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 56fac063f025..61ba12c53702 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1843,6 +1843,12 @@ static void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) drm_crtc_vblank_on(&crtc->base); } +static void intel_crtc_vblank_off(struct intel_crtc *crtc) +{ + drm_crtc_vblank_off(&crtc->base); + assert_vblank_disabled(&crtc->base); +} + static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); @@ -6760,8 +6766,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_encoders_disable(state, intel_crtc); - drm_crtc_vblank_off(crtc); - assert_vblank_disabled(crtc); + intel_crtc_vblank_off(intel_crtc); intel_disable_pipe(old_crtc_state); @@ -6810,8 +6815,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_encoders_disable(state, intel_crtc); - drm_crtc_vblank_off(crtc); - assert_vblank_disabled(crtc); + intel_crtc_vblank_off(intel_crtc); /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) @@ -7184,8 +7188,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_encoders_disable(state, intel_crtc); - drm_crtc_vblank_off(crtc); - assert_vblank_disabled(crtc); + intel_crtc_vblank_off(intel_crtc); intel_disable_pipe(old_crtc_state); -- cgit v1.2.3 From 407b94058b3bceabda4d9033b66096e99ce0a2f7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:23 +0200 Subject: drm/i915: Move assert_vblank_disabled() into intel_crtc_vblank_on() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the assert_vblank_disabled() into intel_crtc_vblank_on() so that we don't have to inline it all over. This does mean we now assert_vblank_disabled() during readout as well but that is totally fine as it happens after drm_crtc_vblank_reset(). One can even argue it's what we want to do anyway to make sure the reset actually happened. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 61ba12c53702..548105659ffa 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1838,6 +1838,7 @@ static void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + assert_vblank_disabled(&crtc->base); drm_crtc_set_max_vblank_count(&crtc->base, intel_crtc_max_vblank_count(crtc_state)); drm_crtc_vblank_on(&crtc->base); @@ -6547,7 +6548,6 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, if (pipe_config->has_pch_encoder) ironlake_pch_enable(state, pipe_config); - assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); intel_encoders_enable(state, intel_crtc); @@ -6713,7 +6713,6 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (pipe_config->has_pch_encoder) lpt_pch_enable(state, pipe_config); - assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); intel_encoders_enable(state, intel_crtc); @@ -7089,7 +7088,6 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, dev_priv->display.initial_watermarks(state, pipe_config); intel_enable_pipe(pipe_config); - assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); intel_encoders_enable(state, intel_crtc); @@ -7149,7 +7147,6 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, intel_update_watermarks(intel_crtc); intel_enable_pipe(pipe_config); - assert_vblank_disabled(crtc); intel_crtc_vblank_on(pipe_config); intel_encoders_enable(state, intel_crtc); -- cgit v1.2.3 From 777bf6d71f7211a66050ae7ab7f4e9c0212a2f1c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:24 +0200 Subject: drm/i915: Move crtc_state to tighter scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_modeset_setup_hw_state() doesn't need the crtc_state at the top level scope. Move it to where it's needed. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 548105659ffa..671d3e06cbab 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17790,7 +17790,6 @@ intel_modeset_setup_hw_state(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx) { struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc_state *crtc_state; struct intel_encoder *encoder; struct intel_crtc *crtc; intel_wakeref_t wakeref; @@ -17823,7 +17822,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev, * waits, so we need vblank interrupts restored beforehand. */ for_each_intel_crtc(&dev_priv->drm, crtc) { - crtc_state = to_intel_crtc_state(crtc->base.state); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); drm_crtc_vblank_reset(&crtc->base); @@ -17837,7 +17837,9 @@ intel_modeset_setup_hw_state(struct drm_device *dev, intel_sanitize_encoder(encoder); for_each_intel_crtc(&dev_priv->drm, crtc) { - crtc_state = to_intel_crtc_state(crtc->base.state); + struct intel_crtc_state *crtc_state = + crtc_state = to_intel_crtc_state(crtc->base.state); + intel_sanitize_crtc(crtc, ctx); intel_dump_pipe_config(crtc_state, NULL, "[setup_hw_state]"); } @@ -17870,9 +17872,10 @@ intel_modeset_setup_hw_state(struct drm_device *dev, } for_each_intel_crtc(dev, crtc) { + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); u64 put_domains; - crtc_state = to_intel_crtc_state(crtc->base.state); put_domains = modeset_get_crtc_power_domains(crtc_state); if (WARN_ON(put_domains)) modeset_put_power_domains(dev_priv, put_domains); -- cgit v1.2.3 From 5b4f4e94df8e441e5fa4138048d6ac9cf51fb85a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:25 +0200 Subject: drm/i915: Pass intel_crtc to ironlake_fdi_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to intel_crtc from drm_crtc. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 671d3e06cbab..545049175e5e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5061,12 +5061,10 @@ static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc) udelay(100); } -static void ironlake_fdi_disable(struct drm_crtc *crtc) +static void ironlake_fdi_disable(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; i915_reg_t reg; u32 temp; @@ -6772,7 +6770,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, ironlake_pfit_disable(old_crtc_state); if (old_crtc_state->has_pch_encoder) - ironlake_fdi_disable(crtc); + ironlake_fdi_disable(intel_crtc); intel_encoders_post_disable(state, intel_crtc); -- cgit v1.2.3 From 7a8fdb1f272b9a3337b10c2d4d8bcca3538aa62c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:26 +0200 Subject: drm/i915: Change watermark hook calling convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just pass the atomic_state+crtc to the watermarks hooks. Eeasier time for the caller when it doesn't have to think what to pass. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 32 +++++++------- drivers/gpu/drm/i915/i915_drv.h | 6 +-- drivers/gpu/drm/i915/intel_pm.c | 63 ++++++++++++++++------------ 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 545049175e5e..775e1df4bf35 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6189,9 +6189,8 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, * we'll continue to update watermarks the old way, if flags tell * us to. */ - if (dev_priv->display.initial_watermarks != NULL) - dev_priv->display.initial_watermarks(intel_state, - pipe_config); + if (dev_priv->display.initial_watermarks) + dev_priv->display.initial_watermarks(intel_state, crtc); else if (pipe_config->update_wm_pre) intel_update_watermarks(crtc); } @@ -6539,8 +6538,8 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, /* update DSPCNTR to configure gamma for pipe bottom color */ intel_disable_primary_plane(pipe_config); - if (dev_priv->display.initial_watermarks != NULL) - dev_priv->display.initial_watermarks(state, pipe_config); + if (dev_priv->display.initial_watermarks) + dev_priv->display.initial_watermarks(state, intel_crtc); intel_enable_pipe(pipe_config); if (pipe_config->has_pch_encoder) @@ -6698,8 +6697,8 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (!transcoder_is_dsi(cpu_transcoder)) intel_ddi_enable_transcoder_func(pipe_config); - if (dev_priv->display.initial_watermarks != NULL) - dev_priv->display.initial_watermarks(state, pipe_config); + if (dev_priv->display.initial_watermarks) + dev_priv->display.initial_watermarks(state, intel_crtc); if (INTEL_GEN(dev_priv) >= 11) icl_pipe_mbus_enable(intel_crtc); @@ -7083,7 +7082,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, /* update DSPCNTR to configure gamma for pipe bottom color */ intel_disable_primary_plane(pipe_config); - dev_priv->display.initial_watermarks(state, pipe_config); + dev_priv->display.initial_watermarks(state, intel_crtc); intel_enable_pipe(pipe_config); intel_crtc_vblank_on(pipe_config); @@ -7138,9 +7137,8 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, /* update DSPCNTR to configure gamma for pipe bottom color */ intel_disable_primary_plane(pipe_config); - if (dev_priv->display.initial_watermarks != NULL) - dev_priv->display.initial_watermarks(state, - pipe_config); + if (dev_priv->display.initial_watermarks) + dev_priv->display.initial_watermarks(state, intel_crtc); else intel_update_watermarks(intel_crtc); intel_enable_pipe(pipe_config); @@ -14321,6 +14319,7 @@ static void commit_pipe_config(struct intel_atomic_state *state, struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(state->base.dev); bool modeset = needs_modeset(new_crtc_state); @@ -14344,8 +14343,7 @@ static void commit_pipe_config(struct intel_atomic_state *state, } if (dev_priv->display.atomic_update_watermarks) - dev_priv->display.atomic_update_watermarks(state, - new_crtc_state); + dev_priv->display.atomic_update_watermarks(state, crtc); } static void intel_update_crtc(struct intel_crtc *crtc, @@ -14449,8 +14447,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, if (!new_crtc_state->hw.active && !HAS_GMCH(dev_priv) && dev_priv->display.initial_watermarks) - dev_priv->display.initial_watermarks(state, - new_crtc_state); + dev_priv->display.initial_watermarks(state, crtc); } static void intel_trans_port_sync_modeset_disables(struct intel_atomic_state *state, @@ -14900,8 +14897,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) */ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (dev_priv->display.optimize_watermarks) - dev_priv->display.optimize_watermarks(state, - new_crtc_state); + dev_priv->display.optimize_watermarks(state, crtc); } for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { @@ -16856,7 +16852,7 @@ retry: /* Write calculated watermark values back */ for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) { crtc_state->wm.need_postvbl_update = true; - dev_priv->display.optimize_watermarks(intel_state, crtc_state); + dev_priv->display.optimize_watermarks(intel_state, crtc); to_intel_crtc_state(crtc->base.state)->wm = crtc_state->wm; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bbf4dfdfa8ba..9b37c0d657de 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -273,11 +273,11 @@ struct drm_i915_display_funcs { int (*compute_pipe_wm)(struct intel_crtc_state *crtc_state); int (*compute_intermediate_wm)(struct intel_crtc_state *crtc_state); void (*initial_watermarks)(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state); + struct intel_crtc *crtc); void (*atomic_update_watermarks)(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state); + struct intel_crtc *crtc); void (*optimize_watermarks)(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state); + struct intel_crtc *crtc); int (*compute_global_watermarks)(struct intel_atomic_state *state); void (*update_wm)(struct intel_crtc *crtc); int (*modeset_calc_cdclk)(struct intel_atomic_state *state); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4c6e70ed3d67..558bf2c42cb8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1528,10 +1528,11 @@ static void g4x_program_watermarks(struct drm_i915_private *dev_priv) } static void g4x_initial_watermarks(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); mutex_lock(&dev_priv->wm.wm_mutex); crtc->wm.active.g4x = crtc_state->wm.g4x.intermediate; @@ -1540,10 +1541,11 @@ static void g4x_initial_watermarks(struct intel_atomic_state *state, } static void g4x_optimize_watermarks(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); if (!crtc_state->wm.need_postvbl_update) return; @@ -1923,11 +1925,12 @@ static int vlv_compute_pipe_wm(struct intel_crtc_state *crtc_state) (((value) << DSPARB_ ## plane ## _SHIFT_VLV) & DSPARB_ ## plane ## _MASK_VLV) static void vlv_atomic_update_fifo(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_uncore *uncore = &dev_priv->uncore; + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); const struct vlv_fifo_state *fifo_state = &crtc_state->wm.vlv.fifo_state; int sprite0_start, sprite1_start, fifo_size; @@ -2147,10 +2150,11 @@ static void vlv_program_watermarks(struct drm_i915_private *dev_priv) } static void vlv_initial_watermarks(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); mutex_lock(&dev_priv->wm.wm_mutex); crtc->wm.active.vlv = crtc_state->wm.vlv.intermediate; @@ -2159,10 +2163,11 @@ static void vlv_initial_watermarks(struct intel_atomic_state *state, } static void vlv_optimize_watermarks(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); if (!crtc_state->wm.need_postvbl_update) return; @@ -5499,11 +5504,12 @@ skl_compute_wm(struct intel_atomic_state *state) } static void skl_atomic_update_crtc_wm(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(state->base.dev); - struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; enum pipe pipe = crtc->pipe; if ((state->wm_results.dirty_pipes & BIT(crtc->pipe)) == 0) @@ -5513,10 +5519,11 @@ static void skl_atomic_update_crtc_wm(struct intel_atomic_state *state, } static void skl_initial_wm(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct skl_ddb_values *results = &state->wm_results; if ((results->dirty_pipes & BIT(crtc->pipe)) == 0) @@ -5525,7 +5532,7 @@ static void skl_initial_wm(struct intel_atomic_state *state, mutex_lock(&dev_priv->wm.wm_mutex); if (crtc_state->uapi.active_changed) - skl_atomic_update_crtc_wm(state, crtc_state); + skl_atomic_update_crtc_wm(state, crtc); mutex_unlock(&dev_priv->wm.wm_mutex); } @@ -5581,10 +5588,11 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv) } static void ilk_initial_watermarks(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); mutex_lock(&dev_priv->wm.wm_mutex); crtc->wm.active.ilk = crtc_state->wm.ilk.intermediate; @@ -5593,10 +5601,11 @@ static void ilk_initial_watermarks(struct intel_atomic_state *state, } static void ilk_optimize_watermarks(struct intel_atomic_state *state, - struct intel_crtc_state *crtc_state) + struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); if (!crtc_state->wm.need_postvbl_update) return; -- cgit v1.2.3 From c684fb44c0ffc645adf471b26395e30582ad0ef5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:27 +0200 Subject: drm/i915: Pass dev_priv to cpt_verify_modeset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get rid of the last 'dev' usage in ironlake_crtc_enable() by passing dev_priv to cpt_verify_modeset(). Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 775e1df4bf35..8653311adbc4 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5474,9 +5474,9 @@ static void lpt_pch_enable(const struct intel_atomic_state *state, lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); } -static void cpt_verify_modeset(struct drm_device *dev, enum pipe pipe) +static void cpt_verify_modeset(struct drm_i915_private *dev_priv, + enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(dev); i915_reg_t dslreg = PIPEDSL(pipe); u32 temp; @@ -6550,7 +6550,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_enable(state, intel_crtc); if (HAS_PCH_CPT(dev_priv)) - cpt_verify_modeset(dev, intel_crtc->pipe); + cpt_verify_modeset(dev_priv, pipe); /* * Must wait for vblank to avoid spurious PCH FIFO underruns. -- cgit v1.2.3 From e44c84a14469d307b06af5bfc50f140040dc5765 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:28 +0200 Subject: drm/i915: s/intel_crtc/crtc/ in .crtc_enable() and .crtc_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get rid of the horrible aliasing drm_crtc and intel_crtc variables in the crtc enable/disable hooks. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 142 ++++++++++++--------------- 1 file changed, 65 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8653311adbc4..333489b88494 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6475,13 +6475,11 @@ static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_stat static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { - struct drm_crtc *crtc = pipe_config->uapi.crtc; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; - if (WARN_ON(intel_crtc->active)) + if (WARN_ON(crtc->active)) return; /* @@ -6513,9 +6511,9 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, ironlake_set_pipeconf(pipe_config); - intel_crtc->active = true; + crtc->active = true; - intel_encoders_pre_enable(state, intel_crtc); + intel_encoders_pre_enable(state, crtc); if (pipe_config->has_pch_encoder) { /* Note: FDI PLL enabling _must_ be done before we enable the @@ -6539,7 +6537,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_disable_primary_plane(pipe_config); if (dev_priv->display.initial_watermarks) - dev_priv->display.initial_watermarks(state, intel_crtc); + dev_priv->display.initial_watermarks(state, crtc); intel_enable_pipe(pipe_config); if (pipe_config->has_pch_encoder) @@ -6547,7 +6545,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc_vblank_on(pipe_config); - intel_encoders_enable(state, intel_crtc); + intel_encoders_enable(state, crtc); if (HAS_PCH_CPT(dev_priv)) cpt_verify_modeset(dev_priv, pipe); @@ -6621,22 +6619,21 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { - struct drm_crtc *crtc = pipe_config->uapi.crtc; - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe, hsw_workaround_pipe; + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe, hsw_workaround_pipe; enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; bool psl_clkgate_wa; - if (WARN_ON(intel_crtc->active)) + if (WARN_ON(crtc->active)) return; - intel_encoders_pre_pll_enable(state, intel_crtc); + intel_encoders_pre_pll_enable(state, crtc); if (pipe_config->shared_dpll) intel_enable_shared_dpll(pipe_config); - intel_encoders_pre_enable(state, intel_crtc); + intel_encoders_pre_enable(state, crtc); if (intel_crtc_has_dp_encoder(pipe_config)) intel_dp_set_m_n(pipe_config, M1_N1); @@ -6668,7 +6665,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) bdw_set_pipemisc(pipe_config); - intel_crtc->active = true; + crtc->active = true; /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */ psl_clkgate_wa = (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && @@ -6692,16 +6689,16 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_disable_primary_plane(pipe_config); if (INTEL_GEN(dev_priv) >= 11) - icl_set_pipe_chicken(intel_crtc); + icl_set_pipe_chicken(crtc); if (!transcoder_is_dsi(cpu_transcoder)) intel_ddi_enable_transcoder_func(pipe_config); if (dev_priv->display.initial_watermarks) - dev_priv->display.initial_watermarks(state, intel_crtc); + dev_priv->display.initial_watermarks(state, crtc); if (INTEL_GEN(dev_priv) >= 11) - icl_pipe_mbus_enable(intel_crtc); + icl_pipe_mbus_enable(crtc); /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) @@ -6712,7 +6709,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc_vblank_on(pipe_config); - intel_encoders_enable(state, intel_crtc); + intel_encoders_enable(state, crtc); if (psl_clkgate_wa) { intel_wait_for_vblank(dev_priv, pipe); @@ -6746,11 +6743,9 @@ static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state) static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, struct intel_atomic_state *state) { - struct drm_crtc *crtc = old_crtc_state->uapi.crtc; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; /* * Sometimes spurious CPU pipe underruns happen when the @@ -6760,18 +6755,18 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); - intel_encoders_disable(state, intel_crtc); + intel_encoders_disable(state, crtc); - intel_crtc_vblank_off(intel_crtc); + intel_crtc_vblank_off(crtc); intel_disable_pipe(old_crtc_state); ironlake_pfit_disable(old_crtc_state); if (old_crtc_state->has_pch_encoder) - ironlake_fdi_disable(intel_crtc); + ironlake_fdi_disable(crtc); - intel_encoders_post_disable(state, intel_crtc); + intel_encoders_post_disable(state, crtc); if (old_crtc_state->has_pch_encoder) { ironlake_disable_pch_transcoder(dev_priv, pipe); @@ -6794,7 +6789,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, I915_WRITE(PCH_DPLL_SEL, temp); } - ironlake_fdi_pll_disable(intel_crtc); + ironlake_fdi_pll_disable(crtc); } intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); @@ -6804,14 +6799,13 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, struct intel_atomic_state *state) { - struct drm_crtc *crtc = old_crtc_state->uapi.crtc; - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; - intel_encoders_disable(state, intel_crtc); + intel_encoders_disable(state, crtc); - intel_crtc_vblank_off(intel_crtc); + intel_crtc_vblank_off(crtc); /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) @@ -6826,13 +6820,13 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_dsc_disable(old_crtc_state); if (INTEL_GEN(dev_priv) >= 9) - skylake_scaler_disable(intel_crtc); + skylake_scaler_disable(crtc); else ironlake_pfit_disable(old_crtc_state); - intel_encoders_post_disable(state, intel_crtc); + intel_encoders_post_disable(state, crtc); - intel_encoders_post_pll_disable(state, intel_crtc); + intel_encoders_post_pll_disable(state, crtc); } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) @@ -7037,13 +7031,11 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv, static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { - struct drm_crtc *crtc = pipe_config->uapi.crtc; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; - if (WARN_ON(intel_crtc->active)) + if (WARN_ON(crtc->active)) return; if (intel_crtc_has_dp_encoder(pipe_config)) @@ -7059,21 +7051,21 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, i9xx_set_pipeconf(pipe_config); - intel_crtc->active = true; + crtc->active = true; intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_encoders_pre_pll_enable(state, intel_crtc); + intel_encoders_pre_pll_enable(state, crtc); if (IS_CHERRYVIEW(dev_priv)) { - chv_prepare_pll(intel_crtc, pipe_config); - chv_enable_pll(intel_crtc, pipe_config); + chv_prepare_pll(crtc, pipe_config); + chv_enable_pll(crtc, pipe_config); } else { - vlv_prepare_pll(intel_crtc, pipe_config); - vlv_enable_pll(intel_crtc, pipe_config); + vlv_prepare_pll(crtc, pipe_config); + vlv_enable_pll(crtc, pipe_config); } - intel_encoders_pre_enable(state, intel_crtc); + intel_encoders_pre_enable(state, crtc); i9xx_pfit_enable(pipe_config); @@ -7082,12 +7074,12 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, /* update DSPCNTR to configure gamma for pipe bottom color */ intel_disable_primary_plane(pipe_config); - dev_priv->display.initial_watermarks(state, intel_crtc); + dev_priv->display.initial_watermarks(state, crtc); intel_enable_pipe(pipe_config); intel_crtc_vblank_on(pipe_config); - intel_encoders_enable(state, intel_crtc); + intel_encoders_enable(state, crtc); } static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state) @@ -7102,13 +7094,11 @@ static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state) static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, struct intel_atomic_state *state) { - struct drm_crtc *crtc = pipe_config->uapi.crtc; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; - if (WARN_ON(intel_crtc->active)) + if (WARN_ON(crtc->active)) return; i9xx_set_pll_dividers(pipe_config); @@ -7121,14 +7111,14 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, i9xx_set_pipeconf(pipe_config); - intel_crtc->active = true; + crtc->active = true; if (!IS_GEN(dev_priv, 2)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_encoders_pre_enable(state, intel_crtc); + intel_encoders_pre_enable(state, crtc); - i9xx_enable_pll(intel_crtc, pipe_config); + i9xx_enable_pll(crtc, pipe_config); i9xx_pfit_enable(pipe_config); @@ -7138,14 +7128,14 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, intel_disable_primary_plane(pipe_config); if (dev_priv->display.initial_watermarks) - dev_priv->display.initial_watermarks(state, intel_crtc); + dev_priv->display.initial_watermarks(state, crtc); else - intel_update_watermarks(intel_crtc); + intel_update_watermarks(crtc); intel_enable_pipe(pipe_config); intel_crtc_vblank_on(pipe_config); - intel_encoders_enable(state, intel_crtc); + intel_encoders_enable(state, crtc); } static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) @@ -7166,11 +7156,9 @@ static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, struct intel_atomic_state *state) { - struct drm_crtc *crtc = old_crtc_state->uapi.crtc; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; /* * On gen2 planes are double buffered but the pipe isn't, so we must @@ -7179,15 +7167,15 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, if (IS_GEN(dev_priv, 2)) intel_wait_for_vblank(dev_priv, pipe); - intel_encoders_disable(state, intel_crtc); + intel_encoders_disable(state, crtc); - intel_crtc_vblank_off(intel_crtc); + intel_crtc_vblank_off(crtc); intel_disable_pipe(old_crtc_state); i9xx_pfit_disable(old_crtc_state); - intel_encoders_post_disable(state, intel_crtc); + intel_encoders_post_disable(state, crtc); if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DSI)) { if (IS_CHERRYVIEW(dev_priv)) @@ -7198,13 +7186,13 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, i9xx_disable_pll(old_crtc_state); } - intel_encoders_post_pll_disable(state, intel_crtc); + intel_encoders_post_pll_disable(state, crtc); if (!IS_GEN(dev_priv, 2)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); if (!dev_priv->display.initial_watermarks) - intel_update_watermarks(intel_crtc); + intel_update_watermarks(crtc); /* clock the pipe down to 640x480@60 to potentially save power */ if (IS_I830(dev_priv)) -- cgit v1.2.3 From 502d871459d25e52358ddbafbc8cf9125fb12e1a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:29 +0200 Subject: drm/i915: s/pipe_config/new_crtc_state/ in .crtc_enable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename pipe_config to new_crtc_state in the .crtc_enable() hooks. The 'pipe_config' name is a zombie that we need to finally put down. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 173 +++++++++++++-------------- 1 file changed, 85 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 333489b88494..4f38e063d02f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6472,10 +6472,10 @@ static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_stat plane->disable_plane(plane, crtc_state); } -static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, +static void ironlake_crtc_enable(struct intel_crtc_state *new_crtc_state, struct intel_atomic_state *state) { - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -6495,55 +6495,54 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); - if (pipe_config->has_pch_encoder) - intel_prepare_shared_dpll(pipe_config); + if (new_crtc_state->has_pch_encoder) + intel_prepare_shared_dpll(new_crtc_state); - if (intel_crtc_has_dp_encoder(pipe_config)) - intel_dp_set_m_n(pipe_config, M1_N1); + if (intel_crtc_has_dp_encoder(new_crtc_state)) + intel_dp_set_m_n(new_crtc_state, M1_N1); - intel_set_pipe_timings(pipe_config); - intel_set_pipe_src_size(pipe_config); + intel_set_pipe_timings(new_crtc_state); + intel_set_pipe_src_size(new_crtc_state); - if (pipe_config->has_pch_encoder) { - intel_cpu_transcoder_set_m_n(pipe_config, - &pipe_config->fdi_m_n, NULL); - } + if (new_crtc_state->has_pch_encoder) + intel_cpu_transcoder_set_m_n(new_crtc_state, + &new_crtc_state->fdi_m_n, NULL); - ironlake_set_pipeconf(pipe_config); + ironlake_set_pipeconf(new_crtc_state); crtc->active = true; intel_encoders_pre_enable(state, crtc); - if (pipe_config->has_pch_encoder) { + if (new_crtc_state->has_pch_encoder) { /* Note: FDI PLL enabling _must_ be done before we enable the * cpu pipes, hence this is separate from all the other fdi/pch * enabling. */ - ironlake_fdi_pll_enable(pipe_config); + ironlake_fdi_pll_enable(new_crtc_state); } else { assert_fdi_tx_disabled(dev_priv, pipe); assert_fdi_rx_disabled(dev_priv, pipe); } - ironlake_pfit_enable(pipe_config); + ironlake_pfit_enable(new_crtc_state); /* * On ILK+ LUT must be loaded before the pipe is running but with * clocks enabled */ - intel_color_load_luts(pipe_config); - intel_color_commit(pipe_config); + intel_color_load_luts(new_crtc_state); + intel_color_commit(new_crtc_state); /* update DSPCNTR to configure gamma for pipe bottom color */ - intel_disable_primary_plane(pipe_config); + intel_disable_primary_plane(new_crtc_state); if (dev_priv->display.initial_watermarks) dev_priv->display.initial_watermarks(state, crtc); - intel_enable_pipe(pipe_config); + intel_enable_pipe(new_crtc_state); - if (pipe_config->has_pch_encoder) - ironlake_pch_enable(state, pipe_config); + if (new_crtc_state->has_pch_encoder) + ironlake_pch_enable(state, new_crtc_state); - intel_crtc_vblank_on(pipe_config); + intel_crtc_vblank_on(new_crtc_state); intel_encoders_enable(state, crtc); @@ -6556,7 +6555,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, * some interlaced HDMI modes. Let's do the double wait always * in case there are more corner cases we don't know about. */ - if (pipe_config->has_pch_encoder) { + if (new_crtc_state->has_pch_encoder) { intel_wait_for_vblank(dev_priv, pipe); intel_wait_for_vblank(dev_priv, pipe); } @@ -6616,13 +6615,13 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) I915_WRITE(reg, val); } -static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, +static void haswell_crtc_enable(struct intel_crtc_state *new_crtc_state, struct intel_atomic_state *state) { - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe, hsw_workaround_pipe; - enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; + enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder; bool psl_clkgate_wa; if (WARN_ON(crtc->active)) @@ -6630,69 +6629,67 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_pre_pll_enable(state, crtc); - if (pipe_config->shared_dpll) - intel_enable_shared_dpll(pipe_config); + if (new_crtc_state->shared_dpll) + intel_enable_shared_dpll(new_crtc_state); intel_encoders_pre_enable(state, crtc); - if (intel_crtc_has_dp_encoder(pipe_config)) - intel_dp_set_m_n(pipe_config, M1_N1); + if (intel_crtc_has_dp_encoder(new_crtc_state)) + intel_dp_set_m_n(new_crtc_state, M1_N1); if (!transcoder_is_dsi(cpu_transcoder)) - intel_set_pipe_timings(pipe_config); + intel_set_pipe_timings(new_crtc_state); if (INTEL_GEN(dev_priv) >= 11) - icl_enable_trans_port_sync(pipe_config); + icl_enable_trans_port_sync(new_crtc_state); - intel_set_pipe_src_size(pipe_config); + intel_set_pipe_src_size(new_crtc_state); if (cpu_transcoder != TRANSCODER_EDP && - !transcoder_is_dsi(cpu_transcoder)) { + !transcoder_is_dsi(cpu_transcoder)) I915_WRITE(PIPE_MULT(cpu_transcoder), - pipe_config->pixel_multiplier - 1); - } + new_crtc_state->pixel_multiplier - 1); - if (pipe_config->has_pch_encoder) { - intel_cpu_transcoder_set_m_n(pipe_config, - &pipe_config->fdi_m_n, NULL); - } + if (new_crtc_state->has_pch_encoder) + intel_cpu_transcoder_set_m_n(new_crtc_state, + &new_crtc_state->fdi_m_n, NULL); if (!transcoder_is_dsi(cpu_transcoder)) { - hsw_set_frame_start_delay(pipe_config); - haswell_set_pipeconf(pipe_config); + hsw_set_frame_start_delay(new_crtc_state); + haswell_set_pipeconf(new_crtc_state); } if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) - bdw_set_pipemisc(pipe_config); + bdw_set_pipemisc(new_crtc_state); crtc->active = true; /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */ psl_clkgate_wa = (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && - pipe_config->pch_pfit.enabled; + new_crtc_state->pch_pfit.enabled; if (psl_clkgate_wa) glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, true); if (INTEL_GEN(dev_priv) >= 9) - skylake_pfit_enable(pipe_config); + skylake_pfit_enable(new_crtc_state); else - ironlake_pfit_enable(pipe_config); + ironlake_pfit_enable(new_crtc_state); /* * On ILK+ LUT must be loaded before the pipe is running but with * clocks enabled */ - intel_color_load_luts(pipe_config); - intel_color_commit(pipe_config); + intel_color_load_luts(new_crtc_state); + intel_color_commit(new_crtc_state); /* update DSPCNTR to configure gamma/csc for pipe bottom color */ if (INTEL_GEN(dev_priv) < 9) - intel_disable_primary_plane(pipe_config); + intel_disable_primary_plane(new_crtc_state); if (INTEL_GEN(dev_priv) >= 11) icl_set_pipe_chicken(crtc); if (!transcoder_is_dsi(cpu_transcoder)) - intel_ddi_enable_transcoder_func(pipe_config); + intel_ddi_enable_transcoder_func(new_crtc_state); if (dev_priv->display.initial_watermarks) dev_priv->display.initial_watermarks(state, crtc); @@ -6702,12 +6699,12 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) - intel_enable_pipe(pipe_config); + intel_enable_pipe(new_crtc_state); - if (pipe_config->has_pch_encoder) - lpt_pch_enable(state, pipe_config); + if (new_crtc_state->has_pch_encoder) + lpt_pch_enable(state, new_crtc_state); - intel_crtc_vblank_on(pipe_config); + intel_crtc_vblank_on(new_crtc_state); intel_encoders_enable(state, crtc); @@ -6718,7 +6715,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, /* If we change the relative order between pipe/planes enabling, we need * to change the workaround. */ - hsw_workaround_pipe = pipe_config->hsw_workaround_pipe; + hsw_workaround_pipe = new_crtc_state->hsw_workaround_pipe; if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) { intel_wait_for_vblank(dev_priv, hsw_workaround_pipe); intel_wait_for_vblank(dev_priv, hsw_workaround_pipe); @@ -7028,28 +7025,28 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv, intel_display_power_put_unchecked(dev_priv, domain); } -static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, +static void valleyview_crtc_enable(struct intel_crtc_state *new_crtc_state, struct intel_atomic_state *state) { - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; if (WARN_ON(crtc->active)) return; - if (intel_crtc_has_dp_encoder(pipe_config)) - intel_dp_set_m_n(pipe_config, M1_N1); + if (intel_crtc_has_dp_encoder(new_crtc_state)) + intel_dp_set_m_n(new_crtc_state, M1_N1); - intel_set_pipe_timings(pipe_config); - intel_set_pipe_src_size(pipe_config); + intel_set_pipe_timings(new_crtc_state); + intel_set_pipe_src_size(new_crtc_state); if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY); I915_WRITE(CHV_CANVAS(pipe), 0); } - i9xx_set_pipeconf(pipe_config); + i9xx_set_pipeconf(new_crtc_state); crtc->active = true; @@ -7058,26 +7055,26 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_pre_pll_enable(state, crtc); if (IS_CHERRYVIEW(dev_priv)) { - chv_prepare_pll(crtc, pipe_config); - chv_enable_pll(crtc, pipe_config); + chv_prepare_pll(crtc, new_crtc_state); + chv_enable_pll(crtc, new_crtc_state); } else { - vlv_prepare_pll(crtc, pipe_config); - vlv_enable_pll(crtc, pipe_config); + vlv_prepare_pll(crtc, new_crtc_state); + vlv_enable_pll(crtc, new_crtc_state); } intel_encoders_pre_enable(state, crtc); - i9xx_pfit_enable(pipe_config); + i9xx_pfit_enable(new_crtc_state); - intel_color_load_luts(pipe_config); - intel_color_commit(pipe_config); + intel_color_load_luts(new_crtc_state); + intel_color_commit(new_crtc_state); /* update DSPCNTR to configure gamma for pipe bottom color */ - intel_disable_primary_plane(pipe_config); + intel_disable_primary_plane(new_crtc_state); dev_priv->display.initial_watermarks(state, crtc); - intel_enable_pipe(pipe_config); + intel_enable_pipe(new_crtc_state); - intel_crtc_vblank_on(pipe_config); + intel_crtc_vblank_on(new_crtc_state); intel_encoders_enable(state, crtc); } @@ -7091,25 +7088,25 @@ static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state) I915_WRITE(FP1(crtc->pipe), crtc_state->dpll_hw_state.fp1); } -static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, +static void i9xx_crtc_enable(struct intel_crtc_state *new_crtc_state, struct intel_atomic_state *state) { - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; if (WARN_ON(crtc->active)) return; - i9xx_set_pll_dividers(pipe_config); + i9xx_set_pll_dividers(new_crtc_state); - if (intel_crtc_has_dp_encoder(pipe_config)) - intel_dp_set_m_n(pipe_config, M1_N1); + if (intel_crtc_has_dp_encoder(new_crtc_state)) + intel_dp_set_m_n(new_crtc_state, M1_N1); - intel_set_pipe_timings(pipe_config); - intel_set_pipe_src_size(pipe_config); + intel_set_pipe_timings(new_crtc_state); + intel_set_pipe_src_size(new_crtc_state); - i9xx_set_pipeconf(pipe_config); + i9xx_set_pipeconf(new_crtc_state); crtc->active = true; @@ -7118,22 +7115,22 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_pre_enable(state, crtc); - i9xx_enable_pll(crtc, pipe_config); + i9xx_enable_pll(crtc, new_crtc_state); - i9xx_pfit_enable(pipe_config); + i9xx_pfit_enable(new_crtc_state); - intel_color_load_luts(pipe_config); - intel_color_commit(pipe_config); + intel_color_load_luts(new_crtc_state); + intel_color_commit(new_crtc_state); /* update DSPCNTR to configure gamma for pipe bottom color */ - intel_disable_primary_plane(pipe_config); + intel_disable_primary_plane(new_crtc_state); if (dev_priv->display.initial_watermarks) dev_priv->display.initial_watermarks(state, crtc); else intel_update_watermarks(crtc); - intel_enable_pipe(pipe_config); + intel_enable_pipe(new_crtc_state); - intel_crtc_vblank_on(pipe_config); + intel_crtc_vblank_on(new_crtc_state); intel_encoders_enable(state, crtc); } -- cgit v1.2.3 From 7451a074bf2f263ed7c92f6d9d21aa9c2beef601 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 18 Nov 2019 18:44:30 +0200 Subject: drm/i915: Change .crtc_enable/disable() calling convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just pass the atomic state+crtc to the .crtc_enable() .crtc_disable(). Life is easier when you don't have to think whether to pass the old or the new crtc state. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191118164430.27265-11-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 58 ++++++++++++++++------------ drivers/gpu/drm/i915/i915_drv.h | 8 ++-- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4f38e063d02f..7d6d0393d73f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6472,10 +6472,11 @@ static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_stat plane->disable_plane(plane, crtc_state); } -static void ironlake_crtc_enable(struct intel_crtc_state *new_crtc_state, - struct intel_atomic_state *state) +static void ironlake_crtc_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -6615,10 +6616,11 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) I915_WRITE(reg, val); } -static void haswell_crtc_enable(struct intel_crtc_state *new_crtc_state, - struct intel_atomic_state *state) +static void haswell_crtc_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe, hsw_workaround_pipe; enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder; @@ -6737,10 +6739,11 @@ static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state) } } -static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, - struct intel_atomic_state *state) +static void ironlake_crtc_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -6793,10 +6796,11 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); } -static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, - struct intel_atomic_state *state) +static void haswell_crtc_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; @@ -7025,10 +7029,11 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv, intel_display_power_put_unchecked(dev_priv, domain); } -static void valleyview_crtc_enable(struct intel_crtc_state *new_crtc_state, - struct intel_atomic_state *state) +static void valleyview_crtc_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -7088,10 +7093,11 @@ static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state) I915_WRITE(FP1(crtc->pipe), crtc_state->dpll_hw_state.fp1); } -static void i9xx_crtc_enable(struct intel_crtc_state *new_crtc_state, - struct intel_atomic_state *state) +static void i9xx_crtc_enable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -7150,10 +7156,11 @@ static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) I915_WRITE(PFIT_CONTROL, 0); } -static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, - struct intel_atomic_state *state) +static void i9xx_crtc_disable(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; @@ -7239,7 +7246,8 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, WARN_ON(IS_ERR(temp_crtc_state) || ret); - dev_priv->display.crtc_disable(temp_crtc_state, to_intel_atomic_state(state)); + dev_priv->display.crtc_disable(to_intel_atomic_state(state), + intel_crtc); drm_atomic_state_put(state); @@ -14345,7 +14353,7 @@ static void intel_update_crtc(struct intel_crtc *crtc, if (modeset) { intel_crtc_update_active_timings(new_crtc_state); - dev_priv->display.crtc_enable(new_crtc_state, state); + dev_priv->display.crtc_enable(state, crtc); /* vblanks work again, re-enable pipe CRC. */ intel_crtc_enable_pipe_crc(crtc); @@ -14416,7 +14424,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, */ intel_crtc_disable_pipe_crc(crtc); - dev_priv->display.crtc_disable(old_crtc_state, state); + dev_priv->display.crtc_disable(state, crtc); crtc->active = false; intel_fbc_disable(crtc); intel_disable_shared_dpll(old_crtc_state); @@ -14531,7 +14539,7 @@ static void intel_crtc_enable_trans_port_sync(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(state->base.dev); intel_crtc_update_active_timings(new_crtc_state); - dev_priv->display.crtc_enable(new_crtc_state, state); + dev_priv->display.crtc_enable(state, crtc); intel_crtc_enable_pipe_crc(crtc); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9b37c0d657de..fdae5a919bc8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -290,10 +290,10 @@ struct drm_i915_display_funcs { struct intel_initial_plane_config *); int (*crtc_compute_clock)(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); - void (*crtc_enable)(struct intel_crtc_state *pipe_config, - struct intel_atomic_state *old_state); - void (*crtc_disable)(struct intel_crtc_state *old_crtc_state, - struct intel_atomic_state *old_state); + void (*crtc_enable)(struct intel_atomic_state *state, + struct intel_crtc *crtc); + void (*crtc_disable)(struct intel_atomic_state *state, + struct intel_crtc *crtc); void (*commit_modeset_enables)(struct intel_atomic_state *state); void (*commit_modeset_disables)(struct intel_atomic_state *state); void (*audio_codec_enable)(struct intel_encoder *encoder, -- cgit v1.2.3 From e7862f476e6f78ebf715d6090e922cd91b1a194c Mon Sep 17 00:00:00 2001 From: Stuart Summers Date: Tue, 19 Nov 2019 16:45:05 -0800 Subject: Skip MCHBAR queries when display is not available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platforms without display do not map the MCHBAR MMIO into the GFX device BAR. Skip this sequence when display is not available. Signed-off-by: Stuart Summers Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191120004505.149516-1-stuart.summers@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index fc8286809e62..aa1d9e25f934 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1052,7 +1052,7 @@ intel_get_dram_info(struct drm_i915_private *dev_priv) */ dram_info->is_16gb_dimm = !IS_GEN9_LP(dev_priv); - if (INTEL_GEN(dev_priv) < 9) + if (INTEL_GEN(dev_priv) < 9 || !HAS_DISPLAY(dev_priv)) return; if (IS_GEN9_LP(dev_priv)) -- cgit v1.2.3 From 8a126392b7d7b95cffbf164b0f85974df7d70852 Mon Sep 17 00:00:00 2001 From: Stuart Summers Date: Tue, 19 Nov 2019 17:10:16 -0800 Subject: drm/i915: Do not initialize display BW when display not available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When display is not available, finding the memory bandwidth available for display is not useful. Skip this sequence here. References: HSDES 1209978255 Signed-off-by: Stuart Summers Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191120011016.18049-1-stuart.summers@intel.com --- drivers/gpu/drm/i915/display/intel_bw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 3f6e29f61323..86e75e858008 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -264,6 +264,9 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv, void intel_bw_init_hw(struct drm_i915_private *dev_priv) { + if (!HAS_DISPLAY(dev_priv)) + return; + if (IS_GEN(dev_priv, 12)) icl_get_bw_info(dev_priv, &tgl_sa_info); else if (IS_GEN(dev_priv, 11)) -- cgit v1.2.3 From 07779a76ee1f93f930cf697b22be73d16e14f50c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Nov 2019 12:54:33 +0000 Subject: drm/i915: Mark up the calling context for intel_wakeref_put() Previously, we assumed we could use mutex_trylock() within an atomic context, falling back to a worker if contended. However, such trickery is illegal inside interrupt context, and so we need to always use a worker under such circumstances. As we normally are in process context, we can typically use a plain mutex, and only defer to a work when we know we are being called from an interrupt path. Fixes: 51fbd8de87dc ("drm/i915/pmu: Atomically acquire the gt_pm wakeref") References: a0855d24fc22d ("locking/mutex: Complain upon mutex API misuse in IRQ contexts") References: https://bugs.freedesktop.org/show_bug.cgi?id=111626 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191120125433.3767149-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 3 ++- drivers/gpu/drm/i915/gt/intel_engine_pm.h | 10 ++++++++++ drivers/gpu/drm/i915/gt/intel_gt_pm.c | 1 - drivers/gpu/drm/i915/gt/intel_gt_pm.h | 5 +++++ drivers/gpu/drm/i915/gt/intel_lrc.c | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- drivers/gpu/drm/i915/gt/selftest_engine_pm.c | 7 ++++--- drivers/gpu/drm/i915/i915_active.c | 5 +++-- drivers/gpu/drm/i915/i915_pmu.c | 6 +++--- drivers/gpu/drm/i915/intel_wakeref.c | 8 ++++---- drivers/gpu/drm/i915/intel_wakeref.h | 30 +++++++++++++++++++--------- 11 files changed, 54 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 3c0f490ff2c7..7269c87c1372 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -177,7 +177,8 @@ static int __engine_park(struct intel_wakeref *wf) engine->execlists.no_priolist = false; - intel_gt_pm_put(engine->gt); + /* While gt calls i915_vma_parked(), we have to break the lock cycle */ + intel_gt_pm_put_async(engine->gt); return 0; } diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.h b/drivers/gpu/drm/i915/gt/intel_engine_pm.h index 739c50fefcef..24e20344dc22 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.h @@ -31,6 +31,16 @@ static inline void intel_engine_pm_put(struct intel_engine_cs *engine) intel_wakeref_put(&engine->wakeref); } +static inline void intel_engine_pm_put_async(struct intel_engine_cs *engine) +{ + intel_wakeref_put_async(&engine->wakeref); +} + +static inline void intel_engine_pm_flush(struct intel_engine_cs *engine) +{ + intel_wakeref_unlock_wait(&engine->wakeref); +} + void intel_engine_init__pm(struct intel_engine_cs *engine); #endif /* INTEL_ENGINE_PM_H */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 470fbdc30e5a..f6b5169d623f 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -105,7 +105,6 @@ static int __gt_park(struct intel_wakeref *wf) static const struct intel_wakeref_ops wf_ops = { .get = __gt_unpark, .put = __gt_park, - .flags = INTEL_WAKEREF_PUT_ASYNC, }; void intel_gt_pm_init_early(struct intel_gt *gt) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index b3e17399be9b..990efc27a4e4 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -32,6 +32,11 @@ static inline void intel_gt_pm_put(struct intel_gt *gt) intel_wakeref_put(>->wakeref); } +static inline void intel_gt_pm_put_async(struct intel_gt *gt) +{ + intel_wakeref_put_async(>->wakeref); +} + static inline int intel_gt_pm_wait_for_idle(struct intel_gt *gt) { return intel_wakeref_wait_for_idle(>->wakeref); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 33ce258d484f..b65bc06855b0 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1172,7 +1172,7 @@ __execlists_schedule_out(struct i915_request *rq, intel_engine_context_out(engine); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); - intel_gt_pm_put(engine->gt); + intel_gt_pm_put_async(engine->gt); /* * If this is part of a virtual engine, its next request may diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index b7007cd78c6f..0388f9375366 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1125,7 +1125,7 @@ int intel_engine_reset(struct intel_engine_cs *engine, const char *msg) out: intel_engine_cancel_stop_cs(engine); reset_finish_engine(engine); - intel_engine_pm_put(engine); + intel_engine_pm_put_async(engine); return ret; } diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c index 20b9c83f43ad..cbf6b0735272 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c @@ -51,11 +51,12 @@ static int live_engine_pm(void *arg) pr_err("intel_engine_pm_get_if_awake(%s) failed under %s\n", engine->name, p->name); else - intel_engine_pm_put(engine); - intel_engine_pm_put(engine); + intel_engine_pm_put_async(engine); + intel_engine_pm_put_async(engine); p->critical_section_end(); - /* engine wakeref is sync (instant) */ + intel_engine_pm_flush(engine); + if (intel_engine_pm_is_awake(engine)) { pr_err("%s is still awake after flushing pm\n", engine->name); diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 5448f37c8102..dca15ace88f6 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -672,12 +672,13 @@ void i915_active_acquire_barrier(struct i915_active *ref) * populated by i915_request_add_active_barriers() to point to the * request that will eventually release them. */ - spin_lock_irqsave_nested(&ref->tree_lock, flags, SINGLE_DEPTH_NESTING); llist_for_each_safe(pos, next, take_preallocated_barriers(ref)) { struct active_node *node = barrier_from_ll(pos); struct intel_engine_cs *engine = barrier_to_engine(node); struct rb_node **p, *parent; + spin_lock_irqsave_nested(&ref->tree_lock, flags, + SINGLE_DEPTH_NESTING); parent = NULL; p = &ref->tree.rb_node; while (*p) { @@ -693,12 +694,12 @@ void i915_active_acquire_barrier(struct i915_active *ref) } rb_link_node(&node->node, parent, p); rb_insert_color(&node->node, &ref->tree); + spin_unlock_irqrestore(&ref->tree_lock, flags); GEM_BUG_ON(!intel_engine_pm_is_awake(engine)); llist_add(barrier_to_ll(node), &engine->barrier_tasks); intel_engine_pm_put(engine); } - spin_unlock_irqrestore(&ref->tree_lock, flags); } void i915_request_add_active_barriers(struct i915_request *rq) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 9b02be0ad4e6..95e824a78d4d 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -190,7 +190,7 @@ static u64 get_rc6(struct intel_gt *gt) val = 0; if (intel_gt_pm_get_if_awake(gt)) { val = __get_rc6(gt); - intel_gt_pm_put(gt); + intel_gt_pm_put_async(gt); } spin_lock_irqsave(&pmu->lock, flags); @@ -360,7 +360,7 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns) skip: if (unlikely(mmio_lock)) spin_unlock_irqrestore(mmio_lock, flags); - intel_engine_pm_put(engine); + intel_engine_pm_put_async(engine); } } @@ -398,7 +398,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns) if (stat) val = intel_get_cagf(rps, stat); - intel_gt_pm_put(gt); + intel_gt_pm_put_async(gt); } add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT], diff --git a/drivers/gpu/drm/i915/intel_wakeref.c b/drivers/gpu/drm/i915/intel_wakeref.c index ad26d7f4ca3d..59aa1b6f1827 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.c +++ b/drivers/gpu/drm/i915/intel_wakeref.c @@ -54,7 +54,8 @@ int __intel_wakeref_get_first(struct intel_wakeref *wf) static void ____intel_wakeref_put_last(struct intel_wakeref *wf) { - if (!atomic_dec_and_test(&wf->count)) + INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); + if (unlikely(!atomic_dec_and_test(&wf->count))) goto unlock; /* ops->put() must reschedule its own release on error/deferral */ @@ -67,13 +68,12 @@ unlock: mutex_unlock(&wf->mutex); } -void __intel_wakeref_put_last(struct intel_wakeref *wf) +void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags) { INTEL_WAKEREF_BUG_ON(work_pending(&wf->work)); /* Assume we are not in process context and so cannot sleep. */ - if (wf->ops->flags & INTEL_WAKEREF_PUT_ASYNC || - !mutex_trylock(&wf->mutex)) { + if (flags & INTEL_WAKEREF_PUT_ASYNC || !mutex_trylock(&wf->mutex)) { schedule_work(&wf->work); return; } diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index affe4de3746b..da6e8fd506e6 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -29,9 +30,6 @@ typedef depot_stack_handle_t intel_wakeref_t; struct intel_wakeref_ops { int (*get)(struct intel_wakeref *wf); int (*put)(struct intel_wakeref *wf); - - unsigned long flags; -#define INTEL_WAKEREF_PUT_ASYNC BIT(0) }; struct intel_wakeref { @@ -57,7 +55,7 @@ void __intel_wakeref_init(struct intel_wakeref *wf, } while (0) int __intel_wakeref_get_first(struct intel_wakeref *wf); -void __intel_wakeref_put_last(struct intel_wakeref *wf); +void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags); /** * intel_wakeref_get: Acquire the wakeref @@ -100,10 +98,9 @@ intel_wakeref_get_if_active(struct intel_wakeref *wf) } /** - * intel_wakeref_put: Release the wakeref - * @i915: the drm_i915_private device + * intel_wakeref_put_flags: Release the wakeref * @wf: the wakeref - * @fn: callback for releasing the wakeref, called only on final release. + * @flags: control flags * * Release our hold on the wakeref. When there are no more users, * the runtime pm wakeref will be released after the @fn callback is called @@ -116,11 +113,25 @@ intel_wakeref_get_if_active(struct intel_wakeref *wf) * code otherwise. */ static inline void -intel_wakeref_put(struct intel_wakeref *wf) +__intel_wakeref_put(struct intel_wakeref *wf, unsigned long flags) +#define INTEL_WAKEREF_PUT_ASYNC BIT(0) { INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); if (unlikely(!atomic_add_unless(&wf->count, -1, 1))) - __intel_wakeref_put_last(wf); + __intel_wakeref_put_last(wf, flags); +} + +static inline void +intel_wakeref_put(struct intel_wakeref *wf) +{ + might_sleep(); + __intel_wakeref_put(wf, 0); +} + +static inline void +intel_wakeref_put_async(struct intel_wakeref *wf) +{ + __intel_wakeref_put(wf, INTEL_WAKEREF_PUT_ASYNC); } /** @@ -185,6 +196,7 @@ intel_wakeref_is_active(const struct intel_wakeref *wf) static inline void __intel_wakeref_defer_park(struct intel_wakeref *wf) { + lockdep_assert_held(&wf->mutex); INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count)); atomic_set_release(&wf->count, 1); } -- cgit v1.2.3 From a6edbca74b305adc165e67065d7ee766006e6a48 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Nov 2019 16:55:13 +0000 Subject: drm/i915/gt: Close race between engine_park and intel_gt_retire_requests The general concept was that intel_timeline.active_count was locked by the intel_timeline.mutex. The exception was for power management, where the engine->kernel_context->timeline could be manipulated under the global wakeref.mutex. This was quite solid, as we always manipulated the timeline only while we held an engine wakeref. And then we started retiring requests outside of struct_mutex, only using the timelines.active_list and the timeline->mutex. There we started manipulating intel_timeline.active_count outside of an engine wakeref, and so introduced a race between __engine_park() and intel_gt_retire_requests(), a race that could result in the engine->kernel_context not being added to the active timelines and so losing requests, which caused us to keep the system permanently powered up [and unloadable]. The race would be easy to close if we could take the engine wakeref for the timeline before we retire -- except timelines are not bound to any engine and so we would need to keep all active engines awake. The alternative is to guard intel_timeline_enter/intel_timeline_exit for use outside of the timeline->mutex. Fixes: e5dadff4b093 ("drm/i915: Protect request retirement with timeline->mutex") Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191120165514.3955081-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 8 +++--- drivers/gpu/drm/i915/gt/intel_timeline.c | 34 ++++++++++++++++++++------ drivers/gpu/drm/i915/gt/intel_timeline_types.h | 2 +- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index 25291e2af21e..1a005da8c588 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -49,8 +49,8 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) continue; intel_timeline_get(tl); - GEM_BUG_ON(!tl->active_count); - tl->active_count++; /* pin the list element */ + GEM_BUG_ON(!atomic_read(&tl->active_count)); + atomic_inc(&tl->active_count); /* pin the list element */ spin_unlock_irqrestore(&timelines->lock, flags); if (timeout > 0) { @@ -71,14 +71,14 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) /* Resume iteration after dropping lock */ list_safe_reset_next(tl, tn, link); - if (!--tl->active_count) + if (atomic_dec_and_test(&tl->active_count)) list_del(&tl->link); mutex_unlock(&tl->mutex); /* Defer the final release to after the spinlock */ if (refcount_dec_and_test(&tl->kref.refcount)) { - GEM_BUG_ON(tl->active_count); + GEM_BUG_ON(atomic_read(&tl->active_count)); list_add(&tl->link, &free); } } diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 0e277835aad0..b35f12729983 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -334,15 +334,33 @@ void intel_timeline_enter(struct intel_timeline *tl) struct intel_gt_timelines *timelines = &tl->gt->timelines; unsigned long flags; + /* + * Pretend we are serialised by the timeline->mutex. + * + * While generally true, there are a few exceptions to the rule + * for the engine->kernel_context being used to manage power + * transitions. As the engine_park may be called from under any + * timeline, it uses the power mutex as a global serialisation + * lock to prevent any other request entering its timeline. + * + * The rule is generally tl->mutex, otherwise engine->wakeref.mutex. + * + * However, intel_gt_retire_request() does not know which engine + * it is retiring along and so cannot partake in the engine-pm + * barrier, and there we use the tl->active_count as a means to + * pin the timeline in the active_list while the locks are dropped. + * Ergo, as that is outside of the engine-pm barrier, we need to + * use atomic to manipulate tl->active_count. + */ lockdep_assert_held(&tl->mutex); - GEM_BUG_ON(!atomic_read(&tl->pin_count)); - if (tl->active_count++) + + if (atomic_add_unless(&tl->active_count, 1, 0)) return; - GEM_BUG_ON(!tl->active_count); /* overflow? */ spin_lock_irqsave(&timelines->lock, flags); - list_add_tail(&tl->link, &timelines->active_list); + if (!atomic_fetch_inc(&tl->active_count)) + list_add_tail(&tl->link, &timelines->active_list); spin_unlock_irqrestore(&timelines->lock, flags); } @@ -351,14 +369,16 @@ void intel_timeline_exit(struct intel_timeline *tl) struct intel_gt_timelines *timelines = &tl->gt->timelines; unsigned long flags; + /* See intel_timeline_enter() */ lockdep_assert_held(&tl->mutex); - GEM_BUG_ON(!tl->active_count); - if (--tl->active_count) + GEM_BUG_ON(!atomic_read(&tl->active_count)); + if (atomic_add_unless(&tl->active_count, -1, 1)) return; spin_lock_irqsave(&timelines->lock, flags); - list_del(&tl->link); + if (atomic_dec_and_test(&tl->active_count)) + list_del(&tl->link); spin_unlock_irqrestore(&timelines->lock, flags); /* diff --git a/drivers/gpu/drm/i915/gt/intel_timeline_types.h b/drivers/gpu/drm/i915/gt/intel_timeline_types.h index 98d9ee166379..5244615ed1cb 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline_types.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline_types.h @@ -42,7 +42,7 @@ struct intel_timeline { * from the intel_context caller plus internal atomicity. */ atomic_t pin_count; - unsigned int active_count; + atomic_t active_count; const u32 *hwsp_seqno; struct i915_vma *hwsp_ggtt; -- cgit v1.2.3 From 5cba288466e9b229feb68295675246e7522fb5eb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Nov 2019 16:55:14 +0000 Subject: drm/i915/gt: Unlock engine-pm after queuing the kernel context switch In commit a79ca656b648 ("drm/i915: Push the wakeref->count deferral to the backend"), I erroneously concluded that we last modify the engine inside __i915_request_commit() meaning that we could enable concurrent submission for userspace as we enqueued this request. However, this falls into a trap with other users of the engine->kernel_context waking up and submitting their request before the idle-switch is queued, with the result that the kernel_context is executed out-of-sequence most likely upsetting the GPU and certainly ourselves when we try to retire the out-of-sequence requests. As such we need to hold onto the effective engine->kernel_context mutex lock (via the engine pm mutex proxy) until we have finish queuing the request to the engine. v2: Serialise against concurrent intel_gt_retire_requests() v3: Describe the hairy locking scheme with intel_gt_retire_requests() for future reference. v4: Combine timeline->lock and engine pm release; it's hairy. Fixes: a79ca656b648 ("drm/i915: Push the wakeref->count deferral to the backend") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191120165514.3955081-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 47 ++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 7269c87c1372..373a4b9f159c 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -73,8 +73,25 @@ static inline void __timeline_mark_unlock(struct intel_context *ce, #endif /* !IS_ENABLED(CONFIG_LOCKDEP) */ +static void +__intel_timeline_enter_and_release_pm(struct intel_timeline *tl, + struct intel_engine_cs *engine) +{ + struct intel_gt_timelines *timelines = &engine->gt->timelines; + + spin_lock(&timelines->lock); + + if (!atomic_fetch_inc(&tl->active_count)) + list_add_tail(&tl->link, &timelines->active_list); + + __intel_wakeref_defer_park(&engine->wakeref); + + spin_unlock(&timelines->lock); +} + static bool switch_to_kernel_context(struct intel_engine_cs *engine) { + struct intel_context *ce = engine->kernel_context; struct i915_request *rq; unsigned long flags; bool result = true; @@ -98,16 +115,31 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) * This should hold true as we can only park the engine after * retiring the last request, thus all rings should be empty and * all timelines idle. + * + * For unlocking, there are 2 other parties and the GPU who have a + * stake here. + * + * A new gpu user will be waiting on the engine-pm to start their + * engine_unpark. New waiters are predicated on engine->wakeref.count + * and so intel_wakeref_defer_park() acts like a mutex_unlock of the + * engine->wakeref. + * + * The other party is intel_gt_retire_requests(), which is walking the + * list of active timelines looking for completions. Meanwhile as soon + * as we call __i915_request_queue(), the GPU may complete our request. + * Ergo, if we put ourselves on the timelines.active_list + * (se intel_timeline_enter()) before we increment the + * engine->wakeref.count, we may see the request completion and retire + * it causing an undeflow of the engine->wakeref. */ - flags = __timeline_mark_lock(engine->kernel_context); + flags = __timeline_mark_lock(ce); + GEM_BUG_ON(atomic_read(&ce->timeline->active_count) < 0); - rq = __i915_request_create(engine->kernel_context, GFP_NOWAIT); + rq = __i915_request_create(ce, GFP_NOWAIT); if (IS_ERR(rq)) /* Context switch failed, hope for the best! Maybe reset? */ goto out_unlock; - intel_timeline_enter(i915_request_timeline(rq)); - /* Check again on the next retirement. */ engine->wakeref_serial = engine->serial + 1; i915_request_add_active_barriers(rq); @@ -116,13 +148,14 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) rq->sched.attr.priority = I915_PRIORITY_BARRIER; __i915_request_commit(rq); - /* Release our exclusive hold on the engine */ - __intel_wakeref_defer_park(&engine->wakeref); __i915_request_queue(rq, NULL); + /* Expose ourselves to intel_gt_retire_requests() and new submission */ + __intel_timeline_enter_and_release_pm(ce->timeline, engine); + result = false; out_unlock: - __timeline_mark_unlock(engine->kernel_context, flags); + __timeline_mark_unlock(ce, flags); return result; } -- cgit v1.2.3 From 88cec4973de1d096282565779bbd9d5c6412a293 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Nov 2019 17:08:58 +0000 Subject: drm/i915/gt: Declare timeline.lock to be irq-free Now that we never allow the intel_wakeref callbacks to be invoked from interrupt context, we do not need the irqsafe spinlock for the timeline. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191120170858.3965380-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 9 ++++----- drivers/gpu/drm/i915/gt/intel_reset.c | 9 ++++----- drivers/gpu/drm/i915/gt/intel_timeline.c | 10 ++++------ 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index 1a005da8c588..4dc3cbeb1b36 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -33,7 +33,6 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) { struct intel_gt_timelines *timelines = >->timelines; struct intel_timeline *tl, *tn; - unsigned long flags; bool interruptible; LIST_HEAD(free); @@ -43,7 +42,7 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) flush_submission(gt); /* kick the ksoftirqd tasklets */ - spin_lock_irqsave(&timelines->lock, flags); + spin_lock(&timelines->lock); list_for_each_entry_safe(tl, tn, &timelines->active_list, link) { if (!mutex_trylock(&tl->mutex)) continue; @@ -51,7 +50,7 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) intel_timeline_get(tl); GEM_BUG_ON(!atomic_read(&tl->active_count)); atomic_inc(&tl->active_count); /* pin the list element */ - spin_unlock_irqrestore(&timelines->lock, flags); + spin_unlock(&timelines->lock); if (timeout > 0) { struct dma_fence *fence; @@ -67,7 +66,7 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) retire_requests(tl); - spin_lock_irqsave(&timelines->lock, flags); + spin_lock(&timelines->lock); /* Resume iteration after dropping lock */ list_safe_reset_next(tl, tn, link); @@ -82,7 +81,7 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) list_add(&tl->link, &free); } } - spin_unlock_irqrestore(&timelines->lock, flags); + spin_unlock(&timelines->lock); list_for_each_entry_safe(tl, tn, &free, link) __intel_timeline_free(&tl->kref); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 0388f9375366..36189238e13c 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -831,7 +831,6 @@ static bool __intel_gt_unset_wedged(struct intel_gt *gt) { struct intel_gt_timelines *timelines = >->timelines; struct intel_timeline *tl; - unsigned long flags; bool ok; if (!test_bit(I915_WEDGED, >->reset.flags)) @@ -853,7 +852,7 @@ static bool __intel_gt_unset_wedged(struct intel_gt *gt) * * No more can be submitted until we reset the wedged bit. */ - spin_lock_irqsave(&timelines->lock, flags); + spin_lock(&timelines->lock); list_for_each_entry(tl, &timelines->active_list, link) { struct dma_fence *fence; @@ -861,7 +860,7 @@ static bool __intel_gt_unset_wedged(struct intel_gt *gt) if (!fence) continue; - spin_unlock_irqrestore(&timelines->lock, flags); + spin_unlock(&timelines->lock); /* * All internal dependencies (i915_requests) will have @@ -874,10 +873,10 @@ static bool __intel_gt_unset_wedged(struct intel_gt *gt) dma_fence_put(fence); /* Restart iteration after droping lock */ - spin_lock_irqsave(&timelines->lock, flags); + spin_lock(&timelines->lock); tl = list_entry(&timelines->active_list, typeof(*tl), link); } - spin_unlock_irqrestore(&timelines->lock, flags); + spin_unlock(&timelines->lock); /* We must reset pending GPU events before restoring our submission */ ok = !HAS_EXECLISTS(gt->i915); /* XXX better agnosticism desired */ diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index b35f12729983..b190a5d9ab02 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -332,7 +332,6 @@ int intel_timeline_pin(struct intel_timeline *tl) void intel_timeline_enter(struct intel_timeline *tl) { struct intel_gt_timelines *timelines = &tl->gt->timelines; - unsigned long flags; /* * Pretend we are serialised by the timeline->mutex. @@ -358,16 +357,15 @@ void intel_timeline_enter(struct intel_timeline *tl) if (atomic_add_unless(&tl->active_count, 1, 0)) return; - spin_lock_irqsave(&timelines->lock, flags); + spin_lock(&timelines->lock); if (!atomic_fetch_inc(&tl->active_count)) list_add_tail(&tl->link, &timelines->active_list); - spin_unlock_irqrestore(&timelines->lock, flags); + spin_unlock(&timelines->lock); } void intel_timeline_exit(struct intel_timeline *tl) { struct intel_gt_timelines *timelines = &tl->gt->timelines; - unsigned long flags; /* See intel_timeline_enter() */ lockdep_assert_held(&tl->mutex); @@ -376,10 +374,10 @@ void intel_timeline_exit(struct intel_timeline *tl) if (atomic_add_unless(&tl->active_count, -1, 1)) return; - spin_lock_irqsave(&timelines->lock, flags); + spin_lock(&timelines->lock); if (atomic_dec_and_test(&tl->active_count)) list_del(&tl->link); - spin_unlock_irqrestore(&timelines->lock, flags); + spin_unlock(&timelines->lock); /* * Since this timeline is idle, all bariers upon which we were waiting -- cgit v1.2.3 From e435c608e89a23aaf0c71280f3be50775d7fdf23 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Nov 2019 18:22:09 +0000 Subject: drm/i915/gt: Fixup config ifdeffery for pm_suspend_target_state pm_suspend_target_state is declared under CONFIG_PM_SLEEP but only defined under CONFIG_SUSPEND. Play safe and only use the symbol if it is both declared and defined. Reported-by: kbuild-all@lists.01.org Signed-off-by: Chris Wilson Fixes: a70a9e998e8e ("drm/i915: Defer rc6 shutdown to suspend_late") Cc: Andi Shyti Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191120182209.3967833-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index f6b5169d623f..9d3045096e37 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -272,7 +272,7 @@ void intel_gt_suspend_prepare(struct intel_gt *gt) static suspend_state_t pm_suspend_target(void) { -#if IS_ENABLED(CONFIG_PM_SLEEP) +#if IS_ENABLED(CONFIG_SUSPEND) && IS_ENABLED(CONFIG_PM_SLEEP) return pm_suspend_target_state; #else return PM_SUSPEND_TO_IDLE; -- cgit v1.2.3 From e18417b48b4bcf5c2d27993ec2e7d075968a0744 Mon Sep 17 00:00:00 2001 From: Stuart Summers Date: Wed, 20 Nov 2019 13:13:21 -0800 Subject: drm/i915: Use intel_gt_pm_put_async in GuC submission path GuC submission path can be called from an interrupt context and so should use a worker to avoid holding a mutex. References: 07779a76ee1f ("drm/i915: Mark up the calling context for intel_wakeref_put()") Signed-off-by: Stuart Summers Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191120211321.88021-1-stuart.summers@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 902e25eb6b9d..dcccbd640809 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -537,7 +537,7 @@ static void schedule_out(struct i915_request *rq) { trace_i915_request_out(rq); - intel_gt_pm_put(rq->engine->gt); + intel_gt_pm_put_async(rq->engine->gt); i915_request_put(rq); } -- cgit v1.2.3 From 689122dcc36e08f53732adf7ae0246f62eff3eb6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Nov 2019 07:10:40 +0000 Subject: Revert "drm/i915/gt: Wait for new requests in intel_gt_retire_requests()" From inside an active timeline in the execbuf ioctl, we may try to reclaim some space in the GGTT. We need GGTT space for all objects on !full-ppgtt platforms, and for context images everywhere. However, to free up space in the GGTT we may need to remove some pinned objects (e.g. context images) that require flushing the idle barriers to remove. For this we use the big hammer of intel_gt_wait_for_idle() However, commit 7936a22dd466 ("drm/i915/gt: Wait for new requests in intel_gt_retire_requests()") will continue spinning on the wait if a timeline is active but lacks requests, as is the case during execbuf reservation. Spinning forever is quite time consuming, so revert that commit and start again. In practice, the effect commit 7936a22dd466 was trying to achieve is accomplished by commit 1683d24c1470 ("drm/i915/gt: Move new timelines to the end of active_list"), so there is no immediate rush to replace the looping. Testcase: igt/gem_exec_reloc/basic-range Fixes: 7936a22dd466 ("drm/i915/gt: Wait for new requests in intel_gt_retire_requests()") References: 1683d24c1470 ("drm/i915/gt: Move new timelines to the end of active_list") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191121071044.97798-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index 4dc3cbeb1b36..f02f781b8492 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -33,6 +33,7 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) { struct intel_gt_timelines *timelines = >->timelines; struct intel_timeline *tl, *tn; + unsigned long active_count = 0; bool interruptible; LIST_HEAD(free); @@ -44,8 +45,10 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) spin_lock(&timelines->lock); list_for_each_entry_safe(tl, tn, &timelines->active_list, link) { - if (!mutex_trylock(&tl->mutex)) + if (!mutex_trylock(&tl->mutex)) { + active_count++; /* report busy to caller, try again? */ continue; + } intel_timeline_get(tl); GEM_BUG_ON(!atomic_read(&tl->active_count)); @@ -72,6 +75,8 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) list_safe_reset_next(tl, tn, link); if (atomic_dec_and_test(&tl->active_count)) list_del(&tl->link); + else + active_count += !!rcu_access_pointer(tl->last_request.fence); mutex_unlock(&tl->mutex); @@ -86,7 +91,7 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) list_for_each_entry_safe(tl, tn, &free, link) __intel_timeline_free(&tl->kref); - return list_empty(&timelines->active_list) ? 0 : timeout; + return active_count ? timeout : 0; } int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout) -- cgit v1.2.3 From 2d0fb251360ab7eccbffd99f6933a2a4de678d52 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Nov 2019 07:10:41 +0000 Subject: drm/i915: Serialise with remote retirement Since retirement may be running in a worker on another CPU, it may be skipped in the local intel_gt_wait_for_idle(). To ensure the state is consistent for our sanity checks upon load, serialise with the remote retirer by waiting on the timeline->mutex. Outside of this use case, e.g. on suspend or module unload, we expect the slack to be picked up by intel_gt_pm_wait_for_idle() and so prefer to put the special case serialisation with retirement in its single user, for now at least. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191121071044.97798-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1ba5f26700b0..61395b03443e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -45,6 +45,7 @@ #include "gem/i915_gem_context.h" #include "gem/i915_gem_ioctls.h" #include "gem/i915_gem_pm.h" +#include "gt/intel_context.h" #include "gt/intel_engine_user.h" #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" @@ -1041,6 +1042,18 @@ out: return err; } +static int __intel_context_flush_retire(struct intel_context *ce) +{ + struct intel_timeline *tl; + + tl = intel_context_timeline_lock(ce); + if (IS_ERR(tl)) + return PTR_ERR(tl); + + intel_context_timeline_unlock(tl); + return 0; +} + static int __intel_engines_record_defaults(struct intel_gt *gt) { struct i915_request *requests[I915_NUM_ENGINES] = {}; @@ -1109,13 +1122,20 @@ err_rq: if (!rq) continue; - /* We want to be able to unbind the state from the GGTT */ - GEM_BUG_ON(intel_context_is_pinned(rq->hw_context)); - + GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT, + &rq->hw_context->flags)); state = rq->hw_context->state; if (!state) continue; + /* Serialise with retirement on another CPU */ + err = __intel_context_flush_retire(rq->hw_context); + if (err) + goto out; + + /* We want to be able to unbind the state from the GGTT */ + GEM_BUG_ON(intel_context_is_pinned(rq->hw_context)); + /* * As we will hold a reference to the logical state, it will * not be torn down with the context, and importantly the -- cgit v1.2.3 From 090a82e9166fbefdb8d371431d4a7f514b3acb86 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Nov 2019 09:33:26 +0000 Subject: drm/i915/gt: Hold request reference while waiting for w/a verification As we wait upon a request, we must be holding a reference to it, and be wary that i915_request_add() consumes the passed in reference. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191121093326.134774-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 399acae2f33f..226bd4cccb48 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -1592,16 +1592,17 @@ static int engine_wa_list_verify(struct intel_context *ce, if (err) goto err_vma; + i915_request_get(rq); i915_request_add(rq); if (i915_request_wait(rq, 0, HZ / 5) < 0) { err = -ETIME; - goto err_vma; + goto err_rq; } results = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); if (IS_ERR(results)) { err = PTR_ERR(results); - goto err_vma; + goto err_rq; } err = 0; @@ -1615,6 +1616,8 @@ static int engine_wa_list_verify(struct intel_context *ce, i915_gem_object_unpin_map(vma->obj); +err_rq: + i915_request_put(rq); err_vma: i915_vma_unpin(vma); i915_vma_put(vma); -- cgit v1.2.3 From c95d31c3df1b9ff29bcd85c47324e16d430bbd5a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Nov 2019 10:35:46 +0000 Subject: drm/i915/execlists: Lock the request while validating it during promotion Since the request is already on the HW as we perform its validation, it and even its subsequent barrier may be concurrently retired before we process the assertions. If it is retired already and so off the HW, our assertions become void and we need to ignore them. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112363 Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191121103546.146487-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index b65bc06855b0..da72794f3707 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1291,38 +1291,53 @@ assert_pending_valid(const struct intel_engine_execlists *execlists, } for (port = execlists->pending; (rq = *port); port++) { + unsigned long flags; + bool ok = true; + if (ce == rq->hw_context) { GEM_TRACE_ERR("Dup context:%llx in pending[%zd]\n", ce->timeline->fence_context, port - execlists->pending); return false; } - ce = rq->hw_context; + + /* Hold tightly onto the lock to prevent concurrent retires! */ + spin_lock_irqsave_nested(&rq->lock, flags, + SINGLE_DEPTH_NESTING); + if (i915_request_completed(rq)) - continue; + goto unlock; if (i915_active_is_idle(&ce->active) && !i915_gem_context_is_kernel(ce->gem_context)) { GEM_TRACE_ERR("Inactive context:%llx in pending[%zd]\n", ce->timeline->fence_context, port - execlists->pending); - return false; + ok = false; + goto unlock; } if (!i915_vma_is_pinned(ce->state)) { GEM_TRACE_ERR("Unpinned context:%llx in pending[%zd]\n", ce->timeline->fence_context, port - execlists->pending); - return false; + ok = false; + goto unlock; } if (!i915_vma_is_pinned(ce->ring->vma)) { GEM_TRACE_ERR("Unpinned ring:%llx in pending[%zd]\n", ce->timeline->fence_context, port - execlists->pending); - return false; + ok = false; + goto unlock; } + +unlock: + spin_unlock_irqrestore(&rq->lock, flags); + if (!ok) + return false; } return ce; -- cgit v1.2.3 From 93b0e8fe4753e052d415284a0849ae878d852bf1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Nov 2019 13:05:28 +0000 Subject: drm/i915: Mark intel_wakeref_get() as a sleeper Assume that intel_wakeref_get() may take the mutex, and perform other sleeping actions in the course of its callbacks and so use might_sleep() to ensure that all callers abide. Anything that cannot sleep has to use e.g. intel_wakeref_get_if_active() to guarantee its avoidance of the non-atomic paths. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191121130528.309474-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_pm.h | 5 +++++ drivers/gpu/drm/i915/gt/intel_lrc.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- drivers/gpu/drm/i915/intel_wakeref.h | 19 +++++++++++++++++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index 990efc27a4e4..4a9e48c12bd4 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -22,6 +22,11 @@ static inline void intel_gt_pm_get(struct intel_gt *gt) intel_wakeref_get(>->wakeref); } +static inline void __intel_gt_pm_get(struct intel_gt *gt) +{ + __intel_wakeref_get(>->wakeref); +} + static inline bool intel_gt_pm_get_if_awake(struct intel_gt *gt) { return intel_wakeref_get_if_active(>->wakeref); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index da72794f3707..0e2065a13f24 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1121,7 +1121,7 @@ __execlists_schedule_in(struct i915_request *rq) BUILD_BUG_ON(NUM_CONTEXT_TAG > GEN12_MAX_CONTEXT_HW_ID); } - intel_gt_pm_get(engine->gt); + __intel_gt_pm_get(engine->gt); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN); intel_engine_context_in(engine); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index dcccbd640809..6f94af7ad1de 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -529,7 +529,7 @@ static struct i915_request *schedule_in(struct i915_request *rq, int idx) * required if we generalise the inflight tracking. */ - intel_gt_pm_get(rq->engine->gt); + __intel_gt_pm_get(rq->engine->gt); return i915_request_get(rq); } diff --git a/drivers/gpu/drm/i915/intel_wakeref.h b/drivers/gpu/drm/i915/intel_wakeref.h index da6e8fd506e6..8d945db94b7a 100644 --- a/drivers/gpu/drm/i915/intel_wakeref.h +++ b/drivers/gpu/drm/i915/intel_wakeref.h @@ -59,9 +59,7 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags); /** * intel_wakeref_get: Acquire the wakeref - * @i915: the drm_i915_private device * @wf: the wakeref - * @fn: callback for acquired the wakeref, called only on first acquire. * * Acquire a hold on the wakeref. The first user to do so, will acquire * the runtime pm wakeref and then call the @fn underneath the wakeref @@ -76,12 +74,29 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags); static inline int intel_wakeref_get(struct intel_wakeref *wf) { + might_sleep(); if (unlikely(!atomic_inc_not_zero(&wf->count))) return __intel_wakeref_get_first(wf); return 0; } +/** + * __intel_wakeref_get: Acquire the wakeref, again + * @wf: the wakeref + * + * Increment the wakeref counter, only valid if it is already held by + * the caller. + * + * See intel_wakeref_get(). + */ +static inline void +__intel_wakeref_get(struct intel_wakeref *wf) +{ + INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); + atomic_inc(&wf->count); +} + /** * intel_wakeref_get_if_in_use: Acquire the wakeref * @wf: the wakeref -- cgit v1.2.3 From 1ff2f9e26c56a18d78507ac88f52bfd0a9e8ed99 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Nov 2019 07:10:43 +0000 Subject: drm/i915/selftests: Always hold a reference on a waited upon request Whenever we wait on a request, make sure we actually hold a reference to it and that it cannot be retired/freed on another CPU! Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191121071044.97798-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/selftest_lrc.c | 87 ++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index 16ebe4d2308e..2baeedd5953f 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -748,15 +748,19 @@ static int live_busywait_preempt(void *arg) *cs++ = 0; intel_ring_advance(lo, cs); + + i915_request_get(lo); i915_request_add(lo); if (wait_for(READ_ONCE(*map), 10)) { + i915_request_put(lo); err = -ETIMEDOUT; goto err_vma; } /* Low priority request should be busywaiting now */ if (i915_request_wait(lo, 0, 1) != -ETIME) { + i915_request_put(lo); pr_err("%s: Busywaiting request did not!\n", engine->name); err = -EIO; @@ -766,6 +770,7 @@ static int live_busywait_preempt(void *arg) hi = igt_request_alloc(ctx_hi, engine); if (IS_ERR(hi)) { err = PTR_ERR(hi); + i915_request_put(lo); goto err_vma; } @@ -773,6 +778,7 @@ static int live_busywait_preempt(void *arg) if (IS_ERR(cs)) { err = PTR_ERR(cs); i915_request_add(hi); + i915_request_put(lo); goto err_vma; } @@ -793,11 +799,13 @@ static int live_busywait_preempt(void *arg) intel_engine_dump(engine, &p, "%s\n", engine->name); GEM_TRACE_DUMP(); + i915_request_put(lo); intel_gt_set_wedged(gt); err = -EIO; goto err_vma; } GEM_BUG_ON(READ_ONCE(*map)); + i915_request_put(lo); if (igt_live_test_end(&t)) { err = -EIO; @@ -1665,6 +1673,7 @@ static int live_suppress_wait_preempt(void *arg) { struct intel_gt *gt = arg; struct preempt_client client[4]; + struct i915_request *rq[ARRAY_SIZE(client)] = {}; struct intel_engine_cs *engine; enum intel_engine_id id; int err = -ENOMEM; @@ -1698,7 +1707,6 @@ static int live_suppress_wait_preempt(void *arg) continue; for (depth = 0; depth < ARRAY_SIZE(client); depth++) { - struct i915_request *rq[ARRAY_SIZE(client)]; struct i915_request *dummy; engine->execlists.preempt_hang.count = 0; @@ -1708,18 +1716,22 @@ static int live_suppress_wait_preempt(void *arg) goto err_client_3; for (i = 0; i < ARRAY_SIZE(client); i++) { - rq[i] = spinner_create_request(&client[i].spin, - client[i].ctx, engine, - MI_NOOP); - if (IS_ERR(rq[i])) { - err = PTR_ERR(rq[i]); + struct i915_request *this; + + this = spinner_create_request(&client[i].spin, + client[i].ctx, engine, + MI_NOOP); + if (IS_ERR(this)) { + err = PTR_ERR(this); goto err_wedged; } /* Disable NEWCLIENT promotion */ - __i915_active_fence_set(&i915_request_timeline(rq[i])->last_request, + __i915_active_fence_set(&i915_request_timeline(this)->last_request, &dummy->fence); - i915_request_add(rq[i]); + + rq[i] = i915_request_get(this); + i915_request_add(this); } dummy_request_free(dummy); @@ -1740,8 +1752,11 @@ static int live_suppress_wait_preempt(void *arg) goto err_wedged; } - for (i = 0; i < ARRAY_SIZE(client); i++) + for (i = 0; i < ARRAY_SIZE(client); i++) { igt_spinner_end(&client[i].spin); + i915_request_put(rq[i]); + rq[i] = NULL; + } if (igt_flush_test(gt->i915)) goto err_wedged; @@ -1769,8 +1784,10 @@ err_client_0: return err; err_wedged: - for (i = 0; i < ARRAY_SIZE(client); i++) + for (i = 0; i < ARRAY_SIZE(client); i++) { igt_spinner_end(&client[i].spin); + i915_request_put(rq[i]); + } intel_gt_set_wedged(gt); err = -EIO; goto err_client_3; @@ -1815,6 +1832,8 @@ static int live_chain_preempt(void *arg) MI_ARB_CHECK); if (IS_ERR(rq)) goto err_wedged; + + i915_request_get(rq); i915_request_add(rq); ring_size = rq->wa_tail - rq->head; @@ -1827,8 +1846,10 @@ static int live_chain_preempt(void *arg) igt_spinner_end(&lo.spin); if (i915_request_wait(rq, 0, HZ / 2) < 0) { pr_err("Timed out waiting to flush %s\n", engine->name); + i915_request_put(rq); goto err_wedged; } + i915_request_put(rq); if (igt_live_test_begin(&t, gt->i915, __func__, engine->name)) { err = -EIO; @@ -1862,6 +1883,8 @@ static int live_chain_preempt(void *arg) rq = igt_request_alloc(hi.ctx, engine); if (IS_ERR(rq)) goto err_wedged; + + i915_request_get(rq); i915_request_add(rq); engine->schedule(rq, &attr); @@ -1874,14 +1897,19 @@ static int live_chain_preempt(void *arg) count); intel_engine_dump(engine, &p, "%s\n", engine->name); + i915_request_put(rq); goto err_wedged; } igt_spinner_end(&lo.spin); + i915_request_put(rq); rq = igt_request_alloc(lo.ctx, engine); if (IS_ERR(rq)) goto err_wedged; + + i915_request_get(rq); i915_request_add(rq); + if (i915_request_wait(rq, 0, HZ / 5) < 0) { struct drm_printer p = drm_info_printer(gt->i915->drm.dev); @@ -1890,8 +1918,11 @@ static int live_chain_preempt(void *arg) count); intel_engine_dump(engine, &p, "%s\n", engine->name); + + i915_request_put(rq); goto err_wedged; } + i915_request_put(rq); } if (igt_live_test_end(&t)) { @@ -2586,7 +2617,7 @@ static int nop_virtual_engine(struct intel_gt *gt, #define CHAIN BIT(0) { IGT_TIMEOUT(end_time); - struct i915_request *request[16]; + struct i915_request *request[16] = {}; struct i915_gem_context *ctx[16]; struct intel_context *ve[16]; unsigned long n, prime, nc; @@ -2632,27 +2663,35 @@ static int nop_virtual_engine(struct intel_gt *gt, if (flags & CHAIN) { for (nc = 0; nc < nctx; nc++) { for (n = 0; n < prime; n++) { - request[nc] = - i915_request_create(ve[nc]); - if (IS_ERR(request[nc])) { - err = PTR_ERR(request[nc]); + struct i915_request *rq; + + rq = i915_request_create(ve[nc]); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); goto out; } - i915_request_add(request[nc]); + if (request[nc]) + i915_request_put(request[nc]); + request[nc] = i915_request_get(rq); + i915_request_add(rq); } } } else { for (n = 0; n < prime; n++) { for (nc = 0; nc < nctx; nc++) { - request[nc] = - i915_request_create(ve[nc]); - if (IS_ERR(request[nc])) { - err = PTR_ERR(request[nc]); + struct i915_request *rq; + + rq = i915_request_create(ve[nc]); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); goto out; } - i915_request_add(request[nc]); + if (request[nc]) + i915_request_put(request[nc]); + request[nc] = i915_request_get(rq); + i915_request_add(rq); } } } @@ -2678,6 +2717,11 @@ static int nop_virtual_engine(struct intel_gt *gt, if (prime == 1) times[0] = times[1]; + for (nc = 0; nc < nctx; nc++) { + i915_request_put(request[nc]); + request[nc] = NULL; + } + if (__igt_timeout(end_time, NULL)) break; } @@ -2695,6 +2739,7 @@ out: err = -EIO; for (nc = 0; nc < nctx; nc++) { + i915_request_put(request[nc]); intel_context_unpin(ve[nc]); intel_context_put(ve[nc]); kernel_context_close(ctx[nc]); -- cgit v1.2.3 From f05bfce3341208de93e4fd08bdb635dc671afec4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 21 Nov 2019 23:30:21 +0000 Subject: drm/i915/selftests: Shorten infinite wait for sseu Use our more regular igt_flush_test() to bind the wait-for-idle and error out instead of waiting around forever on critical failure. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Stuart Summers Link: https://patchwork.freedesktop.org/patch/msgid/20191121233021.507400-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index f1ce5f64b221..e1d8ccd11409 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1168,8 +1168,7 @@ out: igt_spinner_end(spin); if ((flags & TEST_IDLE) && ret == 0) { - ret = intel_gt_wait_for_idle(ce->engine->gt, - MAX_SCHEDULE_TIMEOUT); + ret = igt_flush_test(ce->engine->i915); if (ret) return ret; -- cgit v1.2.3 From 67a3acaab7167157fb827595019eaf55df244824 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 22 Nov 2019 09:49:24 +0000 Subject: drm/i915: Use a ctor for TYPESAFE_BY_RCU i915_request As we start peeking into requests for longer and longer, e.g. incorporating use of spinlocks when only protected by an rcu_read_lock(), we need to be careful in how we reset the request when recycling and need to preserve any barriers that may still be in use as the request is reset for reuse. Quoting Linus Torvalds: > If there is refcounting going on then why use SLAB_TYPESAFE_BY_RCU? .. because the object can be accessed (by RCU) after the refcount has gone down to zero, and the thing has been released. That's the whole and only point of SLAB_TYPESAFE_BY_RCU. That flag basically says: "I may end up accessing this object *after* it has been free'd, because there may be RCU lookups in flight" This has nothing to do with constructors. It's ok if the object gets reused as an object of the same type and does *not* get re-initialized, because we're perfectly fine seeing old stale data. What it guarantees is that the slab isn't shared with any other kind of object, _and_ that the underlying pages are free'd after an RCU quiescent period (so the pages aren't shared with another kind of object either during an RCU walk). And it doesn't necessarily have to have a constructor, because the thing that a RCU walk will care about is (a) guaranteed to be an object that *has* been on some RCU list (so it's not a "new" object) (b) the RCU walk needs to have logic to verify that it's still the *same* object and hasn't been re-used as something else. In contrast, a SLAB_TYPESAFE_BY_RCU memory gets free'd and re-used immediately, but because it gets reused as the same kind of object, the RCU walker can "know" what parts have meaning for re-use, in a way it couidn't if the re-use was random. That said, it *is* subtle, and people should be careful. > So the re-use might initialize the fields lazily, not necessarily using a ctor. If you have a well-defined refcount, and use "atomic_inc_not_zero()" to guard the speculative RCU access section, and use "atomic_dec_and_test()" in the freeing section, then you should be safe wrt new allocations. If you have a completely new allocation that has "random stale content", you know that it cannot be on the RCU list, so there is no speculative access that can ever see that random content. So the only case you need to worry about is a re-use allocation, and you know that the refcount will start out as zero even if you don't have a constructor. So you can think of the refcount itself as always having a zero constructor, *BUT* you need to be careful with ordering. In particular, whoever does the allocation needs to then set the refcount to a non-zero value *after* it has initialized all the other fields. And in particular, it needs to make sure that it uses the proper memory ordering to do so. NOTE! One thing to be very worried about is that re-initializing whatever RCU lists means that now the RCU walker may be walking on the wrong list so the walker may do the right thing for this particular entry, but it may miss walking *other* entries. So then you can get spurious lookup failures, because the RCU walker never walked all the way to the end of the right list. That ends up being a much more subtle bug. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191122094924.629690-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_request.c | 49 +++++++++++++++++++++++------------ drivers/gpu/drm/i915/i915_scheduler.c | 12 +++++++++ drivers/gpu/drm/i915/i915_scheduler.h | 1 + drivers/gpu/drm/i915/i915_sw_fence.c | 18 +++++++++++-- drivers/gpu/drm/i915/i915_sw_fence.h | 2 ++ 5 files changed, 64 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 00011f9533b6..a558f64186fa 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -188,7 +188,7 @@ static void free_capture_list(struct i915_request *request) { struct i915_capture_list *capture; - capture = request->capture_list; + capture = fetch_and_zero(&request->capture_list); while (capture) { struct i915_capture_list *next = capture->next; @@ -214,7 +214,7 @@ static void remove_from_engine(struct i915_request *rq) spin_lock(&engine->active.lock); locked = engine; } - list_del(&rq->sched.link); + list_del_init(&rq->sched.link); spin_unlock_irq(&locked->active.lock); } @@ -586,6 +586,21 @@ out: return kmem_cache_alloc(global.slab_requests, gfp); } +static void __i915_request_ctor(void *arg) +{ + struct i915_request *rq = arg; + + spin_lock_init(&rq->lock); + i915_sched_node_init(&rq->sched); + i915_sw_fence_init(&rq->submit, submit_notify); + i915_sw_fence_init(&rq->semaphore, semaphore_notify); + + rq->file_priv = NULL; + rq->capture_list = NULL; + + INIT_LIST_HEAD(&rq->execute_cb); +} + struct i915_request * __i915_request_create(struct intel_context *ce, gfp_t gfp) { @@ -648,6 +663,7 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp) rq->engine = ce->engine; rq->ring = ce->ring; rq->execution_mask = ce->engine->mask; + rq->flags = 0; rcu_assign_pointer(rq->timeline, tl); rq->hwsp_seqno = tl->hwsp_seqno; @@ -655,23 +671,20 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp) rq->rcustate = get_state_synchronize_rcu(); /* acts as smp_mb() */ - spin_lock_init(&rq->lock); dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock, tl->fence_context, seqno); /* We bump the ref for the fence chain */ - i915_sw_fence_init(&i915_request_get(rq)->submit, submit_notify); - i915_sw_fence_init(&i915_request_get(rq)->semaphore, semaphore_notify); + i915_sw_fence_reinit(&i915_request_get(rq)->submit); + i915_sw_fence_reinit(&i915_request_get(rq)->semaphore); - i915_sched_node_init(&rq->sched); + i915_sched_node_reinit(&rq->sched); - /* No zalloc, must clear what we need by hand */ - rq->file_priv = NULL; + /* No zalloc, everything must be cleared after use */ rq->batch = NULL; - rq->capture_list = NULL; - rq->flags = 0; - - INIT_LIST_HEAD(&rq->execute_cb); + GEM_BUG_ON(rq->file_priv); + GEM_BUG_ON(rq->capture_list); + GEM_BUG_ON(!list_empty(&rq->execute_cb)); /* * Reserve space in the ring buffer for all the commands required to @@ -1533,10 +1546,14 @@ static struct i915_global_request global = { { int __init i915_global_request_init(void) { - global.slab_requests = KMEM_CACHE(i915_request, - SLAB_HWCACHE_ALIGN | - SLAB_RECLAIM_ACCOUNT | - SLAB_TYPESAFE_BY_RCU); + global.slab_requests = + kmem_cache_create("i915_request", + sizeof(struct i915_request), + __alignof__(struct i915_request), + SLAB_HWCACHE_ALIGN | + SLAB_RECLAIM_ACCOUNT | + SLAB_TYPESAFE_BY_RCU, + __i915_request_ctor); if (!global.slab_requests) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index 010d67f48ad9..1937a26d412f 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.c +++ b/drivers/gpu/drm/i915/i915_scheduler.c @@ -387,9 +387,19 @@ void i915_sched_node_init(struct i915_sched_node *node) INIT_LIST_HEAD(&node->signalers_list); INIT_LIST_HEAD(&node->waiters_list); INIT_LIST_HEAD(&node->link); + + i915_sched_node_reinit(node); +} + +void i915_sched_node_reinit(struct i915_sched_node *node) +{ node->attr.priority = I915_PRIORITY_INVALID; node->semaphores = 0; node->flags = 0; + + GEM_BUG_ON(!list_empty(&node->signalers_list)); + GEM_BUG_ON(!list_empty(&node->waiters_list)); + GEM_BUG_ON(!list_empty(&node->link)); } static struct i915_dependency * @@ -481,6 +491,7 @@ void i915_sched_node_fini(struct i915_sched_node *node) if (dep->flags & I915_DEPENDENCY_ALLOC) i915_dependency_free(dep); } + INIT_LIST_HEAD(&node->signalers_list); /* Remove ourselves from everyone who depends upon us */ list_for_each_entry_safe(dep, tmp, &node->waiters_list, wait_link) { @@ -491,6 +502,7 @@ void i915_sched_node_fini(struct i915_sched_node *node) if (dep->flags & I915_DEPENDENCY_ALLOC) i915_dependency_free(dep); } + INIT_LIST_HEAD(&node->waiters_list); spin_unlock_irq(&schedule_lock); } diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h index 07d243acf553..d1dc4efef77b 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.h +++ b/drivers/gpu/drm/i915/i915_scheduler.h @@ -26,6 +26,7 @@ sched.link) void i915_sched_node_init(struct i915_sched_node *node); +void i915_sched_node_reinit(struct i915_sched_node *node); bool __i915_sched_node_add_dependency(struct i915_sched_node *node, struct i915_sched_node *signal, diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 6a88db291252..1584f34a6bf9 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -12,6 +12,12 @@ #include "i915_sw_fence.h" #include "i915_selftest.h" +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG) +#define I915_SW_FENCE_BUG_ON(expr) BUG_ON(expr) +#else +#define I915_SW_FENCE_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) +#endif + #define I915_SW_FENCE_FLAG_ALLOC BIT(3) /* after WQ_FLAG_* for safety */ static DEFINE_SPINLOCK(i915_sw_fence_lock); @@ -218,13 +224,21 @@ void __i915_sw_fence_init(struct i915_sw_fence *fence, { BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK); + __init_waitqueue_head(&fence->wait, name, key); + fence->flags = (unsigned long)fn; + + i915_sw_fence_reinit(fence); +} + +void i915_sw_fence_reinit(struct i915_sw_fence *fence) +{ debug_fence_init(fence); - __init_waitqueue_head(&fence->wait, name, key); atomic_set(&fence->pending, 1); fence->error = 0; - fence->flags = (unsigned long)fn; + I915_SW_FENCE_BUG_ON(!fence->flags); + I915_SW_FENCE_BUG_ON(!list_empty(&fence->wait.head)); } void i915_sw_fence_commit(struct i915_sw_fence *fence) diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index ab7d58bd0b9d..1e90d9a51bd2 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -54,6 +54,8 @@ do { \ __i915_sw_fence_init((fence), (fn), NULL, NULL) #endif +void i915_sw_fence_reinit(struct i915_sw_fence *fence); + #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS void i915_sw_fence_fini(struct i915_sw_fence *fence); #else -- cgit v1.2.3 From cfd821b2439c7eaf56ac473b1233b66dbe342c12 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 22 Nov 2019 11:21:48 +0000 Subject: drm/i915/selftests: Force bonded submission to overlap Bonded request submission is designed to allow requests to execute in parallel as laid out by the user. If the master request is already finished before its bonded pair is submitted, the pair were not destined to run in parallel and we lose the information about the master engine to dictate selection of the secondary. If the second request was required to be run on a particular engine in a virtual set, that should have been specified, rather than left to the whims of a random unconnected requests! In the selftest, I made the mistake of not ensuring the master would overlap with its bonded pairs, meaning that it could indeed complete before we submitted the bonds. Those bonds were then free to select any available engine in their virtual set, and not the one expected by the test. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191122112152.660743-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/selftest_lrc.c | 62 ++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index 2baeedd5953f..fc142dd61dd1 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -3081,15 +3081,60 @@ static int bond_virtual_engine(struct intel_gt *gt, struct i915_gem_context *ctx; struct i915_request *rq[16]; enum intel_engine_id id; + struct igt_spinner spin; unsigned long n; int err; + /* + * A set of bonded requests is intended to be run concurrently + * across a number of engines. We use one request per-engine + * and a magic fence to schedule each of the bonded requests + * at the same time. A consequence of our current scheduler is that + * we only move requests to the HW ready queue when the request + * becomes ready, that is when all of its prerequisite fences have + * been signaled. As one of those fences is the master submit fence, + * there is a delay on all secondary fences as the HW may be + * currently busy. Equally, as all the requests are independent, + * they may have other fences that delay individual request + * submission to HW. Ergo, we do not guarantee that all requests are + * immediately submitted to HW at the same time, just that if the + * rules are abided by, they are ready at the same time as the + * first is submitted. Userspace can embed semaphores in its batch + * to ensure parallel execution of its phases as it requires. + * Though naturally it gets requested that perhaps the scheduler should + * take care of parallel execution, even across preemption events on + * different HW. (The proper answer is of course "lalalala".) + * + * With the submit-fence, we have identified three possible phases + * of synchronisation depending on the master fence: queued (not + * ready), executing, and signaled. The first two are quite simple + * and checked below. However, the signaled master fence handling is + * contentious. Currently we do not distinguish between a signaled + * fence and an expired fence, as once signaled it does not convey + * any information about the previous execution. It may even be freed + * and hence checking later it may not exist at all. Ergo we currently + * do not apply the bonding constraint for an already signaled fence, + * as our expectation is that it should not constrain the secondaries + * and is outside of the scope of the bonded request API (i.e. all + * userspace requests are meant to be running in parallel). As + * it imposes no constraint, and is effectively a no-op, we do not + * check below as normal execution flows are checked extensively above. + * + * XXX Is the degenerate handling of signaled submit fences the + * expected behaviour for userpace? + */ + GEM_BUG_ON(nsibling >= ARRAY_SIZE(rq) - 1); - ctx = kernel_context(gt->i915); - if (!ctx) + if (igt_spinner_init(&spin, gt)) return -ENOMEM; + ctx = kernel_context(gt->i915); + if (!ctx) { + err = -ENOMEM; + goto err_spin; + } + err = 0; rq[0] = ERR_PTR(-ENOMEM); for_each_engine(master, gt, id) { @@ -3100,7 +3145,7 @@ static int bond_virtual_engine(struct intel_gt *gt, memset_p((void *)rq, ERR_PTR(-EINVAL), ARRAY_SIZE(rq)); - rq[0] = igt_request_alloc(ctx, master); + rq[0] = spinner_create_request(&spin, ctx, master, MI_NOOP); if (IS_ERR(rq[0])) { err = PTR_ERR(rq[0]); goto out; @@ -3113,10 +3158,17 @@ static int bond_virtual_engine(struct intel_gt *gt, &fence, GFP_KERNEL); } + i915_request_add(rq[0]); if (err < 0) goto out; + if (!(flags & BOND_SCHEDULE) && + !igt_wait_for_spinner(&spin, rq[0])) { + err = -EIO; + goto out; + } + for (n = 0; n < nsibling; n++) { struct intel_context *ve; @@ -3164,6 +3216,8 @@ static int bond_virtual_engine(struct intel_gt *gt, } } onstack_fence_fini(&fence); + intel_engine_flush_submission(master); + igt_spinner_end(&spin); if (i915_request_wait(rq[0], 0, HZ / 10) < 0) { pr_err("Master request did not execute (on %s)!\n", @@ -3201,6 +3255,8 @@ out: err = -EIO; kernel_context_close(ctx); +err_spin: + igt_spinner_fini(&spin); return err; } -- cgit v1.2.3 From e8e61f105af43f33a60069b5b6a13356862ffb67 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 22 Nov 2019 13:24:04 +0000 Subject: drm/i915/selftests: Flush the active callbacks Before checking the current i915_active state for the asynchronous work we submitted, flush any ongoing callback. This ensures that our sampling is robust and does not sporadically fail due to bad timing as the work is running on another cpu. v2: Drop the fence callback sync, retiring under the lock should be good enough to synchronize with engine_retire() and the intel_gt_retire_requests() background worker. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191122132404.690440-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/selftest_context.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index 3586af636304..5bc124574170 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -48,20 +48,22 @@ static int context_sync(struct intel_context *ce) mutex_lock(&tl->mutex); do { - struct dma_fence *fence; + struct i915_request *rq; long timeout; - fence = i915_active_fence_get(&tl->last_request); - if (!fence) + if (list_empty(&tl->requests)) break; - timeout = dma_fence_wait_timeout(fence, false, HZ / 10); + rq = list_last_entry(&tl->requests, typeof(*rq), link); + i915_request_get(rq); + + timeout = i915_request_wait(rq, 0, HZ / 10); if (timeout < 0) err = timeout; else - i915_request_retire_upto(to_request(fence)); + i915_request_retire_upto(rq); - dma_fence_put(fence); + i915_request_put(rq); } while (!err); mutex_unlock(&tl->mutex); @@ -273,6 +275,7 @@ out_engine: if (err) goto err; + /* Wait for the barrier and in the process wait for engine to park */ err = context_sync(engine->kernel_context); if (err) goto err; @@ -282,6 +285,8 @@ out_engine: err = -EINVAL; } + intel_engine_pm_flush(engine); + if (intel_engine_pm_is_awake(engine)) { struct drm_printer p = drm_debug_printer(__func__); -- cgit v1.2.3 From 6025ba1204713a3d9667cc1a278ed180c5aa367c Mon Sep 17 00:00:00 2001 From: Juston Li Date: Fri, 11 Oct 2019 11:19:18 -0700 Subject: drm/i915: coffeelake supports hdcp2.2 This includes other platforms that utilize the same gen graphics as CFL: AML, WHL and CML. Signed-off-by: Juston Li Reviewed-by: Ramalingam C Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191011181918.29618-1-juston.li@intel.com --- drivers/gpu/drm/i915/display/intel_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index f1f41ca8402b..001ce27d7029 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -1887,7 +1887,7 @@ static bool is_hdcp2_supported(struct drm_i915_private *dev_priv) return false; return (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) || - IS_KABYLAKE(dev_priv)); + IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)); } void intel_hdcp_component_init(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From 9acc99d8f278e3da398e927774431bd3e947ab2e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 22 Nov 2019 10:41:15 +0000 Subject: drm/i915/query: Align flavour of engine data lookup Commit 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") changed the engine query to iterate over uabi engines but left the buffer size calculation look at the physical engine count. Difference has no practical consequence but it is nicer to align both queries. Signed-off-by: Tvrtko Ursulin Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT") Cc: Chris Wilson Cc: Daniele Ceraolo Spurio Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191122104115.29610-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_query.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index c27cfef9281c..ef25ce6e395e 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -103,15 +103,18 @@ query_engine_info(struct drm_i915_private *i915, struct drm_i915_engine_info __user *info_ptr; struct drm_i915_query_engine_info query; struct drm_i915_engine_info info = { }; + unsigned int num_uabi_engines = 0; struct intel_engine_cs *engine; int len, ret; if (query_item->flags) return -EINVAL; + for_each_uabi_engine(engine, i915) + num_uabi_engines++; + len = sizeof(struct drm_i915_query_engine_info) + - RUNTIME_INFO(i915)->num_engines * - sizeof(struct drm_i915_engine_info); + num_uabi_engines * sizeof(struct drm_i915_engine_info); ret = copy_query_item(&query, sizeof(query), len, query_item); if (ret != 0) -- cgit v1.2.3 From 3b054a1c036f09017d78e6ce89a9cb331806c833 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 23 Nov 2019 19:15:47 +0000 Subject: drm/i915/selftests: Include the subsubtest name for live_parallel_engines Include the name of the failing subsubtest, should it fails. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191123191547.925360-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/i915_request.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 50cc7ca9afba..c16d1efd2ad4 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -1214,10 +1214,12 @@ static int live_parallel_engines(void *arg) return -ENOMEM; for (fn = func; !err && *fn; fn++) { + char name[KSYM_NAME_LEN]; struct igt_live_test t; unsigned int idx; - err = igt_live_test_begin(&t, i915, __func__, ""); + snprintf(name, sizeof(name), "%pS", fn); + err = igt_live_test_begin(&t, i915, __func__, name); if (err) break; -- cgit v1.2.3 From bae21dacd7b7167f3c2d61c11245f618a82749a1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Nov 2019 09:14:09 +0000 Subject: drm/i915: Switch kunmap() to take the page not vaddr On converting from kunmap_atomic() to kunamp() one must remember the latter takes the struct page, the former the vaddr. Fixes: 48715f700174 ("drm/i915: Avoid atomic context for error capture") Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191125091409.1630385-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 7118ecb7f144..2b30a45fa25c 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1045,7 +1045,7 @@ i915_error_object_create(struct drm_i915_private *i915, s = kmap(page); ret = compress_page(compress, s, dst); - kunmap(s); + kunmap(page); drm_clflush_pages(&page, 1); -- cgit v1.2.3 From 331bf90591573dfe6c8e892239713ef9702f1396 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Nov 2019 09:43:18 +0000 Subject: drm/i915/gt: Mark the execlists->active as the primary volatile access Since we want to do a lockless read of the current active request, and that request is written to by process_csb also without serialisation, we need to instruct gcc to take care in reading the pointer itself. Otherwise, we have observed execlists_active() to report 0x40. [ 2400.760381] igt/para-4098 1..s. 2376479300us : process_csb: rcs0 cs-irq head=3, tail=4 [ 2400.760826] igt/para-4098 1..s. 2376479303us : process_csb: rcs0 csb[4]: status=0x00000001:0x00000000 [ 2400.761271] igt/para-4098 1..s. 2376479306us : trace_ports: rcs0: promote { b9c59:2622, b9c55:2624 } [ 2400.761726] igt/para-4097 0d... 2376479311us : __i915_schedule: rcs0: -2147483648->3, inflight:0000000000000040, rq:ffff888208c1e940 which is impossible! The answer is that as we keep the existing execlists->active pointing into the array as we copy over that array, the unserialised read may see a partial pointer value. Fixes: df403069029d ("drm/i915/execlists: Lift process_csb() out of the irq-off spinlock") Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191125094318.1630806-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine.h | 4 +--- drivers/gpu/drm/i915/gt/intel_lrc.c | 27 +++++++++++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index bc3b72bfa9e3..01765a7ec18f 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -100,9 +100,7 @@ execlists_num_ports(const struct intel_engine_execlists * const execlists) static inline struct i915_request * execlists_active(const struct intel_engine_execlists *execlists) { - GEM_BUG_ON(execlists->active - execlists->inflight > - execlists_num_ports(execlists)); - return READ_ONCE(*execlists->active); + return *READ_ONCE(execlists->active); } static inline void diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 0e2065a13f24..e533ff7ba334 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -2013,6 +2013,9 @@ cancel_port_requests(struct intel_engine_execlists * const execlists) execlists_schedule_out(rq); memset(execlists->pending, 0, sizeof(execlists->pending)); + /* Mark the end of active before we overwrite *active */ + WRITE_ONCE(execlists->active, execlists->pending); + for (port = execlists->active; (rq = *port); port++) execlists_schedule_out(rq); execlists->active = @@ -2169,23 +2172,27 @@ static void process_csb(struct intel_engine_cs *engine) else promote = gen8_csb_parse(execlists, buf + 2 * head); if (promote) { + struct i915_request * const *old = execlists->active; + + /* Point active to the new ELSP; prevent overwriting */ + WRITE_ONCE(execlists->active, execlists->pending); + set_timeslice(engine); + if (!inject_preempt_hang(execlists)) ring_set_paused(engine, 0); /* cancel old inflight, prepare for switch */ - trace_ports(execlists, "preempted", execlists->active); - while (*execlists->active) - execlists_schedule_out(*execlists->active++); + trace_ports(execlists, "preempted", old); + while (*old) + execlists_schedule_out(*old++); /* switch pending to inflight */ GEM_BUG_ON(!assert_pending_valid(execlists, "promote")); - execlists->active = - memcpy(execlists->inflight, - execlists->pending, - execlists_num_ports(execlists) * - sizeof(*execlists->pending)); - - set_timeslice(engine); + WRITE_ONCE(execlists->active, + memcpy(execlists->inflight, + execlists->pending, + execlists_num_ports(execlists) * + sizeof(*execlists->pending))); WRITE_ONCE(execlists->pending[0], NULL); } else { -- cgit v1.2.3 From da0ef77e1e0ccff703efee82406c629d5c4f4bbb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Nov 2019 11:25:20 +0000 Subject: drm/i915/execlists: Fixup cancel_port_requests() I rushed a last minute correction to cancel_port_requests() to prevent the snooping of *execlists->active as the inflight array was being updated, without noticing we iterated the inflight array starting from active! Oops. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112387 Fixes: 331bf9059157 ("drm/i915/gt: Mark the execlists->active as the primary volatile access") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Tvrtko Ursulin Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191125112520.1760492-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index e533ff7ba334..6090357a00fa 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -2007,19 +2007,17 @@ skip_submit: static void cancel_port_requests(struct intel_engine_execlists * const execlists) { - struct i915_request * const *port, *rq; + struct i915_request * const *port; - for (port = execlists->pending; (rq = *port); port++) - execlists_schedule_out(rq); + for (port = execlists->pending; *port; port++) + execlists_schedule_out(*port); memset(execlists->pending, 0, sizeof(execlists->pending)); /* Mark the end of active before we overwrite *active */ - WRITE_ONCE(execlists->active, execlists->pending); - - for (port = execlists->active; (rq = *port); port++) - execlists_schedule_out(rq); - execlists->active = - memset(execlists->inflight, 0, sizeof(execlists->inflight)); + for (port = xchg(&execlists->active, execlists->pending); *port; port++) + execlists_schedule_out(*port); + WRITE_ONCE(execlists->active, + memset(execlists->inflight, 0, sizeof(execlists->inflight))); } static inline void -- cgit v1.2.3 From de5825beae9a0ae51f14a92859c6ec916235cd4d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Nov 2019 10:58:56 +0000 Subject: drm/i915: Serialise with engine-pm around requests on the kernel_context As the engine->kernel_context is used within the engine-pm barrier, we have to be careful when emitting requests outside of the barrier, as the strict timeline locking rules do not apply. Instead, we must ensure the engine_park() cannot be entered as we build the request, which is simplest by taking an explicit engine-pm wakeref around the request construction. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191125105858.1718307-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 3 +- .../drm/i915/gem/selftests/i915_gem_client_blt.c | 2 ++ .../drm/i915/gem/selftests/i915_gem_coherency.c | 3 +- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 7 +++- drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 3 +- .../drm/i915/gem/selftests/i915_gem_object_blt.c | 18 +++++++--- drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c | 14 ++++++-- drivers/gpu/drm/i915/gt/intel_engine_pm.h | 21 ++++++++++++ drivers/gpu/drm/i915/gt/intel_workarounds.c | 3 ++ drivers/gpu/drm/i915/gt/selftest_context.c | 2 +- drivers/gpu/drm/i915/gt/selftest_engine_cs.c | 12 +++++++ drivers/gpu/drm/i915/gt/selftest_lrc.c | 6 ++-- drivers/gpu/drm/i915/gt/selftest_mocs.c | 2 ++ drivers/gpu/drm/i915/gt/selftest_timeline.c | 6 ++-- drivers/gpu/drm/i915/i915_perf.c | 4 ++- drivers/gpu/drm/i915/selftests/i915_active.c | 2 +- drivers/gpu/drm/i915/selftests/i915_perf.c | 2 +- drivers/gpu/drm/i915/selftests/i915_request.c | 40 ++++++++++++++++------ .../gpu/drm/i915/selftests/intel_memory_region.c | 2 ++ 19 files changed, 119 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 6f1e6181f67a..c94ac838401a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -70,6 +70,7 @@ #include #include "gt/intel_engine_heartbeat.h" +#include "gt/intel_engine_pm.h" #include "gt/intel_engine_user.h" #include "gt/intel_lrc_reg.h" #include "gt/intel_ring.h" @@ -1265,7 +1266,7 @@ gen8_modify_rpcs(struct intel_context *ce, struct intel_sseu sseu) if (!intel_context_is_pinned(ce)) return 0; - rq = i915_request_create(ce->engine->kernel_context); + rq = intel_engine_create_kernel_request(ce->engine); if (IS_ERR(rq)) return PTR_ERR(rq); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c index da8edee4fe0a..b972be165e85 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c @@ -24,6 +24,7 @@ static int __igt_client_fill(struct intel_engine_cs *engine) prandom_seed_state(&prng, i915_selftest.random_seed); + intel_engine_pm_get(engine); do { const u32 max_block_size = S16_MAX * PAGE_SIZE; u32 sz = min_t(u64, ce->vm->total >> 4, prandom_u32_state(&prng)); @@ -99,6 +100,7 @@ err_put: err_flush: if (err == -ENOMEM) err = 0; + intel_engine_pm_put(engine); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index 2b29f6b4e1dd..9d3cd1af61f6 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -6,6 +6,7 @@ #include +#include "gt/intel_engine_pm.h" #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" #include "gt/intel_ring.h" @@ -200,7 +201,7 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v) if (IS_ERR(vma)) return PTR_ERR(vma); - rq = i915_request_create(ctx->engine->kernel_context); + rq = intel_engine_create_kernel_request(ctx->engine); if (IS_ERR(rq)) { i915_vma_unpin(vma); return PTR_ERR(rq); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index e1d8ccd11409..2ea4790f3721 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -7,6 +7,7 @@ #include #include "gem/i915_gem_pm.h" +#include "gt/intel_engine_pm.h" #include "gt/intel_gt.h" #include "gt/intel_gt_requests.h" #include "gt/intel_reset.h" @@ -1190,9 +1191,11 @@ __sseu_test(const char *name, struct igt_spinner *spin = NULL; int ret; + intel_engine_pm_get(ce->engine); + ret = __sseu_prepare(name, flags, ce, &spin); if (ret) - return ret; + goto out_pm; ret = intel_context_reconfigure_sseu(ce, sseu); if (ret) @@ -1207,6 +1210,8 @@ out_spin: igt_spinner_fini(spin); kfree(spin); } +out_pm: + intel_engine_pm_put(ce->engine); return ret; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 9f1a69027a04..6ce9167f8c9f 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -6,6 +6,7 @@ #include +#include "gt/intel_engine_pm.h" #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" #include "huge_gem_object.h" @@ -536,7 +537,7 @@ static int make_obj_busy(struct drm_i915_gem_object *obj) if (err) return err; - rq = i915_request_create(engine->kernel_context); + rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) { i915_vma_unpin(vma); return PTR_ERR(rq); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c index 675c1a20a2f1..62077fe46715 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object_blt.c @@ -41,6 +41,7 @@ static int __perf_fill_blt(struct drm_i915_gem_object *obj) if (!engine) return 0; + intel_engine_pm_get(engine); for (pass = 0; pass < ARRAY_SIZE(t); pass++) { struct intel_context *ce = engine->kernel_context; ktime_t t0, t1; @@ -49,17 +50,20 @@ static int __perf_fill_blt(struct drm_i915_gem_object *obj) err = i915_gem_object_fill_blt(obj, ce, 0); if (err) - return err; + break; err = i915_gem_object_wait(obj, I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT); if (err) - return err; + break; t1 = ktime_get(); t[pass] = ktime_sub(t1, t0); } + intel_engine_pm_put(engine); + if (err) + return err; sort(t, ARRAY_SIZE(t), sizeof(*t), wrap_ktime_compare, NULL); pr_info("%s: blt %zd KiB fill: %lld MiB/s\n", @@ -109,6 +113,7 @@ static int __perf_copy_blt(struct drm_i915_gem_object *src, struct intel_engine_cs *engine; ktime_t t[5]; int pass; + int err = 0; engine = intel_engine_lookup_user(i915, I915_ENGINE_CLASS_COPY, @@ -116,26 +121,29 @@ static int __perf_copy_blt(struct drm_i915_gem_object *src, if (!engine) return 0; + intel_engine_pm_get(engine); for (pass = 0; pass < ARRAY_SIZE(t); pass++) { struct intel_context *ce = engine->kernel_context; ktime_t t0, t1; - int err; t0 = ktime_get(); err = i915_gem_object_copy_blt(src, dst, ce); if (err) - return err; + break; err = i915_gem_object_wait(dst, I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT); if (err) - return err; + break; t1 = ktime_get(); t[pass] = ktime_sub(t1, t0); } + intel_engine_pm_put(engine); + if (err) + return err; sort(t, ARRAY_SIZE(t), sizeof(*t), wrap_ktime_compare, NULL); pr_info("%s: blt %zd KiB copy: %lld MiB/s\n", diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c index c91fd4e4af29..742628e40201 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c @@ -215,18 +215,26 @@ out_rpm: int intel_engine_flush_barriers(struct intel_engine_cs *engine) { struct i915_request *rq; + int err = 0; if (llist_empty(&engine->barrier_tasks)) return 0; + if (!intel_engine_pm_get_if_awake(engine)) + return 0; + rq = i915_request_create(engine->kernel_context); - if (IS_ERR(rq)) - return PTR_ERR(rq); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + goto out_rpm; + } idle_pulse(engine, rq); i915_request_add(rq); - return 0; +out_rpm: + intel_engine_pm_put(engine); + return err; } #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.h b/drivers/gpu/drm/i915/gt/intel_engine_pm.h index 24e20344dc22..e52c2b0cb245 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.h @@ -7,6 +7,7 @@ #ifndef INTEL_ENGINE_PM_H #define INTEL_ENGINE_PM_H +#include "i915_request.h" #include "intel_engine_types.h" #include "intel_wakeref.h" @@ -41,6 +42,26 @@ static inline void intel_engine_pm_flush(struct intel_engine_cs *engine) intel_wakeref_unlock_wait(&engine->wakeref); } +static inline struct i915_request * +intel_engine_create_kernel_request(struct intel_engine_cs *engine) +{ + struct i915_request *rq; + + /* + * The engine->kernel_context is special as it is used inside + * the engine-pm barrier (see __engine_park()), circumventing + * the usual mutexes and relying on the engine-pm barrier + * instead. So whenever we use the engine->kernel_context + * outside of the barrier, we must manually handle the + * engine wakeref to serialise with the use inside. + */ + intel_engine_pm_get(engine); + rq = i915_request_create(engine->kernel_context); + intel_engine_pm_put(engine); + + return rq; +} + void intel_engine_init__pm(struct intel_engine_cs *engine); #endif /* INTEL_ENGINE_PM_H */ diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 226bd4cccb48..0c6d398980ba 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -6,6 +6,7 @@ #include "i915_drv.h" #include "intel_context.h" +#include "intel_engine_pm.h" #include "intel_gt.h" #include "intel_ring.h" #include "intel_workarounds.h" @@ -1582,7 +1583,9 @@ static int engine_wa_list_verify(struct intel_context *ce, if (IS_ERR(vma)) return PTR_ERR(vma); + intel_engine_pm_get(ce->engine); rq = intel_context_create_request(ce); + intel_engine_pm_put(ce->engine); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto err_vma; diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index 5bc124574170..af354ccdbf40 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -121,7 +121,7 @@ static int __live_context_size(struct intel_engine_cs *engine, goto err_unpin; /* Force the context switch */ - rq = i915_request_create(engine->kernel_context); + rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto err_unpin; diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c index 5981a7b71ec9..761d81f4bd68 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c @@ -132,14 +132,18 @@ static int perf_mi_bb_start(void *arg) u32 cycles[COUNT]; int i; + intel_engine_pm_get(engine); + batch = create_empty_batch(ce); if (IS_ERR(batch)) { err = PTR_ERR(batch); + intel_engine_pm_put(engine); break; } err = i915_vma_sync(batch); if (err) { + intel_engine_pm_put(engine); i915_vma_put(batch); break; } @@ -180,6 +184,7 @@ out: cycles[i] = rq->hwsp_seqno[3] - rq->hwsp_seqno[2]; } i915_vma_put(batch); + intel_engine_pm_put(engine); if (err) break; @@ -251,15 +256,19 @@ static int perf_mi_noop(void *arg) u32 cycles[COUNT]; int i; + intel_engine_pm_get(engine); + base = create_empty_batch(ce); if (IS_ERR(base)) { err = PTR_ERR(base); + intel_engine_pm_put(engine); break; } err = i915_vma_sync(base); if (err) { i915_vma_put(base); + intel_engine_pm_put(engine); break; } @@ -267,6 +276,7 @@ static int perf_mi_noop(void *arg) if (IS_ERR(nop)) { err = PTR_ERR(nop); i915_vma_put(base); + intel_engine_pm_put(engine); break; } @@ -274,6 +284,7 @@ static int perf_mi_noop(void *arg) if (err) { i915_vma_put(nop); i915_vma_put(base); + intel_engine_pm_put(engine); break; } @@ -327,6 +338,7 @@ out: } i915_vma_put(nop); i915_vma_put(base); + intel_engine_pm_put(engine); if (err) break; diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index fc142dd61dd1..ac8b9116d307 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -348,7 +348,7 @@ release_queue(struct intel_engine_cs *engine, struct i915_request *rq; u32 *cs; - rq = i915_request_create(engine->kernel_context); + rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) return PTR_ERR(rq); @@ -497,7 +497,7 @@ static struct i915_request *nop_request(struct intel_engine_cs *engine) { struct i915_request *rq; - rq = i915_request_create(engine->kernel_context); + rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) return rq; @@ -3698,7 +3698,7 @@ static int gpr_make_dirty(struct intel_engine_cs *engine) u32 *cs; int n; - rq = i915_request_create(engine->kernel_context); + rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) return PTR_ERR(rq); diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c index a34d4fb52fa1..de010f527757 100644 --- a/drivers/gpu/drm/i915/gt/selftest_mocs.c +++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c @@ -261,7 +261,9 @@ static int live_mocs_kernel(void *arg) return err; for_each_engine(engine, gt, id) { + intel_engine_pm_get(engine); err = check_mocs_engine(&mocs, engine->kernel_context); + intel_engine_pm_put(engine); if (err) break; } diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index f04a59fe5d2c..e2d78cc22fb4 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -458,7 +458,7 @@ tl_write(struct intel_timeline *tl, struct intel_engine_cs *engine, u32 value) goto out; } - rq = i915_request_create(engine->kernel_context); + rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) goto out_unpin; @@ -675,9 +675,7 @@ static int live_hwsp_wrap(void *arg) if (!intel_engine_can_store_dword(engine)) continue; - intel_engine_pm_get(engine); - rq = i915_request_create(engine->kernel_context); - intel_engine_pm_put(engine); + rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out; diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 608e6c3f3c1a..b46715b57576 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1968,7 +1968,9 @@ static int emit_oa_config(struct i915_perf_stream *stream, if (err) goto err_vma_put; + intel_engine_pm_get(ce->engine); rq = i915_request_create(ce); + intel_engine_pm_put(ce->engine); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto err_vma_unpin; @@ -2165,7 +2167,7 @@ static int gen8_modify_context(struct intel_context *ce, lockdep_assert_held(&ce->pin_mutex); - rq = i915_request_create(ce->engine->kernel_context); + rq = intel_engine_create_kernel_request(ce->engine); if (IS_ERR(rq)) return PTR_ERR(rq); diff --git a/drivers/gpu/drm/i915/selftests/i915_active.c b/drivers/gpu/drm/i915/selftests/i915_active.c index 60290f78750d..6c1db3ded446 100644 --- a/drivers/gpu/drm/i915/selftests/i915_active.c +++ b/drivers/gpu/drm/i915/selftests/i915_active.c @@ -99,7 +99,7 @@ __live_active_setup(struct drm_i915_private *i915) for_each_uabi_engine(engine, i915) { struct i915_request *rq; - rq = i915_request_create(engine->kernel_context); + rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) { err = PTR_ERR(rq); break; diff --git a/drivers/gpu/drm/i915/selftests/i915_perf.c b/drivers/gpu/drm/i915/selftests/i915_perf.c index aabd07f67e49..d1a1568c47ba 100644 --- a/drivers/gpu/drm/i915/selftests/i915_perf.c +++ b/drivers/gpu/drm/i915/selftests/i915_perf.c @@ -132,7 +132,7 @@ static int live_noa_delay(void *arg) for (i = 0; i < 4; i++) intel_write_status_page(stream->engine, 0x100 + i, 0); - rq = i915_request_create(stream->engine->kernel_context); + rq = intel_engine_create_kernel_request(stream->engine); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out; diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index c16d1efd2ad4..99c94b4f69fb 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -27,6 +27,7 @@ #include "gem/i915_gem_pm.h" #include "gem/selftests/mock_context.h" +#include "gt/intel_engine_pm.h" #include "gt/intel_gt.h" #include "i915_random.h" @@ -541,6 +542,7 @@ static int live_nop_request(void *arg) if (err) return err; + intel_engine_pm_get(engine); for_each_prime_number_from(prime, 1, 8192) { struct i915_request *request = NULL; @@ -579,6 +581,7 @@ static int live_nop_request(void *arg) if (__igt_timeout(end_time, NULL)) break; } + intel_engine_pm_put(engine); err = igt_live_test_end(&t); if (err) @@ -693,10 +696,13 @@ static int live_empty_request(void *arg) if (err) goto out_batch; + intel_engine_pm_get(engine); + /* Warmup / preload */ request = empty_request(engine, batch); if (IS_ERR(request)) { err = PTR_ERR(request); + intel_engine_pm_put(engine); goto out_batch; } i915_request_wait(request, 0, MAX_SCHEDULE_TIMEOUT); @@ -709,6 +715,7 @@ static int live_empty_request(void *arg) request = empty_request(engine, batch); if (IS_ERR(request)) { err = PTR_ERR(request); + intel_engine_pm_put(engine); goto out_batch; } } @@ -722,6 +729,7 @@ static int live_empty_request(void *arg) break; } i915_request_put(request); + intel_engine_pm_put(engine); err = igt_live_test_end(&t); if (err) @@ -846,7 +854,7 @@ static int live_all_engines(void *arg) idx = 0; for_each_uabi_engine(engine, i915) { - request[idx] = i915_request_create(engine->kernel_context); + request[idx] = intel_engine_create_kernel_request(engine); if (IS_ERR(request[idx])) { err = PTR_ERR(request[idx]); pr_err("%s: Request allocation failed with err=%d\n", @@ -963,7 +971,7 @@ static int live_sequential_engines(void *arg) goto out_free; } - request[idx] = i915_request_create(engine->kernel_context); + request[idx] = intel_engine_create_kernel_request(engine); if (IS_ERR(request[idx])) { err = PTR_ERR(request[idx]); pr_err("%s: Request allocation failed for %s with err=%d\n", @@ -1068,15 +1076,19 @@ static int __live_parallel_engine1(void *arg) struct intel_engine_cs *engine = arg; IGT_TIMEOUT(end_time); unsigned long count; + int err = 0; count = 0; + intel_engine_pm_get(engine); do { struct i915_request *rq; - int err; rq = i915_request_create(engine->kernel_context); - if (IS_ERR(rq)) - return PTR_ERR(rq); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + if (err) + break; + } i915_request_get(rq); i915_request_add(rq); @@ -1086,13 +1098,14 @@ static int __live_parallel_engine1(void *arg) err = -ETIME; i915_request_put(rq); if (err) - return err; + break; count++; } while (!__igt_timeout(end_time, NULL)); + intel_engine_pm_put(engine); pr_info("%s: %lu request + sync\n", engine->name, count); - return 0; + return err; } static int __live_parallel_engineN(void *arg) @@ -1100,21 +1113,26 @@ static int __live_parallel_engineN(void *arg) struct intel_engine_cs *engine = arg; IGT_TIMEOUT(end_time); unsigned long count; + int err = 0; count = 0; + intel_engine_pm_get(engine); do { struct i915_request *rq; rq = i915_request_create(engine->kernel_context); - if (IS_ERR(rq)) - return PTR_ERR(rq); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + break; + } i915_request_add(rq); count++; } while (!__igt_timeout(end_time, NULL)); + intel_engine_pm_put(engine); pr_info("%s: %lu requests\n", engine->name, count); - return 0; + return err; } static bool wake_all(struct drm_i915_private *i915) @@ -1158,9 +1176,11 @@ static int __live_parallel_spin(void *arg) return -ENOMEM; } + intel_engine_pm_get(engine); rq = igt_spinner_create_request(&spin, engine->kernel_context, MI_NOOP); /* no preemption */ + intel_engine_pm_put(engine); if (IS_ERR(rq)) { err = PTR_ERR(rq); if (err == -ENODEV) diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index b60916561462..04d0aa7b349e 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -506,7 +506,9 @@ static int igt_lmem_write_cpu(void *arg) } /* Put the pages into a known state -- from the gpu for added fun */ + intel_engine_pm_get(engine); err = i915_gem_object_fill_blt(obj, engine->kernel_context, 0xdeadbeaf); + intel_engine_pm_put(engine); if (err) goto out_unpin; -- cgit v1.2.3 From 88a4655e75ac8f55eea5e3f38b176cba9cf653b5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Nov 2019 10:58:57 +0000 Subject: drm/i915/gt: Adapt engine_park synchronisation rules for engine_retire In the next patch, we will introduce a new asynchronous retirement worker, fed by execlists CS events. Here we may queue a retirement as soon as a request is submitted to HW (and completes instantly), and we also want to process that retirement as early as possible and cannot afford to postpone (as there may not be another opportunity to retire it for a few seconds). To allow the new async retirer to run in parallel with our submission, pull the __i915_request_queue (that passes the request to HW) inside the timelines spinlock so that the retirement cannot release the timeline before we have completed the submission. v2: Actually to play nicely with engine_retire, we have to raise the timeline.active_lock before releasing the HW. intel_gt_retire_requsts() is still serialised by the outer lock so they cannot see this intermediate state, and engine_retire is serialised by HW submission. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191125105858.1718307-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 373a4b9f159c..0e1ad4a4bd97 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -74,16 +74,33 @@ static inline void __timeline_mark_unlock(struct intel_context *ce, #endif /* !IS_ENABLED(CONFIG_LOCKDEP) */ static void -__intel_timeline_enter_and_release_pm(struct intel_timeline *tl, - struct intel_engine_cs *engine) +__queue_and_release_pm(struct i915_request *rq, + struct intel_timeline *tl, + struct intel_engine_cs *engine) { struct intel_gt_timelines *timelines = &engine->gt->timelines; + GEM_TRACE("%s\n", engine->name); + + /* + * We have to serialise all potential retirement paths with our + * submission, as we don't want to underflow either the + * engine->wakeref.counter or our timeline->active_count. + * + * Equally, we cannot allow a new submission to start until + * after we finish queueing, nor could we allow that submitter + * to retire us before we are ready! + */ spin_lock(&timelines->lock); + /* Let intel_gt_retire_requests() retire us (acquired under lock) */ if (!atomic_fetch_inc(&tl->active_count)) list_add_tail(&tl->link, &timelines->active_list); + /* Hand the request over to HW and so engine_retire() */ + __i915_request_queue(rq, NULL); + + /* Let new submissions commence (and maybe retire this timeline) */ __intel_wakeref_defer_park(&engine->wakeref); spin_unlock(&timelines->lock); @@ -148,10 +165,8 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) rq->sched.attr.priority = I915_PRIORITY_BARRIER; __i915_request_commit(rq); - __i915_request_queue(rq, NULL); - - /* Expose ourselves to intel_gt_retire_requests() and new submission */ - __intel_timeline_enter_and_release_pm(ce->timeline, engine); + /* Expose ourselves to the world */ + __queue_and_release_pm(rq, ce->timeline, engine); result = false; out_unlock: -- cgit v1.2.3 From 4f88f8747fa43c97c3b3712d8d87295ea757cc51 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Nov 2019 10:58:58 +0000 Subject: drm/i915/gt: Schedule request retirement when timeline idles The major drawback of commit 7e34f4e4aad3 ("drm/i915/gen8+: Add RC6 CTX corruption WA") is that it disables RC6 while Skylake (and friends) is active, and we do not consider the GPU idle until all outstanding requests have been retired and the engine switched over to the kernel context. If userspace is idle, this task falls onto our background idle worker, which only runs roughly once a second, meaning that userspace has to have been idle for a couple of seconds before we enable RC6 again. Naturally, this causes us to consume considerably more energy than before as powersaving is effectively disabled while a display server (here's looking at you Xorg) is running. As execlists will get a completion event as each context is completed, we can use this interrupt to queue a retire worker bound to this engine to cleanup idle timelines. We will then immediately notice the idle engine (without userspace intervention or the aid of the background retire worker) and start parking the GPU. Thus during light workloads, we will do much more work to idle the GPU faster... Hopefully with commensurate power saving! v2: Watch context completions and only look at those local to the engine when retiring to reduce the amount of excess work we perform. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112315 References: 7e34f4e4aad3 ("drm/i915/gen8+: Add RC6 CTX corruption WA") References: 2248a28384fe ("drm/i915/gen8+: Add RC6 CTX corruption WA") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191125105858.1718307-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 8 +-- drivers/gpu/drm/i915/gt/intel_engine_types.h | 8 +++ drivers/gpu/drm/i915/gt/intel_gt_requests.c | 75 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_gt_requests.h | 7 +++ drivers/gpu/drm/i915/gt/intel_lrc.c | 9 ++++ drivers/gpu/drm/i915/gt/intel_timeline.c | 1 + drivers/gpu/drm/i915/gt/intel_timeline_types.h | 3 ++ 7 files changed, 108 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index b9613d044393..8f6e353caa66 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -28,13 +28,13 @@ #include "i915_drv.h" -#include "gt/intel_gt.h" - +#include "intel_context.h" #include "intel_engine.h" #include "intel_engine_pm.h" #include "intel_engine_pool.h" #include "intel_engine_user.h" -#include "intel_context.h" +#include "intel_gt.h" +#include "intel_gt_requests.h" #include "intel_lrc.h" #include "intel_reset.h" #include "intel_ring.h" @@ -617,6 +617,7 @@ static int intel_engine_setup_common(struct intel_engine_cs *engine) intel_engine_init_execlists(engine); intel_engine_init_cmd_parser(engine); intel_engine_init__pm(engine); + intel_engine_init_retire(engine); intel_engine_pool_init(&engine->pool); @@ -839,6 +840,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) cleanup_status_page(engine); + intel_engine_fini_retire(engine); intel_engine_pool_fini(&engine->pool); intel_engine_fini_breadcrumbs(engine); intel_engine_cleanup_cmd_parser(engine); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 758f0e8ec672..17f1f1441efc 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -451,6 +451,14 @@ struct intel_engine_cs { struct intel_engine_execlists execlists; + /* + * Keep track of completed timelines on this engine for early + * retirement with the goal of quickly enabling powersaving as + * soon as the engine is idle. + */ + struct intel_timeline *retire; + struct work_struct retire_work; + /* status_notifier: list of callbacks for context-switch changes */ struct atomic_notifier_head context_status_notifier; diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index f02f781b8492..8cb5421e5f0e 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -4,6 +4,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include "i915_drv.h" /* for_each_engine() */ #include "i915_request.h" #include "intel_gt.h" @@ -29,6 +31,79 @@ static void flush_submission(struct intel_gt *gt) intel_engine_flush_submission(engine); } +static void engine_retire(struct work_struct *work) +{ + struct intel_engine_cs *engine = + container_of(work, typeof(*engine), retire_work); + struct intel_timeline *tl = xchg(&engine->retire, NULL); + + do { + struct intel_timeline *next = xchg(&tl->retire, NULL); + + /* + * Our goal here is to retire _idle_ timelines as soon as + * possible (as they are idle, we do not expect userspace + * to be cleaning up anytime soon). + * + * If the timeline is currently locked, either it is being + * retired elsewhere or about to be! + */ + if (mutex_trylock(&tl->mutex)) { + retire_requests(tl); + mutex_unlock(&tl->mutex); + } + intel_timeline_put(tl); + + GEM_BUG_ON(!next); + tl = ptr_mask_bits(next, 1); + } while (tl); +} + +static bool add_retire(struct intel_engine_cs *engine, + struct intel_timeline *tl) +{ + struct intel_timeline *first; + + /* + * We open-code a llist here to include the additional tag [BIT(0)] + * so that we know when the timeline is already on a + * retirement queue: either this engine or another. + * + * However, we rely on that a timeline can only be active on a single + * engine at any one time and that add_retire() is called before the + * engine releases the timeline and transferred to another to retire. + */ + + if (READ_ONCE(tl->retire)) /* already queued */ + return false; + + intel_timeline_get(tl); + first = READ_ONCE(engine->retire); + do + tl->retire = ptr_pack_bits(first, 1, 1); + while (!try_cmpxchg(&engine->retire, &first, tl)); + + return !first; +} + +void intel_engine_add_retire(struct intel_engine_cs *engine, + struct intel_timeline *tl) +{ + if (add_retire(engine, tl)) + schedule_work(&engine->retire_work); +} + +void intel_engine_init_retire(struct intel_engine_cs *engine) +{ + INIT_WORK(&engine->retire_work, engine_retire); +} + +void intel_engine_fini_retire(struct intel_engine_cs *engine) +{ + flush_work(&engine->retire_work); + GEM_BUG_ON(engine->retire); +} + long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) { struct intel_gt_timelines *timelines = >->timelines; diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.h b/drivers/gpu/drm/i915/gt/intel_gt_requests.h index fde546424c63..dbac53baf1cb 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.h @@ -7,7 +7,9 @@ #ifndef INTEL_GT_REQUESTS_H #define INTEL_GT_REQUESTS_H +struct intel_engine_cs; struct intel_gt; +struct intel_timeline; long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout); static inline void intel_gt_retire_requests(struct intel_gt *gt) @@ -15,6 +17,11 @@ static inline void intel_gt_retire_requests(struct intel_gt *gt) intel_gt_retire_requests_timeout(gt, 0); } +void intel_engine_init_retire(struct intel_engine_cs *engine); +void intel_engine_add_retire(struct intel_engine_cs *engine, + struct intel_timeline *tl); +void intel_engine_fini_retire(struct intel_engine_cs *engine); + int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout); void intel_gt_init_requests(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 6090357a00fa..4cd0d46b5da6 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -142,6 +142,7 @@ #include "intel_engine_pm.h" #include "intel_gt.h" #include "intel_gt_pm.h" +#include "intel_gt_requests.h" #include "intel_lrc_reg.h" #include "intel_mocs.h" #include "intel_reset.h" @@ -1170,6 +1171,14 @@ __execlists_schedule_out(struct i915_request *rq, * refrain from doing non-trivial work here. */ + /* + * If we have just completed this context, the engine may now be + * idle and we want to re-enter powersaving. + */ + if (list_is_last(&rq->link, &ce->timeline->requests) && + i915_request_completed(rq)) + intel_engine_add_retire(engine, ce->timeline); + intel_engine_context_out(engine); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); intel_gt_pm_put_async(engine->gt); diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index b190a5d9ab02..c1d2419444f8 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -277,6 +277,7 @@ void intel_timeline_fini(struct intel_timeline *timeline) { GEM_BUG_ON(atomic_read(&timeline->pin_count)); GEM_BUG_ON(!list_empty(&timeline->requests)); + GEM_BUG_ON(timeline->retire); if (timeline->hwsp_cacheline) cacheline_free(timeline->hwsp_cacheline); diff --git a/drivers/gpu/drm/i915/gt/intel_timeline_types.h b/drivers/gpu/drm/i915/gt/intel_timeline_types.h index 5244615ed1cb..aaf15cbe1ce1 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline_types.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline_types.h @@ -66,6 +66,9 @@ struct intel_timeline { */ struct i915_active_fence last_request; + /** A chain of completed timelines ready for early retirement. */ + struct intel_timeline *retire; + /** * We track the most recent seqno that we wait on in every context so * that we only have to emit a new await and dependency on a more -- cgit v1.2.3 From 34f5fe1243f072d9a10065a06d4b421f01636c09 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Nov 2019 12:48:56 +0000 Subject: drm/i915/selftests: Move mock_vma to the heap to reduce stack_frame An i915_vma struct on the stack may push the frame over the limit, if set conservatively, so move it to the heap. Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191125124856.1761176-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index d94db487c4dd..f7aa0036d900 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -212,10 +212,12 @@ static int lowlevel_hole(struct drm_i915_private *i915, unsigned long end_time) { I915_RND_STATE(seed_prng); + struct i915_vma *mock_vma; unsigned int size; - struct i915_vma mock_vma; - memset(&mock_vma, 0, sizeof(struct i915_vma)); + mock_vma = kzalloc(sizeof(*mock_vma), GFP_KERNEL); + if (!mock_vma) + return -ENOMEM; /* Keep creating larger objects until one cannot fit into the hole */ for (size = 12; (hole_end - hole_start) >> size; size++) { @@ -239,8 +241,10 @@ static int lowlevel_hole(struct drm_i915_private *i915, if (order) break; } while (count >>= 1); - if (!count) + if (!count) { + kfree(mock_vma); return -ENOMEM; + } GEM_BUG_ON(!order); GEM_BUG_ON(count * BIT_ULL(size) > vm->total); @@ -283,12 +287,12 @@ static int lowlevel_hole(struct drm_i915_private *i915, vm->allocate_va_range(vm, addr, BIT_ULL(size))) break; - mock_vma.pages = obj->mm.pages; - mock_vma.node.size = BIT_ULL(size); - mock_vma.node.start = addr; + mock_vma->pages = obj->mm.pages; + mock_vma->node.size = BIT_ULL(size); + mock_vma->node.start = addr; with_intel_runtime_pm(&i915->runtime_pm, wakeref) - vm->insert_entries(vm, &mock_vma, + vm->insert_entries(vm, mock_vma, I915_CACHE_NONE, 0); } count = n; @@ -311,6 +315,7 @@ static int lowlevel_hole(struct drm_i915_private *i915, cleanup_freed_objects(i915); } + kfree(mock_vma); return 0; } -- cgit v1.2.3 From 5766a5ffc6a69595903865518c43636bde0e4ac4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 25 Nov 2019 16:27:37 +0000 Subject: drm/i915: Default to a more lenient forced preemption timeout Based on a sampling of a number of benchmarks across platforms, by default opt for a much more lenient timeout so that we should not adversely affect existing "good" clients. 640ms ought to be enough for anyone. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112169 Fixes: 3a7a92aba8fb ("drm/i915/execlists: Force preemption") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Eero Tamminen Cc: Dmitry Rogozhkin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191125162737.2161069-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Kconfig.profile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/Kconfig.profile b/drivers/gpu/drm/i915/Kconfig.profile index 1799537a3228..c280b6ae38eb 100644 --- a/drivers/gpu/drm/i915/Kconfig.profile +++ b/drivers/gpu/drm/i915/Kconfig.profile @@ -25,7 +25,7 @@ config DRM_I915_HEARTBEAT_INTERVAL config DRM_I915_PREEMPT_TIMEOUT int "Preempt timeout (ms, jiffy granularity)" - default 100 # milliseconds + default 640 # milliseconds help How long to wait (in milliseconds) for a preemption event to occur when submitting a new context via execlists. If the current context -- cgit v1.2.3 From 58b4c1a07ada7fb91ea757bdb9bd47df02207357 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 26 Nov 2019 06:55:21 +0000 Subject: drm/i915: Reduce nested prepare_remote_context() to a trylock On context retiring, we may invoke the kernel_context to unpin this context. Elsewhere, we may use the kernel_context to modify this context. This currently leads to an AB-BA lock inversion, so we need to back-off from the contended lock, and repeat. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111732 Signed-off-by: Chris Wilson Fixes: a9877da2d629 ("drm/i915/oa: Reconfigure contexts on the fly") Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191126065521.2331017-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_context.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index ee9d2bcd2c13..ef7bc41ffffa 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -310,10 +310,23 @@ int intel_context_prepare_remote_request(struct intel_context *ce, GEM_BUG_ON(rq->hw_context == ce); if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */ - err = mutex_lock_interruptible_nested(&tl->mutex, - SINGLE_DEPTH_NESTING); - if (err) - return err; + /* + * Ideally, we just want to insert our foreign fence as + * a barrier into the remove context, such that this operation + * occurs after all current operations in that context, and + * all future operations must occur after this. + * + * Currently, the timeline->last_request tracking is guarded + * by its mutex and so we must obtain that to atomically + * insert our barrier. However, since we already hold our + * timeline->mutex, we must be careful against potential + * inversion if we are the kernel_context as the remote context + * will itself poke at the kernel_context when it needs to + * unpin. Ergo, if already locked, we drop both locks and + * try again (through the magic of userspace repeating EAGAIN). + */ + if (!mutex_trylock(&tl->mutex)) + return -EAGAIN; /* Queue this switch after current activity by this context. */ err = i915_active_fence_set(&tl->last_request, rq); -- cgit v1.2.3 From 9b93daa93ebe85bd7f355f4f043f3e52e67c86cf Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Mon, 25 Nov 2019 18:08:00 +0200 Subject: drm/i915: Support more QGV points MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to BSpec 53998, there is a mask of max 8 SAGV/QGV points we need to support. Bumping this up to keep the CI happy(currently preventing tests to run), until all SAGV changes land. v2: Fix second plane where QGV points were hardcoded as well. v3: Change the naming of I915_NUM_SAGV_POINTS to be I915_NUM_QGV_POINTS, as more meaningful (Ville Syrjälä) Reviewed-by: Ville Syrjälä Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112189 Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20191125160800.14740-1-stanislav.lisovskiy@intel.com [vsyrjala: Add missing braces around else (checkpatch), fix Bugzilla tag] Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/display/intel_bw.c | 24 ++++++++++++++++++------ drivers/gpu/drm/i915/i915_drv.h | 6 +++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 86e75e858008..dcb66a33be9b 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -15,7 +15,7 @@ struct intel_qgv_point { }; struct intel_qgv_info { - struct intel_qgv_point points[3]; + struct intel_qgv_point points[I915_NUM_QGV_POINTS]; u8 num_points; u8 num_channels; u8 t_bl; @@ -276,17 +276,29 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv) static unsigned int intel_max_data_rate(struct drm_i915_private *dev_priv, int num_planes) { - if (INTEL_GEN(dev_priv) >= 11) + if (INTEL_GEN(dev_priv) >= 11) { + /* + * Any bw group has same amount of QGV points + */ + const struct intel_bw_info *bi = + &dev_priv->max_bw[0]; + unsigned int min_bw = UINT_MAX; + int i; + /* * FIXME with SAGV disabled maybe we can assume * point 1 will always be used? Seems to match * the behaviour observed in the wild. */ - return min3(icl_max_bw(dev_priv, num_planes, 0), - icl_max_bw(dev_priv, num_planes, 1), - icl_max_bw(dev_priv, num_planes, 2)); - else + for (i = 0; i < bi->num_qgv_points; i++) { + unsigned int bw = icl_max_bw(dev_priv, num_planes, i); + + min_bw = min(bw, min_bw); + } + return min_bw; + } else { return UINT_MAX; + } } static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fdae5a919bc8..14744c114475 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -621,6 +621,9 @@ struct i915_gem_mm { #define I915_ENGINE_WEDGED_TIMEOUT (60 * HZ) /* Reset but no recovery? */ +/* Amount of SAGV/QGV points, BSpec precisely defines this */ +#define I915_NUM_QGV_POINTS 8 + struct ddi_vbt_port_info { /* Non-NULL if port present. */ const struct child_device_config *child; @@ -1232,7 +1235,8 @@ struct drm_i915_private { } dram_info; struct intel_bw_info { - unsigned int deratedbw[3]; /* for each QGV point */ + /* for each QGV point */ + unsigned int deratedbw[I915_NUM_QGV_POINTS]; u8 num_qgv_points; u8 num_planes; } max_bw[6]; -- cgit v1.2.3 From 071309814d68ad7ce01bbbd99c0116e59f13c239 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 25 Nov 2019 14:53:12 +0200 Subject: drm/i915/dp: fix DP audio for PORT_A on gen12+ Starting with gen12, PORT_A can be connected to a transcoder with audio support. Modify the existing logic that disabled audio on PORT_A unconditionally. Signed-off-by: Kai Vehmanen Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191125125313.17584-1-kai.vehmanen@linux.intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9e9593965a9a..511c6ae04ad0 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2308,6 +2308,17 @@ bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state, } } +static bool intel_dp_port_has_audio(struct drm_i915_private *dev_priv, + enum port port) +{ + if (IS_G4X(dev_priv)) + return false; + if (INTEL_GEN(dev_priv) < 12 && port == PORT_A) + return false; + + return true; +} + int intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -2341,7 +2352,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, return ret; pipe_config->has_drrs = false; - if (IS_G4X(dev_priv) || port == PORT_A) + if (!intel_dp_port_has_audio(dev_priv, port)) pipe_config->has_audio = false; else if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) pipe_config->has_audio = intel_dp->has_audio; -- cgit v1.2.3 From 7e7129dcbd81721b8f69a535c686cedfded888c1 Mon Sep 17 00:00:00 2001 From: Clint Taylor Date: Thu, 21 Nov 2019 12:14:55 -0800 Subject: drm/i915: Disable display interrupts during display IRQ handler During the Display Interrupt Service routine the Display Interrupt Enable bit must be disabled, The interrupts handled, then the Display Interrupt Enable bit must be set to prevent possible missed interrupts. Bspec: 49212 V2: Change Title to remove SDE reference. V3: Fix TAB spacing. Cc: Lucas De Marchi Cc: Aditya Swarup Reviewed-by: Matt Roper Signed-off-by: Clint Taylor Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20191121201455.2558-1-clinton.a.taylor@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index dae00f7dd7df..8b338744eddf 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2484,7 +2484,11 @@ __gen11_irq_handler(struct drm_i915_private * const i915, * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ * for the display related bits. */ + raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0); gen8_de_irq_handler(i915, disp_ctl); + raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, + GEN11_DISPLAY_IRQ_ENABLE); + enable_rpm_wakeref_asserts(&i915->runtime_pm); } -- cgit v1.2.3 From 730eaeb5242614eb202dd3ae4cebad3d2438db38 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Nov 2019 09:56:57 +0000 Subject: drm/i915/gt: Manual rc6 entry upon parking Now that we rapidly park the GT when the GPU idles, we often find ourselves idling faster than the RC6 promotion timer. Thus if we tell the GPU to enter RC6 manually as we park, we can do so quicker (by around 50ms, half an EI on average) and marginally increase our powersaving across all execlists platforms. v2: Now with a selftest to check we can enter RC6 manually Signed-off-by: Chris Wilson Cc: Andi Shyti Cc: Mika Kuoppala Cc: Imre Deak Acked-by: Imre Deak Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191127095657.3209854-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 2 ++ drivers/gpu/drm/i915/gt/intel_rc6.c | 53 ++++++++++++++++++++-------- drivers/gpu/drm/i915/gt/intel_rc6.h | 3 ++ drivers/gpu/drm/i915/gt/intel_rc6_types.h | 2 ++ drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 1 + drivers/gpu/drm/i915/gt/selftest_rc6.c | 58 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gt/selftest_rc6.h | 1 + 7 files changed, 105 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 9d3045096e37..2000018b6464 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -64,6 +64,7 @@ static int __gt_unpark(struct intel_wakeref *wf) if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); + intel_rc6_unpark(>->rc6); intel_rps_unpark(>->rps); i915_pmu_gt_unparked(i915); @@ -85,6 +86,7 @@ static int __gt_park(struct intel_wakeref *wf) i915_vma_parked(gt); i915_pmu_gt_parked(i915); intel_rps_park(>->rps); + intel_rc6_park(>->rc6); /* Everything switched off, flush any residual interrupt just in case */ intel_synchronize_irq(i915); diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 7a0bc6dde009..c4379c49c20d 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -96,10 +96,10 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) set(uncore, GEN9_RENDER_PG_IDLE_HYSTERESIS, 60); /* 3a: Enable RC6 */ - set(uncore, GEN6_RC_CONTROL, - GEN6_RC_CTL_HW_ENABLE | - GEN6_RC_CTL_RC6_ENABLE | - GEN6_RC_CTL_EI_MODE(1)); + rc6->ctl_enable = + GEN6_RC_CTL_HW_ENABLE | + GEN6_RC_CTL_RC6_ENABLE | + GEN6_RC_CTL_EI_MODE(1); set(uncore, GEN9_PG_ENABLE, GEN9_RENDER_PG_ENABLE | @@ -170,10 +170,10 @@ static void gen9_rc6_enable(struct intel_rc6 *rc6) else rc6_mode = GEN6_RC_CTL_EI_MODE(1); - set(uncore, GEN6_RC_CONTROL, - GEN6_RC_CTL_HW_ENABLE | - GEN6_RC_CTL_RC6_ENABLE | - rc6_mode); + rc6->ctl_enable = + GEN6_RC_CTL_HW_ENABLE | + GEN6_RC_CTL_RC6_ENABLE | + rc6_mode; /* * WaRsDisableCoarsePowerGating:skl,cnl @@ -200,10 +200,10 @@ static void gen8_rc6_enable(struct intel_rc6 *rc6) set(uncore, GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */ /* 3: Enable RC6 */ - set(uncore, GEN6_RC_CONTROL, + rc6->ctl_enable = GEN6_RC_CTL_HW_ENABLE | GEN7_RC_CTL_TO_MODE | - GEN6_RC_CTL_RC6_ENABLE); + GEN6_RC_CTL_RC6_ENABLE; } static void gen6_rc6_enable(struct intel_rc6 *rc6) @@ -239,10 +239,10 @@ static void gen6_rc6_enable(struct intel_rc6 *rc6) rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; if (HAS_RC6pp(i915)) rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; - set(uncore, GEN6_RC_CONTROL, + rc6->ctl_enable = rc6_mask | GEN6_RC_CTL_EI_MODE(1) | - GEN6_RC_CTL_HW_ENABLE); + GEN6_RC_CTL_HW_ENABLE; rc6vids = 0; ret = sandybridge_pcode_read(i915, GEN6_PCODE_READ_RC6VIDS, @@ -360,7 +360,7 @@ static void chv_rc6_enable(struct intel_rc6 *rc6) VLV_RENDER_RC6_COUNT_EN)); /* 3: Enable RC6 */ - set(uncore, GEN6_RC_CONTROL, GEN7_RC_CTL_TO_MODE); + rc6->ctl_enable = GEN7_RC_CTL_TO_MODE; } static void vlv_rc6_enable(struct intel_rc6 *rc6) @@ -386,8 +386,8 @@ static void vlv_rc6_enable(struct intel_rc6 *rc6) VLV_MEDIA_RC6_COUNT_EN | VLV_RENDER_RC6_COUNT_EN)); - set(uncore, GEN6_RC_CONTROL, - GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL); + rc6->ctl_enable = + GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL; } static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6) @@ -634,6 +634,29 @@ void intel_rc6_enable(struct intel_rc6 *rc6) rc6->enabled = true; } +void intel_rc6_unpark(struct intel_rc6 *rc6) +{ + struct intel_uncore *uncore = rc6_to_uncore(rc6); + + if (!rc6->enabled) + return; + + /* Restore HW timers for automatic RC6 entry while busy */ + set(uncore, GEN6_RC_CONTROL, rc6->ctl_enable); +} + +void intel_rc6_park(struct intel_rc6 *rc6) +{ + struct intel_uncore *uncore = rc6_to_uncore(rc6); + + if (!rc6->enabled) + return; + + /* Turn off the HW timers and go directly to rc6 */ + set(uncore, GEN6_RC_CONTROL, GEN6_RC_CTL_RC6_ENABLE); + set(uncore, GEN6_RC_STATE, 0x4 << RC_SW_TARGET_STATE_SHIFT); +} + void intel_rc6_disable(struct intel_rc6 *rc6) { if (!rc6->enabled) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.h b/drivers/gpu/drm/i915/gt/intel_rc6.h index 1370f6834a4c..20d740ff7e55 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.h +++ b/drivers/gpu/drm/i915/gt/intel_rc6.h @@ -15,6 +15,9 @@ struct intel_rc6; void intel_rc6_init(struct intel_rc6 *rc6); void intel_rc6_fini(struct intel_rc6 *rc6); +void intel_rc6_unpark(struct intel_rc6 *rc6); +void intel_rc6_park(struct intel_rc6 *rc6); + void intel_rc6_sanitize(struct intel_rc6 *rc6); void intel_rc6_enable(struct intel_rc6 *rc6); void intel_rc6_disable(struct intel_rc6 *rc6); diff --git a/drivers/gpu/drm/i915/gt/intel_rc6_types.h b/drivers/gpu/drm/i915/gt/intel_rc6_types.h index 89ad5697a8d4..9f3d56817c97 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6_types.h +++ b/drivers/gpu/drm/i915/gt/intel_rc6_types.h @@ -18,6 +18,8 @@ struct intel_rc6 { u64 prev_hw_residency[4]; u64 cur_residency[4]; + u32 ctl_enable; + struct drm_i915_gem_object *pctx; bool supported : 1; diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c index 5e563b877368..09ff8e4f88af 100644 --- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c @@ -51,6 +51,7 @@ static int live_gt_resume(void *arg) int intel_gt_pm_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { + SUBTEST(live_rc6_manual), SUBTEST(live_gt_resume), }; diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.c b/drivers/gpu/drm/i915/gt/selftest_rc6.c index 67b7a6bc64f5..f8b7691be4d1 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rc6.c +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.c @@ -12,6 +12,64 @@ #include "selftests/i915_random.h" +int live_rc6_manual(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_rc6 *rc6 = >->rc6; + intel_wakeref_t wakeref; + u64 res[2]; + int err = 0; + + /* + * Our claim is that we can "encourage" the GPU to enter rc6 at will. + * Let's try it! + */ + + if (!rc6->enabled) + return 0; + + /* bsw/byt use a PCU and decouple RC6 from our manual control */ + if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) + return 0; + + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + + /* Force RC6 off for starters */ + __intel_rc6_disable(rc6); + msleep(1); /* wakeup is not immediate, takes about 100us on icl */ + + res[0] = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6); + msleep(250); + res[1] = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6); + if ((res[1] - res[0]) >> 10) { + pr_err("RC6 residency increased by %lldus while disabled for 250ms!\n", + (res[1] - res[0]) >> 10); + err = -EINVAL; + goto out_unlock; + } + + /* Manually enter RC6 */ + intel_rc6_park(rc6); + + res[0] = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6); + msleep(100); + res[1] = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6); + + if (res[1] == res[0]) { + pr_err("Did not enter RC6! RC6_STATE=%08x, RC6_CONTROL=%08x\n", + intel_uncore_read_fw(gt->uncore, GEN6_RC_STATE), + intel_uncore_read_fw(gt->uncore, GEN6_RC_CONTROL)); + err = -EINVAL; + } + + /* Restore what should have been the original state! */ + intel_rc6_unpark(rc6); + +out_unlock: + intel_runtime_pm_put(gt->uncore->rpm, wakeref); + return err; +} + static const u32 *__live_rc6_ctx(struct intel_context *ce) { struct i915_request *rq; diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.h b/drivers/gpu/drm/i915/gt/selftest_rc6.h index f907e7b035ab..762fd442d7b2 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rc6.h +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.h @@ -8,5 +8,6 @@ #define SELFTEST_RC6_H int live_rc6_ctx_wa(void *arg); +int live_rc6_manual(void *arg); #endif /* SELFTEST_RC6_H */ -- cgit v1.2.3 From df9f85d8582ebda052835c55ae940e4f866e1ef5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Nov 2019 13:45:27 +0000 Subject: drm/i915: Serialise i915_active_fence_set() with itself The expected downside to commit 58b4c1a07ada ("drm/i915: Reduce nested prepare_remote_context() to a trylock") was that it would need to return -EAGAIN to userspace in order to resolve potential mutex inversion. Such an unsightly round trip is unnecessary if we could atomically insert a barrier into the i915_active_fence, so make it happen. Currently, we use the timeline->mutex (or some other named outer lock) to order insertion into the i915_active_fence (and so individual nodes of i915_active). Inside __i915_active_fence_set, we only need then serialise with the interrupt handler in order to claim the timeline for ourselves. However, if we remove the outer lock, we need to ensure the order is intact between not only multiple threads trying to insert themselves into the timeline, but also with the interrupt handler completing the previous occupant. We use xchg() on insert so that we have an ordered sequence of insertions (and each caller knows the previous fence on which to wait, preserving the chain of all fences in the timeline), but we then have to cmpxchg() in the interrupt handler to avoid overwriting the new occupant. The only nasty side-effect is having to temporarily strip off the RCU-annotations to apply the atomic operations, otherwise the rules are much more conventional! Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112402 Fixes: 58b4c1a07ada ("drm/i915: Reduce nested prepare_remote_context() to a trylock") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191127134527.3438410-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_context.c | 19 ---- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 2 +- drivers/gpu/drm/i915/gt/intel_timeline.c | 2 +- drivers/gpu/drm/i915/gt/selftests/mock_timeline.c | 2 +- drivers/gpu/drm/i915/i915_active.c | 107 ++++++++++++---------- drivers/gpu/drm/i915/i915_active.h | 17 +--- drivers/gpu/drm/i915/i915_active_types.h | 15 --- 7 files changed, 62 insertions(+), 102 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index ef7bc41ffffa..b5e9c35ec6b8 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -310,27 +310,8 @@ int intel_context_prepare_remote_request(struct intel_context *ce, GEM_BUG_ON(rq->hw_context == ce); if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */ - /* - * Ideally, we just want to insert our foreign fence as - * a barrier into the remove context, such that this operation - * occurs after all current operations in that context, and - * all future operations must occur after this. - * - * Currently, the timeline->last_request tracking is guarded - * by its mutex and so we must obtain that to atomically - * insert our barrier. However, since we already hold our - * timeline->mutex, we must be careful against potential - * inversion if we are the kernel_context as the remote context - * will itself poke at the kernel_context when it needs to - * unpin. Ergo, if already locked, we drop both locks and - * try again (through the magic of userspace repeating EAGAIN). - */ - if (!mutex_trylock(&tl->mutex)) - return -EAGAIN; - /* Queue this switch after current activity by this context. */ err = i915_active_fence_set(&tl->last_request, rq); - mutex_unlock(&tl->mutex); if (err) return err; } diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 0e1ad4a4bd97..21183ad87368 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -183,7 +183,7 @@ static void call_idle_barriers(struct intel_engine_cs *engine) container_of((struct list_head *)node, typeof(*cb), node); - cb->func(NULL, cb); + cb->func(ERR_PTR(-EAGAIN), cb); } } diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index c1d2419444f8..038e05a6336c 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -254,7 +254,7 @@ int intel_timeline_init(struct intel_timeline *timeline, mutex_init(&timeline->mutex); - INIT_ACTIVE_FENCE(&timeline->last_request, &timeline->mutex); + INIT_ACTIVE_FENCE(&timeline->last_request); INIT_LIST_HEAD(&timeline->requests); i915_syncmap_init(&timeline->sync); diff --git a/drivers/gpu/drm/i915/gt/selftests/mock_timeline.c b/drivers/gpu/drm/i915/gt/selftests/mock_timeline.c index 2a77c051f36a..aeb1d1f616e8 100644 --- a/drivers/gpu/drm/i915/gt/selftests/mock_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftests/mock_timeline.c @@ -15,7 +15,7 @@ void mock_timeline_init(struct intel_timeline *timeline, u64 context) mutex_init(&timeline->mutex); - INIT_ACTIVE_FENCE(&timeline->last_request, &timeline->mutex); + INIT_ACTIVE_FENCE(&timeline->last_request); INIT_LIST_HEAD(&timeline->requests); i915_syncmap_init(&timeline->sync); diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index dca15ace88f6..479195ecbc6c 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -186,18 +186,33 @@ active_retire(struct i915_active *ref) __active_retire(ref); } +static inline struct dma_fence ** +__active_fence_slot(struct i915_active_fence *active) +{ + return (struct dma_fence ** __force)&active->fence; +} + +static inline bool +active_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb) +{ + struct i915_active_fence *active = + container_of(cb, typeof(*active), cb); + + return cmpxchg(__active_fence_slot(active), fence, NULL) == fence; +} + static void node_retire(struct dma_fence *fence, struct dma_fence_cb *cb) { - i915_active_fence_cb(fence, cb); - active_retire(container_of(cb, struct active_node, base.cb)->ref); + if (active_fence_cb(fence, cb)) + active_retire(container_of(cb, struct active_node, base.cb)->ref); } static void excl_retire(struct dma_fence *fence, struct dma_fence_cb *cb) { - i915_active_fence_cb(fence, cb); - active_retire(container_of(cb, struct i915_active, excl.cb)); + if (active_fence_cb(fence, cb)) + active_retire(container_of(cb, struct i915_active, excl.cb)); } static struct i915_active_fence * @@ -244,7 +259,7 @@ active_instance(struct i915_active *ref, struct intel_timeline *tl) } node = prealloc; - __i915_active_fence_init(&node->base, &tl->mutex, NULL, node_retire); + __i915_active_fence_init(&node->base, NULL, node_retire); node->ref = ref; node->timeline = idx; @@ -281,7 +296,7 @@ void __i915_active_init(struct i915_active *ref, init_llist_head(&ref->preallocated_barriers); atomic_set(&ref->count, 0); __mutex_init(&ref->mutex, "i915_active", key); - __i915_active_fence_init(&ref->excl, &ref->mutex, NULL, excl_retire); + __i915_active_fence_init(&ref->excl, NULL, excl_retire); INIT_WORK(&ref->work, active_work); } @@ -376,15 +391,8 @@ void i915_active_set_exclusive(struct i915_active *ref, struct dma_fence *f) /* We expect the caller to manage the exclusive timeline ordering */ GEM_BUG_ON(i915_active_is_idle(ref)); - /* - * As we don't know which mutex the caller is using, we told a small - * lie to the debug code that it is using the i915_active.mutex; - * and now we must stick to that lie. - */ - mutex_acquire(&ref->mutex.dep_map, 0, 0, _THIS_IP_); if (!__i915_active_fence_set(&ref->excl, f)) atomic_inc(&ref->count); - mutex_release(&ref->mutex.dep_map, 0, _THIS_IP_); } bool i915_active_acquire_if_busy(struct i915_active *ref) @@ -615,10 +623,6 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, goto unwind; } -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) - node->base.lock = - &engine->kernel_context->timeline->mutex; -#endif RCU_INIT_POINTER(node->base.fence, NULL); node->base.cb.func = node_retire; node->timeline = idx; @@ -639,6 +643,7 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, node->base.cb.node.prev = (void *)engine; atomic_inc(&ref->count); } + GEM_BUG_ON(rcu_access_pointer(node->base.fence) != ERR_PTR(-EAGAIN)); GEM_BUG_ON(barrier_to_engine(node) != engine); llist_add(barrier_to_ll(node), &ref->preallocated_barriers); @@ -702,6 +707,11 @@ void i915_active_acquire_barrier(struct i915_active *ref) } } +static struct dma_fence **ll_to_fence_slot(struct llist_node *node) +{ + return __active_fence_slot(&barrier_from_ll(node)->base); +} + void i915_request_add_active_barriers(struct i915_request *rq) { struct intel_engine_cs *engine = rq->engine; @@ -721,19 +731,13 @@ void i915_request_add_active_barriers(struct i915_request *rq) */ spin_lock_irqsave(&rq->lock, flags); llist_for_each_safe(node, next, node) { - RCU_INIT_POINTER(barrier_from_ll(node)->base.fence, &rq->fence); - smp_wmb(); /* serialise with reuse_idle_barrier */ + /* serialise with reuse_idle_barrier */ + smp_store_mb(*ll_to_fence_slot(node), &rq->fence); list_add_tail((struct list_head *)node, &rq->fence.cb_list); } spin_unlock_irqrestore(&rq->lock, flags); } -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) -#define active_is_held(active) lockdep_is_held((active)->lock) -#else -#define active_is_held(active) true -#endif - /* * __i915_active_fence_set: Update the last active fence along its timeline * @active: the active tracker @@ -744,7 +748,7 @@ void i915_request_add_active_barriers(struct i915_request *rq) * fence onto this one. Returns the previous fence (if not already completed), * which the caller must ensure is executed before the new fence. To ensure * that the order of fences within the timeline of the i915_active_fence is - * maintained, it must be locked by the caller. + * understood, it should be locked by the caller. */ struct dma_fence * __i915_active_fence_set(struct i915_active_fence *active, @@ -753,34 +757,41 @@ __i915_active_fence_set(struct i915_active_fence *active, struct dma_fence *prev; unsigned long flags; - /* NB: must be serialised by an outer timeline mutex (active->lock) */ - spin_lock_irqsave(fence->lock, flags); + if (fence == rcu_access_pointer(active->fence)) + return fence; + GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)); - prev = rcu_dereference_protected(active->fence, active_is_held(active)); + /* + * Consider that we have two threads arriving (A and B), with + * C already resident as the active->fence. + * + * A does the xchg first, and so it sees C or NULL depending + * on the timing of the interrupt handler. If it is NULL, the + * previous fence must have been signaled and we know that + * we are first on the timeline. If it is still present, + * we acquire the lock on that fence and serialise with the interrupt + * handler, in the process removing it from any future interrupt + * callback. A will then wait on C before executing (if present). + * + * As B is second, it sees A as the previous fence and so waits for + * it to complete its transition and takes over the occupancy for + * itself -- remembering that it needs to wait on A before executing. + * + * Note the strong ordering of the timeline also provides consistent + * nesting rules for the fence->lock; the inner lock is always the + * older lock. + */ + spin_lock_irqsave(fence->lock, flags); + prev = xchg(__active_fence_slot(active), fence); if (prev) { GEM_BUG_ON(prev == fence); spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING); __list_del_entry(&active->cb.node); spin_unlock(prev->lock); /* serialise with prev->cb_list */ - - /* - * active->fence is reset by the callback from inside - * interrupt context. We need to serialise our list - * manipulation with the fence->lock to prevent the prev - * being lost inside an interrupt (it can't be replaced as - * no other caller is allowed to enter __i915_active_fence_set - * as we hold the timeline lock). After serialising with - * the callback, we need to double check which ran first, - * our list_del() [decoupling prev from the callback] or - * the callback... - */ - prev = rcu_access_pointer(active->fence); } - - rcu_assign_pointer(active->fence, fence); + GEM_BUG_ON(rcu_access_pointer(active->fence) != fence); list_add_tail(&active->cb.node, &fence->cb_list); - spin_unlock_irqrestore(fence->lock, flags); return prev; @@ -792,10 +803,6 @@ int i915_active_fence_set(struct i915_active_fence *active, struct dma_fence *fence; int err = 0; -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) - lockdep_assert_held(active->lock); -#endif - /* Must maintain timeline ordering wrt previous active requests */ rcu_read_lock(); fence = __i915_active_fence_set(active, &rq->fence); @@ -812,7 +819,7 @@ int i915_active_fence_set(struct i915_active_fence *active, void i915_active_noop(struct dma_fence *fence, struct dma_fence_cb *cb) { - i915_active_fence_cb(fence, cb); + active_fence_cb(fence, cb); } #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index 5dd62323b92a..3208cc2e8c1a 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -61,19 +61,15 @@ void i915_active_noop(struct dma_fence *fence, struct dma_fence_cb *cb); */ static inline void __i915_active_fence_init(struct i915_active_fence *active, - struct mutex *lock, void *fence, dma_fence_func_t fn) { RCU_INIT_POINTER(active->fence, fence); active->cb.func = fn ?: i915_active_noop; -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) - active->lock = lock; -#endif } -#define INIT_ACTIVE_FENCE(A, LOCK) \ - __i915_active_fence_init((A), (LOCK), NULL, NULL) +#define INIT_ACTIVE_FENCE(A) \ + __i915_active_fence_init((A), NULL, NULL) struct dma_fence * __i915_active_fence_set(struct i915_active_fence *active, @@ -127,15 +123,6 @@ i915_active_fence_isset(const struct i915_active_fence *active) return rcu_access_pointer(active->fence); } -static inline void -i915_active_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb) -{ - struct i915_active_fence *active = - container_of(cb, typeof(*active), cb); - - RCU_INIT_POINTER(active->fence, NULL); -} - /* * GPU activity tracking * diff --git a/drivers/gpu/drm/i915/i915_active_types.h b/drivers/gpu/drm/i915/i915_active_types.h index 96aed0ee700a..6360c3e4b765 100644 --- a/drivers/gpu/drm/i915/i915_active_types.h +++ b/drivers/gpu/drm/i915/i915_active_types.h @@ -20,21 +20,6 @@ struct i915_active_fence { struct dma_fence __rcu *fence; struct dma_fence_cb cb; -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) - /* - * Incorporeal! - * - * Updates to the i915_active_request must be serialised under a lock - * to ensure that the timeline is ordered. Normally, this is the - * timeline->mutex, but another mutex may be used so long as it is - * done so consistently. - * - * For lockdep tracking of the above, we store the lock we intend - * to always use for updates of this i915_active_request during - * construction and assert that is held on every update. - */ - struct mutex *lock; -#endif }; struct active_node; -- cgit v1.2.3 From e3f3a0f26932b7a3f997b9e969a4663da6eb2429 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Nov 2019 11:58:13 +0000 Subject: drm/i915/gt: Defer breadcrumb processing to after the irq handler The design of our interrupt handlers is that we ack the receipt of the interrupt first, inside the critical section where the master interrupt control is off and other cpus cannot start processing the next interrupt; and then process the interrupt events afterwards. However, Icelake introduced a whole new set of banked GT_IIR that are inherently serialised and slow to retrieve the IIR and must be processed within the critical section. We can still push our breadcrumbs out of this critical section by using our irq_worker. On bdw+, this should not make too much of a difference as we only slightly defer the breadcrumbs, but on icl+ this should make a big difference to our throughput of interrupts from concurrently executing engines. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191127115813.3345823-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index 973ee7eded64..332b12a574fb 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -28,7 +28,7 @@ cs_irq_handler(struct intel_engine_cs *engine, u32 iir) tasklet = true; if (iir & GT_RENDER_USER_INTERRUPT) { - intel_engine_breadcrumbs_irq(engine); + intel_engine_queue_breadcrumbs(engine); tasklet |= intel_engine_needs_breadcrumb_tasklet(engine); } -- cgit v1.2.3 From cd30a5031704aa8d833f62c8475a2f6d42a688a7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 28 Nov 2019 11:34:24 +0000 Subject: drm/i915/gem: Excise the per-batch whitelist from the context One does not lightly add a new hidden struct_mutex dependency deep within the execbuf bowels! The immediate suspicion in seeing the whitelist cached on the context, is that it is intended to be preserved between batches, as the kernel is quite adept at caching small allocations itself. But no, it's sole purpose is to serialise command submission in order to save a kmalloc on a slow, slow path! By removing the whitelist dependency from the context, our freedom to chop the big struct_mutex is greatly augmented. v2: s/set_bit/__set_bit/ as the whitelist shall never be accessed concurrently. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191128113424.3885958-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 -- drivers/gpu/drm/i915/gem/i915_gem_context_types.h | 7 --- drivers/gpu/drm/i915/i915_cmd_parser.c | 71 ++++++++++------------- 3 files changed, 32 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index c94ac838401a..a179e170c936 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -275,8 +275,6 @@ static void i915_gem_context_free(struct i915_gem_context *ctx) free_engines(rcu_access_pointer(ctx->engines)); mutex_destroy(&ctx->engines_mutex); - kfree(ctx->jump_whitelist); - if (ctx->timeline) intel_timeline_put(ctx->timeline); @@ -584,9 +582,6 @@ __create_context(struct drm_i915_private *i915) for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++) ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES; - ctx->jump_whitelist = NULL; - ctx->jump_whitelist_cmds = 0; - spin_lock(&i915->gem.contexts.lock); list_add_tail(&ctx->link, &i915->gem.contexts.list); spin_unlock(&i915->gem.contexts.lock); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index c060bc428f49..69df5459c350 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -168,13 +168,6 @@ struct i915_gem_context { */ struct radix_tree_root handles_vma; - /** jump_whitelist: Bit array for tracking cmds during cmdparsing - * Guarded by struct_mutex - */ - unsigned long *jump_whitelist; - /** jump_whitelist_cmds: No of cmd slots available */ - u32 jump_whitelist_cmds; - /** * @name: arbitrary name, used for user debug * diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index f24096e27bef..9125e89a9e7f 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1310,13 +1310,14 @@ static int check_bbstart(const struct i915_gem_context *ctx, u32 *cmd, u32 offset, u32 length, u32 batch_len, u64 batch_start, - u64 shadow_batch_start) + u64 shadow_batch_start, + const unsigned long *jump_whitelist) { u64 jump_offset, jump_target; u32 target_cmd_offset, target_cmd_index; /* For igt compatibility on older platforms */ - if (CMDPARSER_USES_GGTT(ctx->i915)) { + if (!jump_whitelist) { DRM_DEBUG("CMD: Rejecting BB_START for ggtt based submission\n"); return -EACCES; } @@ -1352,10 +1353,10 @@ static int check_bbstart(const struct i915_gem_context *ctx, if (target_cmd_index == offset) return 0; - if (ctx->jump_whitelist_cmds <= target_cmd_index) { - DRM_DEBUG("CMD: Rejecting BB_START - truncated whitelist array\n"); - return -EINVAL; - } else if (!test_bit(target_cmd_index, ctx->jump_whitelist)) { + if (IS_ERR(jump_whitelist)) + return PTR_ERR(jump_whitelist); + + if (!test_bit(target_cmd_index, jump_whitelist)) { DRM_DEBUG("CMD: BB_START to 0x%llx not a previously executed cmd\n", jump_target); return -EINVAL; @@ -1364,40 +1365,27 @@ static int check_bbstart(const struct i915_gem_context *ctx, return 0; } -static void init_whitelist(struct i915_gem_context *ctx, u32 batch_len) +static unsigned long * +alloc_whitelist(struct drm_i915_private *i915, u32 batch_len) { - const u32 batch_cmds = DIV_ROUND_UP(batch_len, sizeof(u32)); - const u32 exact_size = BITS_TO_LONGS(batch_cmds); - u32 next_size = BITS_TO_LONGS(roundup_pow_of_two(batch_cmds)); - unsigned long *next_whitelist; - - if (CMDPARSER_USES_GGTT(ctx->i915)) - return; - - if (batch_cmds <= ctx->jump_whitelist_cmds) { - bitmap_zero(ctx->jump_whitelist, batch_cmds); - return; - } + unsigned long *jmp; -again: - next_whitelist = kcalloc(next_size, sizeof(long), GFP_KERNEL); - if (next_whitelist) { - kfree(ctx->jump_whitelist); - ctx->jump_whitelist = next_whitelist; - ctx->jump_whitelist_cmds = - next_size * BITS_PER_BYTE * sizeof(long); - return; - } + /* + * We expect batch_len to be less than 256KiB for known users, + * i.e. we need at most an 8KiB bitmap allocation which should be + * reasonably cheap due to kmalloc caches. + */ - if (next_size > exact_size) { - next_size = exact_size; - goto again; - } + if (CMDPARSER_USES_GGTT(i915)) + return NULL; - DRM_DEBUG("CMD: Failed to extend whitelist. BB_START may be disallowed\n"); - bitmap_zero(ctx->jump_whitelist, ctx->jump_whitelist_cmds); + /* Prefer to report transient allocation failure rather than hit oom */ + jmp = bitmap_zalloc(DIV_ROUND_UP(batch_len, sizeof(u32)), + GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); + if (!jmp) + return ERR_PTR(-ENOMEM); - return; + return jmp; } #define LENGTH_BIAS 2 @@ -1433,6 +1421,7 @@ int intel_engine_cmd_parser(struct i915_gem_context *ctx, struct drm_i915_cmd_descriptor default_desc = noop_desc; const struct drm_i915_cmd_descriptor *desc = &default_desc; bool needs_clflush_after = false; + unsigned long *jump_whitelist; int ret = 0; cmd = copy_batch(shadow_batch_obj, batch_obj, @@ -1443,7 +1432,8 @@ int intel_engine_cmd_parser(struct i915_gem_context *ctx, return PTR_ERR(cmd); } - init_whitelist(ctx, batch_len); + /* Defer failure until attempted use */ + jump_whitelist = alloc_whitelist(ctx->i915, batch_len); /* * We use the batch length as size because the shadow object is as @@ -1487,15 +1477,16 @@ int intel_engine_cmd_parser(struct i915_gem_context *ctx, if (desc->cmd.value == MI_BATCH_BUFFER_START) { ret = check_bbstart(ctx, cmd, offset, length, batch_len, batch_start, - shadow_batch_start); + shadow_batch_start, + jump_whitelist); if (ret) goto err; break; } - if (ctx->jump_whitelist_cmds > offset) - set_bit(offset, ctx->jump_whitelist); + if (!IS_ERR_OR_NULL(jump_whitelist)) + __set_bit(offset, jump_whitelist); cmd += length; offset += length; @@ -1513,6 +1504,8 @@ int intel_engine_cmd_parser(struct i915_gem_context *ctx, } err: + if (!IS_ERR_OR_NULL(jump_whitelist)) + kfree(jump_whitelist); i915_gem_object_unpin_map(shadow_batch_obj); return ret; } -- cgit v1.2.3 From 7983990ca94ab69de6c769dd48da1bba91def53c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 28 Nov 2019 10:25:46 +0000 Subject: drm/i915/selftests: Try to show where the pulse went We have a case of a mysteriously absent pulse, so dump the engine details to see if we can find out what happened to it. References: https://bugs.freedesktop.org/show_bug.cgi?id=112405 Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191128102546.3857140-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 ++ drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 8f6e353caa66..df3369c3f330 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1479,6 +1479,8 @@ void intel_engine_dump(struct intel_engine_cs *engine, drm_printf(m, "*** WEDGED ***\n"); drm_printf(m, "\tAwake? %d\n", atomic_read(&engine->wakeref.count)); + drm_printf(m, "\tBarriers?: %s\n", + yesno(!llist_empty(&engine->barrier_tasks))); rcu_read_lock(); rq = READ_ONCE(engine->heartbeat.systole); diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c index f665a0e23c61..0b1148cf3f61 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c @@ -91,6 +91,11 @@ static int __live_idle_pulse(struct intel_engine_cs *engine, GEM_BUG_ON(!llist_empty(&engine->barrier_tasks)); if (intel_gt_retire_requests_timeout(engine->gt, HZ / 5)) { + struct drm_printer m = drm_err_printer("pulse"); + + pr_err("%s: no heartbeat pulse?\n", engine->name); + intel_engine_dump(engine, &m, "%s", engine->name); + err = -ETIME; goto out; } -- cgit v1.2.3 From 212d9994d0b5b951fcdb8ce454c8d91521ae20d6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 27 Nov 2019 22:32:50 +0000 Subject: drm/i915/selftests: Count the number of engines used Don't rely on the RUNTIME_INFO() when we loop over a particular context and only run on a filtered set of engines. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191127223252.3777141-1-chris@chris-wilson.co.uk --- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 2ea4790f3721..33e56d9af061 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1343,11 +1343,13 @@ static int igt_ctx_sseu(void *arg) static int igt_ctx_readonly(void *arg) { struct drm_i915_private *i915 = arg; + unsigned long idx, ndwords, dw, num_engines; struct drm_i915_gem_object *obj = NULL; struct i915_request *tq[5] = {}; + struct i915_gem_engines_iter it; struct i915_address_space *vm; struct i915_gem_context *ctx; - unsigned long idx, ndwords, dw; + struct intel_context *ce; struct igt_live_test t; I915_RND_STATE(prng); IGT_TIMEOUT(end_time); @@ -1381,12 +1383,15 @@ static int igt_ctx_readonly(void *arg) goto out_file; } + num_engines = 0; + for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) + if (intel_engine_can_store_dword(ce->engine)) + num_engines++; + i915_gem_context_unlock_engines(ctx); + ndwords = 0; dw = 0; while (!time_after(jiffies, end_time)) { - struct i915_gem_engines_iter it; - struct intel_context *ce; - for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) { if (!intel_engine_can_store_dword(ce->engine)) @@ -1429,8 +1434,8 @@ static int igt_ctx_readonly(void *arg) } i915_gem_context_unlock_engines(ctx); } - pr_info("Submitted %lu dwords (across %u engines)\n", - ndwords, RUNTIME_INFO(i915)->num_engines); + pr_info("Submitted %lu dwords (across %lu engines)\n", + ndwords, num_engines); dw = 0; idx = 0; @@ -1690,10 +1695,10 @@ static int igt_vm_isolation(void *arg) { struct drm_i915_private *i915 = arg; struct i915_gem_context *ctx_a, *ctx_b; + unsigned long num_engines, count; struct intel_engine_cs *engine; struct igt_live_test t; I915_RND_STATE(prng); - unsigned long count; struct file *file; u64 vm_total; int err; @@ -1735,6 +1740,7 @@ static int igt_vm_isolation(void *arg) vm_total -= I915_GTT_PAGE_SIZE; count = 0; + num_engines = 0; for_each_uabi_engine(engine, i915) { IGT_TIMEOUT(end_time); unsigned long this = 0; @@ -1772,9 +1778,10 @@ static int igt_vm_isolation(void *arg) this++; } count += this; + num_engines++; } - pr_info("Checked %lu scratch offsets across %d engines\n", - count, RUNTIME_INFO(i915)->num_engines); + pr_info("Checked %lu scratch offsets across %lu engines\n", + count, num_engines); out_file: if (igt_live_test_end(&t)) -- cgit v1.2.3 From 952d1a6b0f839e0b5aba33b4799d5bc679a5e60c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 28 Nov 2019 18:54:01 +0000 Subject: drm/i915/selftests: Drop local vm reference! After obtaining a local reference to the vm from the context, remember to drop it before it goes out of scope! Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191128185402.110678-1-chris@chris-wilson.co.uk --- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 34 ++++++++++------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 33e56d9af061..780e58fe5c64 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1500,7 +1500,7 @@ static int write_to_scratch(struct i915_gem_context *ctx, cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto err; + goto out; } *cmd++ = MI_STORE_DWORD_IMM_GEN4; @@ -1522,12 +1522,12 @@ static int write_to_scratch(struct i915_gem_context *ctx, vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) { err = PTR_ERR(vma); - goto err_vm; + goto out_vm; } err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED); if (err) - goto err_vm; + goto out_vm; err = check_scratch(vm, offset); if (err) @@ -1551,22 +1551,20 @@ static int write_to_scratch(struct i915_gem_context *ctx, if (err) goto skip_request; - i915_vma_unpin_and_release(&vma, 0); + i915_vma_unpin(vma); i915_request_add(rq); - i915_vm_put(vm); - return 0; - + goto out_vm; skip_request: i915_request_skip(rq, err); err_request: i915_request_add(rq); err_unpin: i915_vma_unpin(vma); -err_vm: +out_vm: i915_vm_put(vm); -err: +out: i915_gem_object_put(obj); return err; } @@ -1594,7 +1592,7 @@ static int read_from_scratch(struct i915_gem_context *ctx, cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto err; + goto out; } memset(cmd, POISON_INUSE, PAGE_SIZE); @@ -1626,12 +1624,12 @@ static int read_from_scratch(struct i915_gem_context *ctx, vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) { err = PTR_ERR(vma); - goto err_vm; + goto out_vm; } err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED); if (err) - goto err_vm; + goto out_vm; err = check_scratch(vm, offset); if (err) @@ -1664,29 +1662,27 @@ static int read_from_scratch(struct i915_gem_context *ctx, err = i915_gem_object_set_to_cpu_domain(obj, false); i915_gem_object_unlock(obj); if (err) - goto err_vm; + goto out_vm; cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto err_vm; + goto out_vm; } *value = cmd[result / sizeof(*cmd)]; i915_gem_object_unpin_map(obj); - i915_gem_object_put(obj); - - return 0; + goto out_vm; skip_request: i915_request_skip(rq, err); err_request: i915_request_add(rq); err_unpin: i915_vma_unpin(vma); -err_vm: +out_vm: i915_vm_put(vm); -err: +out: i915_gem_object_put(obj); return err; } -- cgit v1.2.3 From ff690b2111ba591abf1ea157c543a4e9f91b309e Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Thu, 28 Nov 2019 07:40:05 +0530 Subject: drm/i915/tgl: Implement Wa_1604555607 Implement Wa_1604555607 (set the DS pairing timer to 128 cycles). FF_MODE2 is part of the register state context, that's why it is implemented here. At TGL A0 stepping, FF_MODE2 register read back is broken, hence disabling the WA verification. v2: Rebased on top of the WA refactoring (Oscar) v3: Correctly add to ctx_workarounds_init (Michel) v4: uncore read is used [Tvrtko] Macros as used for MASK definition [Chris] v5: Skip the Wa_1604555607 verification [Ram] i915 ptr retrieved from engine. [Tvrtko] v6: Added wa_add as a wrapper for __wa_add [Chris] wa_add is directly called instead of new wrapper [tvrtko] BSpec: 19363 HSDES: 1604555607 Signed-off-by: Michel Thierry Signed-off-by: Ramalingam C Reviewed-by: Tvrtko Ursulin [v5] Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191128021005.3350-1-ramalingam.c@intel.com --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 29 +++++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 0c6d398980ba..195ccf7db272 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -147,20 +147,26 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) } } -static void -wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, - u32 val) +static void wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, + u32 val, u32 read_mask) { struct i915_wa wa = { .reg = reg, .mask = mask, .val = val, - .read = mask, + .read = read_mask, }; _wa_add(wal, &wa); } +static void +wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, + u32 val) +{ + wa_add(wal, reg, mask, val, mask); +} + static void wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val) { @@ -569,9 +575,24 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) { + u32 val; + /* Wa_1409142259:tgl */ WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3, GEN12_DISABLE_CPS_AWARE_COLOR_PIPE); + + /* Wa_1604555607:tgl */ + val = intel_uncore_read(engine->uncore, FF_MODE2); + val &= ~FF_MODE2_TDS_TIMER_MASK; + val |= FF_MODE2_TDS_TIMER_128; + /* + * FIXME: FF_MODE2 register is not readable till TGL B0. We can + * enable verification of WA from the later steppings, which enables + * the read of FF_MODE2. + */ + wa_add(wal, FF_MODE2, FF_MODE2_TDS_TIMER_MASK, val, + IS_TGL_REVID(engine->i915, TGL_REVID_A0, TGL_REVID_A0) ? 0 : + FF_MODE2_TDS_TIMER_MASK); } static void diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 94d0f593eeb7..a99fdf8ea53b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7922,6 +7922,10 @@ enum { #define PIXEL_ROUNDING_TRUNC_FB_PASSTHRU (1 << 15) #define PER_PIXEL_ALPHA_BYPASS_EN (1 << 7) +#define FF_MODE2 _MMIO(0x6604) +#define FF_MODE2_TDS_TIMER_MASK REG_GENMASK(23, 16) +#define FF_MODE2_TDS_TIMER_128 REG_FIELD_PREP(FF_MODE2_TDS_TIMER_MASK, 4) + /* PCH */ #define PCH_DISPLAY_BASE 0xc0000u -- cgit v1.2.3 From 69305732796f50c9e74cd850faef668f38a483b3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 28 Nov 2019 23:29:46 +0000 Subject: drm/i915/selftests: Use sgt_iter for huge_pages_free Use the normal sgt_iter to walk the pages scatterlist on free so that we handle the error path correctly. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112225 Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191128232946.546831-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c index 892d12db6c49..fa16f2c3f3ac 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c @@ -12,10 +12,14 @@ static void huge_free_pages(struct drm_i915_gem_object *obj, struct sg_table *pages) { unsigned long nreal = obj->scratch / PAGE_SIZE; - struct scatterlist *sg; + struct sgt_iter sgt_iter; + struct page *page; - for (sg = pages->sgl; sg && nreal--; sg = __sg_next(sg)) - __free_page(sg_page(sg)); + for_each_sgt_page(page, sgt_iter, pages) { + __free_page(page); + if (!--nreal) + break; + } sg_free_table(pages); kfree(pages); @@ -70,7 +74,6 @@ static int huge_get_pages(struct drm_i915_gem_object *obj) err: huge_free_pages(obj, pages); - return -ENOMEM; #undef GFP } -- cgit v1.2.3 From b006869c6e79792cecf27662190f5c5cb73d26fb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 29 Nov 2019 09:56:59 +0000 Subject: drm/i915/selftests: Always lock the drm_mm around insert/remove Be paranoid and make sure the drm_mm is locked whenever we insert/remove our own nodes. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191129095659.665381-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index f7aa0036d900..80cde5bda922 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -1166,11 +1166,13 @@ static int igt_ggtt_page(void *arg) goto out_free; memset(&tmp, 0, sizeof(tmp)); + mutex_lock(&ggtt->vm.mutex); err = drm_mm_insert_node_in_range(&ggtt->vm.mm, &tmp, count * PAGE_SIZE, 0, I915_COLOR_UNEVICTABLE, 0, ggtt->mappable_end, DRM_MM_INSERT_LOW); + mutex_unlock(&ggtt->vm.mutex); if (err) goto out_unpin; @@ -1222,7 +1224,9 @@ static int igt_ggtt_page(void *arg) out_remove: ggtt->vm.clear_range(&ggtt->vm, tmp.start, tmp.size); intel_runtime_pm_put(&i915->runtime_pm, wakeref); + mutex_lock(&ggtt->vm.mutex); drm_mm_remove_node(&tmp); + mutex_unlock(&ggtt->vm.mutex); out_unpin: i915_gem_object_unpin_pages(obj); out_free: -- cgit v1.2.3 From 0cb7da1062f44281f0a8c5a137b1c9af91b6bfd5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 29 Nov 2019 10:34:55 +0000 Subject: drm/i915/selftests: Wait only on the expected barrier Wait on only the last request on the kernel_context after emitting a barrier so that we do not wait for everything in general and by doing so cause an accidental emission of the barrier! Bugzilla; https://bugs.freedesktop.org/show_bug.cgi?id=112405 Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191129103455.744389-1-chris@chris-wilson.co.uk --- .../gpu/drm/i915/gt/selftest_engine_heartbeat.c | 24 +++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c index 0b1148cf3f61..5227e79204a5 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c @@ -11,6 +11,28 @@ #include "intel_gt_requests.h" #include "i915_selftest.h" +static int timeline_sync(struct intel_timeline *tl) +{ + struct dma_fence *fence; + long timeout; + + fence = i915_active_fence_get(&tl->last_request); + if (!fence) + return 0; + + timeout = dma_fence_wait_timeout(fence, true, HZ / 2); + dma_fence_put(fence); + if (timeout < 0) + return timeout; + + return 0; +} + +static int engine_sync_barrier(struct intel_engine_cs *engine) +{ + return timeline_sync(engine->kernel_context->timeline); +} + struct pulse { struct i915_active active; struct kref kref; @@ -90,7 +112,7 @@ static int __live_idle_pulse(struct intel_engine_cs *engine, GEM_BUG_ON(!llist_empty(&engine->barrier_tasks)); - if (intel_gt_retire_requests_timeout(engine->gt, HZ / 5)) { + if (engine_sync_barrier(engine)) { struct drm_printer m = drm_err_printer("pulse"); pr_err("%s: no heartbeat pulse?\n", engine->name); -- cgit v1.2.3 From d92f77deefc9051f2b6fa17836b365bb2a67ce29 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 29 Nov 2019 12:48:46 +0000 Subject: Revert "drm/i915: use a separate context for gpu relocs" Since commit c45e788d95b4 ("drm/i915/tgl: Suspend pre-parser across GTT invalidations"), we now disable the advanced preparser on Tigerlake for the invalidation phase at the start of the batch, we no longer need to emit the GPU relocations from a second context as they are now flushed inlined. References: 8a9a982767b7 ("drm/i915: use a separate context for gpu relocs") References: c45e788d95b4 ("drm/i915/tgl: Suspend pre-parser across GTT invalidations") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Daniele Ceraolo Spurio Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191129124846.949100-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 30 +------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 7a87e8270460..459f4d40b69b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -253,7 +253,6 @@ struct i915_execbuffer { bool has_fence : 1; bool needs_unfenced : 1; - struct intel_context *ce; struct i915_request *rq; u32 *rq_cmd; unsigned int rq_size; @@ -886,9 +885,6 @@ static void eb_destroy(const struct i915_execbuffer *eb) { GEM_BUG_ON(eb->reloc_cache.rq); - if (eb->reloc_cache.ce) - intel_context_put(eb->reloc_cache.ce); - if (eb->lut_size > 0) kfree(eb->buckets); } @@ -912,7 +908,6 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->has_fence = cache->gen < 4; cache->needs_unfenced = INTEL_INFO(i915)->unfenced_needs_alignment; cache->node.flags = 0; - cache->ce = NULL; cache->rq = NULL; cache->rq_size = 0; } @@ -1182,7 +1177,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (err) goto err_unmap; - rq = intel_context_create_request(cache->ce); + rq = i915_request_create(eb->context); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto err_unpin; @@ -1253,29 +1248,6 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, if (!intel_engine_can_store_dword(eb->engine)) return ERR_PTR(-ENODEV); - if (!cache->ce) { - struct intel_context *ce; - - /* - * The CS pre-parser can pre-fetch commands across - * memory sync points and starting gen12 it is able to - * pre-fetch across BB_START and BB_END boundaries - * (within the same context). We therefore use a - * separate context gen12+ to guarantee that the reloc - * writes land before the parser gets to the target - * memory location. - */ - if (cache->gen >= 12) - ce = intel_context_create(eb->context->gem_context, - eb->engine); - else - ce = intel_context_get(eb->context); - if (IS_ERR(ce)) - return ERR_CAST(ce); - - cache->ce = ce; - } - err = __reloc_gpu_alloc(eb, vma, len); if (unlikely(err)) return ERR_PTR(err); -- cgit v1.2.3 From 8d9875b47a5dae0690b04bbb9de68b0a0f1a2cce Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 11 Oct 2019 23:09:45 +0300 Subject: drm/i915: Don't set undefined bits in dirty_pipes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skl_commit_modeset_enables() straight up compares dirty_pipes with a bitmask of already committed pipes. If we set bits in dirty_pipes for non-existent pipes that comparison will never work right. So let's limit ourselves to bits that exist. And we'll do the same for the active_pipes_changed bitmask. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191011200949.7839-5-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 558bf2c42cb8..eaf6397c5c38 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5360,7 +5360,7 @@ skl_ddb_add_affected_pipes(struct intel_atomic_state *state) if (ret) return ret; - state->active_pipe_changes = ~0; + state->active_pipe_changes = INTEL_INFO(dev_priv)->pipe_mask; /* * We usually only initialize state->active_pipes if we @@ -5386,7 +5386,7 @@ skl_ddb_add_affected_pipes(struct intel_atomic_state *state) * to grab the lock on *all* CRTC's. */ if (state->active_pipe_changes || state->modeset) { - state->wm_results.dirty_pipes = ~0; + state->wm_results.dirty_pipes = INTEL_INFO(dev_priv)->pipe_mask; ret = intel_add_all_pipes(state); if (ret) -- cgit v1.2.3 From 7ce596a8036cf3a4cb9ffa0c4edd8a76a7a43cc3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 29 Nov 2019 15:18:45 +0000 Subject: drm/i915/gem: Take timeline->mutex to walk list-of-requests Though the context is closed and so no more requests can be added to the timeline, retirement can still be removing requests. It can even be removing the very request we are inspecting and so cause us to wander into dead links. Serialise with the retirement by taking the timeline->mutex used for guarding the timeline->requests list. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112404 Fixes: 4a3174152147 ("drm/i915/gem: Refine occupancy test in kill_context()") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Matthew Auld Cc: Joonas Lahtinen Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191129151845.1092933-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index a179e170c936..9f1dc96b10a6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -403,7 +403,7 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce) if (!ce->timeline) return NULL; - rcu_read_lock(); + mutex_lock(&ce->timeline->mutex); list_for_each_entry_reverse(rq, &ce->timeline->requests, link) { if (i915_request_completed(rq)) break; @@ -413,7 +413,7 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce) if (engine) break; } - rcu_read_unlock(); + mutex_unlock(&ce->timeline->mutex); return engine; } -- cgit v1.2.3 From 97c16353970aa28418a49ef6980b6e4f36e35feb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 29 Nov 2019 17:25:42 +0000 Subject: drm/i915/execlists: Ensure the tasklet is decoupled upon shutdown As we only cancel the timers asynchronously, they may still be running on another CPU as we shutdown, raising one last softirq. So be safe and make sure the tasklet is flushed before destroying the engine's memory. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191129172542.1222810-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 4cd0d46b5da6..fef4b7e823f5 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -3777,8 +3777,18 @@ void intel_execlists_set_default_submission(struct intel_engine_cs *engine) engine->flags |= I915_ENGINE_HAS_RELATIVE_MMIO; } +static void execlists_shutdown(struct intel_engine_cs *engine) +{ + /* Synchronise with residual timers and any softirq they raise */ + del_timer_sync(&engine->execlists.timer); + del_timer_sync(&engine->execlists.preempt); + tasklet_kill(&engine->execlists.tasklet); +} + static void execlists_destroy(struct intel_engine_cs *engine) { + execlists_shutdown(engine); + intel_engine_cleanup_common(engine); lrc_destroy_wa_ctx(engine); kfree(engine); -- cgit v1.2.3 From f9a863c2ffc17f72137fae8cac3314961dc6be24 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 29 Nov 2019 22:27:02 +0000 Subject: drm/i915/selftests: Keep engine awake during live_coherency Keep the engine awake and so avoid frequent cycling in and out of powersaving mode to eliminate the unnecessary overhead and speed up the testing. Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191129222702.1456292-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index 9d3cd1af61f6..49edc51111d5 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -327,6 +327,7 @@ static int igt_gem_coherency(void *arg) ctx.engine = random_engine(i915, &prng); GEM_BUG_ON(!ctx.engine); pr_info("%s: using %s\n", __func__, ctx.engine->name); + intel_engine_pm_get(ctx.engine); for (over = igt_coherency_mode; over->name; over++) { if (!over->set) @@ -405,6 +406,7 @@ static int igt_gem_coherency(void *arg) } } free: + intel_engine_pm_put(ctx.engine); kfree(offsets); return err; -- cgit v1.2.3 From 3cd6e8860ecd40f358b9d30d5bfecbc74fd7cfef Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 29 Nov 2019 20:13:28 +0000 Subject: drm/i915/gen7: Re-enable full-ppgtt for ivb & hsw After much hair pulling, resort to preallocating the ppGTT entries on init to circumvent the apparent lack of PD invalidate following the write to PP_DCLV upon switching mm between contexts (and here the same context after binding new objects). However, the details of that PP_DCLV invalidate are still unknown, and it appears we need to reload the mm twice to cover over a timing issue. Worrying. Fixes: 3dc007fe9b2b ("drm/i915/gtt: Downgrade gen7 (ivb, byt, hsw) back to aliasing-ppgtt") Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191129201328.1398583-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 21 +++++++++------------ drivers/gpu/drm/i915/i915_gem_gtt.c | 21 ++++++++++++++------- drivers/gpu/drm/i915/i915_gem_gtt.h | 1 + drivers/gpu/drm/i915/i915_pci.c | 2 +- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index f25ceccb335e..f977fc27b001 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1366,7 +1366,7 @@ static int load_pd_dir(struct i915_request *rq, const struct i915_ppgtt *ppgtt) const struct intel_engine_cs * const engine = rq->engine; u32 *cs; - cs = intel_ring_begin(rq, 6); + cs = intel_ring_begin(rq, 10); if (IS_ERR(cs)) return PTR_ERR(cs); @@ -1374,6 +1374,12 @@ static int load_pd_dir(struct i915_request *rq, const struct i915_ppgtt *ppgtt) *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine->mmio_base)); *cs++ = PP_DIR_DCLV_2G; + *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; + *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine->mmio_base)); + *cs++ = intel_gt_scratch_offset(rq->engine->gt, + INTEL_GT_SCRATCH_FIELD_DEFAULT); + *cs++ = MI_NOOP; + *cs++ = MI_LOAD_REGISTER_IMM(1); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine->mmio_base)); *cs++ = px_base(ppgtt->pd)->ggtt_offset << 10; @@ -1579,6 +1585,7 @@ static int switch_context(struct i915_request *rq) { struct intel_context *ce = rq->hw_context; struct i915_address_space *vm = vm_alias(ce); + u32 hw_flags = 0; int ret; GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); @@ -1590,19 +1597,9 @@ static int switch_context(struct i915_request *rq) } if (ce->state) { - u32 hw_flags; - GEM_BUG_ON(rq->engine->id != RCS0); - /* - * The kernel context(s) is treated as pure scratch and is not - * expected to retain any state (as we sacrifice it during - * suspend and on resume it may be corrupted). This is ok, - * as nothing actually executes using the kernel context; it - * is purely used for flushing user contexts. - */ - hw_flags = 0; - if (i915_gem_context_is_kernel(rq->gem_context)) + if (!rq->engine->default_state) hw_flags = MI_RESTORE_INHIBIT; ret = mi_set_context(rq, hw_flags); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6239a9adbf14..98835fea38a9 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1692,7 +1692,6 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, intel_wakeref_t wakeref; u64 from = start; unsigned int pde; - bool flush = false; int ret = 0; wakeref = intel_runtime_pm_get(&vm->i915->runtime_pm); @@ -1717,11 +1716,6 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, spin_lock(&pd->lock); if (pd->entry[pde] == &vm->scratch[1]) { pd->entry[pde] = pt; - if (i915_vma_is_bound(ppgtt->vma, - I915_VMA_GLOBAL_BIND)) { - gen6_write_pde(ppgtt, pde, pt); - flush = true; - } } else { alloc = pt; pt = pd->entry[pde]; @@ -1732,9 +1726,19 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, } spin_unlock(&pd->lock); - if (flush) + if (i915_vma_is_bound(ppgtt->vma, I915_VMA_GLOBAL_BIND)) { + mutex_lock(&ppgtt->flush); + + /* Rewrite them all! Anything less misses an invalidate. */ + gen6_for_all_pdes(pt, pd, pde) + gen6_write_pde(ppgtt, pde, pt); + + ioread32(ppgtt->pd_addr + pde - 1); gen6_ggtt_invalidate(vm->gt->ggtt); + mutex_unlock(&ppgtt->flush); + } + goto out; unwind_out: @@ -1793,6 +1797,7 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm) gen6_ppgtt_free_pd(ppgtt); free_scratch(vm); + mutex_destroy(&ppgtt->flush); mutex_destroy(&ppgtt->pin_mutex); kfree(ppgtt->base.pd); } @@ -1958,6 +1963,7 @@ static struct i915_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915) if (!ppgtt) return ERR_PTR(-ENOMEM); + mutex_init(&ppgtt->flush); mutex_init(&ppgtt->pin_mutex); ppgtt_init(&ppgtt->base, &i915->gt); @@ -1994,6 +2000,7 @@ err_scratch: err_pd: kfree(ppgtt->base.pd); err_free: + mutex_destroy(&ppgtt->pin_mutex); kfree(ppgtt); return ERR_PTR(err); } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 402283ce2864..31a4a96ddd0d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -443,6 +443,7 @@ struct i915_ppgtt { struct gen6_ppgtt { struct i915_ppgtt base; + struct mutex flush; struct i915_vma *vma; gen6_pte_t __iomem *pd_addr; diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index da3e9b5752ac..583e0cd94a6a 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -436,7 +436,7 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info = { .has_rc6 = 1, \ .has_rc6p = 1, \ .has_rps = true, \ - .ppgtt_type = INTEL_PPGTT_ALIASING, \ + .ppgtt_type = INTEL_PPGTT_FULL, \ .ppgtt_size = 31, \ IVB_PIPE_OFFSETS, \ IVB_CURSOR_OFFSETS, \ -- cgit v1.2.3 From f997056d5b17c6b0bdc250d509f384fbd7f8d33a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 30 Nov 2019 12:05:03 +0000 Subject: drm/i915/gt: Push the flush_pd before the set-context Move our "wait for the PD load to complete" paranoia before the MI_SET_CONTEXT just in case the context restore tries to access local addresses. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191130120503.1609483-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 28 ++++++++++++------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index f977fc27b001..dcdeef0a776f 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1591,24 +1591,11 @@ static int switch_context(struct i915_request *rq) GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); if (vm) { - ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm)); - if (ret) - return ret; - } - - if (ce->state) { - GEM_BUG_ON(rq->engine->id != RCS0); - - if (!rq->engine->default_state) - hw_flags = MI_RESTORE_INHIBIT; + struct intel_engine_cs *engine = rq->engine; - ret = mi_set_context(rq, hw_flags); + ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm)); if (ret) return ret; - } - - if (vm) { - struct intel_engine_cs *engine = rq->engine; ret = engine->emit_flush(rq, EMIT_INVALIDATE); if (ret) @@ -1635,6 +1622,17 @@ static int switch_context(struct i915_request *rq) return ret; } + if (ce->state) { + GEM_BUG_ON(rq->engine->id != RCS0); + + if (!rq->engine->default_state) + hw_flags = MI_RESTORE_INHIBIT; + + ret = mi_set_context(rq, hw_flags); + if (ret) + return ret; + } + ret = remap_l3(rq); if (ret) return ret; -- cgit v1.2.3 From 19b6304aee84644482ceb6a87f0ce09db9a8f714 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 30 Nov 2019 16:23:20 +0000 Subject: drm/i915: Serialise access to GFX_FLSH_CNTL Now that many threads may try to use the same mmio to flush the global buffers after updating the PTE, serialise access to the mmio to prevent concurrent access on gen7. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191130162320.1683424-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 98835fea38a9..709bd4c8b3b4 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -123,6 +123,16 @@ static void gen6_ggtt_invalidate(struct i915_ggtt *ggtt) { struct intel_uncore *uncore = ggtt->vm.gt->uncore; + spin_lock_irq(&uncore->lock); + intel_uncore_write_fw(uncore, GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); + intel_uncore_read_fw(uncore, GFX_FLSH_CNTL_GEN6); + spin_unlock_irq(&uncore->lock); +} + +static void gen8_ggtt_invalidate(struct i915_ggtt *ggtt) +{ + struct intel_uncore *uncore = ggtt->vm.gt->uncore; + /* * Note that as an uncached mmio write, this will flush the * WCB of the writes into the GGTT before it triggers the invalidate. @@ -135,7 +145,7 @@ static void guc_ggtt_invalidate(struct i915_ggtt *ggtt) struct intel_uncore *uncore = ggtt->vm.gt->uncore; struct drm_i915_private *i915 = ggtt->vm.i915; - gen6_ggtt_invalidate(ggtt); + gen8_ggtt_invalidate(ggtt); if (INTEL_GEN(i915) >= 12) intel_uncore_write_fw(uncore, GEN12_GUC_TLB_INV_CR, @@ -3048,7 +3058,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) ggtt->vm.clear_range = bxt_vtd_ggtt_clear_range__BKL; } - ggtt->invalidate = gen6_ggtt_invalidate; + ggtt->invalidate = gen8_ggtt_invalidate; ggtt->vm.vma_ops.bind_vma = ggtt_bind_vma; ggtt->vm.vma_ops.unbind_vma = ggtt_unbind_vma; @@ -3288,7 +3298,7 @@ int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv) void i915_ggtt_enable_guc(struct i915_ggtt *ggtt) { - GEM_BUG_ON(ggtt->invalidate != gen6_ggtt_invalidate); + GEM_BUG_ON(ggtt->invalidate != gen8_ggtt_invalidate); ggtt->invalidate = guc_ggtt_invalidate; @@ -3298,13 +3308,13 @@ void i915_ggtt_enable_guc(struct i915_ggtt *ggtt) void i915_ggtt_disable_guc(struct i915_ggtt *ggtt) { /* XXX Temporary pardon for error unload */ - if (ggtt->invalidate == gen6_ggtt_invalidate) + if (ggtt->invalidate == gen8_ggtt_invalidate) return; /* We should only be called after i915_ggtt_enable_guc() */ GEM_BUG_ON(ggtt->invalidate != guc_ggtt_invalidate); - ggtt->invalidate = gen6_ggtt_invalidate; + ggtt->invalidate = gen8_ggtt_invalidate; ggtt->invalidate(ggtt); } -- cgit v1.2.3 From 1bbdd241ffeb86b29e3dc80539cd1b88037b5fdb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 1 Dec 2019 14:09:16 +0000 Subject: drm/i915: Refactor gen6_flush_pd() As the gen6 page directory is written on binding and after every update, the code ended up duplicated. Refactor the code into a single routine to share the locking and serialisation. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191201140916.2128905-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 38 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 709bd4c8b3b4..10b3d6d44045 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1693,6 +1693,23 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; } +static void gen6_flush_pd(struct gen6_ppgtt *ppgtt) +{ + struct i915_page_directory * const pd = ppgtt->base.pd; + struct i915_page_table *pt; + unsigned int pde; + + mutex_lock(&ppgtt->flush); + + gen6_for_all_pdes(pt, pd, pde) + gen6_write_pde(ppgtt, pde, pt); + + ioread32(ppgtt->pd_addr + pde - 1); + gen6_ggtt_invalidate(ppgtt->base.vm.gt->ggtt); + + mutex_unlock(&ppgtt->flush); +} + static int gen6_alloc_va_range(struct i915_address_space *vm, u64 start, u64 length) { @@ -1736,18 +1753,9 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, } spin_unlock(&pd->lock); - if (i915_vma_is_bound(ppgtt->vma, I915_VMA_GLOBAL_BIND)) { - mutex_lock(&ppgtt->flush); - + if (i915_vma_is_bound(ppgtt->vma, I915_VMA_GLOBAL_BIND)) /* Rewrite them all! Anything less misses an invalidate. */ - gen6_for_all_pdes(pt, pd, pde) - gen6_write_pde(ppgtt, pde, pt); - - ioread32(ppgtt->pd_addr + pde - 1); - gen6_ggtt_invalidate(vm->gt->ggtt); - - mutex_unlock(&ppgtt->flush); - } + gen6_flush_pd(ppgtt); goto out; @@ -1832,17 +1840,11 @@ static int pd_vma_bind(struct i915_vma *vma, struct i915_ggtt *ggtt = i915_vm_to_ggtt(vma->vm); struct gen6_ppgtt *ppgtt = vma->private; u32 ggtt_offset = i915_ggtt_offset(vma) / I915_GTT_PAGE_SIZE; - struct i915_page_table *pt; - unsigned int pde; px_base(ppgtt->base.pd)->ggtt_offset = ggtt_offset * sizeof(gen6_pte_t); ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm + ggtt_offset; - gen6_for_all_pdes(pt, ppgtt->base.pd, pde) - gen6_write_pde(ppgtt, pde, pt); - - gen6_ggtt_invalidate(ggtt); - + gen6_flush_pd(ppgtt); return 0; } -- cgit v1.2.3 From 7df49149b29c978162fa68fe4db8160f294e12a0 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2019 20:23:58 +0200 Subject: drm/i915: Use the correct PCH transcoder for LPT/WPT in intel_sanitize_frame_start_delay() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LPT/WPT only have PCH transcoder A. Make sure we poke at its chicken register instead of some non-existent register when FDI is being driven by pipe B or C. Cc: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191128182358.14477-1-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7d6d0393d73f..7ba12d603f59 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17272,7 +17272,8 @@ static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc val |= TRANS_FRAME_START_DELAY(0); I915_WRITE(reg, val); } else { - i915_reg_t reg = TRANS_CHICKEN2(crtc->pipe); + enum pipe pch_transcoder = intel_crtc_pch_transcoder(crtc); + i915_reg_t reg = TRANS_CHICKEN2(pch_transcoder); u32 val; val = I915_READ(reg); -- cgit v1.2.3 From 9695cde6b99f16f8d1c6248de11e5c0c51cdf1ca Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 27 Nov 2019 14:13:12 -0800 Subject: drm/i915: Handle SDEISR according to PCH rather than platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The South Display is part of the PCH so we should technically be basing our port detection logic off the PCH in use rather than the platform generation. Cc: Lucas De Marchi Signed-off-by: Matt Roper Reviewed-by: José Roberto de Souza Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20191127221314.575575-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 511c6ae04ad0..dde1b252d054 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5498,7 +5498,7 @@ static bool icl_combo_port_connected(struct drm_i915_private *dev_priv, return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port); } -static bool icl_digital_port_connected(struct intel_encoder *encoder) +static bool icp_digital_port_connected(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); @@ -5536,9 +5536,9 @@ static bool __intel_digital_port_connected(struct intel_encoder *encoder) return g4x_digital_port_connected(encoder); } - if (INTEL_GEN(dev_priv) >= 11) - return icl_digital_port_connected(encoder); - else if (IS_GEN(dev_priv, 10) || IS_GEN9_BC(dev_priv)) + if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) + return icp_digital_port_connected(encoder); + else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) return spt_digital_port_connected(encoder); else if (IS_GEN9_LP(dev_priv)) return bxt_digital_port_connected(encoder); -- cgit v1.2.3 From 3d1e388d4072dd240e558709d2f73605a742a723 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 27 Nov 2019 14:13:13 -0800 Subject: drm/i915/ehl: Make icp_digital_port_connected() use phy instead of port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When looking at SDEISR to determine the connection status of combo outputs, we should use the phy index rather than the port index. Although they're usually the same thing, EHL's DDI-D (port D) is attached to PHY-A and SDEISR doesn't even have bits for a "D" output. It's also possible that future platforms may map DDIs (the internal display engine programming units) to PHYs (the output handling on the IO side) in ways where port!=phy, so let's look at the PHY index by default. v2: Rename to intel_combo_phy_connected. (Lucas) Fixes: 719d24002602 ("drm/i915/ehl: Enable DDI-D") Cc: José Roberto de Souza Cc: Lucas De Marchi Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191127221314.575575-2-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index dde1b252d054..6611119b9f9b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5487,15 +5487,13 @@ static bool bxt_digital_port_connected(struct intel_encoder *encoder) return I915_READ(GEN8_DE_PORT_ISR) & bit; } -static bool icl_combo_port_connected(struct drm_i915_private *dev_priv, - struct intel_digital_port *intel_dig_port) +static bool intel_combo_phy_connected(struct drm_i915_private *dev_priv, + enum phy phy) { - enum port port = intel_dig_port->base.port; - - if (HAS_PCH_MCC(dev_priv) && port == PORT_C) + if (HAS_PCH_MCC(dev_priv) && phy == PHY_C) return I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(PORT_TC1); - return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port); + return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(phy); } static bool icp_digital_port_connected(struct intel_encoder *encoder) @@ -5505,7 +5503,7 @@ static bool icp_digital_port_connected(struct intel_encoder *encoder) enum phy phy = intel_port_to_phy(dev_priv, encoder->port); if (intel_phy_is_combo(dev_priv, phy)) - return icl_combo_port_connected(dev_priv, dig_port); + return intel_combo_phy_connected(dev_priv, phy); else if (intel_phy_is_tc(dev_priv, phy)) return intel_tc_port_connected(dig_port); else -- cgit v1.2.3 From f49108d0e0e7e46a2fcf7322ab8f6753f3934aa1 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 27 Nov 2019 14:13:14 -0800 Subject: drm/i915: Program SHPD_FILTER_CNT on CNP+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bspec tells us 'Program SHPD_FILTER_CNT with the "500 microseconds adjusted" value before enabling hotplug detection' on CNP+. We haven't been touching this register at all thus far, but we should probably follow the bspec's guidance. The register also exists on LPT and SPT, but there isn't any specific guidance I can find on how we should be programming it there so let's leave it be for now. Bspec: 4342 Bspec: 31297 Bspec: 8407 Bspec: 49305 Bspec: 50473 Signed-off-by: Matt Roper Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191127221314.575575-3-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 5 +++++ drivers/gpu/drm/i915/i915_reg.h | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8b338744eddf..46a9f7dafbf3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2980,6 +2980,8 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv, hotplug_irqs = sde_ddi_mask | sde_tc_mask; enabled_irqs = intel_hpd_enabled_irqs(dev_priv, pins); + I915_WRITE(SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); + ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); icp_hpd_detection_setup(dev_priv, ddi_enable_mask, tc_enable_mask); @@ -3085,6 +3087,9 @@ static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; + if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) + I915_WRITE(SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); + hotplug_irqs = SDE_HOTPLUG_MASK_SPT; enabled_irqs = intel_hpd_enabled_irqs(dev_priv, hpd_spt); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a99fdf8ea53b..1a6376a97d48 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8114,6 +8114,10 @@ enum { #define SHOTPLUG_CTL_TC _MMIO(0xc4034) #define ICP_TC_HPD_ENABLE(tc_port) (8 << (tc_port) * 4) + +#define SHPD_FILTER_CNT _MMIO(0xc4038) +#define SHPD_FILTER_CNT_500_ADJ 0x001D9 + /* Icelake DSC Rate Control Range Parameter Registers */ #define DSCA_RC_RANGE_PARAMETERS_0 _MMIO(0x6B240) #define DSCA_RC_RANGE_PARAMETERS_0_UDW _MMIO(0x6B240 + 4) -- cgit v1.2.3 From 56273062e760373757a3c9dde943f945874202af Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 5 Nov 2019 19:14:47 +0200 Subject: drm/i915: Switch intel_crtc_disable_noatomic() to intel_ types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's hard to see what is going on when the function mixes drm_ and intel_ types. Switch to intel_ types. v2: Deal with another use of 'intel_crtc' being introduced Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191105171447.22111-2-ville.syrjala@linux.intel.com Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/i915/display/intel_display.c | 68 ++++++++++++++-------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7ba12d603f59..5adc48aacbda 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7203,84 +7203,84 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state, i830_enable_pipe(dev_priv, pipe); } -static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, +static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, struct drm_modeset_acquire_ctx *ctx) { struct intel_encoder *encoder; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_bw_state *bw_state = to_intel_bw_state(dev_priv->bw_obj.state); struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->state); + to_intel_crtc_state(crtc->base.state); enum intel_display_power_domain domain; struct intel_plane *plane; - u64 domains; struct drm_atomic_state *state; struct intel_crtc_state *temp_crtc_state; + enum pipe pipe = crtc->pipe; + u64 domains; int ret; - if (!intel_crtc->active) + if (!crtc_state->hw.active) return; - for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc, plane) { + for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { const struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); if (plane_state->uapi.visible) - intel_plane_disable_noatomic(intel_crtc, plane); + intel_plane_disable_noatomic(crtc, plane); } - state = drm_atomic_state_alloc(crtc->dev); + state = drm_atomic_state_alloc(&dev_priv->drm); if (!state) { DRM_DEBUG_KMS("failed to disable [CRTC:%d:%s], out of memory", - crtc->base.id, crtc->name); + crtc->base.base.id, crtc->base.name); return; } state->acquire_ctx = ctx; /* Everything's already locked, -EDEADLK can't happen. */ - temp_crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); - ret = drm_atomic_add_affected_connectors(state, crtc); + temp_crtc_state = intel_atomic_get_crtc_state(state, crtc); + ret = drm_atomic_add_affected_connectors(state, &crtc->base); WARN_ON(IS_ERR(temp_crtc_state) || ret); - dev_priv->display.crtc_disable(to_intel_atomic_state(state), - intel_crtc); + dev_priv->display.crtc_disable(to_intel_atomic_state(state), crtc); drm_atomic_state_put(state); DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", - crtc->base.id, crtc->name); - - WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0); - crtc->state->active = false; - intel_crtc->active = false; - crtc->enabled = false; - crtc->state->connector_mask = 0; - crtc->state->encoder_mask = 0; + crtc->base.base.id, crtc->base.name); + + crtc->active = false; + crtc->base.enabled = false; + + WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->uapi, NULL) < 0); + crtc_state->uapi.active = false; + crtc_state->uapi.connector_mask = 0; + crtc_state->uapi.encoder_mask = 0; intel_crtc_free_hw_state(crtc_state); memset(&crtc_state->hw, 0, sizeof(crtc_state->hw)); - for_each_encoder_on_crtc(crtc->dev, crtc, encoder) + for_each_encoder_on_crtc(&dev_priv->drm, &crtc->base, encoder) encoder->base.crtc = NULL; - intel_fbc_disable(intel_crtc); - intel_update_watermarks(intel_crtc); - intel_disable_shared_dpll(to_intel_crtc_state(crtc->state)); + intel_fbc_disable(crtc); + intel_update_watermarks(crtc); + intel_disable_shared_dpll(crtc_state); - domains = intel_crtc->enabled_power_domains; + domains = crtc->enabled_power_domains; for_each_power_domain(domain, domains) intel_display_power_put_unchecked(dev_priv, domain); - intel_crtc->enabled_power_domains = 0; + crtc->enabled_power_domains = 0; - dev_priv->active_pipes &= ~BIT(intel_crtc->pipe); - dev_priv->min_cdclk[intel_crtc->pipe] = 0; - dev_priv->min_voltage_level[intel_crtc->pipe] = 0; + dev_priv->active_pipes &= ~BIT(pipe); + dev_priv->min_cdclk[pipe] = 0; + dev_priv->min_voltage_level[pipe] = 0; - bw_state->data_rate[intel_crtc->pipe] = 0; - bw_state->num_active_planes[intel_crtc->pipe] = 0; + bw_state->data_rate[pipe] = 0; + bw_state->num_active_planes[pipe] = 0; } /* @@ -17319,7 +17319,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, /* Adjust the state of the output pipe according to whether we * have active connectors/encoders. */ if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc)) - intel_crtc_disable_noatomic(&crtc->base, ctx); + intel_crtc_disable_noatomic(crtc, ctx); if (crtc_state->hw.active || HAS_GMCH(dev_priv)) { /* -- cgit v1.2.3 From 6d37bc73976f5306f39b9d34a2e95f0285e6e862 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:26 +0200 Subject: drm/i915: Use drm_rect to simplify plane {crtc,src}_{x,y,w,h} printing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use DRM_RECT_FMT & co. to simpify the code. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-2-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/i915_debugfs.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index cab632791f73..3f54e66ab762 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2599,6 +2599,7 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) struct drm_plane_state *state; struct drm_plane *plane = &intel_plane->base; struct drm_format_name_buf format_name; + struct drm_rect src, dst; char rot_str[48]; if (!plane->state) { @@ -2608,6 +2609,9 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) state = plane->state; + src = drm_plane_state_src(state); + dst = drm_plane_state_dest(state); + if (state->fb) { drm_get_format_name(state->fb->format->format, &format_name); @@ -2617,19 +2621,11 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) plane_rotation(rot_str, sizeof(rot_str), state->rotation); - seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n", + seq_printf(m, "\t--Plane id %d: type=%s, dst=" DRM_RECT_FMT ", src=" DRM_RECT_FP_FMT ", format=%s, rotation=%s\n", plane->base.id, plane_type(intel_plane->base.type), - state->crtc_x, state->crtc_y, - state->crtc_w, state->crtc_h, - (state->src_x >> 16), - ((state->src_x & 0xffff) * 15625) >> 10, - (state->src_y >> 16), - ((state->src_y & 0xffff) * 15625) >> 10, - (state->src_w >> 16), - ((state->src_w & 0xffff) * 15625) >> 10, - (state->src_h >> 16), - ((state->src_h & 0xffff) * 15625) >> 10, + DRM_RECT_ARG(&dst), + DRM_RECT_FP_ARG(&src), format_name.str, rot_str); } -- cgit v1.2.3 From cb634d3c850ec84810a8964b730020daf2601bb0 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:27 +0200 Subject: drm/i915: Switch to intel_ types in debugfs display_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to using intel_ types in the debugfs display_info code. Should make it easier to handle bigjoiner etc. in the future. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-3-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/i915_debugfs.c | 119 ++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3f54e66ab762..16d3c273a453 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2367,7 +2367,7 @@ out: } static void intel_seq_print_mode(struct seq_file *m, int tabs, - struct drm_display_mode *mode) + const struct drm_display_mode *mode) { int i; @@ -2378,51 +2378,52 @@ static void intel_seq_print_mode(struct seq_file *m, int tabs, } static void intel_encoder_info(struct seq_file *m, - struct intel_crtc *intel_crtc, - struct intel_encoder *intel_encoder) + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_device *dev = &dev_priv->drm; - struct drm_crtc *crtc = &intel_crtc->base; - struct intel_connector *intel_connector; - struct drm_encoder *encoder; + struct intel_connector *connector; - encoder = &intel_encoder->base; seq_printf(m, "\tencoder %d: type: %s, connectors:\n", - encoder->base.id, encoder->name); - for_each_connector_on_encoder(dev, encoder, intel_connector) { - struct drm_connector *connector = &intel_connector->base; + encoder->base.base.id, encoder->base.name); + + for_each_connector_on_encoder(dev, &encoder->base, connector) { seq_printf(m, "\t\tconnector %d: type: %s, status: %s", - connector->base.id, - connector->name, - drm_get_connector_status_name(connector->status)); - if (connector->status == connector_status_connected) { - struct drm_display_mode *mode = &crtc->mode; + connector->base.base.id, connector->base.name, + drm_get_connector_status_name(connector->base.status)); + + if (connector->base.status == connector_status_connected) { + const struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + seq_printf(m, ", mode:\n"); - intel_seq_print_mode(m, 2, mode); + intel_seq_print_mode(m, 2, &crtc_state->hw.mode); } else { seq_putc(m, '\n'); } } } -static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc) +static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_device *dev = &dev_priv->drm; - struct drm_crtc *crtc = &intel_crtc->base; - struct intel_encoder *intel_encoder; - struct drm_plane_state *plane_state = crtc->primary->state; - struct drm_framebuffer *fb = plane_state->fb; + struct intel_encoder *encoder; + struct intel_plane *plane = to_intel_plane(crtc->base.primary); + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + const struct drm_framebuffer *fb = plane_state->uapi.fb; if (fb) seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n", - fb->base.id, plane_state->src_x >> 16, - plane_state->src_y >> 16, fb->width, fb->height); + fb->base.id, plane_state->uapi.src_x >> 16, + plane_state->uapi.src_y >> 16, + fb->width, fb->height); else seq_puts(m, "\tprimary plane disabled\n"); - for_each_encoder_on_crtc(dev, crtc, intel_encoder) - intel_encoder_info(m, intel_crtc, intel_encoder); + for_each_encoder_on_crtc(dev, &crtc->base, encoder) + intel_encoder_info(m, crtc, encoder); } static void intel_panel_info(struct seq_file *m, struct intel_panel *panel) @@ -2589,66 +2590,63 @@ static void plane_rotation(char *buf, size_t bufsize, unsigned int rotation) rotation); } -static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) +static void intel_plane_info(struct seq_file *m, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_device *dev = &dev_priv->drm; - struct intel_plane *intel_plane; + struct intel_plane *plane; - for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { - struct drm_plane_state *state; - struct drm_plane *plane = &intel_plane->base; + for_each_intel_plane_on_crtc(dev, crtc, plane) { + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + const struct drm_framebuffer *fb; struct drm_format_name_buf format_name; struct drm_rect src, dst; char rot_str[48]; - if (!plane->state) { + if (!plane_state) { seq_puts(m, "plane->state is NULL!\n"); continue; } - state = plane->state; - - src = drm_plane_state_src(state); - dst = drm_plane_state_dest(state); + src = drm_plane_state_src(&plane_state->uapi); + dst = drm_plane_state_dest(&plane_state->uapi); + fb = plane_state->uapi.fb; - if (state->fb) { - drm_get_format_name(state->fb->format->format, - &format_name); - } else { + if (fb) + drm_get_format_name(fb->format->format, &format_name); + else sprintf(format_name.str, "N/A"); - } - plane_rotation(rot_str, sizeof(rot_str), state->rotation); + plane_rotation(rot_str, sizeof(rot_str), + plane_state->uapi.rotation); seq_printf(m, "\t--Plane id %d: type=%s, dst=" DRM_RECT_FMT ", src=" DRM_RECT_FP_FMT ", format=%s, rotation=%s\n", - plane->base.id, - plane_type(intel_plane->base.type), + plane->base.base.id, + plane_type(plane->base.type), DRM_RECT_ARG(&dst), DRM_RECT_FP_ARG(&src), - format_name.str, - rot_str); + format_name.str, rot_str); } } -static void intel_scaler_info(struct seq_file *m, struct intel_crtc *intel_crtc) +static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc) { - struct intel_crtc_state *pipe_config; - int num_scalers = intel_crtc->num_scalers; + const struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + int num_scalers = crtc->num_scalers; int i; - pipe_config = to_intel_crtc_state(intel_crtc->base.state); - /* Not all platformas have a scaler */ if (num_scalers) { seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d", num_scalers, - pipe_config->scaler_state.scaler_users, - pipe_config->scaler_state.scaler_id); + crtc_state->scaler_state.scaler_users, + crtc_state->scaler_state.scaler_id); for (i = 0; i < num_scalers; i++) { - struct intel_scaler *sc = - &pipe_config->scaler_state.scalers[i]; + const struct intel_scaler *sc = + &crtc_state->scaler_state.scalers[i]; seq_printf(m, ", scalers[%d]: use=%s, mode=%x", i, yesno(sc->in_use), sc->mode); @@ -2673,18 +2671,19 @@ static int i915_display_info(struct seq_file *m, void *unused) seq_printf(m, "CRTC info\n"); seq_printf(m, "---------\n"); for_each_intel_crtc(dev, crtc) { - struct intel_crtc_state *pipe_config; + const struct intel_crtc_state *crtc_state; drm_modeset_lock(&crtc->base.mutex, NULL); - pipe_config = to_intel_crtc_state(crtc->base.state); + + crtc_state = to_intel_crtc_state(crtc->base.state); seq_printf(m, "CRTC %d: pipe: %c, active=%s, (size=%dx%d), dither=%s, bpp=%d\n", crtc->base.base.id, pipe_name(crtc->pipe), - yesno(pipe_config->hw.active), - pipe_config->pipe_src_w, pipe_config->pipe_src_h, - yesno(pipe_config->dither), pipe_config->pipe_bpp); + yesno(crtc_state->hw.active), + crtc_state->pipe_src_w, crtc_state->pipe_src_h, + yesno(crtc_state->dither), crtc_state->pipe_bpp); - if (pipe_config->hw.active) { + if (crtc_state->hw.active) { struct intel_plane *cursor = to_intel_plane(crtc->base.cursor); -- cgit v1.2.3 From 9de833722e2188a05071c479ee328959424b01d7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:28 +0200 Subject: drm/i915: Reorganize plane/fb dump in debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate the special cases for the primary and cursor planes and just dump all the information consistently for all the planes. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-4-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/i915_debugfs.c | 52 ++++++++++--------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 16d3c273a453..b4fffcce2d12 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2405,27 +2405,6 @@ static void intel_encoder_info(struct seq_file *m, } } -static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct intel_encoder *encoder; - struct intel_plane *plane = to_intel_plane(crtc->base.primary); - const struct intel_plane_state *plane_state = - to_intel_plane_state(plane->base.state); - const struct drm_framebuffer *fb = plane_state->uapi.fb; - - if (fb) - seq_printf(m, "\tfb: %d, pos: %dx%d, size: %dx%d\n", - fb->base.id, plane_state->uapi.src_x >> 16, - plane_state->uapi.src_y >> 16, - fb->width, fb->height); - else - seq_puts(m, "\tprimary plane disabled\n"); - for_each_encoder_on_crtc(dev, &crtc->base, encoder) - intel_encoder_info(m, crtc, encoder); -} - static void intel_panel_info(struct seq_file *m, struct intel_panel *panel) { struct drm_display_mode *mode = panel->fixed_mode; @@ -2611,22 +2590,24 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *crtc) src = drm_plane_state_src(&plane_state->uapi); dst = drm_plane_state_dest(&plane_state->uapi); - fb = plane_state->uapi.fb; + fb = plane_state->uapi.fb; if (fb) drm_get_format_name(fb->format->format, &format_name); - else - sprintf(format_name.str, "N/A"); plane_rotation(rot_str, sizeof(rot_str), plane_state->uapi.rotation); - seq_printf(m, "\t--Plane id %d: type=%s, dst=" DRM_RECT_FMT ", src=" DRM_RECT_FP_FMT ", format=%s, rotation=%s\n", + seq_printf(m, "\t--Plane id %d: type=%s, fb=%d,%s,%dx%d, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", plane->base.base.id, plane_type(plane->base.type), - DRM_RECT_ARG(&dst), + fb ? fb->base.id : 0, + fb ? format_name.str : "n/a", + fb ? fb->width : 0, + fb ? fb->height : 0, DRM_RECT_FP_ARG(&src), - format_name.str, rot_str); + DRM_RECT_ARG(&dst), + rot_str); } } @@ -2684,18 +2665,11 @@ static int i915_display_info(struct seq_file *m, void *unused) yesno(crtc_state->dither), crtc_state->pipe_bpp); if (crtc_state->hw.active) { - struct intel_plane *cursor = - to_intel_plane(crtc->base.cursor); - - intel_crtc_info(m, crtc); - - seq_printf(m, "\tcursor visible? %s, position (%d, %d), size %dx%d, addr 0x%08x\n", - yesno(cursor->base.state->visible), - cursor->base.state->crtc_x, - cursor->base.state->crtc_y, - cursor->base.state->crtc_w, - cursor->base.state->crtc_h, - cursor->cursor.base); + struct intel_encoder *encoder; + + for_each_encoder_on_crtc(dev, &crtc->base, encoder) + intel_encoder_info(m, crtc, encoder); + intel_scaler_info(m, crtc); intel_plane_info(m, crtc); } -- cgit v1.2.3 From 647542337786fc87cc1e8c48ee2c3cec92c2bc80 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:29 +0200 Subject: drm/i915: Refactor debugfs display info code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the crtc dumping stuff into a nice function so the loop over the crtcs doesn't look like crap. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-5-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/i915_debugfs.c | 52 ++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b4fffcce2d12..28f45f25cfc0 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2638,6 +2638,33 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc) } } +static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = node_to_i915(m->private); + const struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + + seq_printf(m, "CRTC %d: pipe: %c, active=%s, (size=%dx%d), dither=%s, bpp=%d\n", + crtc->base.base.id, pipe_name(crtc->pipe), + yesno(crtc_state->hw.active), + crtc_state->pipe_src_w, crtc_state->pipe_src_h, + yesno(crtc_state->dither), crtc_state->pipe_bpp); + + if (crtc_state->hw.active) { + struct intel_encoder *encoder; + + for_each_encoder_on_crtc(&dev_priv->drm, &crtc->base, encoder) + intel_encoder_info(m, crtc, encoder); + + intel_scaler_info(m, crtc); + intel_plane_info(m, crtc); + } + + seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s\n", + yesno(!crtc->cpu_fifo_underrun_disabled), + yesno(!crtc->pch_fifo_underrun_disabled)); +} + static int i915_display_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -2652,31 +2679,8 @@ static int i915_display_info(struct seq_file *m, void *unused) seq_printf(m, "CRTC info\n"); seq_printf(m, "---------\n"); for_each_intel_crtc(dev, crtc) { - const struct intel_crtc_state *crtc_state; - drm_modeset_lock(&crtc->base.mutex, NULL); - - crtc_state = to_intel_crtc_state(crtc->base.state); - - seq_printf(m, "CRTC %d: pipe: %c, active=%s, (size=%dx%d), dither=%s, bpp=%d\n", - crtc->base.base.id, pipe_name(crtc->pipe), - yesno(crtc_state->hw.active), - crtc_state->pipe_src_w, crtc_state->pipe_src_h, - yesno(crtc_state->dither), crtc_state->pipe_bpp); - - if (crtc_state->hw.active) { - struct intel_encoder *encoder; - - for_each_encoder_on_crtc(dev, &crtc->base, encoder) - intel_encoder_info(m, crtc, encoder); - - intel_scaler_info(m, crtc); - intel_plane_info(m, crtc); - } - - seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n", - yesno(!crtc->cpu_fifo_underrun_disabled), - yesno(!crtc->pch_fifo_underrun_disabled)); + intel_crtc_info(m, crtc); drm_modeset_unlock(&crtc->base.mutex); } -- cgit v1.2.3 From 5244221ee89b30f0e8add9e88482da873b6e0a54 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:30 +0200 Subject: drm/i915: Dump the mode for the crtc just the once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in repeating the crtc mode for each cloned encoder. Just print it once, and avoid using multiple lines for it. And while at let's polish the fixed mode print to fit on one line as well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-6-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/i915_debugfs.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 28f45f25cfc0..11f3f91befb9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2388,29 +2388,16 @@ static void intel_encoder_info(struct seq_file *m, seq_printf(m, "\tencoder %d: type: %s, connectors:\n", encoder->base.base.id, encoder->base.name); - for_each_connector_on_encoder(dev, &encoder->base, connector) { - seq_printf(m, "\t\tconnector %d: type: %s, status: %s", - connector->base.base.id, connector->base.name, - drm_get_connector_status_name(connector->base.status)); - - if (connector->base.status == connector_status_connected) { - const struct intel_crtc_state *crtc_state = - to_intel_crtc_state(crtc->base.state); - - seq_printf(m, ", mode:\n"); - intel_seq_print_mode(m, 2, &crtc_state->hw.mode); - } else { - seq_putc(m, '\n'); - } - } + for_each_connector_on_encoder(dev, &encoder->base, connector) + seq_printf(m, "\t\tconnector %d: type: %s\n", + connector->base.base.id, connector->base.name); } static void intel_panel_info(struct seq_file *m, struct intel_panel *panel) { - struct drm_display_mode *mode = panel->fixed_mode; + const struct drm_display_mode *mode = panel->fixed_mode; - seq_printf(m, "\tfixed mode:\n"); - intel_seq_print_mode(m, 2, mode); + seq_printf(m, "\tfixed mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); } static void intel_hdcp_info(struct seq_file *m, @@ -2651,8 +2638,12 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) yesno(crtc_state->dither), crtc_state->pipe_bpp); if (crtc_state->hw.active) { + const struct drm_display_mode *mode = + &crtc_state->hw.mode; struct intel_encoder *encoder; + seq_printf(m, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); + for_each_encoder_on_crtc(&dev_priv->drm, &crtc->base, encoder) intel_encoder_info(m, crtc, encoder); -- cgit v1.2.3 From 3ff11a0ab5fe69b66e4a2608b3dca13712c0634a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:31 +0200 Subject: drm/i915: Use drm_modeset_lock_all() in debugfs display info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make out life easier by just grabbing all modeset locks around the display_info dump. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-7-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/i915_debugfs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 11f3f91befb9..3bf7d4e2f940 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2667,23 +2667,22 @@ static int i915_display_info(struct seq_file *m, void *unused) wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); + drm_modeset_lock_all(dev); + seq_printf(m, "CRTC info\n"); seq_printf(m, "---------\n"); - for_each_intel_crtc(dev, crtc) { - drm_modeset_lock(&crtc->base.mutex, NULL); + for_each_intel_crtc(dev, crtc) intel_crtc_info(m, crtc); - drm_modeset_unlock(&crtc->base.mutex); - } seq_printf(m, "\n"); seq_printf(m, "Connector info\n"); seq_printf(m, "--------------\n"); - mutex_lock(&dev->mode_config.mutex); drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) intel_connector_info(m, connector); drm_connector_list_iter_end(&conn_iter); - mutex_unlock(&dev->mode_config.mutex); + + drm_modeset_unlock_all(dev); intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); -- cgit v1.2.3 From d029a139eb9880caef7c9c32f8eb6c637cd4db54 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:32 +0200 Subject: drm/i915: Use the canonical [CRTC:%d:%s]/etc. format in i915_display_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the canonical "[CRTC:%d:%s]" format for the obj id/name in the debugfs display_info dump. Everyone should already be familiar with the format since it's used in the debug logs extensively. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-8-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/i915_debugfs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3bf7d4e2f940..4dffbff1b8bd 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2385,11 +2385,11 @@ static void intel_encoder_info(struct seq_file *m, struct drm_device *dev = &dev_priv->drm; struct intel_connector *connector; - seq_printf(m, "\tencoder %d: type: %s, connectors:\n", + seq_printf(m, "\t[ENCODER:%d:%s]: connectors:\n", encoder->base.base.id, encoder->base.name); for_each_connector_on_encoder(dev, &encoder->base, connector) - seq_printf(m, "\t\tconnector %d: type: %s\n", + seq_printf(m, "\t\t[CONNECTOR:%d:%s]\n", connector->base.base.id, connector->base.name); } @@ -2478,7 +2478,7 @@ static void intel_connector_info(struct seq_file *m, struct intel_encoder *intel_encoder = intel_connector->encoder; struct drm_display_mode *mode; - seq_printf(m, "connector %d: type %s, status: %s\n", + seq_printf(m, "[CONNECTOR:%d:%s]: status: %s\n", connector->base.id, connector->name, drm_get_connector_status_name(connector->status)); @@ -2585,8 +2585,8 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *crtc) plane_rotation(rot_str, sizeof(rot_str), plane_state->uapi.rotation); - seq_printf(m, "\t--Plane id %d: type=%s, fb=%d,%s,%dx%d, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", - plane->base.base.id, + seq_printf(m, "\t[PLANE:%d:%s]: type=%s, fb=%d,%s,%dx%d, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", + plane->base.base.id, plane->base.name, plane_type(plane->base.type), fb ? fb->base.id : 0, fb ? format_name.str : "n/a", @@ -2631,8 +2631,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - seq_printf(m, "CRTC %d: pipe: %c, active=%s, (size=%dx%d), dither=%s, bpp=%d\n", - crtc->base.base.id, pipe_name(crtc->pipe), + seq_printf(m, "[CRTC:%d:%s]: active=%s, (size=%dx%d), dither=%s, bpp=%d\n", + crtc->base.base.id, crtc->base.name, yesno(crtc_state->hw.active), crtc_state->pipe_src_w, crtc_state->pipe_src_h, yesno(crtc_state->dither), crtc_state->pipe_bpp); -- cgit v1.2.3 From 3cf12da44f7f73d1c75fd9da8509f320a262ca3c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:33 +0200 Subject: drm/i915: Dump both the uapi and hw states for crtcs and planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's make the display info more useful by dumping both the uapi and hw states for each crtc/plane. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-9-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/i915_debugfs.c | 112 +++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4dffbff1b8bd..414da0a542d6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2556,45 +2556,68 @@ static void plane_rotation(char *buf, size_t bufsize, unsigned int rotation) rotation); } -static void intel_plane_info(struct seq_file *m, struct intel_crtc *crtc) +static void intel_plane_uapi_info(struct seq_file *m, struct intel_plane *plane) { - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct intel_plane *plane; + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + const struct drm_framebuffer *fb = plane_state->uapi.fb; + struct drm_format_name_buf format_name; + struct drm_rect src, dst; + char rot_str[48]; - for_each_intel_plane_on_crtc(dev, crtc, plane) { - const struct intel_plane_state *plane_state = - to_intel_plane_state(plane->base.state); - const struct drm_framebuffer *fb; - struct drm_format_name_buf format_name; - struct drm_rect src, dst; - char rot_str[48]; + src = drm_plane_state_src(&plane_state->uapi); + dst = drm_plane_state_dest(&plane_state->uapi); - if (!plane_state) { - seq_puts(m, "plane->state is NULL!\n"); - continue; - } + if (fb) + drm_get_format_name(fb->format->format, &format_name); + + plane_rotation(rot_str, sizeof(rot_str), + plane_state->uapi.rotation); + + seq_printf(m, "\t\tuapi: fb=%d,%s,%dx%d, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", + fb ? fb->base.id : 0, fb ? format_name.str : "n/a", + fb ? fb->width : 0, fb ? fb->height : 0, + DRM_RECT_FP_ARG(&src), + DRM_RECT_ARG(&dst), + rot_str); +} + +static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane) +{ + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + const struct drm_framebuffer *fb = plane_state->hw.fb; + struct drm_format_name_buf format_name; + char rot_str[48]; - src = drm_plane_state_src(&plane_state->uapi); - dst = drm_plane_state_dest(&plane_state->uapi); + if (!fb) + return; + + drm_get_format_name(fb->format->format, &format_name); - fb = plane_state->uapi.fb; - if (fb) - drm_get_format_name(fb->format->format, &format_name); + plane_rotation(rot_str, sizeof(rot_str), + plane_state->hw.rotation); - plane_rotation(rot_str, sizeof(rot_str), - plane_state->uapi.rotation); + seq_printf(m, "\t\thw: fb=%d,%s,%dx%d, visible=%s, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", + fb ? fb->base.id : 0, fb ? format_name.str : "n/a", + fb ? fb->width : 0, fb ? fb->height : 0, + yesno(plane_state->uapi.visible), + DRM_RECT_FP_ARG(&plane_state->uapi.src), + DRM_RECT_ARG(&plane_state->uapi.dst), + rot_str); +} - seq_printf(m, "\t[PLANE:%d:%s]: type=%s, fb=%d,%s,%dx%d, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", +static void intel_plane_info(struct seq_file *m, struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct intel_plane *plane; + + for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { + seq_printf(m, "\t[PLANE:%d:%s]: type=%s\n", plane->base.base.id, plane->base.name, - plane_type(plane->base.type), - fb ? fb->base.id : 0, - fb ? format_name.str : "n/a", - fb ? fb->width : 0, - fb ? fb->height : 0, - DRM_RECT_FP_ARG(&src), - DRM_RECT_ARG(&dst), - rot_str); + plane_type(plane->base.type)); + intel_plane_uapi_info(m, plane); + intel_plane_hw_info(m, plane); } } @@ -2631,26 +2654,33 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); - seq_printf(m, "[CRTC:%d:%s]: active=%s, (size=%dx%d), dither=%s, bpp=%d\n", - crtc->base.base.id, crtc->base.name, - yesno(crtc_state->hw.active), - crtc_state->pipe_src_w, crtc_state->pipe_src_h, - yesno(crtc_state->dither), crtc_state->pipe_bpp); + seq_printf(m, "[CRTC:%d:%s]:\n", + crtc->base.base.id, crtc->base.name); + + seq_printf(m, "\tuapi: enable=%s, active=%s, mode=" DRM_MODE_FMT "\n", + yesno(crtc_state->uapi.enable), + yesno(crtc_state->uapi.active), + DRM_MODE_ARG(&crtc_state->uapi.mode)); - if (crtc_state->hw.active) { - const struct drm_display_mode *mode = - &crtc_state->hw.mode; + if (crtc_state->hw.enable) { struct intel_encoder *encoder; - seq_printf(m, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); + seq_printf(m, "\thw: active=%s, adjusted_mode=" DRM_MODE_FMT "\n", + yesno(crtc_state->hw.active), + DRM_MODE_ARG(&crtc_state->hw.adjusted_mode)); + + seq_printf(m, "\tpipe src size=%dx%d, dither=%s, bpp=%d\n", + crtc_state->pipe_src_w, crtc_state->pipe_src_h, + yesno(crtc_state->dither), crtc_state->pipe_bpp); for_each_encoder_on_crtc(&dev_priv->drm, &crtc->base, encoder) intel_encoder_info(m, crtc, encoder); intel_scaler_info(m, crtc); - intel_plane_info(m, crtc); } + intel_plane_info(m, crtc); + seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s\n", yesno(!crtc->cpu_fifo_underrun_disabled), yesno(!crtc->pch_fifo_underrun_disabled)); -- cgit v1.2.3 From ca851c224853fb0eb6e4f45c92896f89e6013a44 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 29 Nov 2019 20:54:34 +0200 Subject: drm/i915: Stop using connector->encoder and encoder->crtc links in i915_display_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate away from the legacy encoder->crtc and connector->encoder links in the debugfs display_info code. Other users still remain so can't kill these off yet. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191129185434.25549-10-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/display/intel_display.h | 7 +++++ drivers/gpu/drm/i915/i915_debugfs.c | 43 +++++++++++++++++----------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index a5ec5eeff056..5ed716a986ad 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -380,6 +380,13 @@ enum phy_fia { &(dev)->mode_config.encoder_list, \ base.head) +#define for_each_intel_encoder_mask(dev, intel_encoder, encoder_mask) \ + list_for_each_entry(intel_encoder, \ + &(dev)->mode_config.encoder_list, \ + base.head) \ + for_each_if((encoder_mask) & \ + drm_encoder_mask(&intel_encoder->base)) + #define for_each_intel_dp(dev, intel_encoder) \ for_each_intel_encoder(dev, intel_encoder) \ for_each_if(intel_encoder_is_dp(intel_encoder)) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 414da0a542d6..eb80a2c4b55b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2382,15 +2382,24 @@ static void intel_encoder_info(struct seq_file *m, struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct intel_connector *connector; + struct drm_connector_list_iter conn_iter; + struct drm_connector *connector; seq_printf(m, "\t[ENCODER:%d:%s]: connectors:\n", encoder->base.base.id, encoder->base.name); - for_each_connector_on_encoder(dev, &encoder->base, connector) + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + const struct drm_connector_state *conn_state = + connector->state; + + if (conn_state->best_encoder != &encoder->base) + continue; + seq_printf(m, "\t\t[CONNECTOR:%d:%s]\n", - connector->base.base.id, connector->base.name); + connector->base.id, connector->name); + } + drm_connector_list_iter_end(&conn_iter); } static void intel_panel_info(struct seq_file *m, struct intel_panel *panel) @@ -2475,8 +2484,10 @@ static void intel_connector_info(struct seq_file *m, struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); - struct intel_encoder *intel_encoder = intel_connector->encoder; - struct drm_display_mode *mode; + const struct drm_connector_state *conn_state = connector->state; + struct intel_encoder *encoder = + to_intel_encoder(conn_state->best_encoder); + const struct drm_display_mode *mode; seq_printf(m, "[CONNECTOR:%d:%s]: status: %s\n", connector->base.id, connector->name, @@ -2492,24 +2503,24 @@ static void intel_connector_info(struct seq_file *m, drm_get_subpixel_order_name(connector->display_info.subpixel_order)); seq_printf(m, "\tCEA rev: %d\n", connector->display_info.cea_rev); - if (!intel_encoder) + if (!encoder) return; switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_eDP: - if (intel_encoder->type == INTEL_OUTPUT_DP_MST) + if (encoder->type == INTEL_OUTPUT_DP_MST) intel_dp_mst_info(m, intel_connector); else intel_dp_info(m, intel_connector); break; case DRM_MODE_CONNECTOR_LVDS: - if (intel_encoder->type == INTEL_OUTPUT_LVDS) + if (encoder->type == INTEL_OUTPUT_LVDS) intel_lvds_info(m, intel_connector); break; case DRM_MODE_CONNECTOR_HDMIA: - if (intel_encoder->type == INTEL_OUTPUT_HDMI || - intel_encoder->type == INTEL_OUTPUT_DDI) + if (encoder->type == INTEL_OUTPUT_HDMI || + encoder->type == INTEL_OUTPUT_DDI) intel_hdmi_info(m, intel_connector); break; default: @@ -2653,6 +2664,7 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) struct drm_i915_private *dev_priv = node_to_i915(m->private); const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); + struct intel_encoder *encoder; seq_printf(m, "[CRTC:%d:%s]:\n", crtc->base.base.id, crtc->base.name); @@ -2663,8 +2675,6 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) DRM_MODE_ARG(&crtc_state->uapi.mode)); if (crtc_state->hw.enable) { - struct intel_encoder *encoder; - seq_printf(m, "\thw: active=%s, adjusted_mode=" DRM_MODE_FMT "\n", yesno(crtc_state->hw.active), DRM_MODE_ARG(&crtc_state->hw.adjusted_mode)); @@ -2673,12 +2683,13 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) crtc_state->pipe_src_w, crtc_state->pipe_src_h, yesno(crtc_state->dither), crtc_state->pipe_bpp); - for_each_encoder_on_crtc(&dev_priv->drm, &crtc->base, encoder) - intel_encoder_info(m, crtc, encoder); - intel_scaler_info(m, crtc); } + for_each_intel_encoder_mask(&dev_priv->drm, encoder, + crtc_state->uapi.encoder_mask) + intel_encoder_info(m, crtc, encoder); + intel_plane_info(m, crtc); seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s\n", -- cgit v1.2.3 From 13caf7bea4432e8d192d412eae9ee8efb2f47fe8 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 27 Nov 2019 14:11:21 -0800 Subject: drm/i915/dsb: fix cmd_buf being wrongly set The "err" label is not really "err", but rather "out" since the return path is shared between error condition and normal path. This broke when commit 03cea61076f0 ("drm/i915/dsb: fix extra warning on error path handling") added a "dsb->cmd_buf = NULL;" there, making DSB to stop working since now all writes would pass-through via mmio. Remove the set to NULL since it's actually not needed: we only set it if all steps are successful. While at it, rename the label so this confusion doesn't happen again. Fixes: 03cea61076f0 ("drm/i915/dsb: fix extra warning on error path handling") Resolves: https://gitlab.freedesktop.org/drm/intel/issues/8 Signed-off-by: Lucas De Marchi Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20191127221119.384754-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_dsb.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 5bf67bdc8182..ada006a690df 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -116,34 +116,34 @@ intel_dsb_get(struct intel_crtc *crtc) obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); if (IS_ERR(obj)) { DRM_ERROR("Gem object creation failed\n"); - goto err; + goto out; } vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); if (IS_ERR(vma)) { DRM_ERROR("Vma creation failed\n"); i915_gem_object_put(obj); - goto err; + goto out; } buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC); if (IS_ERR(buf)) { DRM_ERROR("Command buffer creation failed\n"); - goto err; + goto out; } dsb->id = DSB1; dsb->vma = vma; dsb->cmd_buf = buf; -err: +out: /* - * Set cmd_buf to NULL so the writes pass-through, but leave the - * dangling refcount to be removed later by the corresponding - * intel_dsb_put(): the important error message will already be - * logged above. + * On error dsb->cmd_buf will continue to be NULL, making the writes + * pass-through. Leave the dangling ref to be removed later by the + * corresponding intel_dsb_put(): the important error message will + * already be logged above. */ - dsb->cmd_buf = NULL; + intel_runtime_pm_put(&i915->runtime_pm, wakeref); return dsb; -- cgit v1.2.3 From f98837e85fcdcdbeec3cadc40456da85d07256a3 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Wed, 27 Nov 2019 17:48:48 -0800 Subject: drm/i915/psr: Add bits per pixel limitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PSR2 HW only support a limited number of bits per pixel, if mode has more than supported PSR2 should not be enabled. BSpec: 50422 BSpec: 7713 Cc: Gwan-gyeong Mun Cc: Matt Roper Reviewed-by: Lucas De Marchi Reviewed-by: Matt Roper Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191128014852.214135-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index c1d133362b76..0d84ea28bc6f 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -608,7 +608,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay; int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay; - int psr_max_h = 0, psr_max_v = 0; + int psr_max_h = 0, psr_max_v = 0, max_bpp = 0; if (!dev_priv->psr.sink_psr2_support) return false; @@ -632,12 +632,15 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, if (INTEL_GEN(dev_priv) >= 12) { psr_max_h = 5120; psr_max_v = 3200; + max_bpp = 30; } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { psr_max_h = 4096; psr_max_v = 2304; + max_bpp = 24; } else if (IS_GEN(dev_priv, 9)) { psr_max_h = 3640; psr_max_v = 2304; + max_bpp = 24; } if (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v) { @@ -647,6 +650,12 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } + if (crtc_state->pipe_bpp > max_bpp) { + DRM_DEBUG_KMS("PSR2 not enabled, pipe bpp %d > max supported %d\n", + crtc_state->pipe_bpp, max_bpp); + return false; + } + /* * HW sends SU blocks of size four scan lines, which means the starting * X coordinate and Y granularity requirements will always be met. We -- cgit v1.2.3 From 95851205f9b3d2bb81cc5f63afd1124c9eb79940 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Wed, 27 Nov 2019 17:48:49 -0800 Subject: drm/i915/psr: Refactor psr short pulse handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit eDP spec states that when sink enconters a problem that prevents it to keep PSR running it should set PSR status to internal error and set the reason why it happen to PSR_ERROR_STATUS but it is not how it was implemented. But also I don't want to change this behavior, who knows if there is a panel out there that only set the PSR_ERROR_STATUS. So here refactoring the code a bit to make more easy to read what was state above as more checks will be added to this function. v2: returning a int instead of a bool in psr_get_status_and_error_status() Cc: Gwan-gyeong Mun Cc: Matt Roper Reviewed-by: Matt Roper Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191128014852.214135-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 51 +++++++++++++++++++------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 0d84ea28bc6f..1a1ac3f46bf7 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1386,11 +1386,30 @@ void intel_psr_init(struct drm_i915_private *dev_priv) mutex_init(&dev_priv->psr.lock); } +static int psr_get_status_and_error_status(struct intel_dp *intel_dp, + u8 *status, u8 *error_status) +{ + struct drm_dp_aux *aux = &intel_dp->aux; + int ret; + + ret = drm_dp_dpcd_readb(aux, DP_PSR_STATUS, status); + if (ret != 1) + return ret; + + ret = drm_dp_dpcd_readb(aux, DP_PSR_ERROR_STATUS, error_status); + if (ret != 1) + return ret; + + *status = *status & DP_PSR_SINK_STATE_MASK; + + return 0; +} + void intel_psr_short_pulse(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct i915_psr *psr = &dev_priv->psr; - u8 val; + u8 status, error_status; const u8 errors = DP_PSR_RFB_STORAGE_ERROR | DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR | DP_PSR_LINK_CRC_ERROR; @@ -1403,38 +1422,30 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) if (!psr->enabled || psr->dp != intel_dp) goto exit; - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val) != 1) { - DRM_ERROR("PSR_STATUS dpcd read failed\n"); + if (psr_get_status_and_error_status(intel_dp, &status, &error_status)) { + DRM_ERROR("Error reading PSR status or error status\n"); goto exit; } - if ((val & DP_PSR_SINK_STATE_MASK) == DP_PSR_SINK_INTERNAL_ERROR) { - DRM_DEBUG_KMS("PSR sink internal error, disabling PSR\n"); + if (status == DP_PSR_SINK_INTERNAL_ERROR || (error_status & errors)) { intel_psr_disable_locked(intel_dp); psr->sink_not_reliable = true; } - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_ERROR_STATUS, &val) != 1) { - DRM_ERROR("PSR_ERROR_STATUS dpcd read failed\n"); - goto exit; - } - - if (val & DP_PSR_RFB_STORAGE_ERROR) + if (status == DP_PSR_SINK_INTERNAL_ERROR && !error_status) + DRM_DEBUG_KMS("PSR sink internal error, disabling PSR\n"); + if (error_status & DP_PSR_RFB_STORAGE_ERROR) DRM_DEBUG_KMS("PSR RFB storage error, disabling PSR\n"); - if (val & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR) + if (error_status & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR) DRM_DEBUG_KMS("PSR VSC SDP uncorrectable error, disabling PSR\n"); - if (val & DP_PSR_LINK_CRC_ERROR) + if (error_status & DP_PSR_LINK_CRC_ERROR) DRM_DEBUG_KMS("PSR Link CRC error, disabling PSR\n"); - if (val & ~errors) + if (error_status & ~errors) DRM_ERROR("PSR_ERROR_STATUS unhandled errors %x\n", - val & ~errors); - if (val & errors) { - intel_psr_disable_locked(intel_dp); - psr->sink_not_reliable = true; - } + error_status & ~errors); /* clear status register */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ERROR_STATUS, val); + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ERROR_STATUS, error_status); exit: mutex_unlock(&psr->lock); } -- cgit v1.2.3 From 700355af64bbb6c6dc4e552fa727513dccdcfe62 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Wed, 27 Nov 2019 17:48:50 -0800 Subject: drm/i915/psr: Enable ALPM lock timeout error interruption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When this error happens sink link is not stable after the required FW_EXIT_LATENCY period so it will miss the selective update. As the other PSR errors, for now we are not trying to recover from it. Cc: Gwan-gyeong Mun Reviewed-by: Matt Roper Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191128014852.214135-3-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 1a1ac3f46bf7..a757b6445f21 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -402,7 +402,9 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp) /* Enable ALPM at sink for psr2 */ if (dev_priv->psr.psr2_enabled) { drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, - DP_ALPM_ENABLE); + DP_ALPM_ENABLE | + DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE); + dpcd_val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS; } else { if (dev_priv->psr.link_standby) @@ -934,6 +936,9 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) /* Disable PSR on Sink */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); + if (dev_priv->psr.psr2_enabled) + drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, 0); + dev_priv->psr.enabled = false; } @@ -1405,6 +1410,33 @@ static int psr_get_status_and_error_status(struct intel_dp *intel_dp, return 0; } +static void psr_alpm_check(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct drm_dp_aux *aux = &intel_dp->aux; + struct i915_psr *psr = &dev_priv->psr; + u8 val; + int r; + + if (!psr->psr2_enabled) + return; + + r = drm_dp_dpcd_readb(aux, DP_RECEIVER_ALPM_STATUS, &val); + if (r != 1) { + DRM_ERROR("Error reading ALPM status\n"); + return; + } + + if (val & DP_ALPM_LOCK_TIMEOUT_ERROR) { + intel_psr_disable_locked(intel_dp); + psr->sink_not_reliable = true; + DRM_DEBUG_KMS("ALPM lock timeout error, disabling PSR\n"); + + /* Clearing error */ + drm_dp_dpcd_writeb(aux, DP_RECEIVER_ALPM_STATUS, val); + } +} + void intel_psr_short_pulse(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -1446,6 +1478,9 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) error_status & ~errors); /* clear status register */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ERROR_STATUS, error_status); + + psr_alpm_check(intel_dp); + exit: mutex_unlock(&psr->lock); } -- cgit v1.2.3 From ba0af30d24e992534212b453a39695c6feae886e Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Wed, 27 Nov 2019 17:48:51 -0800 Subject: drm/i915/psr: Check if sink PSR capability changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit eDP specification states that sink can have its PSR capability changed, I have never found any panel doing that but lets add that for completeness. For now it is not reading back the PSR capabilities and if possible re-enabling PSR, this will be added if a panel is found using this feature. v4: Cleaning DP_PSR_CAPS_CHANGE Reviewed-by: Matt Roper Cc: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191128014852.214135-4-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index a757b6445f21..16e9ff47d519 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1437,6 +1437,29 @@ static void psr_alpm_check(struct intel_dp *intel_dp) } } +static void psr_capability_changed_check(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct i915_psr *psr = &dev_priv->psr; + u8 val; + int r; + + r = drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_ESI, &val); + if (r != 1) { + DRM_ERROR("Error reading DP_PSR_ESI\n"); + return; + } + + if (val & DP_PSR_CAPS_CHANGE) { + intel_psr_disable_locked(intel_dp); + psr->sink_not_reliable = true; + DRM_DEBUG_KMS("Sink PSR capability changed, disabling PSR\n"); + + /* Clearing it */ + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ESI, val); + } +} + void intel_psr_short_pulse(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -1480,6 +1503,7 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ERROR_STATUS, error_status); psr_alpm_check(intel_dp); + psr_capability_changed_check(intel_dp); exit: mutex_unlock(&psr->lock); -- cgit v1.2.3 From 551fb93d4ab3845f358c9e24a5eb38275796073a Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Wed, 27 Nov 2019 17:48:52 -0800 Subject: drm/i915/vbt: Parse power conservation features block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From VBT 228+ this is block that PSR and other power saving features configuration should be read from. v3: Using DRRS from this new block v4: Using BIT() Fixing DRRS comment in parse_power_conservation_features() Cc: Matt Roper Cc: Gwan-gyeong Mun Reviewed-by: Matt Roper Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191128014852.214135-5-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 38 ++++++++++++++++++++++++--- drivers/gpu/drm/i915/display/intel_vbt_defs.h | 29 ++++++++++++++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index f6a9a5ccb556..70e644082bec 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -659,16 +659,45 @@ parse_driver_features(struct drm_i915_private *dev_priv, dev_priv->vbt.int_lvds_support = 0; } - DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled); + if (bdb->version < 228) { + DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled); + /* + * If DRRS is not supported, drrs_type has to be set to 0. + * This is because, VBT is configured in such a way that + * static DRRS is 0 and DRRS not supported is represented by + * driver->drrs_enabled=false + */ + if (!driver->drrs_enabled) + dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED; + + dev_priv->vbt.psr.enable = driver->psr_enabled; + } +} + +static void +parse_power_conservation_features(struct drm_i915_private *dev_priv, + const struct bdb_header *bdb) +{ + const struct bdb_lfp_power *power; + u8 panel_type = dev_priv->vbt.panel_type; + + if (bdb->version < 228) + return; + + power = find_section(bdb, BDB_LVDS_POWER); + if (!power) + return; + + dev_priv->vbt.psr.enable = power->psr & BIT(panel_type); + /* * If DRRS is not supported, drrs_type has to be set to 0. * This is because, VBT is configured in such a way that * static DRRS is 0 and DRRS not supported is represented by - * driver->drrs_enabled=false + * power->drrs & BIT(panel_type)=false */ - if (!driver->drrs_enabled) + if (!(power->drrs & BIT(panel_type))) dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED; - dev_priv->vbt.psr.enable = driver->psr_enabled; } static void @@ -1973,6 +2002,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv) parse_lfp_backlight(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); parse_driver_features(dev_priv, bdb); + parse_power_conservation_features(dev_priv, bdb); parse_edp(dev_priv, bdb); parse_psr(dev_priv, bdb); parse_mipi_config(dev_priv, bdb); diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index f0338da3a82a..98b71dc32d2a 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -793,6 +793,35 @@ struct bdb_lfp_backlight_data { struct lfp_backlight_control_method backlight_control[16]; } __packed; +/* + * Block 44 - LFP Power Conservation Features Block + */ + +struct als_data_entry { + u16 backlight_adjust; + u16 lux; +} __packed; + +struct agressiveness_profile_entry { + u8 dpst_agressiveness : 4; + u8 lace_agressiveness : 4; +} __packed; + +struct bdb_lfp_power { + u8 lfp_feature_bits; + struct als_data_entry als[5]; + u8 lace_aggressiveness_profile; + u16 dpst; + u16 psr; + u16 drrs; + u16 lace_support; + u16 adt; + u16 dmrrs; + u16 adb; + u16 lace_enabled_status; + struct agressiveness_profile_entry aggressivenes[16]; +} __packed; + /* * Block 52 - MIPI Configuration Block */ -- cgit v1.2.3 From d5746bf20e971caf194b1e69b9332570041fc6d6 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Tue, 26 Nov 2019 18:16:09 -0800 Subject: drm/i915/display: Suspend MST topology manager before destroy fbdev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MST topology needs to be suspended so we don't have any calls to fbdev after it's finalized. MST will be destroyed later as part of drm_mode_config_cleanup(). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109964 Signed-off-by: José Roberto de Souza Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20191127021609.162700-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5adc48aacbda..947739f18b0a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17947,6 +17947,13 @@ void intel_modeset_driver_remove(struct drm_i915_private *i915) */ intel_hpd_poll_fini(i915); + /* + * MST topology needs to be suspended so we don't have any calls to + * fbdev after it's finalized. MST will be destroyed later as part of + * drm_mode_config_cleanup() + */ + intel_dp_mst_suspend(i915); + /* poll work can call into fbdev, hence clean that up afterwards */ intel_fbdev_fini(i915); -- cgit v1.2.3 From fd0186ce185161915d0d51e6efd2c632571f948f Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 26 Nov 2019 14:51:08 -0800 Subject: drm/i915/bios: do not discard address space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we map the VBT through pci_map_rom() we may not be allowed to simply discard the address space and go on reading the memory. That doesn't work on my test system, but by dumping the rom via sysfs I can can get the correct vbt. So change our find_vbt() to do the same as done by pci_read_rom(), i.e. use memcpy_fromio(). v2: the just the minimal changes by not bothering with the unaligned io reads: this can be done on top (from Ville and Jani) v3: drop const in function return since now we are copying the vbt, rather than just finding it Signed-off-by: Lucas De Marchi Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191126225110.8127-2-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 51 +++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 70e644082bec..ce19f434ab37 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1925,28 +1925,52 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) return vbt; } -static const struct vbt_header *find_vbt(void __iomem *oprom, size_t size) +static struct vbt_header *copy_vbt(void __iomem *oprom, size_t size) { + void __iomem *p = NULL; + struct vbt_header *vbt; + u16 vbt_size; size_t i; /* Scour memory looking for the VBT signature. */ for (i = 0; i + 4 < size; i++) { - void *vbt; - if (ioread32(oprom + i) != *((const u32 *)"$VBT")) continue; - /* - * This is the one place where we explicitly discard the address - * space (__iomem) of the BIOS/VBT. - */ - vbt = (void __force *)oprom + i; - if (intel_bios_is_valid_vbt(vbt, size - i)) - return vbt; - + p = oprom + i; + size -= i; break; } + if (!p) + return NULL; + + if (sizeof(struct vbt_header) > size) { + DRM_DEBUG_DRIVER("VBT header incomplete\n"); + return NULL; + } + + vbt_size = ioread16(p + offsetof(struct vbt_header, vbt_size)); + if (vbt_size > size) { + DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n"); + return NULL; + } + + /* The rest will be validated by intel_bios_is_valid_vbt() */ + vbt = kmalloc(vbt_size, GFP_KERNEL); + if (!vbt) + return NULL; + + memcpy_fromio(vbt, p, vbt_size); + + if (!intel_bios_is_valid_vbt(vbt, vbt_size)) + goto err_free_vbt; + + return vbt; + +err_free_vbt: + kfree(vbt); + return NULL; } @@ -1982,7 +2006,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv) if (!oprom) goto out; - vbt = find_vbt(oprom, size); + vbt = copy_vbt(oprom, size); if (!vbt) goto out; @@ -2020,6 +2044,9 @@ out: if (oprom) pci_unmap_rom(pdev, oprom); + + if (vbt != dev_priv->opregion.vbt) + kfree(vbt); } /** -- cgit v1.2.3 From 2cded152ad43875e8e01cef328e886861129c3a9 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 26 Nov 2019 14:51:09 -0800 Subject: drm/i915/bios: fold pci rom map/unmap into copy function We don't need to keep the pci rom mapped during the entire intel_bios_init() anymore. Move it to the previous copy_vbt() function and rename it to oprom_get_vbt() since now it's responsible to to all operations related to get the vbt from the oprom. v2: fix double __iomem attribute detected by sparse v3: fix missing unmap on success (Ville) Signed-off-by: Lucas De Marchi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191126225110.8127-3-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index ce19f434ab37..b75db4a2e42f 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1925,12 +1925,17 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size) return vbt; } -static struct vbt_header *copy_vbt(void __iomem *oprom, size_t size) +static struct vbt_header *oprom_get_vbt(struct drm_i915_private *dev_priv) { - void __iomem *p = NULL; + struct pci_dev *pdev = dev_priv->drm.pdev; + void __iomem *p = NULL, *oprom; struct vbt_header *vbt; u16 vbt_size; - size_t i; + size_t i, size; + + oprom = pci_map_rom(pdev, &size); + if (!oprom) + return NULL; /* Scour memory looking for the VBT signature. */ for (i = 0; i + 4 < size; i++) { @@ -1943,33 +1948,37 @@ static struct vbt_header *copy_vbt(void __iomem *oprom, size_t size) } if (!p) - return NULL; + goto err_unmap_oprom; if (sizeof(struct vbt_header) > size) { DRM_DEBUG_DRIVER("VBT header incomplete\n"); - return NULL; + goto err_unmap_oprom; } vbt_size = ioread16(p + offsetof(struct vbt_header, vbt_size)); if (vbt_size > size) { DRM_DEBUG_DRIVER("VBT incomplete (vbt_size overflows)\n"); - return NULL; + goto err_unmap_oprom; } /* The rest will be validated by intel_bios_is_valid_vbt() */ vbt = kmalloc(vbt_size, GFP_KERNEL); if (!vbt) - return NULL; + goto err_unmap_oprom; memcpy_fromio(vbt, p, vbt_size); if (!intel_bios_is_valid_vbt(vbt, vbt_size)) goto err_free_vbt; + pci_unmap_rom(pdev, oprom); + return vbt; err_free_vbt: kfree(vbt); +err_unmap_oprom: + pci_unmap_rom(pdev, oprom); return NULL; } @@ -1984,10 +1993,9 @@ err_free_vbt: */ void intel_bios_init(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev_priv->drm.pdev; const struct vbt_header *vbt = dev_priv->opregion.vbt; + struct vbt_header *oprom_vbt = NULL; const struct bdb_header *bdb; - u8 __iomem *oprom = NULL; INIT_LIST_HEAD(&dev_priv->vbt.display_devices); @@ -2000,15 +2008,11 @@ void intel_bios_init(struct drm_i915_private *dev_priv) /* If the OpRegion does not have VBT, look in PCI ROM. */ if (!vbt) { - size_t size; - - oprom = pci_map_rom(pdev, &size); - if (!oprom) + oprom_vbt = oprom_get_vbt(dev_priv); + if (!oprom_vbt) goto out; - vbt = copy_vbt(oprom, size); - if (!vbt) - goto out; + vbt = oprom_vbt; DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n"); } @@ -2042,11 +2046,7 @@ out: init_vbt_missing_defaults(dev_priv); } - if (oprom) - pci_unmap_rom(pdev, oprom); - - if (vbt != dev_priv->opregion.vbt) - kfree(vbt); + kfree(oprom_vbt); } /** -- cgit v1.2.3 From 98cf5c9a482d975b91d2cf00e09c061b535b8ee4 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 26 Nov 2019 14:51:10 -0800 Subject: drm/i915/bios: assume vbt is 4-byte aligned into oprom The unaligned ioread32() will make us read byte by byte looking for the vbt. We could just as well have done a ioread8() + a shift and avoid the extra confusion on how we are looking for "$VBT". However when using ACPI it's guaranteed the VBT is 4-byte aligned per spec, so we can probably assume it here as well. v2: do not try to simplify the loop by eliminating the auxiliary counter (Jani and Ville) Signed-off-by: Lucas De Marchi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191126225110.8127-4-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index b75db4a2e42f..1aeecdd02293 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1938,7 +1938,7 @@ static struct vbt_header *oprom_get_vbt(struct drm_i915_private *dev_priv) return NULL; /* Scour memory looking for the VBT signature. */ - for (i = 0; i + 4 < size; i++) { + for (i = 0; i + 4 < size; i += 4) { if (ioread32(oprom + i) != *((const u32 *)"$VBT")) continue; -- cgit v1.2.3 From 61e258ee33328ea8dbd9208ad79d281693d5e0e4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2019 11:08:35 +0000 Subject: drm/i915/gt: Use soft-rc6 for w/a protection Now that we have soft-rc6 in place, we can use that instead of the forcewake to disable rc6 while active; preferred by a few microbenchmarks. Signed-off-by: Chris Wilson Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191202110836.2342685-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 8 -------- drivers/gpu/drm/i915/gt/intel_rc6.c | 19 +++++++++++++------ drivers/gpu/drm/i915/gt/intel_rc6.h | 1 - 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 2000018b6464..ecde67a75e32 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -61,9 +61,6 @@ static int __gt_unpark(struct intel_wakeref *wf) gt->awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ); GEM_BUG_ON(!gt->awake); - if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) - intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); - intel_rc6_unpark(>->rc6); intel_rps_unpark(>->rps); i915_pmu_gt_unparked(i915); @@ -91,11 +88,6 @@ static int __gt_park(struct intel_wakeref *wf) /* Everything switched off, flush any residual interrupt just in case */ intel_synchronize_irq(i915); - if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) { - intel_rc6_ctx_wa_check(>->rc6); - intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); - } - GEM_BUG_ON(!wakeref); intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref); diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index c4379c49c20d..f58674f4aaec 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -527,26 +527,25 @@ void intel_rc6_ctx_wa_resume(struct intel_rc6 *rc6) * Check if an RC6 CTX corruption has happened since the last check and if so * disable RC6 and runtime power management. */ -void intel_rc6_ctx_wa_check(struct intel_rc6 *rc6) +static bool intel_rc6_ctx_wa_check(struct intel_rc6 *rc6) { struct drm_i915_private *i915 = rc6_to_i915(rc6); if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915)) - return; + return false; if (rc6->ctx_corrupted) - return; + return false; if (!intel_rc6_ctx_corrupted(rc6)) - return; + return false; dev_notice(i915->drm.dev, "RC6 context corruption, disabling runtime power management\n"); - intel_rc6_disable(rc6); rc6->ctx_corrupted = true; - return; + return true; } static void __intel_rc6_disable(struct intel_rc6 *rc6) @@ -627,6 +626,9 @@ void intel_rc6_enable(struct intel_rc6 *rc6) else if (INTEL_GEN(i915) >= 6) gen6_rc6_enable(rc6); + if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) + rc6->ctl_enable = 0; + intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL); /* rc6 is ready, runtime-pm is go! */ @@ -652,6 +654,11 @@ void intel_rc6_park(struct intel_rc6 *rc6) if (!rc6->enabled) return; + if (unlikely(intel_rc6_ctx_wa_check(rc6))) { + intel_rc6_disable(rc6); + return; + } + /* Turn off the HW timers and go directly to rc6 */ set(uncore, GEN6_RC_CONTROL, GEN6_RC_CTL_RC6_ENABLE); set(uncore, GEN6_RC_STATE, 0x4 << RC_SW_TARGET_STATE_SHIFT); diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.h b/drivers/gpu/drm/i915/gt/intel_rc6.h index 20d740ff7e55..f2821576bfd3 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.h +++ b/drivers/gpu/drm/i915/gt/intel_rc6.h @@ -25,7 +25,6 @@ void intel_rc6_disable(struct intel_rc6 *rc6); u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, i915_reg_t reg); u64 intel_rc6_residency_us(struct intel_rc6 *rc6, i915_reg_t reg); -void intel_rc6_ctx_wa_check(struct intel_rc6 *rc6); void intel_rc6_ctx_wa_resume(struct intel_rc6 *rc6); #endif /* INTEL_RC6_H */ -- cgit v1.2.3 From 65f6d12c6b0b610c92d6a2c3d964ff2943ac8fbf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2019 11:08:36 +0000 Subject: drm/i915/gt: Simplify rc6 w/a application Quite simply we only need to check for prior corruption on enabling rc6 on module load and resume, so by hooking into the common entry points. Signed-off-by: Chris Wilson Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191202110836.2342685-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rc6.c | 59 ++++--------------------------- drivers/gpu/drm/i915/gt/intel_rc6.h | 2 -- drivers/gpu/drm/i915/gt/intel_rc6_types.h | 1 - drivers/gpu/drm/i915/i915_drv.c | 2 -- 4 files changed, 6 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index f58674f4aaec..4dc82196b285 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -488,63 +488,18 @@ static void rpm_put(struct intel_rc6 *rc6) rc6->wakeref = false; } -static bool intel_rc6_ctx_corrupted(struct intel_rc6 *rc6) -{ - return !intel_uncore_read(rc6_to_uncore(rc6), GEN8_RC6_CTX_INFO); -} - -static void intel_rc6_ctx_wa_init(struct intel_rc6 *rc6) -{ - struct drm_i915_private *i915 = rc6_to_i915(rc6); - - if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915)) - return; - - if (intel_rc6_ctx_corrupted(rc6)) { - DRM_INFO("RC6 context corrupted, disabling runtime power management\n"); - rc6->ctx_corrupted = true; - } -} - -/** - * intel_rc6_ctx_wa_resume - system resume sequence for the RC6 CTX WA - * @rc6: rc6 state - * - * Perform any steps needed to re-init the RC6 CTX WA after system resume. - */ -void intel_rc6_ctx_wa_resume(struct intel_rc6 *rc6) -{ - if (rc6->ctx_corrupted && !intel_rc6_ctx_corrupted(rc6)) { - DRM_INFO("RC6 context restored, re-enabling runtime power management\n"); - rc6->ctx_corrupted = false; - } -} - -/** - * intel_rc6_ctx_wa_check - check for a new RC6 CTX corruption - * @rc6: rc6 state - * - * Check if an RC6 CTX corruption has happened since the last check and if so - * disable RC6 and runtime power management. -*/ -static bool intel_rc6_ctx_wa_check(struct intel_rc6 *rc6) +static bool pctx_corrupted(struct intel_rc6 *rc6) { struct drm_i915_private *i915 = rc6_to_i915(rc6); if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915)) return false; - if (rc6->ctx_corrupted) - return false; - - if (!intel_rc6_ctx_corrupted(rc6)) + if (intel_uncore_read(rc6_to_uncore(rc6), GEN8_RC6_CTX_INFO)) return false; dev_notice(i915->drm.dev, "RC6 context corruption, disabling runtime power management\n"); - - rc6->ctx_corrupted = true; - return true; } @@ -572,8 +527,6 @@ void intel_rc6_init(struct intel_rc6 *rc6) if (!rc6_supported(rc6)) return; - intel_rc6_ctx_wa_init(rc6); - if (IS_CHERRYVIEW(i915)) err = chv_rc6_init(rc6); else if (IS_VALLEYVIEW(i915)) @@ -608,9 +561,6 @@ void intel_rc6_enable(struct intel_rc6 *rc6) GEM_BUG_ON(rc6->enabled); - if (rc6->ctx_corrupted) - return; - intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); if (IS_CHERRYVIEW(i915)) @@ -631,6 +581,9 @@ void intel_rc6_enable(struct intel_rc6 *rc6) intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL); + if (unlikely(pctx_corrupted(rc6))) + return; + /* rc6 is ready, runtime-pm is go! */ rpm_put(rc6); rc6->enabled = true; @@ -654,7 +607,7 @@ void intel_rc6_park(struct intel_rc6 *rc6) if (!rc6->enabled) return; - if (unlikely(intel_rc6_ctx_wa_check(rc6))) { + if (unlikely(pctx_corrupted(rc6))) { intel_rc6_disable(rc6); return; } diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.h b/drivers/gpu/drm/i915/gt/intel_rc6.h index f2821576bfd3..9f0f23fca8af 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.h +++ b/drivers/gpu/drm/i915/gt/intel_rc6.h @@ -25,6 +25,4 @@ void intel_rc6_disable(struct intel_rc6 *rc6); u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, i915_reg_t reg); u64 intel_rc6_residency_us(struct intel_rc6 *rc6, i915_reg_t reg); -void intel_rc6_ctx_wa_resume(struct intel_rc6 *rc6); - #endif /* INTEL_RC6_H */ diff --git a/drivers/gpu/drm/i915/gt/intel_rc6_types.h b/drivers/gpu/drm/i915/gt/intel_rc6_types.h index 9f3d56817c97..60decae1abc9 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6_types.h +++ b/drivers/gpu/drm/i915/gt/intel_rc6_types.h @@ -25,7 +25,6 @@ struct intel_rc6 { bool supported : 1; bool enabled : 1; bool wakeref : 1; - bool ctx_corrupted : 1; }; #endif /* INTEL_RC6_TYPES_H */ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index aa1d9e25f934..018914ba2005 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1817,8 +1817,6 @@ static int i915_drm_resume(struct drm_device *dev) disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); - intel_rc6_ctx_wa_resume(&dev_priv->gt.rc6); - intel_gt_sanitize(&dev_priv->gt, true); ret = i915_ggtt_enable_hw(dev_priv); -- cgit v1.2.3 From 7d0aa0db4375edb0a2de66e9099fe0f9b197b80d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2019 17:43:10 +0000 Subject: drm/i915/gem: Unbind all current vma on changing cache-level Avoid dangerous race handling of destroyed vma by unbinding all vma instead. Unfortunately, this stops us from trying to be clever and only doing the minimal change required, so on first use of scanout we may encounter an annoying stall as it transitions to a new cache level. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112413 Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191202174310.2630302-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 123 +---------------------------- 1 file changed, 4 insertions(+), 119 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 9aebcf263191..3119f7be9bc0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -184,7 +184,6 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, enum i915_cache_level cache_level) { - struct i915_vma *vma; int ret; assert_object_held(obj); @@ -192,126 +191,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, if (obj->cache_level == cache_level) return 0; - /* Inspect the list of currently bound VMA and unbind any that would - * be invalid given the new cache-level. This is principally to - * catch the issue of the CS prefetch crossing page boundaries and - * reading an invalid PTE on older architectures. - */ -restart: - list_for_each_entry(vma, &obj->vma.list, obj_link) { - if (!drm_mm_node_allocated(&vma->node)) - continue; - - if (i915_vma_is_pinned(vma)) { - DRM_DEBUG("can not change the cache level of pinned objects\n"); - return -EBUSY; - } - - if (!i915_vma_is_closed(vma) && - i915_gem_valid_gtt_space(vma, cache_level)) - continue; - - ret = i915_vma_unbind(vma); - if (ret) - return ret; - - /* As unbinding may affect other elements in the - * obj->vma_list (due to side-effects from retiring - * an active vma), play safe and restart the iterator. - */ - goto restart; - } - - /* We can reuse the existing drm_mm nodes but need to change the - * cache-level on the PTE. We could simply unbind them all and - * rebind with the correct cache-level on next use. However since - * we already have a valid slot, dma mapping, pages etc, we may as - * rewrite the PTE in the belief that doing so tramples upon less - * state and so involves less work. - */ - if (atomic_read(&obj->bind_count)) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); + ret = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE); + if (ret) + return ret; - /* Before we change the PTE, the GPU must not be accessing it. - * If we wait upon the object, we know that all the bound - * VMA are no longer active. - */ - ret = i915_gem_object_wait(obj, - I915_WAIT_INTERRUPTIBLE | - I915_WAIT_ALL, - MAX_SCHEDULE_TIMEOUT); - if (ret) - return ret; - - if (!HAS_LLC(i915) && cache_level != I915_CACHE_NONE) { - intel_wakeref_t wakeref = - intel_runtime_pm_get(&i915->runtime_pm); - - /* - * Access to snoopable pages through the GTT is - * incoherent and on some machines causes a hard - * lockup. Relinquish the CPU mmaping to force - * userspace to refault in the pages and we can - * then double check if the GTT mapping is still - * valid for that pointer access. - */ - ret = mutex_lock_interruptible(&i915->ggtt.vm.mutex); - if (ret) { - intel_runtime_pm_put(&i915->runtime_pm, - wakeref); - return ret; - } - - if (obj->userfault_count) - __i915_gem_object_release_mmap(obj); - - /* - * As we no longer need a fence for GTT access, - * we can relinquish it now (and so prevent having - * to steal a fence from someone else on the next - * fence request). Note GPU activity would have - * dropped the fence as all snoopable access is - * supposed to be linear. - */ - for_each_ggtt_vma(vma, obj) { - ret = i915_vma_revoke_fence(vma); - if (ret) - break; - } - mutex_unlock(&i915->ggtt.vm.mutex); - intel_runtime_pm_put(&i915->runtime_pm, wakeref); - if (ret) - return ret; - } else { - /* - * We either have incoherent backing store and - * so no GTT access or the architecture is fully - * coherent. In such cases, existing GTT mmaps - * ignore the cache bit in the PTE and we can - * rewrite it without confusing the GPU or having - * to force userspace to fault back in its mmaps. - */ - } - - list_for_each_entry(vma, &obj->vma.list, obj_link) { - if (!drm_mm_node_allocated(&vma->node)) - continue; - - /* Wait for an earlier async bind, need to rewrite it */ - ret = i915_vma_sync(vma); - if (ret) - return ret; - - ret = i915_vma_bind(vma, cache_level, PIN_UPDATE, NULL); - if (ret) - return ret; - } - } + /* The cache-level will be applied when each vma is rebound. */ - list_for_each_entry(vma, &obj->vma.list, obj_link) { - if (i915_vm_has_cache_coloring(vma->vm)) - vma->node.color = cache_level; - } i915_gem_object_set_cache_coherency(obj, cache_level); obj->cache_dirty = true; /* Always invalidate stale cachelines */ -- cgit v1.2.3 From ae30300490fe9790857d3780f46aa5ad926d6261 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2019 14:01:32 +0000 Subject: drm/i915: Specialise i915_active.work lock classes Similar to for i915_active.mutex, we require each class of i915_active to have distinct lockdep chains as some, but by no means all, i915_active are used within the shrinker and so have much more severe usage constraints. By using a lockclass local to i915_active_init() all i915_active workers have the same lock class, and we may generate false positives when waiting for the i915_active. If we push the lockclass into the caller, each class of i915_active will have distinct lockdep chains. Signed-off-by: Chris Wilson Acked-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191202140133.2444217-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_active.c | 8 ++++++-- drivers/gpu/drm/i915/i915_active.h | 10 +++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 479195ecbc6c..e60e44986c9d 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -277,7 +277,8 @@ out: void __i915_active_init(struct i915_active *ref, int (*active)(struct i915_active *ref), void (*retire)(struct i915_active *ref), - struct lock_class_key *key) + struct lock_class_key *mkey, + struct lock_class_key *wkey) { unsigned long bits; @@ -295,9 +296,12 @@ void __i915_active_init(struct i915_active *ref, init_llist_head(&ref->preallocated_barriers); atomic_set(&ref->count, 0); - __mutex_init(&ref->mutex, "i915_active", key); + __mutex_init(&ref->mutex, "i915_active", mkey); __i915_active_fence_init(&ref->excl, NULL, excl_retire); INIT_WORK(&ref->work, active_work); +#if IS_ENABLED(CONFIG_LOCKDEP) + lockdep_init_map(&ref->work.lockdep_map, "i915_active.work", wkey, 0); +#endif } static bool ____active_del_barrier(struct i915_active *ref, diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index 3208cc2e8c1a..b571f675c795 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -152,11 +152,15 @@ i915_active_fence_isset(const struct i915_active_fence *active) void __i915_active_init(struct i915_active *ref, int (*active)(struct i915_active *ref), void (*retire)(struct i915_active *ref), - struct lock_class_key *key); + struct lock_class_key *mkey, + struct lock_class_key *wkey); + +/* Specialise each class of i915_active to avoid impossible lockdep cycles. */ #define i915_active_init(ref, active, retire) do { \ - static struct lock_class_key __key; \ + static struct lock_class_key __mkey; \ + static struct lock_class_key __wkey; \ \ - __i915_active_init(ref, active, retire, &__key); \ + __i915_active_init(ref, active, retire, &__mkey, &__wkey); \ } while (0) int i915_active_ref(struct i915_active *ref, -- cgit v1.2.3 From e1cda6a529aa1f310badcb20d63d9cd1d1f164a1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2019 14:01:33 +0000 Subject: drm/i915: Serialise i915_active_wait() with its retirement As the i915_active.retire() may be running on another CPU as we detect that the i915_active is idle, we may not wait for the retirement itself. Wait for the remote callback by waiting for the retirement worker. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112424 Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191202140133.2444217-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_active.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index e60e44986c9d..e3fcec4834c2 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -473,6 +473,7 @@ int i915_active_wait(struct i915_active *ref) if (wait_var_event_interruptible(ref, i915_active_is_idle(ref))) return -EINTR; + flush_work(&ref->work); return 0; } -- cgit v1.2.3 From 3e817471a34cf94ca6edbb2e0b1076e6209153e2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 3 Dec 2019 10:13:46 +0000 Subject: drm/i915/gem: Take runtime-pm wakeref prior to unbinding Some machines require ACPI for runtime resume, and ACPI is quite kmalloc happy. We cannot handle kmalloc from inside the vm->mutex, as they are used by the shrinker, and so we must ensure the global runtime-pm is awake prior to unbinding to avoid the potential inversion. <4> [57.121748] ====================================================== <4> [57.121750] WARNING: possible circular locking dependency detected <4> [57.121753] 5.4.0-rc8-CI-CI_DRM_7466+ #1 Tainted: G U <4> [57.121754] ------------------------------------------------------ <4> [57.121756] i915_pm_rpm/1105 is trying to acquire lock: <4> [57.121758] ffffffff82263a40 (fs_reclaim){+.+.}, at: fs_reclaim_acquire.part.117+0x0/0x30 <4> [57.121766] but task is already holding lock: <4> [57.121768] ffff888475a593c0 (&vm->mutex){+.+.}, at: i915_vma_unbind+0x21/0x50 [i915] <4> [57.121868] which lock already depends on the new lock. <4> [57.121869] the existing dependency chain (in reverse order) is: <4> [57.121871] -> #1 (&vm->mutex){+.+.}: <4> [57.121951] i915_gem_shrinker_taints_mutex+0xa2/0xd0 [i915] <4> [57.122028] i915_address_space_init+0xa9/0x170 [i915] <4> [57.122104] i915_ggtt_init_hw+0x47/0x130 [i915] <4> [57.122150] i915_driver_probe+0xbb4/0x15f0 [i915] <4> [57.122197] i915_pci_probe+0x43/0x1c0 [i915] <4> [57.122202] pci_device_probe+0x9e/0x120 <4> [57.122206] really_probe+0xea/0x420 <4> [57.122209] driver_probe_device+0x10b/0x120 <4> [57.122212] device_driver_attach+0x4a/0x50 <4> [57.122214] __driver_attach+0x97/0x130 <4> [57.122217] bus_for_each_dev+0x74/0xc0 <4> [57.122220] bus_add_driver+0x142/0x220 <4> [57.122222] driver_register+0x56/0xf0 <4> [57.122226] do_one_initcall+0x58/0x2ff <4> [57.122230] do_init_module+0x56/0x1f8 <4> [57.122233] load_module+0x243e/0x29f0 <4> [57.122236] __do_sys_finit_module+0xe9/0x110 <4> [57.122239] do_syscall_64+0x4f/0x210 <4> [57.122242] entry_SYSCALL_64_after_hwframe+0x49/0xbe <4> [57.122244] -> #0 (fs_reclaim){+.+.}: <4> [57.122249] __lock_acquire+0x1328/0x15d0 <4> [57.122251] lock_acquire+0xa7/0x1c0 <4> [57.122254] fs_reclaim_acquire.part.117+0x24/0x30 <4> [57.122257] __kmalloc+0x48/0x320 <4> [57.122261] acpi_ns_internalize_name+0x44/0x9b <4> [57.122264] acpi_ns_get_node_unlocked+0x6b/0xd3 <4> [57.122267] acpi_ns_get_node+0x3b/0x50 <4> [57.122271] acpi_get_handle+0x8a/0xb4 <4> [57.122274] acpi_has_method+0x1c/0x40 <4> [57.122278] acpi_pci_set_power_state+0x40/0xe0 <4> [57.122281] pci_platform_power_transition+0x3e/0x90 <4> [57.122284] pci_set_power_state+0x83/0xf0 <4> [57.122287] pci_restore_standard_config+0x22/0x40 <4> [57.122289] pci_pm_runtime_resume+0x23/0xc0 <4> [57.122293] __rpm_callback+0xb1/0x110 <4> [57.122296] rpm_callback+0x1a/0x70 <4> [57.122299] rpm_resume+0x50e/0x790 <4> [57.122302] __pm_runtime_resume+0x42/0x80 <4> [57.122357] __intel_runtime_pm_get+0x15/0x60 [i915] <4> [57.122435] ggtt_unbind_vma+0x24/0x60 [i915] <4> [57.122514] __i915_vma_unbind.part.39+0xb5/0x500 [i915] <4> [57.122593] i915_vma_unbind+0x2d/0x50 [i915] <4> [57.122668] i915_gem_object_unbind+0x11c/0x260 [i915] <4> [57.122740] i915_gem_object_set_cache_level+0x32/0x90 [i915] <4> [57.122810] i915_gem_set_caching_ioctl+0x1f7/0x2f0 [i915] <4> [57.122815] drm_ioctl_kernel+0xa7/0xf0 <4> [57.122818] drm_ioctl+0x2e1/0x390 <4> [57.122822] do_vfs_ioctl+0xa0/0x6f0 <4> [57.122825] ksys_ioctl+0x35/0x60 <4> [57.122828] __x64_sys_ioctl+0x11/0x20 <4> [57.122830] do_syscall_64+0x4f/0x210 <4> [57.122833] entry_SYSCALL_64_after_hwframe+0x49/0xbe Closes: https://gitlab.freedesktop.org/drm/intel/issues/711 Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191203101347.2836057-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 61395b03443e..f7b5fe0f5424 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -119,10 +119,23 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, int i915_gem_object_unbind(struct drm_i915_gem_object *obj, unsigned long flags) { - struct i915_vma *vma; + struct intel_runtime_pm *rpm = &to_i915(obj->base.dev)->runtime_pm; LIST_HEAD(still_in_list); + intel_wakeref_t wakeref; + struct i915_vma *vma; int ret = 0; + if (!atomic_read(&obj->bind_count)) + return 0; + + /* + * As some machines use ACPI to handle runtime-resume callbacks, and + * ACPI is quite kmalloc happy, we cannot resume beneath the vm->mutex + * as they are required by the shrinker. Ergo, we wake the device up + * first just in case. + */ + wakeref = intel_runtime_pm_get(rpm); + spin_lock(&obj->vma.lock); while (!ret && (vma = list_first_entry_or_null(&obj->vma.list, struct i915_vma, @@ -146,6 +159,8 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj, list_splice(&still_in_list, &obj->vma.list); spin_unlock(&obj->vma.lock); + intel_runtime_pm_put(rpm, wakeref); + return ret; } -- cgit v1.2.3 From 42d105113018a5c1bd2c86897b1737adf16b3f5f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2019 20:43:14 +0000 Subject: drm/i915: Lift i915_vma_pin() out of intel_renderstate_emit() Once inside a request, inside the timeline->mutex, pinning is verboten. <4> [896.032829] ====================================================== <4> [896.032831] WARNING: possible circular locking dependency detected <4> [896.032835] 5.4.0-rc8-CI-Patchwork_15533+ #1 Tainted: G U <4> [896.032838] ------------------------------------------------------ <4> [896.032841] gem_exec_parall/3720 is trying to acquire lock: <4> [896.032844] ffff888401863270 (&kernel#2){+.+.}, at: i915_request_create+0x16/0x1c0 [i915] <4> [896.032915] but task is already holding lock: <4> [896.032917] ffff8883ec1c93c0 (&vm->mutex){+.+.}, at: i915_vma_pin+0xf3/0x11c0 [i915] <4> [896.032952] which lock already depends on the new lock. <4> [896.032954] the existing dependency chain (in reverse order) is: <4> [896.032956] -> #1 (&vm->mutex){+.+.}: <4> [896.032961] __mutex_lock+0x9a/0x9d0 <4> [896.032995] i915_vma_pin+0xf3/0x11c0 [i915] <4> [896.033033] intel_renderstate_emit+0xb9/0x9e0 [i915] <4> [896.033081] i915_gem_init+0x5a9/0xa50 [i915] <4> [896.033112] i915_driver_probe+0xb00/0x15f0 [i915] <4> [896.033144] i915_pci_probe+0x43/0x1c0 [i915] <4> [896.033149] pci_device_probe+0x9e/0x120 <4> [896.033154] really_probe+0xea/0x420 <4> [896.033158] driver_probe_device+0x10b/0x120 <4> [896.033161] device_driver_attach+0x4a/0x50 <4> [896.033164] __driver_attach+0x97/0x130 <4> [896.033168] bus_for_each_dev+0x74/0xc0 <4> [896.033171] bus_add_driver+0x142/0x220 <4> [896.033174] driver_register+0x56/0xf0 <4> [896.033178] do_one_initcall+0x58/0x2ff <4> [896.033183] do_init_module+0x56/0x1f8 <4> [896.033187] load_module+0x243e/0x29f0 <4> [896.033190] __do_sys_finit_module+0xe9/0x110 <4> [896.033194] do_syscall_64+0x4f/0x210 <4> [896.033197] entry_SYSCALL_64_after_hwframe+0x49/0xbe <4> [896.033200] -> #0 (&kernel#2){+.+.}: <4> [896.033206] __lock_acquire+0x1328/0x15d0 <4> [896.033209] lock_acquire+0xa7/0x1c0 <4> [896.033213] __mutex_lock+0x9a/0x9d0 <4> [896.033255] i915_request_create+0x16/0x1c0 [i915] <4> [896.033287] intel_engine_flush_barriers+0x4c/0x100 [i915] <4> [896.033327] ggtt_flush+0x37/0x60 [i915] <4> [896.033366] i915_gem_evict_something+0x46b/0x5a0 [i915] <4> [896.033407] i915_gem_gtt_insert+0x21d/0x6a0 [i915] <4> [896.033449] i915_vma_pin+0xb36/0x11c0 [i915] <4> [896.033488] gen6_ppgtt_pin+0xd5/0x170 [i915] <4> [896.033523] ring_context_pin+0x2e/0xc0 [i915] <4> [896.033554] __intel_context_do_pin+0x6b/0x190 [i915] <4> [896.033591] i915_gem_do_execbuffer+0x1814/0x26c0 [i915] <4> [896.033627] i915_gem_execbuffer2_ioctl+0x11b/0x460 [i915] <4> [896.033632] drm_ioctl_kernel+0xa7/0xf0 <4> [896.033635] drm_ioctl+0x2e1/0x390 <4> [896.033638] do_vfs_ioctl+0xa0/0x6f0 <4> [896.033641] ksys_ioctl+0x35/0x60 <4> [896.033644] __x64_sys_ioctl+0x11/0x20 <4> [896.033647] do_syscall_64+0x4f/0x210 <4> [896.033650] entry_SYSCALL_64_after_hwframe+0x49/0xbe Lift the object allocation and pin prior to the request construction. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Maarten Lankhorst Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191202204316.2665847-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_renderstate.c | 97 ++++++++++++++++------------- drivers/gpu/drm/i915/gt/intel_renderstate.h | 17 ++++- drivers/gpu/drm/i915/i915_gem.c | 8 ++- 3 files changed, 78 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.c b/drivers/gpu/drm/i915/gt/intel_renderstate.c index c4edc35e7d89..5954ecc3207f 100644 --- a/drivers/gpu/drm/i915/gt/intel_renderstate.c +++ b/drivers/gpu/drm/i915/gt/intel_renderstate.c @@ -29,16 +29,6 @@ #include "intel_renderstate.h" #include "intel_ring.h" -struct intel_renderstate { - const struct intel_renderstate_rodata *rodata; - struct drm_i915_gem_object *obj; - struct i915_vma *vma; - u32 batch_offset; - u32 batch_size; - u32 aux_offset; - u32 aux_size; -}; - static const struct intel_renderstate_rodata * render_state_get_rodata(const struct intel_engine_cs *engine) { @@ -84,11 +74,11 @@ static int render_state_setup(struct intel_renderstate *so, u32 *d; int ret; - ret = i915_gem_object_prepare_write(so->obj, &needs_clflush); + ret = i915_gem_object_prepare_write(so->vma->obj, &needs_clflush); if (ret) return ret; - d = kmap_atomic(i915_gem_object_get_dirty_page(so->obj, 0)); + d = kmap_atomic(i915_gem_object_get_dirty_page(so->vma->obj, 0)); while (i < rodata->batch_items) { u32 s = rodata->batch[i]; @@ -166,7 +156,7 @@ static int render_state_setup(struct intel_renderstate *so, ret = 0; out: - i915_gem_object_finish_access(so->obj); + i915_gem_object_finish_access(so->vma->obj); return ret; err: @@ -177,61 +167,84 @@ err: #undef OUT_BATCH -int intel_renderstate_emit(struct i915_request *rq) +int intel_renderstate_init(struct intel_renderstate *so, + struct intel_engine_cs *engine) { - struct intel_engine_cs *engine = rq->engine; - struct intel_renderstate so = {}; /* keep the compiler happy */ + struct drm_i915_gem_object *obj; int err; - so.rodata = render_state_get_rodata(engine); - if (!so.rodata) + memset(so, 0, sizeof(*so)); + + so->rodata = render_state_get_rodata(engine); + if (!so->rodata) return 0; - if (so.rodata->batch_items * 4 > PAGE_SIZE) + if (so->rodata->batch_items * 4 > PAGE_SIZE) return -EINVAL; - so.obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); - if (IS_ERR(so.obj)) - return PTR_ERR(so.obj); + obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); - so.vma = i915_vma_instance(so.obj, &engine->gt->ggtt->vm, NULL); - if (IS_ERR(so.vma)) { - err = PTR_ERR(so.vma); + so->vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); + if (IS_ERR(so->vma)) { + err = PTR_ERR(so->vma); goto err_obj; } - err = i915_vma_pin(so.vma, 0, 0, PIN_GLOBAL | PIN_HIGH); + err = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH); if (err) goto err_vma; - err = render_state_setup(&so, rq->i915); + err = render_state_setup(so, engine->i915); if (err) goto err_unpin; + return 0; + +err_unpin: + i915_vma_unpin(so->vma); +err_vma: + i915_vma_close(so->vma); +err_obj: + i915_gem_object_put(obj); + so->vma = NULL; + return err; +} + +int intel_renderstate_emit(struct intel_renderstate *so, + struct i915_request *rq) +{ + struct intel_engine_cs *engine = rq->engine; + int err; + + if (!so->vma) + return 0; + err = engine->emit_bb_start(rq, - so.batch_offset, so.batch_size, + so->batch_offset, so->batch_size, I915_DISPATCH_SECURE); if (err) - goto err_unpin; + return err; - if (so.aux_size > 8) { + if (so->aux_size > 8) { err = engine->emit_bb_start(rq, - so.aux_offset, so.aux_size, + so->aux_offset, so->aux_size, I915_DISPATCH_SECURE); if (err) - goto err_unpin; + return err; } - i915_vma_lock(so.vma); - err = i915_request_await_object(rq, so.vma->obj, false); + i915_vma_lock(so->vma); + err = i915_request_await_object(rq, so->vma->obj, false); if (err == 0) - err = i915_vma_move_to_active(so.vma, rq, 0); - i915_vma_unlock(so.vma); -err_unpin: - i915_vma_unpin(so.vma); -err_vma: - i915_vma_close(so.vma); -err_obj: - i915_gem_object_put(so.obj); + err = i915_vma_move_to_active(so->vma, rq, 0); + i915_vma_unlock(so->vma); + return err; } + +void intel_renderstate_fini(struct intel_renderstate *so) +{ + i915_vma_unpin_and_release(&so->vma, 0); +} diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.h b/drivers/gpu/drm/i915/gt/intel_renderstate.h index 8d5079145054..5700be69a05a 100644 --- a/drivers/gpu/drm/i915/gt/intel_renderstate.h +++ b/drivers/gpu/drm/i915/gt/intel_renderstate.h @@ -27,6 +27,8 @@ #include struct i915_request; +struct intel_engine_cs; +struct i915_vma; struct intel_renderstate_rodata { const u32 *reloc; @@ -46,6 +48,19 @@ extern const struct intel_renderstate_rodata gen7_null_state; extern const struct intel_renderstate_rodata gen8_null_state; extern const struct intel_renderstate_rodata gen9_null_state; -int intel_renderstate_emit(struct i915_request *rq); +struct intel_renderstate { + const struct intel_renderstate_rodata *rodata; + struct i915_vma *vma; + u32 batch_offset; + u32 batch_size; + u32 aux_offset; + u32 aux_size; +}; + +int intel_renderstate_init(struct intel_renderstate *so, + struct intel_engine_cs *engine); +int intel_renderstate_emit(struct intel_renderstate *so, + struct i915_request *rq); +void intel_renderstate_fini(struct intel_renderstate *so); #endif /* _INTEL_RENDERSTATE_H_ */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f7b5fe0f5424..bfdc8a9f82f8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1086,9 +1086,14 @@ static int __intel_engines_record_defaults(struct intel_gt *gt) */ for_each_engine(engine, gt, id) { + struct intel_renderstate so; struct intel_context *ce; struct i915_request *rq; + err = intel_renderstate_init(&so, engine); + if (err) + goto out; + /* We must be able to switch to something! */ GEM_BUG_ON(!engine->kernel_context); engine->serial++; /* force the kernel context switch */ @@ -1111,13 +1116,14 @@ static int __intel_engines_record_defaults(struct intel_gt *gt) if (err) goto err_rq; - err = intel_renderstate_emit(rq); + err = intel_renderstate_emit(&so, rq); if (err) goto err_rq; err_rq: requests[id] = i915_request_get(rq); i915_request_add(rq); + intel_renderstate_fini(&so); if (err) goto out; } -- cgit v1.2.3 From 80aac91b27e130566ba529162021ff47086efca7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 3 Dec 2019 15:26:30 +0000 Subject: drm/i915/execlists: Add a couple more validity checks to assert_pending() Check the pending request submission is valid: that it at least has a reference for the submission and that the request is on the active list. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191203152631.3107653-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index fef4b7e823f5..37ab9742abe7 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1303,6 +1303,9 @@ assert_pending_valid(const struct intel_engine_execlists *execlists, unsigned long flags; bool ok = true; + GEM_BUG_ON(!kref_read(&rq->fence.refcount)); + GEM_BUG_ON(!i915_request_is_active(rq)); + if (ce == rq->hw_context) { GEM_TRACE_ERR("Dup context:%llx in pending[%zd]\n", ce->timeline->fence_context, -- cgit v1.2.3 From 49e74c8f9ae635a1c87fab06966da4c713cf9d63 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 3 Dec 2019 15:26:31 +0000 Subject: drm/i915/execlists: Skip nested spinlock for validating pending Only along the submission path can we guarantee that the locked request is indeed from a foreign engine, and so the nesting of engine/rq is permissible. On the submission tasklet (process_csb()), we may find ourselves competing with the normal nesting of rq/engine, invalidating our nesting. As we only use the spinlock for debug purposes, skip the debug if we cannot acquire the spinlock for safe validation - catching 99% of the bugs is better than causing a hard lockup. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Fixes: c95d31c3df1b ("drm/i915/execlists: Lock the request while validating it during promotion") Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191203152631.3107653-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 37ab9742abe7..82807918382d 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1315,8 +1315,8 @@ assert_pending_valid(const struct intel_engine_execlists *execlists, ce = rq->hw_context; /* Hold tightly onto the lock to prevent concurrent retires! */ - spin_lock_irqsave_nested(&rq->lock, flags, - SINGLE_DEPTH_NESTING); + if (!spin_trylock_irqsave(&rq->lock, flags)) + continue; if (i915_request_completed(rq)) goto unlock; -- cgit v1.2.3 From f70de8d2ca6be552fbdc40d434ad471ae20b7cae Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 3 Dec 2019 12:41:55 +0000 Subject: drm/i915/gt: Track the context validity explicitly Rather than assume if and only if the engine->default_state is not set that the context is invalid, instead track when we know the context has valid state -- either because we have copied the default_state or we have completed a context switch to save the HW state. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191203124155.3019926-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_context.c | 1 + drivers/gpu/drm/i915/gt/intel_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_lrc.c | 1 + drivers/gpu/drm/i915/gt/intel_ring_submission.c | 4 +++- 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index b5e9c35ec6b8..c5e52ad39463 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -147,6 +147,7 @@ static void __intel_context_retire(struct i915_active *active) GEM_TRACE("%s context:%llx retire\n", ce->engine->name, ce->timeline->fence_context); + set_bit(CONTEXT_VALID_BIT, &ce->flags); if (ce->state) __context_unpin_state(ce->state); diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 6959b05ae5f8..d1204cc899a3 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -55,6 +55,7 @@ struct intel_context { unsigned long flags; #define CONTEXT_ALLOC_BIT 0 +#define CONTEXT_VALID_BIT 1 u32 *lrc_reg_state; u64 lrc_desc; diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 82807918382d..a74387664583 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4102,6 +4102,7 @@ populate_lr_context(struct intel_context *ce, memcpy(vaddr, defaults, engine->context_size); i915_gem_object_unpin_map(engine->default_state); + __set_bit(CONTEXT_VALID_BIT, &ce->flags); inhibit = false; } diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index dcdeef0a776f..093cec103b4c 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1319,6 +1319,8 @@ static int ring_context_alloc(struct intel_context *ce) return PTR_ERR(vma); ce->state = vma; + if (engine->default_state) + __set_bit(CONTEXT_VALID_BIT, &ce->flags); } return 0; @@ -1625,7 +1627,7 @@ static int switch_context(struct i915_request *rq) if (ce->state) { GEM_BUG_ON(rq->engine->id != RCS0); - if (!rq->engine->default_state) + if (!test_bit(CONTEXT_VALID_BIT, &ce->flags)) hw_flags = MI_RESTORE_INHIBIT; ret = mi_set_context(rq, hw_flags); -- cgit v1.2.3 From a3265d851e28a5d87bf20edf025d7da3d21a760c Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 2 Dec 2019 09:16:08 -0800 Subject: drm/i915/irq: Refactor gen11 display interrupt handling Let's move handling and reset for gen11 display IRQs to their own functions, similar to how we deal with GT interrupts. This will make the top-level functions a bit easier to read and potentially make things easier to deal with in the future if new platforms wind up needing different display handling logic. Cc: Lucas De Marchi Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191202171608.3361125-1-matthew.d.roper@intel.com Reviewed-by: Radhakrishna Sripada --- drivers/gpu/drm/i915/i915_irq.c | 57 +++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 46a9f7dafbf3..a5348f79114f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2453,6 +2453,25 @@ static inline void gen11_master_intr_enable(void __iomem * const regs) raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, GEN11_MASTER_IRQ); } +static void +gen11_display_irq_handler(struct drm_i915_private *i915) +{ + void __iomem * const regs = i915->uncore.regs; + const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); + + disable_rpm_wakeref_asserts(&i915->runtime_pm); + /* + * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ + * for the display related bits. + */ + raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0); + gen8_de_irq_handler(i915, disp_ctl); + raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, + GEN11_DISPLAY_IRQ_ENABLE); + + enable_rpm_wakeref_asserts(&i915->runtime_pm); +} + static __always_inline irqreturn_t __gen11_irq_handler(struct drm_i915_private * const i915, u32 (*intr_disable)(void __iomem * const regs), @@ -2476,21 +2495,8 @@ __gen11_irq_handler(struct drm_i915_private * const i915, gen11_gt_irq_handler(gt, master_ctl); /* IRQs are synced during runtime_suspend, we don't require a wakeref */ - if (master_ctl & GEN11_DISPLAY_IRQ) { - const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL); - - disable_rpm_wakeref_asserts(&i915->runtime_pm); - /* - * GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ - * for the display related bits. - */ - raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0); - gen8_de_irq_handler(i915, disp_ctl); - raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, - GEN11_DISPLAY_IRQ_ENABLE); - - enable_rpm_wakeref_asserts(&i915->runtime_pm); - } + if (master_ctl & GEN11_DISPLAY_IRQ) + gen11_display_irq_handler(i915); gu_misc_iir = gen11_gu_misc_irq_ack(gt, master_ctl); @@ -2792,15 +2798,11 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv) ibx_irq_reset(dev_priv); } -static void gen11_irq_reset(struct drm_i915_private *dev_priv) +static void gen11_display_irq_reset(struct drm_i915_private *dev_priv) { struct intel_uncore *uncore = &dev_priv->uncore; enum pipe pipe; - gen11_master_intr_disable(dev_priv->uncore.regs); - - gen11_gt_irq_reset(&dev_priv->gt); - intel_uncore_write(uncore, GEN11_DISPLAY_INT_CTL, 0); if (INTEL_GEN(dev_priv) >= 12) { @@ -2829,13 +2831,24 @@ static void gen11_irq_reset(struct drm_i915_private *dev_priv) GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_); GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_); GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_); - GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); - GEN3_IRQ_RESET(uncore, GEN8_PCU_); if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) GEN3_IRQ_RESET(uncore, SDE); } +static void gen11_irq_reset(struct drm_i915_private *dev_priv) +{ + struct intel_uncore *uncore = &dev_priv->uncore; + + gen11_master_intr_disable(dev_priv->uncore.regs); + + gen11_gt_irq_reset(&dev_priv->gt); + gen11_display_irq_reset(dev_priv); + + GEN3_IRQ_RESET(uncore, GEN11_GU_MISC_); + GEN3_IRQ_RESET(uncore, GEN8_PCU_); +} + void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, u8 pipe_mask) { -- cgit v1.2.3 From e815aff59dcf3f4aaf7ca061b07c0a6ef63f2351 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Mon, 2 Dec 2019 14:25:11 -0800 Subject: drm/i915/display: Check the old state to find port sync slave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the CRTC is going from enabled to disabled and it is a port sync slave, it needs to check to the old state to be disabled before the port sync master. Cc: Manasi Navare Cc: Matt Roper Cc: Maarten Lankhorst Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191202222513.337777-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 947739f18b0a..c2161ce8fe65 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14497,8 +14497,8 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) * slave CRTCs are disabled first and then master CRTC since * Slave vblanks are masked till Master Vblanks. */ - if (is_trans_port_sync_mode(new_crtc_state)) { - if (is_trans_port_sync_master(new_crtc_state)) + if (is_trans_port_sync_mode(old_crtc_state)) { + if (is_trans_port_sync_master(old_crtc_state)) intel_trans_port_sync_modeset_disables(state, crtc, old_crtc_state, -- cgit v1.2.3 From 50a7efb280a8f13a4cfdfd5f921f53925a09a09a Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Mon, 2 Dec 2019 14:25:12 -0800 Subject: drm/i915/dp: Power down sink before disable pipe/transcoder clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disabling pipe/transcoder clock before power down sink could cause sink lost signal, causing it to trigger a hotplug to notify source that link signal was lost. Cc: Lucas De Marchi Reviewed-by: Ville Syrjälä Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191202222513.337777-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index a976606d21c7..0ce06a94a27e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3802,12 +3802,12 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, enum phy phy = intel_port_to_phy(dev_priv, encoder->port); if (!is_mst) { - intel_ddi_disable_pipe_clock(old_crtc_state); /* * Power down sink before disabling the port, otherwise we end * up getting interrupts from the sink on detecting link loss. */ intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); + intel_ddi_disable_pipe_clock(old_crtc_state); } intel_disable_ddi_buf(encoder, old_crtc_state); -- cgit v1.2.3 From 78eaaba3cd786718f6ed0c9013879d3c11a00998 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Mon, 2 Dec 2019 14:25:13 -0800 Subject: drm/i915/display/mst: Move DPMS_OFF call to post_disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving just to simplify handling as there is no change in behavior. Cc: Lucas De Marchi Reviewed-by: Ville Syrjälä Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191202222513.337777-3-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 14 +++++++------- drivers/gpu/drm/i915/display/intel_dp_mst.c | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0ce06a94a27e..ebcc7302706b 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3801,14 +3801,14 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, INTEL_OUTPUT_DP_MST); enum phy phy = intel_port_to_phy(dev_priv, encoder->port); - if (!is_mst) { - /* - * Power down sink before disabling the port, otherwise we end - * up getting interrupts from the sink on detecting link loss. - */ - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); + /* + * Power down sink before disabling the port, otherwise we end + * up getting interrupts from the sink on detecting link loss. + */ + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); + + if (!is_mst) intel_ddi_disable_pipe_clock(old_crtc_state); - } intel_disable_ddi_buf(encoder, old_crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index f8a350359346..a1e4f4197a67 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -256,7 +256,6 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, intel_mst->connector = NULL; if (intel_dp->active_mst_links == 0) { - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); intel_dig_port->base.post_disable(&intel_dig_port->base, old_crtc_state, NULL); } -- cgit v1.2.3 From cb6c3d45f948f8f184687a23fea30017d01e892f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 3 Dec 2019 15:50:32 +0000 Subject: drm/i915/gem: Avoid parking the vma as we unbind In order to avoid keeping a reference on the i915_vma (which is long overdue!) we have to coordinate all the possible lifetimes and only use the vma while we know it is alive. In this episode, we are reminded that while idle, the closed vma are destroyed. So if the GT idles while we are working with the vma, the vma itself becomes invalid. First class i915_vma here we come, but in the meantime keep piling on the straw. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191203155032.3137263-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index bfdc8a9f82f8..eb9e2609c569 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -141,18 +141,33 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj, struct i915_vma, obj_link))) { struct i915_address_space *vm = vma->vm; + bool awake = false; - ret = -EBUSY; + ret = -EAGAIN; if (!i915_vm_tryopen(vm)) break; + /* Prevent vma being freed by i915_vma_parked as we unbind */ + if (intel_gt_pm_get_if_awake(vm->gt)) { + awake = true; + } else { + if (i915_vma_is_closed(vma)) { + spin_unlock(&obj->vma.lock); + goto err_vm; + } + } + list_move_tail(&vma->obj_link, &still_in_list); spin_unlock(&obj->vma.lock); + ret = -EBUSY; if (flags & I915_GEM_OBJECT_UNBIND_ACTIVE || !i915_vma_is_active(vma)) ret = i915_vma_unbind(vma); + if (awake) + intel_gt_pm_put(vm->gt); +err_vm: i915_vm_close(vm); spin_lock(&obj->vma.lock); } -- cgit v1.2.3 From 13bb5b99eca022902be508470c3092fcd08b93ed Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 3 Dec 2019 21:16:31 +0000 Subject: drm/i915/gt: Set the PD again for Haswell And Haswell still occasionally forgets it is meant to be using a new page directory, so repeat ourselves a little louder. <7> [509.919864] heartbeat rcs0 heartbeat {prio:-2147483645} not ticking <7> [509.919895] heartbeat Awake? 8 <7> [509.919903] heartbeat Barriers?: no <7> [509.919912] heartbeat Heartbeat: 3008 ms ago <7> [509.919930] heartbeat Reset count: 0 (global 0) <7> [509.919937] heartbeat Requests: <7> [509.921008] heartbeat active a7eb:56e1* @ 5847ms: <7> [509.921157] heartbeat ring->start: 0x00001000 <7> [509.921164] heartbeat ring->head: 0x00001610 <7> [509.921170] heartbeat ring->tail: 0x000023d8 <7> [509.921176] heartbeat ring->emit: 0x000023d8 <7> [509.921182] heartbeat ring->space: 0x00002570 <7> [509.921189] heartbeat ring->hwsp: 0x7fffe100 <7> [509.921197] heartbeat [head 1628, postfix 1738, tail 1750, batch 0xffffffff_ffffffff]: <7> [509.921289] heartbeat [0000] 7a000002 00100002 00000000 00000000 7a000002 01154c1e 7ffff080 00000000 <7> [509.921299] heartbeat [0020] 11000001 00002220 ffffffff 12400001 00002220 7ffff000 00000000 11000001 <7> [509.921308] heartbeat [0040] 00002228 6e900000 7a000002 00100002 00000000 00000000 7a000002 01154c1e <7> [509.921317] heartbeat [0060] 7ffff080 00000000 12400001 00002228 7ffff000 00000000 7a000002 00100002 <7> [509.921326] heartbeat [0080] 00000000 00000000 7a000002 01154c1e 7ffff080 00000000 7a000002 001010a1 <7> [509.921335] heartbeat [00a0] 7ffff080 00000000 04000000 11000005 00022050 00010001 00012050 00010001 <7> [509.921345] heartbeat [00c0] 0001a050 00010001 00000000 0c000000 459a110c 00000000 11000005 00022050 <7> [509.921354] heartbeat [00e0] 00010000 00012050 00010000 0001a050 00010000 12400001 0001a050 7ffff000 <7> [509.921363] heartbeat [0100] 00000000 04000001 18802100 00000000 7a000002 011050a1 7fffe100 000056e1 <7> [509.921370] heartbeat [0120] 01000000 00000000 <7> [509.921538] heartbeat MMIO base: 0x00002000 <7> [509.921682] heartbeat CCID: 0x3fa0110d <7> [509.922342] heartbeat RING_START: 0x00001000 <7> [509.922353] heartbeat RING_HEAD: 0x00001628 <7> [509.922366] heartbeat RING_TAIL: 0x000023d8 <7> [509.922381] heartbeat RING_CTL: 0x00003001 <7> [509.922396] heartbeat RING_MODE: 0x00004000 <7> [509.922408] heartbeat RING_IMR: ffffffde <7> [509.922421] heartbeat ACTHD: 0x00000000_30e01628 <7> [509.922434] heartbeat BBADDR: 0x00000000_00004004 <7> [509.922446] heartbeat DMA_FADDR: 0x00000000_00002800 <7> [509.922458] heartbeat IPEIR: 0x00000000 <7> [509.922470] heartbeat IPEHR: 0x780c0000 <7> [509.922642] heartbeat PP_DIR_BASE: 0x6e700000 <7> [509.922652] heartbeat PP_DIR_BASE_READ: 0x00000000 <7> [509.922662] heartbeat PP_DIR_DCLV: 0xffffffff <7> [509.922678] heartbeat E a7eb:56e1* @ 5849ms: <7> [509.922689] heartbeat E a7eb:56e2- @ 5849ms: <7> [509.922698] heartbeat E a7eb:56e3 @ 5848ms: <7> [509.922707] heartbeat E a7eb:56e4 @ 5848ms: <7> [509.922715] heartbeat E a7eb:56e5 @ 5847ms: <7> [509.922724] heartbeat E a7eb:56e6 @ 5846ms: <7> [509.922735] heartbeat E a7eb:56e7 @ 5846ms: <7> [509.922744] heartbeat ...skipping 4 executing requests... <7> [509.922754] heartbeat E a7eb:56ec @ 3010ms: <7> [509.922796] heartbeat HWSP: <7> [509.922807] heartbeat [0000] 00000001 00000000 00000000 00000000 00000000 00000000 00000000 00000000 <7> [509.922817] heartbeat [0020] 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 <7> [509.922826] heartbeat * <7> [509.922836] heartbeat [0100] 000056e0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 <7> [509.922845] heartbeat [0120] 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 <7> [509.922851] heartbeat * <7> [509.922870] heartbeat Idle? no <7> [509.922878] heartbeat Signals: <7> [509.923000] heartbeat [a7eb:56e2] @ 5850ms Here, we have a failed context restore after the PD switch, but note that the PP_DIR_BASE register does not match the LRI in the ring. Bump it to 8^W 4 loops, and with that Baytrail starts passing the sanity checks. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191203211631.3167430-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 49 +++++++------------------ drivers/gpu/drm/i915/i915_pci.c | 2 +- 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 093cec103b4c..42e3405b9996 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1368,7 +1368,7 @@ static int load_pd_dir(struct i915_request *rq, const struct i915_ppgtt *ppgtt) const struct intel_engine_cs * const engine = rq->engine; u32 *cs; - cs = intel_ring_begin(rq, 10); + cs = intel_ring_begin(rq, 12); if (IS_ERR(cs)) return PTR_ERR(cs); @@ -1380,34 +1380,19 @@ static int load_pd_dir(struct i915_request *rq, const struct i915_ppgtt *ppgtt) *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine->mmio_base)); *cs++ = intel_gt_scratch_offset(rq->engine->gt, INTEL_GT_SCRATCH_FIELD_DEFAULT); - *cs++ = MI_NOOP; *cs++ = MI_LOAD_REGISTER_IMM(1); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine->mmio_base)); *cs++ = px_base(ppgtt->pd)->ggtt_offset << 10; - intel_ring_advance(rq, cs); - - return 0; -} - -static int flush_pd_dir(struct i915_request *rq) -{ - const struct intel_engine_cs * const engine = rq->engine; - u32 *cs; - - cs = intel_ring_begin(rq, 4); - if (IS_ERR(cs)) - return PTR_ERR(cs); - - /* Stall until the page table load is complete */ + /* Stall until the page table load is complete? */ *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine->mmio_base)); *cs++ = intel_gt_scratch_offset(rq->engine->gt, INTEL_GT_SCRATCH_FIELD_DEFAULT); - *cs++ = MI_NOOP; intel_ring_advance(rq, cs); + return 0; } @@ -1593,19 +1578,7 @@ static int switch_context(struct i915_request *rq) GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); if (vm) { - struct intel_engine_cs *engine = rq->engine; - - ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm)); - if (ret) - return ret; - - ret = engine->emit_flush(rq, EMIT_INVALIDATE); - if (ret) - return ret; - - ret = flush_pd_dir(rq); - if (ret) - return ret; + int loops = 4; /* 2 for Haswell? 4 for Baytrail! */ /* * Not only do we need a full barrier (post-sync write) after @@ -1615,11 +1588,17 @@ static int switch_context(struct i915_request *rq) * post-sync op, this extra pass appears vital before a * mm switch! */ - ret = engine->emit_flush(rq, EMIT_INVALIDATE); - if (ret) - return ret; + do { + ret = rq->engine->emit_flush(rq, EMIT_FLUSH); + if (ret) + return ret; + + ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm)); + if (ret) + return ret; + } while (--loops); - ret = engine->emit_flush(rq, EMIT_FLUSH); + ret = rq->engine->emit_flush(rq, EMIT_INVALIDATE); if (ret) return ret; } diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 583e0cd94a6a..bba6b50e6beb 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -493,7 +493,7 @@ static const struct intel_device_info intel_valleyview_info = { .has_rps = true, .display.has_gmch = 1, .display.has_hotplug = 1, - .ppgtt_type = INTEL_PPGTT_ALIASING, + .ppgtt_type = INTEL_PPGTT_FULL, .ppgtt_size = 31, .has_snoop = true, .has_coherent_ggtt = false, -- cgit v1.2.3 From d2432796dc72cad9544207f22a219e61fddb5fcb Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 21:05:50 +0200 Subject: drm/i915: Clean up arguments to nv12/scaler w/a funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't pass the redundant dev_priv to needs_nv12_wa() and needs_scalerclk_wa(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127190556.1574-2-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c2161ce8fe65..6b0f8cd3a948 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6037,9 +6037,10 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s return !old_crtc_state->ips_enabled; } -static bool needs_nv12_wa(struct drm_i915_private *dev_priv, - const struct intel_crtc_state *crtc_state) +static bool needs_nv12_wa(const struct intel_crtc_state *crtc_state) { + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + if (!crtc_state->nv12_planes) return false; @@ -6050,9 +6051,10 @@ static bool needs_nv12_wa(struct drm_i915_private *dev_priv, return false; } -static bool needs_scalerclk_wa(struct drm_i915_private *dev_priv, - const struct intel_crtc_state *crtc_state) +static bool needs_scalerclk_wa(const struct intel_crtc_state *crtc_state) { + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + /* Wa_2006604312:icl */ if (crtc_state->scaler_state.scaler_users > 0 && IS_ICELAKE(dev_priv)) return true; @@ -6093,12 +6095,12 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) intel_post_enable_primary(&crtc->base, pipe_config); } - if (needs_nv12_wa(dev_priv, old_crtc_state) && - !needs_nv12_wa(dev_priv, pipe_config)) + if (needs_nv12_wa(old_crtc_state) && + !needs_nv12_wa(pipe_config)) skl_wa_827(dev_priv, crtc->pipe, false); - if (needs_scalerclk_wa(dev_priv, old_crtc_state) && - !needs_scalerclk_wa(dev_priv, pipe_config)) + if (needs_scalerclk_wa(old_crtc_state) && + !needs_scalerclk_wa(pipe_config)) icl_wa_scalerclkgating(dev_priv, crtc->pipe, false); } @@ -6135,13 +6137,13 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, } /* Display WA 827 */ - if (!needs_nv12_wa(dev_priv, old_crtc_state) && - needs_nv12_wa(dev_priv, pipe_config)) + if (!needs_nv12_wa(old_crtc_state) && + needs_nv12_wa(pipe_config)) skl_wa_827(dev_priv, crtc->pipe, true); /* Wa_2006604312:icl */ - if (!needs_scalerclk_wa(dev_priv, old_crtc_state) && - needs_scalerclk_wa(dev_priv, pipe_config)) + if (!needs_scalerclk_wa(old_crtc_state) && + needs_scalerclk_wa(pipe_config)) icl_wa_scalerclkgating(dev_priv, crtc->pipe, true); /* -- cgit v1.2.3 From 60aca5741a695666218f8eefcd436e7dcc508552 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 21:05:51 +0200 Subject: drm/i915: Pass dev_priv to ilk_disable_lp_wm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get rid of another 'dev' usage by passing dev_priv instead. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127190556.1574-3-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 4 +--- drivers/gpu/drm/i915/intel_pm.h | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6b0f8cd3a948..243f692fc586 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6166,7 +6166,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, * * WaCxSRDisabledForSpriteScaling:ivb */ - if (pipe_config->disable_lp_wm && ilk_disable_lp_wm(dev) && + if (pipe_config->disable_lp_wm && ilk_disable_lp_wm(dev_priv) && old_crtc_state->hw.active) intel_wait_for_vblank(dev_priv, crtc->pipe); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index eaf6397c5c38..669d45e6e6d7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3592,10 +3592,8 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, dev_priv->wm.hw = *results; } -bool ilk_disable_lp_wm(struct drm_device *dev) +bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL); } diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h index b579c724b915..c06c6a846d9a 100644 --- a/drivers/gpu/drm/i915/intel_pm.h +++ b/drivers/gpu/drm/i915/intel_pm.h @@ -54,7 +54,7 @@ void skl_write_plane_wm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state); void skl_write_cursor_wm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state); -bool ilk_disable_lp_wm(struct drm_device *dev); +bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv); void intel_init_ipc(struct drm_i915_private *dev_priv); void intel_enable_ipc(struct drm_i915_private *dev_priv); -- cgit v1.2.3 From 0e75fb8c03aa430e88f1393ea089b881c7b86f5f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 21:05:52 +0200 Subject: drm/i915: s/pipe_config/new_crtc_state/ intel_{pre,post}_plane_update() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the old world 'pipe_config' variable name with the new thing. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127190556.1574-4-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 40 ++++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 243f692fc586..0e3cf97d6d93 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6068,20 +6068,20 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_atomic_state *state = old_crtc_state->uapi.state; - struct intel_crtc_state *pipe_config = + struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(to_intel_atomic_state(state), crtc); struct drm_plane *primary = crtc->base.primary; struct drm_plane_state *old_primary_state = drm_atomic_get_old_plane_state(state, primary); - intel_frontbuffer_flip(to_i915(crtc->base.dev), pipe_config->fb_bits); + intel_frontbuffer_flip(to_i915(crtc->base.dev), new_crtc_state->fb_bits); - if (pipe_config->update_wm_post && pipe_config->hw.active) + if (new_crtc_state->update_wm_post && new_crtc_state->hw.active) intel_update_watermarks(crtc); - if (hsw_post_update_enable_ips(old_crtc_state, pipe_config)) - hsw_enable_ips(pipe_config); + if (hsw_post_update_enable_ips(old_crtc_state, new_crtc_state)) + hsw_enable_ips(new_crtc_state); if (old_primary_state) { struct drm_plane_state *new_primary_state = @@ -6090,22 +6090,22 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) intel_fbc_post_update(crtc); if (new_primary_state->visible && - (needs_modeset(pipe_config) || + (needs_modeset(new_crtc_state) || !old_primary_state->visible)) - intel_post_enable_primary(&crtc->base, pipe_config); + intel_post_enable_primary(&crtc->base, new_crtc_state); } if (needs_nv12_wa(old_crtc_state) && - !needs_nv12_wa(pipe_config)) + !needs_nv12_wa(new_crtc_state)) skl_wa_827(dev_priv, crtc->pipe, false); if (needs_scalerclk_wa(old_crtc_state) && - !needs_scalerclk_wa(pipe_config)) + !needs_scalerclk_wa(new_crtc_state)) icl_wa_scalerclkgating(dev_priv, crtc->pipe, false); } static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_device *dev = crtc->base.dev; @@ -6114,11 +6114,11 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, struct drm_plane *primary = crtc->base.primary; struct drm_plane_state *old_primary_state = drm_atomic_get_old_plane_state(state, primary); - bool modeset = needs_modeset(pipe_config); + bool modeset = needs_modeset(new_crtc_state); struct intel_atomic_state *intel_state = to_intel_atomic_state(state); - if (hsw_pre_update_disable_ips(old_crtc_state, pipe_config)) + if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state)) hsw_disable_ips(old_crtc_state); if (old_primary_state) { @@ -6126,7 +6126,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, intel_atomic_get_new_plane_state(intel_state, to_intel_plane(primary)); - intel_fbc_pre_update(crtc, pipe_config, new_primary_state); + intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state); /* * Gen2 reports pipe underruns whenever all planes are disabled. * So disable underrun reporting before all the planes get disabled. @@ -6138,12 +6138,12 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, /* Display WA 827 */ if (!needs_nv12_wa(old_crtc_state) && - needs_nv12_wa(pipe_config)) + needs_nv12_wa(new_crtc_state)) skl_wa_827(dev_priv, crtc->pipe, true); /* Wa_2006604312:icl */ if (!needs_scalerclk_wa(old_crtc_state) && - needs_scalerclk_wa(pipe_config)) + needs_scalerclk_wa(new_crtc_state)) icl_wa_scalerclkgating(dev_priv, crtc->pipe, true); /* @@ -6156,7 +6156,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, * wait-for-vblank between disabling the plane and the pipe. */ if (HAS_GMCH(dev_priv) && old_crtc_state->hw.active && - pipe_config->disable_cxsr && intel_set_memory_cxsr(dev_priv, false)) + new_crtc_state->disable_cxsr && intel_set_memory_cxsr(dev_priv, false)) intel_wait_for_vblank(dev_priv, crtc->pipe); /* @@ -6166,15 +6166,15 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, * * WaCxSRDisabledForSpriteScaling:ivb */ - if (pipe_config->disable_lp_wm && ilk_disable_lp_wm(dev_priv) && - old_crtc_state->hw.active) + if (old_crtc_state->hw.active && + new_crtc_state->disable_lp_wm && ilk_disable_lp_wm(dev_priv)) intel_wait_for_vblank(dev_priv, crtc->pipe); /* * If we're doing a modeset, we're done. No need to do any pre-vblank * watermark programming here. */ - if (needs_modeset(pipe_config)) + if (needs_modeset(new_crtc_state)) return; /* @@ -6193,7 +6193,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, */ if (dev_priv->display.initial_watermarks) dev_priv->display.initial_watermarks(intel_state, crtc); - else if (pipe_config->update_wm_pre) + else if (new_crtc_state->update_wm_pre) intel_update_watermarks(crtc); } -- cgit v1.2.3 From bee43ca4c1cc1ae2157a3aed34f033a7fcbf596b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 21:05:53 +0200 Subject: drm/i915: Clean up intel_{pre,post}_plane_update() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the calling convention to just pass the state+crtc and switch to intel_ types throughout. We'll also do a quick s/if (old_primary_state)/if (new_primary_state)/ so that we'll be able to eliminate old_primary_state later. This is fine since we always have either both old and new state or neither. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127190556.1574-5-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 88 +++++++++++++--------------- drivers/gpu/drm/i915/display/intel_fbc.c | 14 ++--- drivers/gpu/drm/i915/display/intel_fbc.h | 8 +-- 3 files changed, 51 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0e3cf97d6d93..a9cf2cedeab8 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5920,13 +5920,10 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc) * completely hide the primary plane. */ static void -intel_post_enable_primary(struct drm_crtc *crtc, - const struct intel_crtc_state *new_crtc_state) +intel_post_enable_primary(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; /* * Gen2 reports pipe underruns whenever all planes are disabled. @@ -6062,20 +6059,21 @@ static bool needs_scalerclk_wa(const struct intel_crtc_state *crtc_state) return false; } -static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) +static void intel_post_plane_update(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_atomic_state *state = old_crtc_state->uapi.state; - struct intel_crtc_state *new_crtc_state = - intel_atomic_get_new_crtc_state(to_intel_atomic_state(state), - crtc); - struct drm_plane *primary = crtc->base.primary; - struct drm_plane_state *old_primary_state = - drm_atomic_get_old_plane_state(state, primary); + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_plane *primary = to_intel_plane(crtc->base.primary); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct intel_plane_state *old_primary_state = + intel_atomic_get_old_plane_state(state, primary); + const struct intel_plane_state *new_primary_state = + intel_atomic_get_new_plane_state(state, primary); - intel_frontbuffer_flip(to_i915(crtc->base.dev), new_crtc_state->fb_bits); + intel_frontbuffer_flip(dev_priv, new_crtc_state->fb_bits); if (new_crtc_state->update_wm_post && new_crtc_state->hw.active) intel_update_watermarks(crtc); @@ -6083,16 +6081,13 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) if (hsw_post_update_enable_ips(old_crtc_state, new_crtc_state)) hsw_enable_ips(new_crtc_state); - if (old_primary_state) { - struct drm_plane_state *new_primary_state = - drm_atomic_get_new_plane_state(state, primary); - + if (new_primary_state) { intel_fbc_post_update(crtc); - if (new_primary_state->visible && + if (new_primary_state->uapi.visible && (needs_modeset(new_crtc_state) || - !old_primary_state->visible)) - intel_post_enable_primary(&crtc->base, new_crtc_state); + !old_primary_state->uapi.visible)) + intel_post_enable_primary(crtc); } if (needs_nv12_wa(old_crtc_state) && @@ -6104,34 +6099,31 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) icl_wa_scalerclkgating(dev_priv, crtc->pipe, false); } -static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state) +static void intel_pre_plane_update(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_atomic_state *state = old_crtc_state->uapi.state; - struct drm_plane *primary = crtc->base.primary; - struct drm_plane_state *old_primary_state = - drm_atomic_get_old_plane_state(state, primary); + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_plane *primary = to_intel_plane(crtc->base.primary); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct intel_plane_state *old_primary_state = + intel_atomic_get_old_plane_state(state, primary); + const struct intel_plane_state *new_primary_state = + intel_atomic_get_new_plane_state(state, primary); bool modeset = needs_modeset(new_crtc_state); - struct intel_atomic_state *intel_state = - to_intel_atomic_state(state); if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state)) hsw_disable_ips(old_crtc_state); - if (old_primary_state) { - struct intel_plane_state *new_primary_state = - intel_atomic_get_new_plane_state(intel_state, - to_intel_plane(primary)); - + if (new_primary_state) { intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state); /* * Gen2 reports pipe underruns whenever all planes are disabled. * So disable underrun reporting before all the planes get disabled. */ - if (IS_GEN(dev_priv, 2) && old_primary_state->visible && + if (IS_GEN(dev_priv, 2) && old_primary_state->uapi.visible && (modeset || !new_primary_state->uapi.visible)) intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); } @@ -6192,7 +6184,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, * us to. */ if (dev_priv->display.initial_watermarks) - dev_priv->display.initial_watermarks(intel_state, crtc); + dev_priv->display.initial_watermarks(state, crtc); else if (new_crtc_state->update_wm_pre) intel_update_watermarks(crtc); } @@ -14365,7 +14357,7 @@ static void intel_update_crtc(struct intel_crtc *crtc, new_crtc_state->update_pipe)) intel_color_load_luts(new_crtc_state); - intel_pre_plane_update(old_crtc_state, new_crtc_state); + intel_pre_plane_update(state, crtc); if (new_crtc_state->update_pipe) intel_encoders_update_pipe(state, crtc); @@ -14460,7 +14452,7 @@ static void intel_trans_port_sync_modeset_disables(struct intel_atomic_state *st !old_slave_crtc_state); /* Disable Slave first */ - intel_pre_plane_update(old_slave_crtc_state, new_slave_crtc_state); + intel_pre_plane_update(state, slave_crtc); if (old_slave_crtc_state->hw.active) intel_old_crtc_state_disables(state, old_slave_crtc_state, @@ -14468,7 +14460,7 @@ static void intel_trans_port_sync_modeset_disables(struct intel_atomic_state *st slave_crtc); /* Disable Master */ - intel_pre_plane_update(old_crtc_state, new_crtc_state); + intel_pre_plane_update(state, crtc); if (old_crtc_state->hw.active) intel_old_crtc_state_disables(state, old_crtc_state, @@ -14508,7 +14500,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) else continue; } else { - intel_pre_plane_update(old_crtc_state, new_crtc_state); + intel_pre_plane_update(state, crtc); if (old_crtc_state->hw.active) intel_old_crtc_state_disables(state, @@ -14896,7 +14888,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) } for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - intel_post_plane_update(old_crtc_state); + intel_post_plane_update(state, crtc); if (put_domains[i]) modeset_put_power_domains(dev_priv, put_domains[i]); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 92c7eb243559..70c56abe1a83 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -420,7 +420,7 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv, } static bool multiple_pipes_ok(struct intel_crtc *crtc, - struct intel_plane_state *plane_state) + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; @@ -656,8 +656,8 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) } static void intel_fbc_update_state_cache(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state) + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; @@ -855,8 +855,8 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, } void intel_fbc_pre_update(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state) + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; @@ -1081,8 +1081,8 @@ out: * intel_fbc_disable in the middle, as long as it is deactivated. */ void intel_fbc_enable(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state) + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index 50272eda8d43..f58b0b1e3c5c 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -20,14 +20,14 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, struct intel_atomic_state *state); bool intel_fbc_is_active(struct drm_i915_private *dev_priv); void intel_fbc_pre_update(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state); + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); void intel_fbc_post_update(struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv); void intel_fbc_enable(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state); + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); void intel_fbc_disable(struct intel_crtc *crtc); void intel_fbc_global_disable(struct drm_i915_private *dev_priv); void intel_fbc_invalidate(struct drm_i915_private *dev_priv, -- cgit v1.2.3 From 7181f5c5861013fc39fb51f3e8e804985d23250a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 21:05:54 +0200 Subject: drm/i915: Clean up the gen2 "no planes -> underrun" workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have the active_planes bitmask now so use it to properly determine when some planes are visible for the gen2 underrun workaround. This let's us almost eliminate intel_post_enable_primary(). The manual underrun checks we can simply move into intel_atomic_commit_tail() since they loop over all the pipes already. No point in repeating the checks multiple times when there are multiple pipes in the commit. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127190556.1574-6-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 155 ++++++++++++--------------- 1 file changed, 70 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a9cf2cedeab8..be7f2cab21ba 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5908,37 +5908,6 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc) */ } -/** - * intel_post_enable_primary - Perform operations after enabling primary plane - * @crtc: the CRTC whose primary plane was just enabled - * @new_crtc_state: the enabling state - * - * Performs potentially sleeping operations that must be done after the primary - * plane is enabled, such as updating FBC and IPS. Note that this may be - * called due to an explicit primary plane update, or due to an implicit - * re-enable that is caused when a sprite plane is updated to no longer - * completely hide the primary plane. - */ -static void -intel_post_enable_primary(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - - /* - * Gen2 reports pipe underruns whenever all planes are disabled. - * So don't enable underrun reporting before at least some planes - * are enabled. - * FIXME: Need to fix the logic to work when we turn off all planes - * but leave the pipe running. - */ - if (IS_GEN(dev_priv, 2)) - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - - /* Underruns don't always raise interrupts, so check manually. */ - intel_check_cpu_fifo_underruns(dev_priv); - intel_check_pch_fifo_underruns(dev_priv); -} /* FIXME get rid of this and use pre_plane_update */ static void @@ -6059,6 +6028,20 @@ static bool needs_scalerclk_wa(const struct intel_crtc_state *crtc_state) return false; } +static bool planes_enabling(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + return (!old_crtc_state->active_planes || needs_modeset(new_crtc_state)) && + new_crtc_state->active_planes; +} + +static bool planes_disabling(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + return old_crtc_state->active_planes && + (!new_crtc_state->active_planes || needs_modeset(new_crtc_state)); +} + static void intel_post_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -6068,10 +6051,9 @@ static void intel_post_plane_update(struct intel_atomic_state *state, intel_atomic_get_old_crtc_state(state, crtc); const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - const struct intel_plane_state *old_primary_state = - intel_atomic_get_old_plane_state(state, primary); const struct intel_plane_state *new_primary_state = intel_atomic_get_new_plane_state(state, primary); + enum pipe pipe = crtc->pipe; intel_frontbuffer_flip(dev_priv, new_crtc_state->fb_bits); @@ -6081,22 +6063,16 @@ static void intel_post_plane_update(struct intel_atomic_state *state, if (hsw_post_update_enable_ips(old_crtc_state, new_crtc_state)) hsw_enable_ips(new_crtc_state); - if (new_primary_state) { + if (new_primary_state) intel_fbc_post_update(crtc); - if (new_primary_state->uapi.visible && - (needs_modeset(new_crtc_state) || - !old_primary_state->uapi.visible)) - intel_post_enable_primary(crtc); - } - if (needs_nv12_wa(old_crtc_state) && !needs_nv12_wa(new_crtc_state)) - skl_wa_827(dev_priv, crtc->pipe, false); + skl_wa_827(dev_priv, pipe, false); if (needs_scalerclk_wa(old_crtc_state) && !needs_scalerclk_wa(new_crtc_state)) - icl_wa_scalerclkgating(dev_priv, crtc->pipe, false); + icl_wa_scalerclkgating(dev_priv, pipe, false); } static void intel_pre_plane_update(struct intel_atomic_state *state, @@ -6108,35 +6084,25 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_atomic_get_old_crtc_state(state, crtc); const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - const struct intel_plane_state *old_primary_state = - intel_atomic_get_old_plane_state(state, primary); const struct intel_plane_state *new_primary_state = intel_atomic_get_new_plane_state(state, primary); - bool modeset = needs_modeset(new_crtc_state); + enum pipe pipe = crtc->pipe; if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state)) hsw_disable_ips(old_crtc_state); - if (new_primary_state) { + if (new_primary_state) intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state); - /* - * Gen2 reports pipe underruns whenever all planes are disabled. - * So disable underrun reporting before all the planes get disabled. - */ - if (IS_GEN(dev_priv, 2) && old_primary_state->uapi.visible && - (modeset || !new_primary_state->uapi.visible)) - intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); - } /* Display WA 827 */ if (!needs_nv12_wa(old_crtc_state) && needs_nv12_wa(new_crtc_state)) - skl_wa_827(dev_priv, crtc->pipe, true); + skl_wa_827(dev_priv, pipe, true); /* Wa_2006604312:icl */ if (!needs_scalerclk_wa(old_crtc_state) && needs_scalerclk_wa(new_crtc_state)) - icl_wa_scalerclkgating(dev_priv, crtc->pipe, true); + icl_wa_scalerclkgating(dev_priv, pipe, true); /* * Vblank time updates from the shadow to live plane control register @@ -6149,7 +6115,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, */ if (HAS_GMCH(dev_priv) && old_crtc_state->hw.active && new_crtc_state->disable_cxsr && intel_set_memory_cxsr(dev_priv, false)) - intel_wait_for_vblank(dev_priv, crtc->pipe); + intel_wait_for_vblank(dev_priv, pipe); /* * IVB workaround: must disable low power watermarks for at least @@ -6160,33 +6126,43 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, */ if (old_crtc_state->hw.active && new_crtc_state->disable_lp_wm && ilk_disable_lp_wm(dev_priv)) - intel_wait_for_vblank(dev_priv, crtc->pipe); + intel_wait_for_vblank(dev_priv, pipe); /* - * If we're doing a modeset, we're done. No need to do any pre-vblank - * watermark programming here. + * If we're doing a modeset we don't need to do any + * pre-vblank watermark programming here. */ - if (needs_modeset(new_crtc_state)) - return; + if (!needs_modeset(new_crtc_state)) { + /* + * For platforms that support atomic watermarks, program the + * 'intermediate' watermarks immediately. On pre-gen9 platforms, these + * will be the intermediate values that are safe for both pre- and + * post- vblank; when vblank happens, the 'active' values will be set + * to the final 'target' values and we'll do this again to get the + * optimal watermarks. For gen9+ platforms, the values we program here + * will be the final target values which will get automatically latched + * at vblank time; no further programming will be necessary. + * + * If a platform hasn't been transitioned to atomic watermarks yet, + * we'll continue to update watermarks the old way, if flags tell + * us to. + */ + if (dev_priv->display.initial_watermarks) + dev_priv->display.initial_watermarks(state, crtc); + else if (new_crtc_state->update_wm_pre) + intel_update_watermarks(crtc); + } /* - * For platforms that support atomic watermarks, program the - * 'intermediate' watermarks immediately. On pre-gen9 platforms, these - * will be the intermediate values that are safe for both pre- and - * post- vblank; when vblank happens, the 'active' values will be set - * to the final 'target' values and we'll do this again to get the - * optimal watermarks. For gen9+ platforms, the values we program here - * will be the final target values which will get automatically latched - * at vblank time; no further programming will be necessary. + * Gen2 reports pipe underruns whenever all planes are disabled. + * So disable underrun reporting before all the planes get disabled. * - * If a platform hasn't been transitioned to atomic watermarks yet, - * we'll continue to update watermarks the old way, if flags tell - * us to. + * We do this after .initial_watermarks() so that we have a + * chance of catching underruns with the intermediate watermarks + * vs. the old plane configuration. */ - if (dev_priv->display.initial_watermarks) - dev_priv->display.initial_watermarks(state, crtc); - else if (new_crtc_state->update_wm_pre) - intel_update_watermarks(crtc); + if (IS_GEN(dev_priv, 2) && planes_disabling(old_crtc_state, new_crtc_state)) + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); } static void intel_crtc_disable_planes(struct intel_atomic_state *state, @@ -14423,13 +14399,6 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, intel_fbc_disable(crtc); intel_disable_shared_dpll(old_crtc_state); - /* - * Underruns don't always raise interrupts, - * so check manually. - */ - intel_check_cpu_fifo_underruns(dev_priv); - intel_check_pch_fifo_underruns(dev_priv); - /* FIXME unify this for all platforms */ if (!new_crtc_state->hw.active && !HAS_GMCH(dev_priv) && @@ -14882,7 +14851,19 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) * * TODO: Move this (and other cleanup) to an async worker eventually. */ - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { + /* + * Gen2 reports pipe underruns whenever all planes are disabled. + * So re-enable underrun reporting after some planes get enabled. + * + * We do this before .optimize_watermarks() so that we have a + * chance of catching underruns with the intermediate watermarks + * vs. the new plane configuration. + */ + if (IS_GEN(dev_priv, 2) && planes_enabling(old_crtc_state, new_crtc_state)) + intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true); + if (dev_priv->display.optimize_watermarks) dev_priv->display.optimize_watermarks(state, crtc); } @@ -14896,6 +14877,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state); } + /* Underruns don't always raise interrupts, so check manually */ + intel_check_cpu_fifo_underruns(dev_priv); + intel_check_pch_fifo_underruns(dev_priv); + if (state->modeset) intel_verify_planes(state); -- cgit v1.2.3 From 23526249fc4ef1810d3567ff52ed7606f3548517 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 21:05:55 +0200 Subject: drm/i915: Nuke intel_pre_disable_primary_noatomic() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's just inline intel_pre_disable_primary_noatomic() into intel_plane_disable_noatomic(). The CxSR disable we can do regardless of which plane we're disabling, and while at it we can make the gen2 underrun w/a accurate by consulting the active_planes bitmask. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127190556.1574-7-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 57 +++++++++++----------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index be7f2cab21ba..45d73b278051 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -171,7 +171,6 @@ static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state) static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state); static void intel_modeset_setup_hw_state(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx); -static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc); struct intel_limit { struct { @@ -3212,6 +3211,7 @@ static void fixup_active_planes(struct intel_crtc_state *crtc_state) static void intel_plane_disable_noatomic(struct intel_crtc *crtc, struct intel_plane *plane) { + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_plane_state *plane_state = @@ -3227,7 +3227,27 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc, crtc_state->min_cdclk[plane->id] = 0; if (plane->id == PLANE_PRIMARY) - intel_pre_disable_primary_noatomic(&crtc->base); + hsw_disable_ips(crtc_state); + + /* + * Vblank time updates from the shadow to live plane control register + * are blocked if the memory self-refresh mode is active at that + * moment. So to make sure the plane gets truly disabled, disable + * first the self-refresh mode. The self-refresh enable bit in turn + * will be checked/applied by the HW only at the next frame start + * event which is after the vblank start event, so we need to have a + * wait-for-vblank between disabling the plane and the pipe. + */ + if (HAS_GMCH(dev_priv) && + intel_set_memory_cxsr(dev_priv, false)) + intel_wait_for_vblank(dev_priv, crtc->pipe); + + /* + * Gen2 reports pipe underruns whenever all planes are disabled. + * So disable underrun reporting before all the planes get disabled. + */ + if (IS_GEN(dev_priv, 2) && !crtc_state->active_planes) + intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); intel_disable_plane(plane, crtc_state); } @@ -5908,39 +5928,6 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc) */ } - -/* FIXME get rid of this and use pre_plane_update */ -static void -intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - - /* - * Gen2 reports pipe underruns whenever all planes are disabled. - * So disable underrun reporting before all the planes get disabled. - */ - if (IS_GEN(dev_priv, 2)) - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - - hsw_disable_ips(to_intel_crtc_state(crtc->state)); - - /* - * Vblank time updates from the shadow to live plane control register - * are blocked if the memory self-refresh mode is active at that - * moment. So to make sure the plane gets truly disabled, disable - * first the self-refresh mode. The self-refresh enable bit in turn - * will be checked/applied by the HW only at the next frame start - * event which is after the vblank start event, so we need to have a - * wait-for-vblank between disabling the plane and the pipe. - */ - if (HAS_GMCH(dev_priv) && - intel_set_memory_cxsr(dev_priv, false)) - intel_wait_for_vblank(dev_priv, pipe); -} - static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state) { -- cgit v1.2.3 From cfdd174798334421a4648f6c5a1515c8526e8939 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 21:05:56 +0200 Subject: drm/i915: Make intel_crtc_arm_fifo_underrun() functional on gen2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assuming intel_crtc_arm_fifo_underrun() only gets called when there's no pending plane updates we can utilize it on gen2 by checking the active_planes bitmask so that we only re-enable underrun reporting if some planes are active. i915_fifo_underrun_reset_write() seems to have the necessary hw_done/flip_done waits in place. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127190556.1574-8-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 45d73b278051..63f95666b801 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14221,7 +14221,7 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - if (!IS_GEN(dev_priv, 2)) + if (!IS_GEN(dev_priv, 2) || crtc_state->active_planes) intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true); if (crtc_state->has_pch_encoder) { -- cgit v1.2.3 From c415ef2a267cdfda429bb519e651c82132ef89fa Mon Sep 17 00:00:00 2001 From: Mao Wenan Date: Wed, 4 Dec 2019 09:01:54 +0800 Subject: drm/i915/perf: drop pointless static qualifier in i915_perf_add_config_ioctl() There is no need to have the 'T *v' variable static since new value always be assigned before use it. Reported-by: Hulk Robot Signed-off-by: Mao Wenan Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191204010154.152396-1-maowenan@huawei.com --- drivers/gpu/drm/i915/i915_perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index b46715b57576..f20dda40b378 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -3964,7 +3964,7 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, struct i915_perf *perf = &to_i915(dev)->perf; struct drm_i915_perf_oa_config *args = data; struct i915_oa_config *oa_config, *tmp; - static struct i915_oa_reg *regs; + struct i915_oa_reg *regs; int err, id; if (!perf->i915) { -- cgit v1.2.3 From cc662126b4134e25fcfb6cad480de0fa95a4d3d8 Mon Sep 17 00:00:00 2001 From: Abdiel Janulgue Date: Wed, 4 Dec 2019 12:00:32 +0000 Subject: drm/i915: Introduce DRM_I915_GEM_MMAP_OFFSET This is really just an alias of mmap_gtt. The 'mmap offset' nomenclature comes from the value returned by this ioctl which is the offset into the device fd which userpace uses with mmap(2). mmap_gtt was our initial mmap_offset implementation, this extends our CPU mmap support to allow additional fault handlers that depends on the object's backing pages. Note that we multiplex mmap_gtt and mmap_offset through the same ioctl, and use the zero extending behaviour of drm to differentiate between them, when we inspect the flags. To support multiple mmap types on an object we need to support multiple mmap_offsets for an object (each offset in the global device address space corresponding to a unique instance of the object for a file + mmap type). As we drop the simplified drm core idea of a single mmap_offset, we need to provide replacement hooks for the dumb mmap interface as well. Link: https://gitlab.freedesktop.org/mesa/mesa/merge_requests/1675 Testcase: igt/gem_mmap_offset Signed-off-by: Abdiel Janulgue Signed-off-by: Matthew Auld Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191204120032.3682839-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_ioctls.h | 4 +- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 461 +++++++++++++++++---- drivers/gpu/drm/i915/gem/i915_gem_mman.h | 31 ++ drivers/gpu/drm/i915/gem/i915_gem_object.c | 27 ++ drivers/gpu/drm/i915/gem/i915_gem_object.h | 7 +- drivers/gpu/drm/i915/gem/i915_gem_object_types.h | 23 + drivers/gpu/drm/i915/gem/i915_gem_pages.c | 3 + drivers/gpu/drm/i915/gem/i915_gem_tiling.c | 1 + drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 88 ++-- drivers/gpu/drm/i915/gt/intel_reset.c | 7 +- drivers/gpu/drm/i915/i915_drv.c | 15 +- drivers/gpu/drm/i915/i915_drv.h | 4 - drivers/gpu/drm/i915/i915_gem.c | 3 +- drivers/gpu/drm/i915/i915_getparam.c | 1 + drivers/gpu/drm/i915/i915_vma.c | 5 +- drivers/gpu/drm/i915/i915_vma.h | 3 + include/uapi/drm/i915_drm.h | 32 ++ 18 files changed, 574 insertions(+), 142 deletions(-) create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_mman.h diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 3119f7be9bc0..f2064950622b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -13,6 +13,7 @@ #include "i915_gem_object.h" #include "i915_vma.h" #include "i915_gem_lmem.h" +#include "i915_gem_mman.h" static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ioctls.h b/drivers/gpu/drm/i915/gem/i915_gem_ioctls.h index ddc7f2a52b3e..87d8b27f426d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ioctls.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_ioctls.h @@ -28,8 +28,8 @@ int i915_gem_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *file); int i915_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file); -int i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, - struct drm_file *file); +int i915_gem_mmap_offset_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); int i915_gem_pread_ioctl(struct drm_device *dev, void *data, struct drm_file *file); int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index d60973603cc1..37aabbfa869a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -5,6 +5,7 @@ */ #include +#include #include #include "gt/intel_gt.h" @@ -14,6 +15,7 @@ #include "i915_gem_gtt.h" #include "i915_gem_ioctls.h" #include "i915_gem_object.h" +#include "i915_gem_mman.h" #include "i915_trace.h" #include "i915_vma.h" @@ -144,6 +146,9 @@ static unsigned int tile_row_pages(const struct drm_i915_gem_object *obj) * 3 - Remove implicit set-domain(GTT) and synchronisation on initial * pagefault; swapin remains transparent. * + * 4 - Support multiple fault handlers per object depending on object's + * backing storage (a.k.a. MMAP_OFFSET). + * * Restrictions: * * * snoopable objects cannot be accessed via the GTT. It can cause machine @@ -171,7 +176,7 @@ static unsigned int tile_row_pages(const struct drm_i915_gem_object *obj) */ int i915_gem_mmap_gtt_version(void) { - return 3; + return 4; } static inline struct i915_ggtt_view @@ -197,29 +202,83 @@ compute_partial_view(const struct drm_i915_gem_object *obj, return view; } -/** - * i915_gem_fault - fault a page into the GTT - * @vmf: fault info - * - * The fault handler is set up by drm_gem_mmap() when a object is GTT mapped - * from userspace. The fault handler takes care of binding the object to - * the GTT (if needed), allocating and programming a fence register (again, - * only if needed based on whether the old reg is still valid or the object - * is tiled) and inserting a new PTE into the faulting process. - * - * Note that the faulting process may involve evicting existing objects - * from the GTT and/or fence registers to make room. So performance may - * suffer if the GTT working set is large or there are few fence registers - * left. - * - * The current feature set supported by i915_gem_fault() and thus GTT mmaps - * is exposed via I915_PARAM_MMAP_GTT_VERSION (see i915_gem_mmap_gtt_version). - */ -vm_fault_t i915_gem_fault(struct vm_fault *vmf) +static vm_fault_t i915_error_to_vmf_fault(int err) +{ + switch (err) { + default: + WARN_ONCE(err, "unhandled error in %s: %i\n", __func__, err); + /* fallthrough */ + case -EIO: /* shmemfs failure from swap device */ + case -EFAULT: /* purged object */ + case -ENODEV: /* bad object, how did you get here! */ + return VM_FAULT_SIGBUS; + + case -ENOSPC: /* shmemfs allocation failure */ + case -ENOMEM: /* our allocation failure */ + return VM_FAULT_OOM; + + case 0: + case -EAGAIN: + case -ERESTARTSYS: + case -EINTR: + case -EBUSY: + /* + * EBUSY is ok: this just means that another thread + * already did the job. + */ + return VM_FAULT_NOPAGE; + } +} + +static vm_fault_t vm_fault_cpu(struct vm_fault *vmf) +{ + struct vm_area_struct *area = vmf->vma; + struct i915_mmap_offset *mmo = area->vm_private_data; + struct drm_i915_gem_object *obj = mmo->obj; + unsigned long i, size = area->vm_end - area->vm_start; + bool write = area->vm_flags & VM_WRITE; + vm_fault_t ret = VM_FAULT_SIGBUS; + int err; + + if (!i915_gem_object_has_struct_page(obj)) + return ret; + + /* Sanity check that we allow writing into this object */ + if (i915_gem_object_is_readonly(obj) && write) + return ret; + + err = i915_gem_object_pin_pages(obj); + if (err) + return i915_error_to_vmf_fault(err); + + /* PTEs are revoked in obj->ops->put_pages() */ + for (i = 0; i < size >> PAGE_SHIFT; i++) { + struct page *page = i915_gem_object_get_page(obj, i); + + ret = vmf_insert_pfn(area, + (unsigned long)area->vm_start + i * PAGE_SIZE, + page_to_pfn(page)); + if (ret != VM_FAULT_NOPAGE) + break; + } + + if (write) { + GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); + obj->cache_dirty = true; /* XXX flush after PAT update? */ + obj->mm.dirty = true; + } + + i915_gem_object_unpin_pages(obj); + + return ret; +} + +static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) { #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT) struct vm_area_struct *area = vmf->vma; - struct drm_i915_gem_object *obj = to_intel_bo(area->vm_private_data); + struct i915_mmap_offset *mmo = area->vm_private_data; + struct drm_i915_gem_object *obj = mmo->obj; struct drm_device *dev = obj->base.dev; struct drm_i915_private *i915 = to_i915(dev); struct intel_runtime_pm *rpm = &i915->runtime_pm; @@ -312,6 +371,9 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf) list_add(&obj->userfault_link, &i915->ggtt.userfault_list); mutex_unlock(&i915->ggtt.vm.mutex); + /* Track the mmo associated with the fenced vma */ + vma->mmo = mmo; + if (IS_ACTIVE(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)) intel_wakeref_auto(&i915->ggtt.userfault_wakeref, msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)); @@ -332,67 +394,36 @@ err_rpm: intel_runtime_pm_put(rpm, wakeref); i915_gem_object_unpin_pages(obj); err: - switch (ret) { - default: - WARN_ONCE(ret, "unhandled error in %s: %i\n", __func__, ret); - /* fallthrough */ - case -EIO: /* shmemfs failure from swap device */ - case -EFAULT: /* purged object */ - case -ENODEV: /* bad object, how did you get here! */ - return VM_FAULT_SIGBUS; - - case -ENOSPC: /* shmemfs allocation failure */ - case -ENOMEM: /* our allocation failure */ - return VM_FAULT_OOM; - - case 0: - case -EAGAIN: - case -ERESTARTSYS: - case -EINTR: - case -EBUSY: - /* - * EBUSY is ok: this just means that another thread - * already did the job. - */ - return VM_FAULT_NOPAGE; - } + return i915_error_to_vmf_fault(ret); } -void __i915_gem_object_release_mmap(struct drm_i915_gem_object *obj) +void __i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj) { struct i915_vma *vma; GEM_BUG_ON(!obj->userfault_count); - obj->userfault_count = 0; - list_del(&obj->userfault_link); - drm_vma_node_unmap(&obj->base.vma_node, - obj->base.dev->anon_inode->i_mapping); - for_each_ggtt_vma(vma, obj) - i915_vma_unset_userfault(vma); + i915_vma_revoke_mmap(vma); + + GEM_BUG_ON(obj->userfault_count); } -/** - * i915_gem_object_release_mmap - remove physical page mappings - * @obj: obj in question - * - * Preserve the reservation of the mmapping with the DRM core code, but - * relinquish ownership of the pages back to the system. - * +/* * It is vital that we remove the page mapping if we have mapped a tiled * object through the GTT and then lose the fence register due to * resource pressure. Similarly if the object has been moved out of the * aperture, than pages mapped into userspace must be revoked. Removing the * mapping will then trigger a page fault on the next user access, allowing - * fixup by i915_gem_fault(). + * fixup by vm_fault_gtt(). */ -void i915_gem_object_release_mmap(struct drm_i915_gem_object *obj) +static void i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = to_i915(obj->base.dev); intel_wakeref_t wakeref; - /* Serialisation between user GTT access and our code depends upon + /* + * Serialisation between user GTT access and our code depends upon * revoking the CPU's PTE whilst the mutex is held. The next user * pagefault then has to wait until we release the mutex. * @@ -406,9 +437,10 @@ void i915_gem_object_release_mmap(struct drm_i915_gem_object *obj) if (!obj->userfault_count) goto out; - __i915_gem_object_release_mmap(obj); + __i915_gem_object_release_mmap_gtt(obj); - /* Ensure that the CPU's PTE are revoked and there are not outstanding + /* + * Ensure that the CPU's PTE are revoked and there are not outstanding * memory transactions from userspace before we return. The TLB * flushing implied above by changing the PTE above *should* be * sufficient, an extra barrier here just provides us with a bit @@ -422,57 +454,149 @@ out: intel_runtime_pm_put(&i915->runtime_pm, wakeref); } -static int create_mmap_offset(struct drm_i915_gem_object *obj) +void i915_gem_object_release_mmap_offset(struct drm_i915_gem_object *obj) +{ + struct i915_mmap_offset *mmo; + + spin_lock(&obj->mmo.lock); + list_for_each_entry(mmo, &obj->mmo.offsets, offset) { + /* + * vma_node_unmap for GTT mmaps handled already in + * __i915_gem_object_release_mmap_gtt + */ + if (mmo->mmap_type == I915_MMAP_TYPE_GTT) + continue; + + spin_unlock(&obj->mmo.lock); + drm_vma_node_unmap(&mmo->vma_node, + obj->base.dev->anon_inode->i_mapping); + spin_lock(&obj->mmo.lock); + } + spin_unlock(&obj->mmo.lock); +} + +/** + * i915_gem_object_release_mmap - remove physical page mappings + * @obj: obj in question + * + * Preserve the reservation of the mmapping with the DRM core code, but + * relinquish ownership of the pages back to the system. + */ +void i915_gem_object_release_mmap(struct drm_i915_gem_object *obj) +{ + i915_gem_object_release_mmap_gtt(obj); + i915_gem_object_release_mmap_offset(obj); +} + +static struct i915_mmap_offset * +mmap_offset_attach(struct drm_i915_gem_object *obj, + enum i915_mmap_type mmap_type, + struct drm_file *file) { struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct intel_gt *gt = &i915->gt; + struct i915_mmap_offset *mmo; int err; - err = drm_gem_create_mmap_offset(&obj->base); + mmo = kmalloc(sizeof(*mmo), GFP_KERNEL); + if (!mmo) + return ERR_PTR(-ENOMEM); + + mmo->obj = obj; + mmo->dev = obj->base.dev; + mmo->file = file; + mmo->mmap_type = mmap_type; + drm_vma_node_reset(&mmo->vma_node); + + err = drm_vma_offset_add(mmo->dev->vma_offset_manager, &mmo->vma_node, + obj->base.size / PAGE_SIZE); if (likely(!err)) - return 0; + goto out; /* Attempt to reap some mmap space from dead objects */ - err = intel_gt_retire_requests_timeout(gt, MAX_SCHEDULE_TIMEOUT); + err = intel_gt_retire_requests_timeout(&i915->gt, MAX_SCHEDULE_TIMEOUT); if (err) - return err; + goto err; i915_gem_drain_freed_objects(i915); - return drm_gem_create_mmap_offset(&obj->base); + err = drm_vma_offset_add(mmo->dev->vma_offset_manager, &mmo->vma_node, + obj->base.size / PAGE_SIZE); + if (err) + goto err; + +out: + if (file) + drm_vma_node_allow(&mmo->vma_node, file); + + spin_lock(&obj->mmo.lock); + list_add(&mmo->offset, &obj->mmo.offsets); + spin_unlock(&obj->mmo.lock); + + return mmo; + +err: + kfree(mmo); + return ERR_PTR(err); } -int -i915_gem_mmap_gtt(struct drm_file *file, - struct drm_device *dev, - u32 handle, - u64 *offset) +static int +__assign_mmap_offset(struct drm_file *file, + u32 handle, + enum i915_mmap_type mmap_type, + u64 *offset) { struct drm_i915_gem_object *obj; - int ret; - - if (!i915_ggtt_has_aperture(&to_i915(dev)->ggtt)) - return -ENODEV; + struct i915_mmap_offset *mmo; + int err; obj = i915_gem_object_lookup(file, handle); if (!obj) return -ENOENT; - if (i915_gem_object_never_bind_ggtt(obj)) { - ret = -ENODEV; + if (mmap_type == I915_MMAP_TYPE_GTT && + i915_gem_object_never_bind_ggtt(obj)) { + err = -ENODEV; goto out; } - ret = create_mmap_offset(obj); - if (ret == 0) - *offset = drm_vma_node_offset_addr(&obj->base.vma_node); + if (mmap_type != I915_MMAP_TYPE_GTT && + !i915_gem_object_has_struct_page(obj)) { + err = -ENODEV; + goto out; + } + + mmo = mmap_offset_attach(obj, mmap_type, file); + if (IS_ERR(mmo)) { + err = PTR_ERR(mmo); + goto out; + } + *offset = drm_vma_node_offset_addr(&mmo->vma_node); + err = 0; out: i915_gem_object_put(obj); - return ret; + return err; +} + +int +i915_gem_dumb_mmap_offset(struct drm_file *file, + struct drm_device *dev, + u32 handle, + u64 *offset) +{ + enum i915_mmap_type mmap_type; + + if (boot_cpu_has(X86_FEATURE_PAT)) + mmap_type = I915_MMAP_TYPE_WC; + else if (!i915_ggtt_has_aperture(&to_i915(dev)->ggtt)) + return -ENODEV; + else + mmap_type = I915_MMAP_TYPE_GTT; + + return __assign_mmap_offset(file, handle, mmap_type, offset); } /** - * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing + * i915_gem_mmap_offset_ioctl - prepare an object for GTT mmap'ing * @dev: DRM device * @data: GTT mapping ioctl data * @file: GEM object info @@ -487,12 +611,167 @@ out: * userspace. */ int -i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) +i915_gem_mmap_offset_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { - struct drm_i915_gem_mmap_gtt *args = data; + struct drm_i915_private *i915 = to_i915(dev); + struct drm_i915_gem_mmap_offset *args = data; + enum i915_mmap_type type; + + if (args->extensions) + return -EINVAL; + + switch (args->flags) { + case I915_MMAP_OFFSET_GTT: + if (!i915_ggtt_has_aperture(&i915->ggtt)) + return -ENODEV; + type = I915_MMAP_TYPE_GTT; + break; + + case I915_MMAP_OFFSET_WC: + if (!boot_cpu_has(X86_FEATURE_PAT)) + return -ENODEV; + type = I915_MMAP_TYPE_WC; + break; + + case I915_MMAP_OFFSET_WB: + type = I915_MMAP_TYPE_WB; + break; + + case I915_MMAP_OFFSET_UC: + if (!boot_cpu_has(X86_FEATURE_PAT)) + return -ENODEV; + type = I915_MMAP_TYPE_UC; + break; + + default: + return -EINVAL; + } - return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset); + return __assign_mmap_offset(file, args->handle, type, &args->offset); +} + +static void vm_open(struct vm_area_struct *vma) +{ + struct i915_mmap_offset *mmo = vma->vm_private_data; + struct drm_i915_gem_object *obj = mmo->obj; + + GEM_BUG_ON(!obj); + i915_gem_object_get(obj); +} + +static void vm_close(struct vm_area_struct *vma) +{ + struct i915_mmap_offset *mmo = vma->vm_private_data; + struct drm_i915_gem_object *obj = mmo->obj; + + GEM_BUG_ON(!obj); + i915_gem_object_put(obj); +} + +static const struct vm_operations_struct vm_ops_gtt = { + .fault = vm_fault_gtt, + .open = vm_open, + .close = vm_close, +}; + +static const struct vm_operations_struct vm_ops_cpu = { + .fault = vm_fault_cpu, + .open = vm_open, + .close = vm_close, +}; + +/* + * This overcomes the limitation in drm_gem_mmap's assignment of a + * drm_gem_object as the vma->vm_private_data. Since we need to + * be able to resolve multiple mmap offsets which could be tied + * to a single gem object. + */ +int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_vma_offset_node *node; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->minor->dev; + struct i915_mmap_offset *mmo = NULL; + struct drm_gem_object *obj = NULL; + + if (drm_dev_is_unplugged(dev)) + return -ENODEV; + + drm_vma_offset_lock_lookup(dev->vma_offset_manager); + node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, + vma->vm_pgoff, + vma_pages(vma)); + if (likely(node)) { + mmo = container_of(node, struct i915_mmap_offset, + vma_node); + /* + * In our dependency chain, the drm_vma_offset_node + * depends on the validity of the mmo, which depends on + * the gem object. However the only reference we have + * at this point is the mmo (as the parent of the node). + * Try to check if the gem object was at least cleared. + */ + if (!mmo || !mmo->obj) { + drm_vma_offset_unlock_lookup(dev->vma_offset_manager); + return -EINVAL; + } + /* + * Skip 0-refcnted objects as it is in the process of being + * destroyed and will be invalid when the vma manager lock + * is released. + */ + obj = &mmo->obj->base; + if (!kref_get_unless_zero(&obj->refcount)) + obj = NULL; + } + drm_vma_offset_unlock_lookup(dev->vma_offset_manager); + if (!obj) + return -EINVAL; + + if (!drm_vma_node_is_allowed(node, priv)) { + drm_gem_object_put_unlocked(obj); + return -EACCES; + } + + if (i915_gem_object_is_readonly(to_intel_bo(obj))) { + if (vma->vm_flags & VM_WRITE) { + drm_gem_object_put_unlocked(obj); + return -EINVAL; + } + vma->vm_flags &= ~VM_MAYWRITE; + } + + vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_private_data = mmo; + + switch (mmo->mmap_type) { + case I915_MMAP_TYPE_WC: + vma->vm_page_prot = + pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + vma->vm_ops = &vm_ops_cpu; + break; + + case I915_MMAP_TYPE_WB: + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + vma->vm_ops = &vm_ops_cpu; + break; + + case I915_MMAP_TYPE_UC: + vma->vm_page_prot = + pgprot_noncached(vm_get_page_prot(vma->vm_flags)); + vma->vm_ops = &vm_ops_cpu; + break; + + case I915_MMAP_TYPE_GTT: + vma->vm_page_prot = + pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + vma->vm_ops = &vm_ops_gtt; + break; + } + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); + + return 0; } #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.h b/drivers/gpu/drm/i915/gem/i915_gem_mman.h new file mode 100644 index 000000000000..862e01b7cb69 --- /dev/null +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.h @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2019 Intel Corporation + */ + +#ifndef __I915_GEM_MMAN_H__ +#define __I915_GEM_MMAN_H__ + +#include +#include + +struct drm_device; +struct drm_file; +struct drm_i915_gem_object; +struct file; +struct i915_mmap_offset; +struct mutex; + +int i915_gem_mmap_gtt_version(void); +int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma); + +int i915_gem_dumb_mmap_offset(struct drm_file *file_priv, + struct drm_device *dev, + u32 handle, u64 *offset); + +void __i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj); +void i915_gem_object_release_mmap(struct drm_i915_gem_object *obj); +void i915_gem_object_release_mmap_offset(struct drm_i915_gem_object *obj); + +#endif diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 458945e1823e..16d611db9ca6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -29,6 +29,7 @@ #include "i915_drv.h" #include "i915_gem_clflush.h" #include "i915_gem_context.h" +#include "i915_gem_mman.h" #include "i915_gem_object.h" #include "i915_globals.h" #include "i915_trace.h" @@ -61,6 +62,9 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, INIT_LIST_HEAD(&obj->lut_list); + spin_lock_init(&obj->mmo.lock); + INIT_LIST_HEAD(&obj->mmo.offsets); + init_rcu_head(&obj->rcu); obj->ops = ops; @@ -97,6 +101,7 @@ void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file) struct drm_i915_gem_object *obj = to_intel_bo(gem); struct drm_i915_file_private *fpriv = file->driver_priv; struct i915_lut_handle *lut, *ln; + struct i915_mmap_offset *mmo; LIST_HEAD(close); i915_gem_object_lock(obj); @@ -111,6 +116,17 @@ void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file) } i915_gem_object_unlock(obj); + spin_lock(&obj->mmo.lock); + list_for_each_entry(mmo, &obj->mmo.offsets, offset) { + if (mmo->file != file) + continue; + + spin_unlock(&obj->mmo.lock); + drm_vma_node_revoke(&mmo->vma_node, file); + spin_lock(&obj->mmo.lock); + } + spin_unlock(&obj->mmo.lock); + list_for_each_entry_safe(lut, ln, &close, obj_link) { struct i915_gem_context *ctx = lut->ctx; struct i915_vma *vma; @@ -158,6 +174,8 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, wakeref = intel_runtime_pm_get(&i915->runtime_pm); llist_for_each_entry_safe(obj, on, freed, freed) { + struct i915_mmap_offset *mmo, *mn; + trace_i915_gem_object_destroy(obj); if (!list_empty(&obj->vma.list)) { @@ -183,6 +201,15 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, spin_unlock(&obj->vma.lock); } + i915_gem_object_release_mmap(obj); + + list_for_each_entry_safe(mmo, mn, &obj->mmo.offsets, offset) { + drm_vma_offset_remove(obj->base.dev->vma_offset_manager, + &mmo->vma_node); + kfree(mmo); + } + INIT_LIST_HEAD(&obj->mmo.offsets); + GEM_BUG_ON(atomic_read(&obj->bind_count)); GEM_BUG_ON(obj->userfault_count); GEM_BUG_ON(!list_empty(&obj->lut_list)); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index e5750d506cc9..a1eb7c0b23ac 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -132,13 +132,13 @@ void i915_gem_object_unlock_fence(struct drm_i915_gem_object *obj, static inline void i915_gem_object_set_readonly(struct drm_i915_gem_object *obj) { - obj->base.vma_node.readonly = true; + obj->flags |= I915_BO_READONLY; } static inline bool i915_gem_object_is_readonly(const struct drm_i915_gem_object *obj) { - return obj->base.vma_node.readonly; + return obj->flags & I915_BO_READONLY; } static inline bool @@ -387,9 +387,6 @@ static inline void i915_gem_object_unpin_map(struct drm_i915_gem_object *obj) i915_gem_object_unpin_pages(obj); } -void __i915_gem_object_release_mmap(struct drm_i915_gem_object *obj); -void i915_gem_object_release_mmap(struct drm_i915_gem_object *obj); - void i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 15f8297dc34e..2d404e6f63df 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -63,6 +63,23 @@ struct drm_i915_gem_object_ops { void (*release)(struct drm_i915_gem_object *obj); }; +enum i915_mmap_type { + I915_MMAP_TYPE_GTT = 0, + I915_MMAP_TYPE_WC, + I915_MMAP_TYPE_WB, + I915_MMAP_TYPE_UC, +}; + +struct i915_mmap_offset { + struct drm_device *dev; + struct drm_vma_offset_node vma_node; + struct drm_i915_gem_object *obj; + struct drm_file *file; + enum i915_mmap_type mmap_type; + + struct list_head offset; +}; + struct drm_i915_gem_object { struct drm_gem_object base; @@ -118,12 +135,18 @@ struct drm_i915_gem_object { unsigned int userfault_count; struct list_head userfault_link; + struct { + spinlock_t lock; /* Protects access to mmo offsets */ + struct list_head offsets; + } mmo; + I915_SELFTEST_DECLARE(struct list_head st_link); unsigned long flags; #define I915_BO_ALLOC_CONTIGUOUS BIT(0) #define I915_BO_ALLOC_VOLATILE BIT(1) #define I915_BO_ALLOC_FLAGS (I915_BO_ALLOC_CONTIGUOUS | I915_BO_ALLOC_VOLATILE) +#define I915_BO_READONLY BIT(2) /* * Is the object to be mapped as read-only to the GPU diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index f402c2c415c2..75197ca696a8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -8,6 +8,7 @@ #include "i915_gem_object.h" #include "i915_scatterlist.h" #include "i915_gem_lmem.h" +#include "i915_gem_mman.h" void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, struct sg_table *pages, @@ -207,6 +208,8 @@ int __i915_gem_object_put_pages(struct drm_i915_gem_object *obj) goto unlock; } + i915_gem_object_release_mmap_offset(obj); + /* * ->put_pages might need to allocate memory for the bit17 swizzle * array, hence protect them from being reaped by removing them from gtt diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c index 1fa592d82af5..6c7825a2dc2a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c @@ -11,6 +11,7 @@ #include "i915_drv.h" #include "i915_gem.h" #include "i915_gem_ioctls.h" +#include "i915_gem_mman.h" #include "i915_gem_object.h" /** diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 6ce9167f8c9f..591435c5f368 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -565,16 +565,16 @@ static bool assert_mmap_offset(struct drm_i915_private *i915, int expected) { struct drm_i915_gem_object *obj; - int err; + struct i915_mmap_offset *mmo; obj = i915_gem_object_create_internal(i915, size); if (IS_ERR(obj)) return PTR_ERR(obj); - err = create_mmap_offset(obj); + mmo = mmap_offset_attach(obj, I915_MMAP_OFFSET_GTT, NULL); i915_gem_object_put(obj); - return err == expected; + return PTR_ERR_OR_ZERO(mmo) == expected; } static void disable_retire_worker(struct drm_i915_private *i915) @@ -609,7 +609,8 @@ static int igt_mmap_offset_exhaustion(void *arg) struct drm_mm *mm = &i915->drm.vma_offset_manager->vm_addr_space_mm; struct drm_i915_gem_object *obj; struct drm_mm_node *hole, *next; - int loop, err; + struct i915_mmap_offset *mmo; + int loop, err = 0; /* Disable background reaper */ disable_retire_worker(i915); @@ -673,9 +674,10 @@ static int igt_mmap_offset_exhaustion(void *arg) goto out; } - err = create_mmap_offset(obj); - if (err) { + mmo = mmap_offset_attach(obj, I915_MMAP_OFFSET_GTT, NULL); + if (IS_ERR(mmo)) { pr_err("Unable to insert object into reclaimed hole\n"); + err = PTR_ERR(mmo); goto err_obj; } @@ -724,14 +726,15 @@ err_obj: } #define expand32(x) (((x) << 0) | ((x) << 8) | ((x) << 16) | ((x) << 24)) -static int igt_mmap_gtt(void *arg) +static int igt_mmap(void *arg, enum i915_mmap_type type) { struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; + struct i915_mmap_offset *mmo; struct vm_area_struct *area; unsigned long addr; void *vaddr; - int err, i; + int err = 0, i; if (!i915_ggtt_has_aperture(&i915->ggtt)) return 0; @@ -749,18 +752,19 @@ static int igt_mmap_gtt(void *arg) i915_gem_object_flush_map(obj); i915_gem_object_unpin_map(obj); - err = create_mmap_offset(obj); - if (err) + mmo = mmap_offset_attach(obj, type, NULL); + if (IS_ERR(mmo)) { + err = PTR_ERR(mmo); goto out; + } - addr = igt_mmap_node(i915, &obj->base.vma_node, - 0, PROT_WRITE, MAP_SHARED); + addr = igt_mmap_node(i915, &mmo->vma_node, 0, PROT_WRITE, MAP_SHARED); if (IS_ERR_VALUE(addr)) { err = addr; goto out; } - pr_debug("igt_mmap(obj:gtt) @ %lx\n", addr); + pr_debug("igt_mmap() @ %lx\n", addr); area = find_vma(current->mm, addr); if (!area) { @@ -769,8 +773,8 @@ static int igt_mmap_gtt(void *arg) goto out_unmap; } - if (area->vm_private_data != obj) { - pr_err("vm_area_struct did not point back to our object!\n"); + if (area->vm_private_data != mmo) { + pr_err("vm_area_struct did not point back to our mmap_offset object!\n"); err = -EINVAL; goto out_unmap; } @@ -780,14 +784,14 @@ static int igt_mmap_gtt(void *arg) u32 x; if (get_user(x, ux)) { - pr_err("Unable to read from GTT mmap, offset:%zd\n", + pr_err("Unable to read from mmap, offset:%zd\n", i * sizeof(x)); err = -EFAULT; break; } if (x != expand32(POISON_INUSE)) { - pr_err("Read incorrect value from GTT mmap, offset:%zd, found:%x, expected:%x\n", + pr_err("Read incorrect value from mmap, offset:%zd, found:%x, expected:%x\n", i * sizeof(x), x, expand32(POISON_INUSE)); err = -EINVAL; break; @@ -795,7 +799,7 @@ static int igt_mmap_gtt(void *arg) x = expand32(POISON_FREE); if (put_user(x, ux)) { - pr_err("Unable to write to GTT mmap, offset:%zd\n", + pr_err("Unable to write to mmap, offset:%zd\n", i * sizeof(x)); err = -EFAULT; break; @@ -811,7 +815,7 @@ out_unmap: goto out; } if (err == 0 && memchr_inv(vaddr, POISON_FREE, PAGE_SIZE)) { - pr_err("Write via GGTT mmap did not land in backing store\n"); + pr_err("Write via mmap did not land in backing store\n"); err = -EINVAL; } i915_gem_object_unpin_map(obj); @@ -821,6 +825,16 @@ out: return err; } +static int igt_mmap_gtt(void *arg) +{ + return igt_mmap(arg, I915_MMAP_TYPE_GTT); +} + +static int igt_mmap_cpu(void *arg) +{ + return igt_mmap(arg, I915_MMAP_TYPE_WC); +} + static int check_present_pte(pte_t *pte, unsigned long addr, void *data) { if (!pte_present(*pte) || pte_none(*pte)) { @@ -873,10 +887,11 @@ static int prefault_range(u64 start, u64 len) return __get_user(c, end - 1); } -static int igt_mmap_gtt_revoke(void *arg) +static int igt_mmap_revoke(void *arg, enum i915_mmap_type type) { struct drm_i915_private *i915 = arg; struct drm_i915_gem_object *obj; + struct i915_mmap_offset *mmo; unsigned long addr; int err; @@ -887,12 +902,13 @@ static int igt_mmap_gtt_revoke(void *arg) if (IS_ERR(obj)) return PTR_ERR(obj); - err = create_mmap_offset(obj); - if (err) + mmo = mmap_offset_attach(obj, type, NULL); + if (IS_ERR(mmo)) { + err = PTR_ERR(mmo); goto out; + } - addr = igt_mmap_node(i915, &obj->base.vma_node, - 0, PROT_WRITE, MAP_SHARED); + addr = igt_mmap_node(i915, &mmo->vma_node, 0, PROT_WRITE, MAP_SHARED); if (IS_ERR_VALUE(addr)) { err = addr; goto out; @@ -902,7 +918,8 @@ static int igt_mmap_gtt_revoke(void *arg) if (err) goto out_unmap; - GEM_BUG_ON(!atomic_read(&obj->bind_count)); + GEM_BUG_ON(mmo->mmap_type == I915_MMAP_TYPE_GTT && + !atomic_read(&obj->bind_count)); err = check_present(addr, obj->base.size); if (err) @@ -920,6 +937,15 @@ static int igt_mmap_gtt_revoke(void *arg) } GEM_BUG_ON(atomic_read(&obj->bind_count)); + if (type != I915_MMAP_TYPE_GTT) { + __i915_gem_object_put_pages(obj); + if (i915_gem_object_has_pages(obj)) { + pr_err("Failed to put-pages object!\n"); + err = -EINVAL; + goto out_unmap; + } + } + err = check_absent(addr, obj->base.size); if (err) goto out_unmap; @@ -931,6 +957,16 @@ out: return err; } +static int igt_mmap_gtt_revoke(void *arg) +{ + return igt_mmap_revoke(arg, I915_MMAP_TYPE_GTT); +} + +static int igt_mmap_cpu_revoke(void *arg) +{ + return igt_mmap_revoke(arg, I915_MMAP_TYPE_WC); +} + int i915_gem_mman_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { @@ -938,7 +974,9 @@ int i915_gem_mman_live_selftests(struct drm_i915_private *i915) SUBTEST(igt_smoke_tiling), SUBTEST(igt_mmap_offset_exhaustion), SUBTEST(igt_mmap_gtt), + SUBTEST(igt_mmap_cpu), SUBTEST(igt_mmap_gtt_revoke), + SUBTEST(igt_mmap_cpu_revoke), }; return i915_subtests(tests, i915); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 36189238e13c..0e94b720c993 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -678,8 +678,13 @@ static void revoke_mmaps(struct intel_gt *gt) continue; GEM_BUG_ON(vma->fence != >->ggtt->fence_regs[i]); - node = &vma->obj->base.vma_node; + + if (!vma->mmo) + continue; + + node = &vma->mmo->vma_node; vma_offset = vma->ggtt_view.partial.offset << PAGE_SHIFT; + unmap_mapping_range(gt->i915->drm.anon_inode->i_mapping, drm_vma_node_offset_addr(node) + vma_offset, vma->size, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 018914ba2005..5d7e11927729 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -61,6 +61,7 @@ #include "gem/i915_gem_context.h" #include "gem/i915_gem_ioctls.h" +#include "gem/i915_gem_mman.h" #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" #include "gt/intel_rc6.h" @@ -2660,18 +2661,12 @@ const struct dev_pm_ops i915_pm_ops = { .runtime_resume = intel_runtime_resume, }; -static const struct vm_operations_struct i915_gem_vm_ops = { - .fault = i915_gem_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - static const struct file_operations i915_driver_fops = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, - .mmap = drm_gem_mmap, + .mmap = i915_gem_mmap, .poll = drm_poll, .read = drm_read, .compat_ioctl = i915_compat_ioctl, @@ -2718,7 +2713,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_OFFSET, i915_gem_mmap_offset_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling_ioctl, DRM_RENDER_ALLOW), @@ -2760,7 +2755,6 @@ static struct drm_driver driver = { .gem_close_object = i915_gem_close_object, .gem_free_object_unlocked = i915_gem_free_object, - .gem_vm_ops = &i915_gem_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, @@ -2771,7 +2765,8 @@ static struct drm_driver driver = { .get_scanout_position = i915_get_crtc_scanoutpos, .dumb_create = i915_gem_dumb_create, - .dumb_map_offset = i915_gem_mmap_gtt, + .dumb_map_offset = i915_gem_dumb_mmap_offset, + .ioctls = i915_ioctls, .num_ioctls = ARRAY_SIZE(i915_ioctls), .fops = &i915_driver_fops, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 14744c114475..0d4ad18e10dd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1857,9 +1857,6 @@ i915_mutex_lock_interruptible(struct drm_device *dev) int i915_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args); -int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev, - u32 handle, u64 *offset); -int i915_gem_mmap_gtt_version(void); int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno); @@ -1882,7 +1879,6 @@ void i915_gem_driver_release(struct drm_i915_private *dev_priv); void i915_gem_suspend(struct drm_i915_private *dev_priv); void i915_gem_suspend_late(struct drm_i915_private *dev_priv); void i915_gem_resume(struct drm_i915_private *dev_priv); -vm_fault_t i915_gem_fault(struct vm_fault *vmf); int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file); void i915_gem_release(struct drm_device *dev, struct drm_file *file); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index eb9e2609c569..07b7a8a671d0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -44,6 +44,7 @@ #include "gem/i915_gem_clflush.h" #include "gem/i915_gem_context.h" #include "gem/i915_gem_ioctls.h" +#include "gem/i915_gem_mman.h" #include "gem/i915_gem_pm.h" #include "gt/intel_context.h" #include "gt/intel_engine_user.h" @@ -885,7 +886,7 @@ void i915_gem_runtime_suspend(struct drm_i915_private *i915) list_for_each_entry_safe(obj, on, &i915->ggtt.userfault_list, userfault_link) - __i915_gem_object_release_mmap(obj); + __i915_gem_object_release_mmap_gtt(obj); /* * The fence will be lost when the device powers down. If any were diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c index cf8a8c3ef047..54fce81d5724 100644 --- a/drivers/gpu/drm/i915/i915_getparam.c +++ b/drivers/gpu/drm/i915/i915_getparam.c @@ -2,6 +2,7 @@ * SPDX-License-Identifier: MIT */ +#include "gem/i915_gem_mman.h" #include "gt/intel_engine_user.h" #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index e5512f26e20a..564fa97558c5 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1054,17 +1054,16 @@ static void __i915_vma_iounmap(struct i915_vma *vma) void i915_vma_revoke_mmap(struct i915_vma *vma) { - struct drm_vma_offset_node *node = &vma->obj->base.vma_node; + struct drm_vma_offset_node *node; u64 vma_offset; - lockdep_assert_held(&vma->vm->mutex); - if (!i915_vma_has_userfault(vma)) return; GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma)); GEM_BUG_ON(!vma->obj->userfault_count); + node = &vma->mmo->vma_node; vma_offset = vma->ggtt_view.partial.offset << PAGE_SHIFT; unmap_mapping_range(vma->vm->i915->drm.anon_inode->i_mapping, drm_vma_node_offset_addr(node) + vma_offset, diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 465932813bc5..f09f4f513c41 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -63,6 +63,9 @@ struct i915_vma { u64 display_alignment; struct i915_page_sizes page_sizes; + /* mmap-offset associated with fencing for this vma */ + struct i915_mmap_offset *mmo; + u32 fence_size; u32 fence_alignment; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 5400d7e057f1..829c0a48577f 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -395,6 +395,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) #define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) +#define DRM_IOCTL_I915_GEM_MMAP_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_offset) #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) @@ -793,6 +794,37 @@ struct drm_i915_gem_mmap_gtt { __u64 offset; }; +struct drm_i915_gem_mmap_offset { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; + + /** + * Flags for extended behaviour. + * + * It is mandatory that one of the MMAP_OFFSET types + * (GTT, WC, WB, UC, etc) should be included. + */ + __u64 flags; +#define I915_MMAP_OFFSET_GTT 0 +#define I915_MMAP_OFFSET_WC 1 +#define I915_MMAP_OFFSET_WB 2 +#define I915_MMAP_OFFSET_UC 3 + + /* + * Zero-terminated chain of extensions. + * + * No current extensions defined; mbz. + */ + __u64 extensions; +}; + struct drm_i915_gem_set_domain { /** Handle for the object */ __u32 handle; -- cgit v1.2.3 From aa5e4453dc055e188c792c3e5f1b256436332a59 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2019 12:35:56 +0000 Subject: drm/i915/gem: Try to flush pending unbind events If we cannot handle a vma within the unbind loop, try to flush the pending events (i915_vma_parked, i915_vm_release) and try again. This avoids a round trip to userspace that is not guaranteed to make forward progress, as the events we wait upon require being idle. References: cb6c3d45f948 ("drm/i915/gem: Avoid parking the vma as we unbind") Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191204123556.3740002-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 07b7a8a671d0..cc8c6960b689 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -124,7 +124,7 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj, LIST_HEAD(still_in_list); intel_wakeref_t wakeref; struct i915_vma *vma; - int ret = 0; + int ret; if (!atomic_read(&obj->bind_count)) return 0; @@ -137,6 +137,8 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj, */ wakeref = intel_runtime_pm_get(rpm); +try_again: + ret = 0; spin_lock(&obj->vma.lock); while (!ret && (vma = list_first_entry_or_null(&obj->vma.list, struct i915_vma, @@ -154,6 +156,7 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj, } else { if (i915_vma_is_closed(vma)) { spin_unlock(&obj->vma.lock); + i915_vma_parked(vm->gt); goto err_vm; } } @@ -175,6 +178,11 @@ err_vm: list_splice(&still_in_list, &obj->vma.list); spin_unlock(&obj->vma.lock); + if (ret == -EAGAIN && flags & I915_GEM_OBJECT_UNBIND_ACTIVE) { + rcu_barrier(); /* flush the i915_vm_release() */ + goto try_again; + } + intel_runtime_pm_put(rpm, wakeref); return ret; -- cgit v1.2.3 From 780ccb5a5a43a7787b7cbdc49f7660232fd26aaf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2019 16:45:27 +0000 Subject: drm/i915/gem: Hold the obj->vma.lock while walking the vma.list Remember to take the lock before walking the obj->vma.list so that the nodes do not change beneath us! E.g., i915_gem_object_bump_inactive_ggtt:387 GEM_BUG_ON(vma->vm != &i915->ggtt.vm) Closes: https://gitlab.freedesktop.org/drm/intel/issues/691 Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191204164527.3872783-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index f2064950622b..808eb327a29b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -379,8 +379,11 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj) struct i915_vma *vma; GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); + if (!atomic_read(&obj->bind_count)) + return; mutex_lock(&i915->ggtt.vm.mutex); + spin_lock(&obj->vma.lock); for_each_ggtt_vma(vma, obj) { if (!drm_mm_node_allocated(&vma->node)) continue; @@ -388,6 +391,7 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj) GEM_BUG_ON(vma->vm != &i915->ggtt.vm); list_move_tail(&vma->vm_link, &vma->vm->bound_list); } + spin_unlock(&obj->vma.lock); mutex_unlock(&i915->ggtt.vm.mutex); if (i915_gem_object_is_shrinkable(obj)) { -- cgit v1.2.3 From 126d5de38542d47d5d8385ce374e33c2a7f34e51 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2019 18:06:28 +0000 Subject: drm/i915/gem: Hook user-extensions upto MMAP_OFFSET_IOCTL Call i915_user_extensions() to validate the arg->extensions pointer, and so return consistent error numbers for the future. Signed-off-by: Chris Wilson Cc: Abdiel Janulgue Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191204162803.3841140-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 37aabbfa869a..3a3f30bc8ac7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -17,6 +17,7 @@ #include "i915_gem_object.h" #include "i915_gem_mman.h" #include "i915_trace.h" +#include "i915_user_extensions.h" #include "i915_vma.h" static inline bool @@ -617,9 +618,12 @@ i915_gem_mmap_offset_ioctl(struct drm_device *dev, void *data, struct drm_i915_private *i915 = to_i915(dev); struct drm_i915_gem_mmap_offset *args = data; enum i915_mmap_type type; + int err; - if (args->extensions) - return -EINVAL; + err = i915_user_extensions(u64_to_user_ptr(args->extensions), + NULL, 0, NULL); + if (err) + return err; switch (args->flags) { case I915_MMAP_OFFSET_GTT: -- cgit v1.2.3 From 05975cd9eb8422d11fdcb29b065e5e942ec6b62c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2019 23:26:16 +0000 Subject: drm/i915: Remove vestigal i915_gem_context locals from cmdparser The use GEM context itself was removed in commit cd30a5031704 ("drm/i915/gem: Excise the per-batch whitelist from the context"), but the locals were left in place as an oversight. Remove the parameters and clean up. References: cd30a5031704 ("drm/i915/gem: Excise the per-batch whitelist from the context") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191204232616.94397-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 3 +-- drivers/gpu/drm/i915/i915_cmd_parser.c | 11 ++++------- drivers/gpu/drm/i915/i915_drv.h | 3 +-- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 459f4d40b69b..34044c6203a5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2022,8 +2022,7 @@ static struct i915_vma *eb_parse(struct i915_execbuffer *eb) shadow_batch_start = gen8_canonical_addr(vma->node.start); - err = intel_engine_cmd_parser(eb->gem_context, - eb->engine, + err = intel_engine_cmd_parser(eb->engine, eb->batch->obj, batch_start, eb->batch_start_offset, diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 9125e89a9e7f..2ed497e7c9fd 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1306,8 +1306,7 @@ static bool check_cmd(const struct intel_engine_cs *engine, return true; } -static int check_bbstart(const struct i915_gem_context *ctx, - u32 *cmd, u32 offset, u32 length, +static int check_bbstart(u32 *cmd, u32 offset, u32 length, u32 batch_len, u64 batch_start, u64 shadow_batch_start, @@ -1392,7 +1391,6 @@ alloc_whitelist(struct drm_i915_private *i915, u32 batch_len) /** * i915_parse_cmds() - parse a submitted batch buffer for privilege violations - * @ctx: the context in which the batch is to execute * @engine: the engine on which the batch is to execute * @batch_obj: the batch buffer in question * @batch_start: Canonical base address of batch @@ -1408,8 +1406,7 @@ alloc_whitelist(struct drm_i915_private *i915, u32 batch_len) * if the batch appears legal but should use hardware parsing */ -int intel_engine_cmd_parser(struct i915_gem_context *ctx, - struct intel_engine_cs *engine, +int intel_engine_cmd_parser(struct intel_engine_cs *engine, struct drm_i915_gem_object *batch_obj, u64 batch_start, u32 batch_start_offset, @@ -1433,7 +1430,7 @@ int intel_engine_cmd_parser(struct i915_gem_context *ctx, } /* Defer failure until attempted use */ - jump_whitelist = alloc_whitelist(ctx->i915, batch_len); + jump_whitelist = alloc_whitelist(engine->i915, batch_len); /* * We use the batch length as size because the shadow object is as @@ -1475,7 +1472,7 @@ int intel_engine_cmd_parser(struct i915_gem_context *ctx, } if (desc->cmd.value == MI_BATCH_BUFFER_START) { - ret = check_bbstart(ctx, cmd, offset, length, + ret = check_bbstart(cmd, offset, length, batch_len, batch_start, shadow_batch_start, jump_whitelist); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0d4ad18e10dd..c3d8af28bfc1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1947,8 +1947,7 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type); int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv); void intel_engine_init_cmd_parser(struct intel_engine_cs *engine); void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine); -int intel_engine_cmd_parser(struct i915_gem_context *cxt, - struct intel_engine_cs *engine, +int intel_engine_cmd_parser(struct intel_engine_cs *engine, struct drm_i915_gem_object *batch_obj, u64 user_batch_start, u32 batch_start_offset, -- cgit v1.2.3 From a725d711e8d7bb1eb15cd19b5a2386a66f2e2ef5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 11:37:24 +0000 Subject: drm/i915: Ignore most failures during evict-vm Removing all vma from the VM is best effort -- we only remove all those ready to be removed, so forgive and VMA that becomes pinned. While forgiving those that become pinned, also take a second look for any that became unpinned as we waited. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191205113726.413351-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_evict.c | 39 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 7e62c310290f..0697bedebeef 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -359,9 +359,7 @@ int i915_gem_evict_for_node(struct i915_address_space *vm, */ int i915_gem_evict_vm(struct i915_address_space *vm) { - struct list_head eviction_list; - struct i915_vma *vma, *next; - int ret; + int ret = 0; lockdep_assert_held(&vm->mutex); trace_i915_gem_evict_vm(vm); @@ -377,21 +375,30 @@ int i915_gem_evict_vm(struct i915_address_space *vm) return ret; } - INIT_LIST_HEAD(&eviction_list); - list_for_each_entry(vma, &vm->bound_list, vm_link) { - if (i915_vma_is_pinned(vma)) - continue; + do { + struct i915_vma *vma, *vn; + LIST_HEAD(eviction_list); - __i915_vma_pin(vma); - list_add(&vma->evict_link, &eviction_list); - } + list_for_each_entry(vma, &vm->bound_list, vm_link) { + if (i915_vma_is_pinned(vma)) + continue; + + __i915_vma_pin(vma); + list_add(&vma->evict_link, &eviction_list); + } + if (list_empty(&eviction_list)) + break; + + ret = 0; + list_for_each_entry_safe(vma, vn, &eviction_list, evict_link) { + __i915_vma_unpin(vma); + if (ret == 0) + ret = __i915_vma_unbind(vma); + if (ret != -EINTR) /* "Get me out of here!" */ + ret = 0; + } + } while (ret == 0); - ret = 0; - list_for_each_entry_safe(vma, next, &eviction_list, evict_link) { - __i915_vma_unpin(vma); - if (ret == 0) - ret = __i915_vma_unbind(vma); - } return ret; } -- cgit v1.2.3 From ccd2094559d8639f04c6d2e59c3c93a6ae226ec0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 11:37:25 +0000 Subject: drm/i915: Try hard to bind the context It is not acceptable for context pinning to fail with -ENOSPC as we should always be able to make space in the GGTT. The only reason we may fail is that other "temporary" context pins are reserving their space and we need to wait for an available slot. Closes: https://gitlab.freedesktop.org/drm/intel/issues/676 Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191205113726.413351-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_context.c | 7 ++----- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 +--- drivers/gpu/drm/i915/i915_vma.c | 34 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_vma.h | 1 + 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index c5e52ad39463..61c39e943f69 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -113,13 +113,10 @@ void intel_context_unpin(struct intel_context *ce) static int __context_pin_state(struct i915_vma *vma) { - u64 flags; + unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS; int err; - flags = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS; - flags |= PIN_HIGH | PIN_GLOBAL; - - err = i915_vma_pin(vma, 0, 0, flags); + err = i915_ggtt_pin(vma, 0, bias | PIN_HIGH); if (err) return err; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 10b3d6d44045..4da1dfe11007 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1934,9 +1934,7 @@ int gen6_ppgtt_pin(struct i915_ppgtt *base) * size. We allocate at the top of the GTT to avoid fragmentation. */ if (!atomic_read(&ppgtt->pin_count)) { - err = i915_vma_pin(ppgtt->vma, - 0, GEN6_PD_ALIGN, - PIN_GLOBAL | PIN_HIGH); + err = i915_ggtt_pin(ppgtt->vma, GEN6_PD_ALIGN, PIN_HIGH); } if (!err) atomic_inc(&ppgtt->pin_count); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 564fa97558c5..6db35b9dead8 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -28,7 +28,9 @@ #include "display/intel_frontbuffer.h" #include "gt/intel_engine.h" +#include "gt/intel_engine_heartbeat.h" #include "gt/intel_gt.h" +#include "gt/intel_gt_requests.h" #include "i915_drv.h" #include "i915_globals.h" @@ -939,6 +941,38 @@ err_pages: return err; } +static void flush_idle_contexts(struct intel_gt *gt) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + + for_each_engine(engine, gt, id) + intel_engine_flush_barriers(engine); + + intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT); +} + +int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags) +{ + struct i915_address_space *vm = vma->vm; + int err; + + GEM_BUG_ON(!i915_vma_is_ggtt(vma)); + + do { + err = i915_vma_pin(vma, 0, align, flags | PIN_GLOBAL); + if (err != -ENOSPC) + return err; + + /* Unlike i915_vma_pin, we don't take no for an answer! */ + flush_idle_contexts(vm->gt); + if (mutex_lock_interruptible(&vm->mutex) == 0) { + i915_gem_evict_vm(vm); + mutex_unlock(&vm->mutex); + } + } while (1); +} + void i915_vma_close(struct i915_vma *vma) { struct intel_gt *gt = vma->vm->gt; diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index f09f4f513c41..0e0b61c24551 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -352,6 +352,7 @@ static inline void i915_vma_unlock(struct i915_vma *vma) int __must_check i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags); +int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags); static inline int i915_vma_pin_count(const struct i915_vma *vma) { -- cgit v1.2.3 From 0471a44871cf304edbea3efac72e3e0ac8702b16 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 11:37:26 +0000 Subject: drm/i915/gt: Bump the PP_DIR invalidation for Baytrail Invalidate the ring TLB and increase the delay required for Baytrail. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191205113726.413351-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 39 ++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 42e3405b9996..9f27289b7249 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1396,6 +1396,25 @@ static int load_pd_dir(struct i915_request *rq, const struct i915_ppgtt *ppgtt) return 0; } +static int flush_tlb(struct i915_request *rq) +{ + const struct intel_engine_cs * const engine = rq->engine; + u32 *cs; + + cs = intel_ring_begin(rq, 4); + if (IS_ERR(cs)) + return PTR_ERR(cs); + + *cs++ = MI_LOAD_REGISTER_IMM(1); + *cs++ = i915_mmio_reg_offset(RING_INSTPM(engine->mmio_base)); + *cs++ = _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE); + + *cs++ = MI_NOOP; + intel_ring_advance(rq, cs); + + return 0; +} + static inline int mi_set_context(struct i915_request *rq, u32 flags) { struct drm_i915_private *i915 = rq->i915; @@ -1588,16 +1607,28 @@ static int switch_context(struct i915_request *rq) * post-sync op, this extra pass appears vital before a * mm switch! */ - do { - ret = rq->engine->emit_flush(rq, EMIT_FLUSH); - if (ret) - return ret; + ret = rq->engine->emit_flush(rq, EMIT_INVALIDATE); + if (ret) + return ret; + + ret = flush_tlb(rq); + if (ret) + return ret; + do { ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm)); if (ret) return ret; } while (--loops); + ret = flush_tlb(rq); + if (ret) + return ret; + + ret = rq->engine->emit_flush(rq, EMIT_FLUSH); + if (ret) + return ret; + ret = rq->engine->emit_flush(rq, EMIT_INVALIDATE); if (ret) return ret; -- cgit v1.2.3 From 5c4fe63abae8866dda31dd84f1bcc98e1e645734 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 13:29:12 +0000 Subject: drm/i915/gem: Reinitialise the local list before repeating As we may start the loop again, we require our local list of i915_vma we've processed to be reinitialised. Fixes: aa5e4453dc05 ("drm/i915/gem: Try to flush pending unbind events") Closes: https://gitlab.freedesktop.org/drm/intel/issues/731 Signed-off-by: Chris Wilson Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191205132912.606868-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cc8c6960b689..98b65b718e1a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -175,7 +175,7 @@ err_vm: i915_vm_close(vm); spin_lock(&obj->vma.lock); } - list_splice(&still_in_list, &obj->vma.list); + list_splice_init(&still_in_list, &obj->vma.list); spin_unlock(&obj->vma.lock); if (ret == -EAGAIN && flags & I915_GEM_OBJECT_UNBIND_ACTIVE) { -- cgit v1.2.3 From 6f7ac8285371fb0df58aba861eaab387f79ed04d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 14:59:34 +0000 Subject: drm/i915/gt: Save irqstate around virtual_context_destroy As virtual_context_destroy() may be called from a request signal, it may be called from inside an irq-off section, and so we need to do a full save/restore of the irq state rather than blindly re-enable irqs upon unlocking. <4> [110.024262] WARNING: inconsistent lock state <4> [110.024277] 5.4.0-rc8-CI-CI_DRM_7489+ #1 Tainted: G U <4> [110.024292] -------------------------------- <4> [110.024305] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. <4> [110.024323] kworker/0:0/5 [HC0[0]:SC0[0]:HE1:SE1] takes: <4> [110.024338] ffff88826a0c7a18 (&(&rq->lock)->rlock){?.-.}, at: i915_request_retire+0x221/0x930 [i915] <4> [110.024592] {IN-HARDIRQ-W} state was registered at: <4> [110.024612] lock_acquire+0xa7/0x1c0 <4> [110.024627] _raw_spin_lock_irqsave+0x33/0x50 <4> [110.024788] intel_engine_breadcrumbs_irq+0x38c/0x600 [i915] <4> [110.024808] irq_work_run_list+0x49/0x70 <4> [110.024824] irq_work_run+0x26/0x50 <4> [110.024839] smp_irq_work_interrupt+0x44/0x1e0 <4> [110.024855] irq_work_interrupt+0xf/0x20 <4> [110.024871] __do_softirq+0xb7/0x47f <4> [110.024885] irq_exit+0xba/0xc0 <4> [110.024898] do_IRQ+0x83/0x160 <4> [110.024910] ret_from_intr+0x0/0x1d <4> [110.024922] irq event stamp: 172864 <4> [110.024938] hardirqs last enabled at (172863): [] _raw_spin_unlock_irq+0x24/0x50 <4> [110.024963] hardirqs last disabled at (172864): [] _raw_spin_lock_irq+0xa/0x40 <4> [110.024988] softirqs last enabled at (172812): [] __do_softirq+0x385/0x47f <4> [110.025012] softirqs last disabled at (172797): [] irq_exit+0xba/0xc0 <4> [110.025031] other info that might help us debug this: <4> [110.025049] Possible unsafe locking scenario: <4> [110.025065] CPU0 <4> [110.025075] ---- <4> [110.025084] lock(&(&rq->lock)->rlock); <4> [110.025099] <4> [110.025109] lock(&(&rq->lock)->rlock); <4> [110.025124] *** DEADLOCK *** <4> [110.025144] 4 locks held by kworker/0:0/5: <4> [110.025156] #0: ffff88827588f528 ((wq_completion)events){+.+.}, at: process_one_work+0x1de/0x620 <4> [110.025187] #1: ffffc9000006fe78 ((work_completion)(&engine->retire_work)){+.+.}, at: process_one_work+0x1de/0x620 <4> [110.025219] #2: ffff88825605e270 (&kernel#2){+.+.}, at: engine_retire+0x57/0xe0 [i915] <4> [110.025405] #3: ffff88826a0c7a18 (&(&rq->lock)->rlock){?.-.}, at: i915_request_retire+0x221/0x930 [i915] <4> [110.025634] stack backtrace: <4> [110.025653] CPU: 0 PID: 5 Comm: kworker/0:0 Tainted: G U 5.4.0-rc8-CI-CI_DRM_7489+ #1 <4> [110.025675] Hardware name: /NUC7i5BNB, BIOS BNKBL357.86A.0054.2017.1025.1822 10/25/2017 <4> [110.025856] Workqueue: events engine_retire [i915] <4> [110.025872] Call Trace: <4> [110.025891] dump_stack+0x71/0x9b <4> [110.025907] mark_lock+0x49a/0x500 <4> [110.025926] ? print_shortest_lock_dependencies+0x200/0x200 <4> [110.025946] mark_held_locks+0x49/0x70 <4> [110.025962] ? _raw_spin_unlock_irq+0x24/0x50 <4> [110.025978] lockdep_hardirqs_on+0xa2/0x1c0 <4> [110.025995] _raw_spin_unlock_irq+0x24/0x50 <4> [110.026171] virtual_context_destroy+0xc5/0x2e0 [i915] <4> [110.026376] __active_retire+0xb4/0x290 [i915] <4> [110.026396] dma_fence_signal_locked+0x9e/0x1b0 <4> [110.026613] i915_request_retire+0x451/0x930 [i915] <4> [110.026766] retire_requests+0x4d/0x60 [i915] <4> [110.026919] engine_retire+0x63/0xe0 [i915] Fixes: b1e3177bd1d8 ("drm/i915: Coordinate i915_active with its own mutex") Fixes: 6d06779e8672 ("drm/i915: Load balancing across a virtual engine") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191205145934.663183-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index a74387664583..c7ea8a055005 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4200,17 +4200,18 @@ static void virtual_context_destroy(struct kref *kref) for (n = 0; n < ve->num_siblings; n++) { struct intel_engine_cs *sibling = ve->siblings[n]; struct rb_node *node = &ve->nodes[sibling->id].rb; + unsigned long flags; if (RB_EMPTY_NODE(node)) continue; - spin_lock_irq(&sibling->active.lock); + spin_lock_irqsave(&sibling->active.lock, flags); /* Detachment is lazily performed in the execlists tasklet */ if (!RB_EMPTY_NODE(node)) rb_erase_cached(node, &sibling->execlists.virtual); - spin_unlock_irq(&sibling->active.lock); + spin_unlock_irqrestore(&sibling->active.lock, flags); } GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.execlists.tasklet)); -- cgit v1.2.3 From 92c964ca3e160aaf4828526f09d72507508bf28d Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Thu, 5 Dec 2019 16:44:22 +0000 Subject: drm/i915/gt: Replace I915_READ with intel_uncore_read Get rid of the last remaining I915_READ in gt/ and make gt-land the first I915_READ-free happy island. Suggested-by: Chris Wilson Signed-off-by: Andi Shyti Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191205164422.727968-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine.h | 2 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 24 ++++++++++++------------ drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 3 ++- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index 01765a7ec18f..c294ea80605e 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -296,7 +296,7 @@ ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine); struct i915_request * intel_engine_find_active_request(struct intel_engine_cs *engine); -u32 intel_engine_context_size(struct drm_i915_private *i915, u8 class); +u32 intel_engine_context_size(struct intel_gt *gt, u8 class); #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index df3369c3f330..49473c25916c 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -141,7 +141,7 @@ static const struct engine_info intel_engines[] = { /** * intel_engine_context_size() - return the size of the context for an engine - * @dev_priv: i915 device private + * @gt: the gt * @class: engine class * * Each engine class may require a different amount of space for a context @@ -153,17 +153,18 @@ static const struct engine_info intel_engines[] = { * in LRC mode, but does not include the "shared data page" used with * GuC submission. The caller should account for this if using the GuC. */ -u32 intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) +u32 intel_engine_context_size(struct intel_gt *gt, u8 class) { + struct intel_uncore *uncore = gt->uncore; u32 cxt_size; BUILD_BUG_ON(I915_GTT_PAGE_SIZE != PAGE_SIZE); switch (class) { case RENDER_CLASS: - switch (INTEL_GEN(dev_priv)) { + switch (INTEL_GEN(gt->i915)) { default: - MISSING_CASE(INTEL_GEN(dev_priv)); + MISSING_CASE(INTEL_GEN(gt->i915)); return DEFAULT_LR_CONTEXT_RENDER_SIZE; case 12: case 11: @@ -175,14 +176,14 @@ u32 intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) case 8: return GEN8_LR_CONTEXT_RENDER_SIZE; case 7: - if (IS_HASWELL(dev_priv)) + if (IS_HASWELL(gt->i915)) return HSW_CXT_TOTAL_SIZE; - cxt_size = I915_READ(GEN7_CXT_SIZE); + cxt_size = intel_uncore_read(uncore, GEN7_CXT_SIZE); return round_up(GEN7_CXT_TOTAL_SIZE(cxt_size) * 64, PAGE_SIZE); case 6: - cxt_size = I915_READ(CXT_SIZE); + cxt_size = intel_uncore_read(uncore, CXT_SIZE); return round_up(GEN6_CXT_TOTAL_SIZE(cxt_size) * 64, PAGE_SIZE); case 5: @@ -197,9 +198,9 @@ u32 intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) * minimum allocation anyway so it should all come * out in the wash. */ - cxt_size = I915_READ(CXT_SIZE) + 1; + cxt_size = intel_uncore_read(uncore, CXT_SIZE) + 1; DRM_DEBUG_DRIVER("gen%d CXT_SIZE = %d bytes [0x%08x]\n", - INTEL_GEN(dev_priv), + INTEL_GEN(gt->i915), cxt_size * 64, cxt_size - 1); return round_up(cxt_size * 64, PAGE_SIZE); @@ -216,7 +217,7 @@ u32 intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) case VIDEO_DECODE_CLASS: case VIDEO_ENHANCEMENT_CLASS: case COPY_ENGINE_CLASS: - if (INTEL_GEN(dev_priv) < 8) + if (INTEL_GEN(gt->i915) < 8) return 0; return GEN8_LR_CONTEXT_OTHER_SIZE; } @@ -324,8 +325,7 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id) */ engine->destroy = (typeof(engine->destroy))kfree; - engine->context_size = intel_engine_context_size(gt->i915, - engine->class); + engine->context_size = intel_engine_context_size(gt, engine->class); if (WARN_ON(engine->context_size > BIT(20))) engine->context_size = 0; if (engine->context_size) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index ca6674b8e00c..05ca90456a2c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -93,7 +93,8 @@ static void __guc_ads_init(struct intel_guc *guc) */ blob->ads.golden_context_lrca[engine_class] = 0; blob->ads.eng_state_size[engine_class] = - intel_engine_context_size(dev_priv, engine_class) - + intel_engine_context_size(guc_to_gt(guc), + engine_class) - skipped_size; } -- cgit v1.2.3 From bbca083de291a03ffe1a1eb0832a0d74f8b64898 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 18:33:32 +0000 Subject: drm/i915: Serialise i915_active_acquire() with __active_retire() As __active_retire() does it's final atomic_dec() under the ref->tree_lock spinlock, in order to prevent ourselves from reusing the ref->cache and ref->tree as they are being destroyed, we need to serialise with the retirement during i915_active_acquire(). [ +0.000005] kernel BUG at drivers/gpu/drm/i915/i915_active.c:157! [ +0.000011] invalid opcode: 0000 [#1] SMP [ +0.000004] CPU: 7 PID: 188 Comm: kworker/u16:4 Not tainted 5.4.0-rc8-03070-gac5e57322614 #89 [ +0.000002] Hardware name: Razer Razer Blade Stealth 13 Late 2019/LY320, BIOS 1.02 09/10/2019 [ +0.000082] Workqueue: events_unbound active_work [i915] [ +0.000059] RIP: 0010:__active_retire+0x115/0x120 [i915] [ +0.000003] Code: 75 28 48 8b 3d 8c 6e 1a 00 48 89 ee e8 e4 5f a5 c0 48 8b 44 24 10 65 48 33 04 25 28 00 00 00 75 0f 48 83 c4 18 5b 5d 41 5c c3 <0f> 0b 0f 0b 0f 0b e8 a0 90 87 c0 0f 1f 44 00 00 48 8b 3d 54 6e 1a [ +0.000002] RSP: 0018:ffffb833003f7e48 EFLAGS: 00010286 [ +0.000003] RAX: ffff8d6e8d726d00 RBX: ffff8d6f9db4e840 RCX: 0000000000000000 [ +0.000001] RDX: ffffffff82605930 RSI: ffff8d6f9adc4908 RDI: ffff8d6e96cefe28 [ +0.000002] RBP: ffff8d6e96cefe00 R08: 0000000000000000 R09: ffff8d6f9ffe9a50 [ +0.000002] R10: 0000000000000048 R11: 0000000000000018 R12: ffff8d6f9adc4930 [ +0.000001] R13: ffff8d6f9e04fb00 R14: 0000000000000000 R15: ffff8d6f9adc4988 [ +0.000002] FS: 0000000000000000(0000) GS:ffff8d6f9ffc0000(0000) knlGS:0000000000000000 [ +0.000002] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ +0.000002] CR2: 000055eb5a34cf10 CR3: 000000018d609002 CR4: 0000000000760ee0 [ +0.000002] PKRU: 55555554 [ +0.000001] Call Trace: [ +0.000010] process_one_work+0x1aa/0x350 [ +0.000004] worker_thread+0x4d/0x3a0 [ +0.000004] kthread+0xfb/0x130 [ +0.000004] ? process_one_work+0x350/0x350 [ +0.000003] ? kthread_park+0x90/0x90 [ +0.000005] ret_from_fork+0x1f/0x40 Reported-by: Kenneth Graunke Fixes: c9ad602feabe ("drm/i915: Split i915_active.mutex into an irq-safe spinlock for the rbtree") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Kenneth Graunke Cc: Matthew Auld Tested-by: Kenneth Graunke Reviewed-by: Kenneth Graunke Link: https://patchwork.freedesktop.org/patch/msgid/20191205183332.801237-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_active.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index e3fcec4834c2..3d0edde84705 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -91,10 +91,9 @@ static void debug_active_init(struct i915_active *ref) static void debug_active_activate(struct i915_active *ref) { - spin_lock_irq(&ref->tree_lock); + lockdep_assert_held(&ref->tree_lock); if (!atomic_read(&ref->count)) /* before the first inc */ debug_object_activate(ref, &active_debug_desc); - spin_unlock_irq(&ref->tree_lock); } static void debug_active_deactivate(struct i915_active *ref) @@ -419,8 +418,10 @@ int i915_active_acquire(struct i915_active *ref) if (!atomic_read(&ref->count) && ref->active) err = ref->active(ref); if (!err) { + spin_lock_irq(&ref->tree_lock); /* vs __active_retire() */ debug_active_activate(ref); atomic_inc(&ref->count); + spin_unlock_irq(&ref->tree_lock); } mutex_unlock(&ref->mutex); -- cgit v1.2.3 From d315fe8bde5cd052ab1e839d1f6c09919297c7a8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 23:40:59 +0000 Subject: drm/i915/gt: Trim gen6 ppgtt updates to PD cachelines It appears now that we have the ring TLB invalidation in place, we need only update the page directory cachelines that we have altered. A great reduction from rewriting the whole 2MiB ppgtt on every update. Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191205234059.1010030-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 4da1dfe11007..6a2183442fed 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1693,15 +1693,18 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; } -static void gen6_flush_pd(struct gen6_ppgtt *ppgtt) +static void gen6_flush_pd(struct gen6_ppgtt *ppgtt, u64 start, u64 end) { struct i915_page_directory * const pd = ppgtt->base.pd; struct i915_page_table *pt; unsigned int pde; + start = round_down(start, SZ_64K); + end = round_up(end, SZ_64K) - start; + mutex_lock(&ppgtt->flush); - gen6_for_all_pdes(pt, pd, pde) + gen6_for_each_pde(pt, pd, start, end, pde) gen6_write_pde(ppgtt, pde, pt); ioread32(ppgtt->pd_addr + pde - 1); @@ -1754,8 +1757,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, spin_unlock(&pd->lock); if (i915_vma_is_bound(ppgtt->vma, I915_VMA_GLOBAL_BIND)) - /* Rewrite them all! Anything less misses an invalidate. */ - gen6_flush_pd(ppgtt); + gen6_flush_pd(ppgtt, from, start); goto out; @@ -1844,7 +1846,7 @@ static int pd_vma_bind(struct i915_vma *vma, px_base(ppgtt->base.pd)->ggtt_offset = ggtt_offset * sizeof(gen6_pte_t); ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm + ggtt_offset; - gen6_flush_pd(ppgtt); + gen6_flush_pd(ppgtt, 0, ppgtt->base.vm.total); return 0; } -- cgit v1.2.3 From 77853186e547bda70d0df0cf2587fb4f7fc29a6b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 21:41:59 +0000 Subject: drm/i915: Claim vma while under closed_lock in i915_vma_parked() Remove the vma we wish to destroy from the gt->closed_list to avoid having two i915_vma_parked() try and free it. Fixes: aa5e4453dc05 ("drm/i915/gem: Try to flush pending unbind events") References: 2850748ef876 ("drm/i915: Pull i915_vma_pin under the vm->mutex") Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191205214159.829727-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_vma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 6db35b9dead8..9ca6664c190c 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1053,7 +1053,9 @@ void i915_vma_parked(struct intel_gt *gt) if (!kref_get_unless_zero(&obj->base.refcount)) continue; - if (!i915_vm_tryopen(vm)) { + if (i915_vm_tryopen(vm)) { + list_del_init(&vma->closed_link); + } else { i915_gem_object_put(obj); obj = NULL; } -- cgit v1.2.3 From 045d1fb79616f138a2e51f04537acd40b9a38ce0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 5 Dec 2019 21:58:42 +0000 Subject: drm/i915/gt: Acquire a GT wakeref for the breadcrumb interrupt Take a wakeref on the intel_gt specifically for the enabled breadcrumb interrupt so that we can safely process the mmio. If the intel_gt is already asleep by the time we try and setup the breadcrumb interrupt, by a process of elimination we know the request must have been completed and we can skip its enablement! <4> [1518.350005] Unclaimed write to register 0x220a8 <4> [1518.350323] WARNING: CPU: 2 PID: 3685 at drivers/gpu/drm/i915/intel_uncore.c:1163 __unclaimed_reg_debug+0x40/0x50 [i915] <4> [1518.350393] Modules linked in: vgem snd_hda_codec_hdmi x86_pkg_temp_thermal i915 coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hwdep snd_hda_core btusb cdc_ether btrtl usbnet btbcm btintel r8152 snd_pcm mii bluetooth ecdh_generic ecc i2c_hid pinctrl_sunrisepoint pinctrl_intel intel_lpss_pci prime_numbers [last unloaded: vgem] <4> [1518.350646] CPU: 2 PID: 3685 Comm: gem_exec_parse_ Tainted: G U 5.4.0-rc8-CI-CI_DRM_7490+ #1 <4> [1518.350708] Hardware name: Google Caroline/Caroline, BIOS MrChromebox 08/27/2018 <4> [1518.350946] RIP: 0010:__unclaimed_reg_debug+0x40/0x50 [i915] <4> [1518.350992] Code: 74 05 5b 5d 41 5c c3 45 84 e4 48 c7 c0 95 8d 47 a0 48 c7 c6 8b 8d 47 a0 48 0f 44 f0 89 ea 48 c7 c7 9e 8d 47 a0 e8 40 45 e3 e0 <0f> 0b 83 2d 27 4f 2a 00 01 5b 5d 41 5c c3 66 90 41 55 41 54 55 53 <4> [1518.351100] RSP: 0018:ffffc900007f39c8 EFLAGS: 00010086 <4> [1518.351140] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000006 <4> [1518.351202] RDX: 0000000080000006 RSI: 0000000000000000 RDI: 00000000ffffffff <4> [1518.351249] RBP: 00000000000220a8 R08: 0000000000000000 R09: 0000000000000000 <4> [1518.351296] R10: ffffc900007f3990 R11: ffffc900007f3868 R12: 0000000000000000 <4> [1518.351342] R13: 00000000fefeffff R14: 0000000000000092 R15: ffff888155fea000 <4> [1518.351391] FS: 00007fc255abfe40(0000) GS:ffff88817ab00000(0000) knlGS:0000000000000000 <4> [1518.351445] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4> [1518.351485] CR2: 00007fc2554882d0 CR3: 0000000168ca2005 CR4: 00000000003606e0 <4> [1518.351529] Call Trace: <4> [1518.351746] fwtable_write32+0x114/0x1d0 [i915] <4> [1518.351795] ? sync_file_alloc+0x80/0x80 <4> [1518.352039] gen8_logical_ring_enable_irq+0x30/0x50 [i915] <4> [1518.352295] irq_enable.part.10+0x23/0x40 [i915] <4> [1518.352523] i915_request_enable_breadcrumb+0xb5/0x330 [i915] <4> [1518.352575] ? sync_file_alloc+0x80/0x80 <4> [1518.352612] __dma_fence_enable_signaling+0x60/0x160 <4> [1518.352653] ? sync_file_alloc+0x80/0x80 <4> [1518.352685] dma_fence_add_callback+0x44/0xd0 <4> [1518.352726] sync_file_poll+0x95/0xc0 <4> [1518.352767] do_sys_poll+0x24d/0x570 Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191205215842.862750-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 55317081d48b..8a9facf4f3b6 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -28,6 +28,7 @@ #include "i915_drv.h" #include "i915_trace.h" +#include "intel_gt_pm.h" static void irq_enable(struct intel_engine_cs *engine) { @@ -53,15 +54,17 @@ static void irq_disable(struct intel_engine_cs *engine) static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) { + struct intel_engine_cs *engine = + container_of(b, struct intel_engine_cs, breadcrumbs); + lockdep_assert_held(&b->irq_lock); GEM_BUG_ON(!b->irq_enabled); if (!--b->irq_enabled) - irq_disable(container_of(b, - struct intel_engine_cs, - breadcrumbs)); + irq_disable(engine); b->irq_armed = false; + intel_gt_pm_put_async(engine->gt); } void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) @@ -207,14 +210,17 @@ static void signal_irq_work(struct irq_work *work) intel_engine_breadcrumbs_irq(engine); } -static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) +static bool __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) { struct intel_engine_cs *engine = container_of(b, struct intel_engine_cs, breadcrumbs); lockdep_assert_held(&b->irq_lock); if (b->irq_armed) - return; + return true; + + if (!intel_gt_pm_get_if_awake(engine->gt)) + return false; /* * The breadcrumb irq will be disarmed on the interrupt after the @@ -234,6 +240,8 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) if (!b->irq_enabled++) irq_enable(engine); + + return true; } void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine) @@ -277,7 +285,8 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) spin_lock(&b->irq_lock); GEM_BUG_ON(test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)); - __intel_breadcrumbs_arm_irq(b); + if (!__intel_breadcrumbs_arm_irq(b)) + goto unlock; /* * We keep the seqno in retirement order, so we can break @@ -306,6 +315,7 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) GEM_BUG_ON(!check_signal_order(ce, rq)); set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); +unlock: spin_unlock(&b->irq_lock); } -- cgit v1.2.3 From 1a74934b0effbd979c520e1122b680624a1a6372 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Dec 2019 10:55:23 +0000 Subject: drm/i915/gem: Flush the pwrite through the chipset before signaling Before we signal the fence to indicate completion, ensure the pwrite through the indirect GGTT is coherent (as best as we know) in memory. Any listeners to the fence may start immediately and sample from the backing store prior to the writes being posted, thus seeing stale data. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191206105527.1130413-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 98b65b718e1a..919d3a723c50 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -670,11 +670,12 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, user_data += page_length; offset += page_length; } + + intel_gt_flush_ggtt_writes(ggtt->vm.gt); intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); i915_gem_object_unlock_fence(obj, fence); out_unpin: - intel_gt_flush_ggtt_writes(ggtt->vm.gt); if (drm_mm_node_allocated(&node)) { ggtt->vm.clear_range(&ggtt->vm, node.start, node.size); remove_mappable_node(ggtt, &node); -- cgit v1.2.3 From b66ecd0438bf6079d08e8f2afea6114f468f56f4 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 29 Nov 2019 10:54:36 +0000 Subject: drm/i915/pmu: Report frequency as zero while GPU is sleeping We used to report the minimum possible frequency as both requested and active while GPU was in sleep state. This was a consequence of sampling the value from the "current frequency" field in our software tracking. This was strictly speaking wrong, but given that until recently the current frequency in sleeping state used to be equal to minimum, it did not stand out sufficiently to be noticed as such. After some recent changes have made the current frequency be reported as last active before GPU went to sleep, meaning both requested and active frequencies could end up being reported at their maximum values for the duration of the GPU idle state, it became much more obvious that this does not make sense. To fix this we will now sample the frequency counters only when the GPU is awake. As a consequence reported frequencies could be reported as below the GPU reported minimum but that should be much less confusing that the current situation. v2: * Split out early exit conditions for readability. (Chris) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Closes: https://gitlab.freedesktop.org/drm/intel/issues/675 Link: https://patchwork.freedesktop.org/patch/msgid/20191129105436.20100-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 52 ++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 95e824a78d4d..eaad9c97d031 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -370,6 +370,13 @@ add_sample_mult(struct i915_pmu_sample *sample, u32 val, u32 mul) sample->cur += mul_u32_u32(val, mul); } +static bool frequency_sampling_enabled(struct i915_pmu *pmu) +{ + return pmu->enable & + (config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) | + config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)); +} + static void frequency_sample(struct intel_gt *gt, unsigned int period_ns) { @@ -378,32 +385,33 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns) struct i915_pmu *pmu = &i915->pmu; struct intel_rps *rps = >->rps; + if (!frequency_sampling_enabled(pmu)) + return; + + /* Report 0/0 (actual/requested) frequency while parked. */ + if (!intel_gt_pm_get_if_awake(gt)) + return; + if (pmu->enable & config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) { u32 val; - val = rps->cur_freq; - if (intel_gt_pm_get_if_awake(gt)) { - u32 stat; - - /* - * We take a quick peek here without using forcewake - * so that we don't perturb the system under observation - * (forcewake => !rc6 => increased power use). We expect - * that if the read fails because it is outside of the - * mmio power well, then it will return 0 -- in which - * case we assume the system is running at the intended - * frequency. Fortunately, the read should rarely fail! - */ - stat = intel_uncore_read_fw(uncore, GEN6_RPSTAT1); - if (stat) - val = intel_get_cagf(rps, stat); - - intel_gt_pm_put_async(gt); - } + /* + * We take a quick peek here without using forcewake + * so that we don't perturb the system under observation + * (forcewake => !rc6 => increased power use). We expect + * that if the read fails because it is outside of the + * mmio power well, then it will return 0 -- in which + * case we assume the system is running at the intended + * frequency. Fortunately, the read should rarely fail! + */ + val = intel_uncore_read_fw(uncore, GEN6_RPSTAT1); + if (val) + val = intel_get_cagf(rps, val); + else + val = rps->cur_freq; add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT], - intel_gpu_freq(rps, val), - period_ns / 1000); + intel_gpu_freq(rps, val), period_ns / 1000); } if (pmu->enable & config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) { @@ -411,6 +419,8 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns) intel_gpu_freq(rps, rps->cur_freq), period_ns / 1000); } + + intel_gt_pm_put_async(gt); } static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) -- cgit v1.2.3 From 5e6a94713be051c491cd47c85263661af07b629c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Dec 2019 16:04:26 +0000 Subject: drm/i915: Check for error before calling cmpxchg() Only do the locked compare of the existing fence->error if we actually need to set an error. As we tend to call i915_sw_fence_set_error_once() unconditionally, it saves on typing to put the common has-error check into the inline. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191206160428.1503343-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_sw_fence.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index 1e90d9a51bd2..19e806ce43bc 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -112,7 +112,8 @@ static inline void i915_sw_fence_wait(struct i915_sw_fence *fence) static inline void i915_sw_fence_set_error_once(struct i915_sw_fence *fence, int error) { - cmpxchg(&fence->error, 0, error); + if (unlikely(error)) + cmpxchg(&fence->error, 0, error); } #endif /* _I915_SW_FENCE_H_ */ -- cgit v1.2.3 From 9e31c1fe45d555a948ff66f1f0e3fe1f83ca63f7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Dec 2019 16:04:27 +0000 Subject: drm/i915: Propagate errors on awaiting already signaled fences If we see an already signaled fence that we want to await on, we skip adding to the i915_sw_fence. However, we should pay attention to whether there was an error on that fence and if so propagate it for our future request. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191206160428.1503343-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_request.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index a558f64186fa..3fa1650975b8 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -958,8 +958,10 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence) do { fence = *child++; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + i915_sw_fence_set_error_once(&rq->submit, fence->error); continue; + } /* * Requests on the same timeline are explicitly ordered, along @@ -1015,8 +1017,10 @@ i915_request_await_execution(struct i915_request *rq, do { fence = *child++; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + i915_sw_fence_set_error_once(&rq->submit, fence->error); continue; + } /* * We don't squash repeated fence dependencies here as we -- cgit v1.2.3 From cbab8d87f7865d09d93e4a6d6db0b799ba0c3407 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Dec 2019 16:04:28 +0000 Subject: drm/i915: Propagate errors on awaiting already signaled dma-fences If we see an already signaled dma-fence that we want to await on, we skip adding to the i915_sw_fence. However, we should pay attention to whether there was an error on that fence and if so propagate it for our future request. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191206160428.1503343-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_sw_fence.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 1584f34a6bf9..51ba97daf2a0 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -428,8 +428,10 @@ static void dma_i915_sw_fence_wake_timer(struct dma_fence *dma, struct i915_sw_fence *fence; fence = xchg(&cb->base.fence, NULL); - if (fence) + if (fence) { + i915_sw_fence_set_error_once(fence, dma->error); i915_sw_fence_complete(fence); + } irq_work_queue(&cb->work); } @@ -457,8 +459,10 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, debug_fence_assert(fence); might_sleep_if(gfpflags_allow_blocking(gfp)); - if (dma_fence_is_signaled(dma)) + if (dma_fence_is_signaled(dma)) { + i915_sw_fence_set_error_once(fence, dma->error); return 0; + } cb = kmalloc(timeout ? sizeof(struct i915_sw_dma_fence_cb_timer) : @@ -468,7 +472,12 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, if (!gfpflags_allow_blocking(gfp)) return -ENOMEM; - return dma_fence_wait(dma, false); + ret = dma_fence_wait(dma, false); + if (ret) + return ret; + + i915_sw_fence_set_error_once(fence, dma->error); + return 0; } cb->fence = fence; @@ -518,8 +527,10 @@ int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, debug_fence_assert(fence); - if (dma_fence_is_signaled(dma)) + if (dma_fence_is_signaled(dma)) { + i915_sw_fence_set_error_once(fence, dma->error); return 0; + } cb->fence = fence; i915_sw_fence_await(fence); @@ -553,8 +564,7 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, struct dma_fence **shared; unsigned int count, i; - ret = dma_resv_get_fences_rcu(resv, - &excl, &count, &shared); + ret = dma_resv_get_fences_rcu(resv, &excl, &count, &shared); if (ret) return ret; -- cgit v1.2.3 From 651cc835d5f6855e8bca6d5d3587234d74e82864 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Tue, 3 Dec 2019 13:13:08 -0800 Subject: drm/i915: Add new EHL/JSL PCI ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding the recently added EHL/JSL PCI ids. BSpec: 29153 Cc: James Ausmus Cc: Matt Roper Signed-off-by: José Roberto de Souza Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191203211308.109703-1-jose.souza@intel.com --- include/drm/i915_pciids.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index b1f66b117c74..3e26a9178aaf 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -579,12 +579,15 @@ INTEL_VGA_DEVICE(0x8A51, info), \ INTEL_VGA_DEVICE(0x8A5D, info) -/* EHL */ +/* EHL/JSL */ #define INTEL_EHL_IDS(info) \ INTEL_VGA_DEVICE(0x4500, info), \ INTEL_VGA_DEVICE(0x4571, info), \ INTEL_VGA_DEVICE(0x4551, info), \ - INTEL_VGA_DEVICE(0x4541, info) + INTEL_VGA_DEVICE(0x4541, info), \ + INTEL_VGA_DEVICE(0x4E71, info), \ + INTEL_VGA_DEVICE(0x4E61, info), \ + INTEL_VGA_DEVICE(0x4E51, info) /* TGL */ #define INTEL_TGL_12_IDS(info) \ -- cgit v1.2.3 From 1ac87297e50e5c6721b87711d4a0fff8423ab991 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 5 Dec 2019 13:03:48 -0800 Subject: drm/i915/display: Do not check for the ddb allocations of turned off pipes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It should not care about DDB allocations of pipes going through a fullmodeset, as at this point those pipes are disabled. The comment in the code also points to that but that was not what was being executed. Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191205210350.96795-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 63f95666b801..cd8a1715c0c9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14603,7 +14603,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) /* ignore allocations for crtc's that have been turned off. */ - if (new_crtc_state->hw.active) + if (!needs_modeset(new_crtc_state) && new_crtc_state->hw.active) entries[i] = old_crtc_state->wm.skl.ddb; /* If 2nd DBuf slice required, enable it here */ -- cgit v1.2.3 From 3ca8f1918883796eaf48c02c50288a255f33c864 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 5 Dec 2019 13:03:49 -0800 Subject: drm/i915/display/tgl: Fix the order of the step to turn transcoder clock off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For TGL the step to turn off the transcoder clock was moved to after the complete shutdown of DDI. Only the MST slave transcoders should disable the clock before that. v2: - Adding last_mst_stream to intel_mst_post_disable_dp, make code more easy to read and is similar to first_mst_stream in intel_mst_pre_enable_dp()(Ville's idea) - Calling intel_ddi_disable_pipe_clock() for GEN12+ right intel_disable_ddi_buf() as stated in BSpec(Ville) BSpec: 49190 Cc: Lucas De Marchi Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20191205210350.96795-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 10 +++++++++- drivers/gpu/drm/i915/display/intel_dp_mst.c | 20 +++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index ebcc7302706b..3cacb1e279c1 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3807,11 +3807,19 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, */ intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); - if (!is_mst) + if (INTEL_GEN(dev_priv) < 12 && !is_mst) intel_ddi_disable_pipe_clock(old_crtc_state); intel_disable_ddi_buf(encoder, old_crtc_state); + /* + * From TGL spec: "If single stream or multi-stream master transcoder: + * Configure Transcoder Clock select to direct no clock to the + * transcoder" + */ + if (INTEL_GEN(dev_priv) >= 12) + intel_ddi_disable_pipe_clock(old_crtc_state); + intel_edp_panel_vdd_on(intel_dp); intel_edp_panel_off(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index a1e4f4197a67..926e49f449a6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -235,8 +235,21 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, struct intel_dp *intel_dp = &intel_dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + bool last_mst_stream; - intel_ddi_disable_pipe_clock(old_crtc_state); + intel_dp->active_mst_links--; + last_mst_stream = intel_dp->active_mst_links == 0; + + /* + * From TGL spec: "If multi-stream slave transcoder: Configure + * Transcoder Clock Select to direct no clock to the transcoder" + * + * From older GENs spec: "Configure Transcoder Clock Select to direct + * no clock to the transcoder" + */ + if (INTEL_GEN(dev_priv) < 12 || !last_mst_stream) + intel_ddi_disable_pipe_clock(old_crtc_state); /* this can fail */ drm_dp_check_act_status(&intel_dp->mst_mgr); @@ -252,13 +265,10 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, false); - intel_dp->active_mst_links--; - intel_mst->connector = NULL; - if (intel_dp->active_mst_links == 0) { + if (last_mst_stream) intel_dig_port->base.post_disable(&intel_dig_port->base, old_crtc_state, NULL); - } DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); } -- cgit v1.2.3 From ad457191015a197b3daf1a259ed8e7f70bf68bb9 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 5 Dec 2019 13:03:50 -0800 Subject: drm/i915/display: Refactor intel_commit_modeset_disables() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 9c722e17c1b9 ("drm/i915: Disable pipes in reverse order") reverted the order that pipes gets disabled because of TGL master/slave relationship between transcoders in MST mode. But as stated in a comment in skl_commit_modeset_enables() the enabling order is not always crescent, possibly causing previously selected slave transcoder being enabled before master so another approach will be needed to select a transcoder to master in MST mode. It will be similar to the approach taken in port sync. But instead of implement something like intel_trans_port_sync_modeset_disables() to MST lets simply it and iterate over all pipes 2 times, the first one disabling any slave and then disabling everything else. The MST bits will be added in another patch. v2: Not using crtc->active as it is deprecated v3: Removing is_trans_port_sync_mode() check, just check for is_trans_port_sync_master() is enough v4: Adding and using is_trans_port_sync_slave(), otherwise non-port sync pipes will be disabled in the first loop, what is not wrong but is not what patch description promises Cc: Lucas De Marchi Cc: Manasi Navare Cc: Matt Roper Cc: Maarten Lankhorst Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä (v2) Signed-off-by: José Roberto de Souza Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191205210350.96795-3-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 88 ++++++++++------------------ 1 file changed, 32 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index cd8a1715c0c9..a35ec8e027c7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -561,6 +561,12 @@ is_trans_port_sync_master(const struct intel_crtc_state *crtc_state) crtc_state->sync_mode_slaves_mask); } +static bool +is_trans_port_sync_slave(const struct intel_crtc_state *crtc_state) +{ + return crtc_state->master_transcoder != INVALID_TRANSCODER; +} + /* * Platform specific helpers to calculate the port PLL loopback- (clock.m), * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast @@ -14393,77 +14399,47 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, dev_priv->display.initial_watermarks(state, crtc); } -static void intel_trans_port_sync_modeset_disables(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state) -{ - struct intel_crtc *slave_crtc = intel_get_slave_crtc(new_crtc_state); - struct intel_crtc_state *new_slave_crtc_state = - intel_atomic_get_new_crtc_state(state, slave_crtc); - struct intel_crtc_state *old_slave_crtc_state = - intel_atomic_get_old_crtc_state(state, slave_crtc); - - WARN_ON(!slave_crtc || !new_slave_crtc_state || - !old_slave_crtc_state); - - /* Disable Slave first */ - intel_pre_plane_update(state, slave_crtc); - if (old_slave_crtc_state->hw.active) - intel_old_crtc_state_disables(state, - old_slave_crtc_state, - new_slave_crtc_state, - slave_crtc); - - /* Disable Master */ - intel_pre_plane_update(state, crtc); - if (old_crtc_state->hw.active) - intel_old_crtc_state_disables(state, - old_crtc_state, - new_crtc_state, - crtc); -} - static void intel_commit_modeset_disables(struct intel_atomic_state *state) { struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; + u32 handled = 0; int i; - /* - * Disable CRTC/pipes in reverse order because some features(MST in - * TGL+) requires master and slave relationship between pipes, so it - * should always pick the lowest pipe as master as it will be enabled - * first and disable in the reverse order so the master will be the - * last one to be disabled. - */ - for_each_oldnew_intel_crtc_in_state_reverse(state, crtc, old_crtc_state, - new_crtc_state, i) { + /* Only disable port sync slaves */ + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { if (!needs_modeset(new_crtc_state)) continue; + if (!old_crtc_state->hw.active) + continue; + /* In case of Transcoder port Sync master slave CRTCs can be * assigned in any order and we need to make sure that * slave CRTCs are disabled first and then master CRTC since * Slave vblanks are masked till Master Vblanks. */ - if (is_trans_port_sync_mode(old_crtc_state)) { - if (is_trans_port_sync_master(old_crtc_state)) - intel_trans_port_sync_modeset_disables(state, - crtc, - old_crtc_state, - new_crtc_state); - else - continue; - } else { - intel_pre_plane_update(state, crtc); + if (!is_trans_port_sync_slave(old_crtc_state)) + continue; - if (old_crtc_state->hw.active) - intel_old_crtc_state_disables(state, - old_crtc_state, - new_crtc_state, - crtc); - } + intel_pre_plane_update(state, crtc); + intel_old_crtc_state_disables(state, old_crtc_state, + new_crtc_state, crtc); + handled |= BIT(crtc->pipe); + } + + /* Disable everything else left on */ + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { + if (!needs_modeset(new_crtc_state) || + (handled & BIT(crtc->pipe))) + continue; + + intel_pre_plane_update(state, crtc); + if (old_crtc_state->hw.active) + intel_old_crtc_state_disables(state, old_crtc_state, + new_crtc_state, crtc); } } -- cgit v1.2.3 From 795a4aea63b1d8c1d7369046e851aa6834ecdb95 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Fri, 6 Dec 2019 23:24:17 +0200 Subject: drm/i915/gt: Replace I915_WRITE with its uncore counterpart Get rid of the last remaining I915_WRITEs and replace them with intel_uncore_write(). Signed-off-by: Andi Shyti Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191206212417.20178-1-andi@etezian.org --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 48 +++++++++++++------------ 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 9f27289b7249..f66220f3c0e6 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -497,14 +497,13 @@ static void set_hwstam(struct intel_engine_cs *engine, u32 mask) static void set_hws_pga(struct intel_engine_cs *engine, phys_addr_t phys) { - struct drm_i915_private *dev_priv = engine->i915; u32 addr; addr = lower_32_bits(phys); - if (INTEL_GEN(dev_priv) >= 4) + if (INTEL_GEN(engine->i915) >= 4) addr |= (phys >> 28) & 0xf0; - I915_WRITE(HWS_PGA, addr); + intel_uncore_write(engine->uncore, HWS_PGA, addr); } static struct page *status_page(struct intel_engine_cs *engine) @@ -523,14 +522,13 @@ static void ring_setup_phys_status_page(struct intel_engine_cs *engine) static void set_hwsp(struct intel_engine_cs *engine, u32 offset) { - struct drm_i915_private *dev_priv = engine->i915; i915_reg_t hwsp; /* * The ring status page addresses are no longer next to the rest of * the ring registers as of gen7. */ - if (IS_GEN(dev_priv, 7)) { + if (IS_GEN(engine->i915, 7)) { switch (engine->id) { /* * No more rings exist on Gen7. Default case is only to shut up @@ -552,14 +550,14 @@ static void set_hwsp(struct intel_engine_cs *engine, u32 offset) hwsp = VEBOX_HWS_PGA_GEN7; break; } - } else if (IS_GEN(dev_priv, 6)) { + } else if (IS_GEN(engine->i915, 6)) { hwsp = RING_HWS_PGA_GEN6(engine->mmio_base); } else { hwsp = RING_HWS_PGA(engine->mmio_base); } - I915_WRITE(hwsp, offset); - POSTING_READ(hwsp); + intel_uncore_write(engine->uncore, hwsp, offset); + intel_uncore_posting_read(engine->uncore, hwsp); } static void flush_cs_tlb(struct intel_engine_cs *engine) @@ -843,7 +841,8 @@ static void reset_finish(struct intel_engine_cs *engine) static int rcs_resume(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = engine->i915; + struct drm_i915_private *i915 = engine->i915; + struct intel_uncore *uncore = engine->uncore; /* * Disable CONSTANT_BUFFER before it is loaded from the context @@ -855,13 +854,14 @@ static int rcs_resume(struct intel_engine_cs *engine) * they are already accustomed to from before contexts were * enabled. */ - if (IS_GEN(dev_priv, 4)) - I915_WRITE(ECOSKPD, + if (IS_GEN(i915, 4)) + intel_uncore_write(uncore, ECOSKPD, _MASKED_BIT_ENABLE(ECO_CONSTANT_BUFFER_SR_DISABLE)); /* WaTimedSingleVertexDispatch:cl,bw,ctg,elk,ilk,snb */ - if (IS_GEN_RANGE(dev_priv, 4, 6)) - I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); + if (IS_GEN_RANGE(i915, 4, 6)) + intel_uncore_write(uncore, MI_MODE, + _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); /* We need to disable the AsyncFlip performance optimisations in order * to use MI_WAIT_FOR_EVENT within the CS. It should already be @@ -869,33 +869,35 @@ static int rcs_resume(struct intel_engine_cs *engine) * * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv */ - if (IS_GEN_RANGE(dev_priv, 6, 7)) - I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); + if (IS_GEN_RANGE(i915, 6, 7)) + intel_uncore_write(uncore, MI_MODE, + _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); /* Required for the hardware to program scanline values for waiting */ /* WaEnableFlushTlbInvalidationMode:snb */ - if (IS_GEN(dev_priv, 6)) - I915_WRITE(GFX_MODE, + if (IS_GEN(i915, 6)) + intel_uncore_write(uncore, GFX_MODE, _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT)); /* WaBCSVCSTlbInvalidationMode:ivb,vlv,hsw */ - if (IS_GEN(dev_priv, 7)) - I915_WRITE(GFX_MODE_GEN7, + if (IS_GEN(i915, 7)) + intel_uncore_write(uncore, GFX_MODE_GEN7, _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); - if (IS_GEN(dev_priv, 6)) { + if (IS_GEN(i915, 6)) { /* From the Sandybridge PRM, volume 1 part 3, page 24: * "If this bit is set, STCunit will have LRA as replacement * policy. [...] This bit must be reset. LRA replacement * policy is not supported." */ - I915_WRITE(CACHE_MODE_0, + intel_uncore_write(uncore, CACHE_MODE_0, _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); } - if (IS_GEN_RANGE(dev_priv, 6, 7)) - I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); + if (IS_GEN_RANGE(i915, 6, 7)) + intel_uncore_write(uncore, INSTPM, + _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); return xcs_resume(engine); } -- cgit v1.2.3 From aef820799274e3bd66e1857f6aa3ee8cff2c30eb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Dec 2019 10:55:26 +0000 Subject: drm/i915/gem: Pin gen6_ppgtt prior to constructing the request All pinning must be done prior to i915_request_create, to avoid timeline->mutex inversions. Here we slightly abuse the context_barrier_task stages to utilise the 'skip' decision as an opportunity to acquire the pin on the new ppgtt. Consider it s/skip/prepare/. At the moment, we only have on user of context_barrier_task, so it might be worth breaking it down for the specific task of set-vm and refactor it later if we find a second purpose. <4> [402.377487] WARNING: possible circular locking dependency detected <4> [402.377493] 5.4.0-rc8-CI-CI_DRM_7491+ #1 Tainted: G U <4> [402.377497] ------------------------------------------------------ <4> [402.377502] gem_exec_parall/2506 is trying to acquire lock: <4> [402.377507] ffff888403cdac70 (&kernel#2){+.+.}, at: i915_request_create+0x16/0x1c0 [i915] <4> [402.377593] but task is already holding lock: <4> [402.377597] ffff88835efad550 (&ppgtt->pin_mutex){+.+.}, at: gen6_ppgtt_pin+0x4d/0x110 [i915] <4> [402.377660] which lock already depends on the new lock. <4> [402.377664] the existing dependency chain (in reverse order) is: <4> [402.377668] -> #1 (&ppgtt->pin_mutex){+.+.}: <4> [402.377674] __mutex_lock+0x9a/0x9d0 <4> [402.377713] gen6_ppgtt_pin+0x4d/0x110 [i915] <4> [402.377756] emit_ppgtt_update+0x1dc/0x370 [i915] <4> [402.377801] context_barrier_task+0x176/0x310 [i915] <4> [402.377844] ctx_setparam+0x400/0xb10 [i915] <4> [402.377886] i915_gem_context_setparam_ioctl+0xc8/0x160 [i915] <4> [402.377891] drm_ioctl_kernel+0xa7/0xf0 <4> [402.377895] drm_ioctl+0x2e1/0x390 <4> [402.377899] do_vfs_ioctl+0xa0/0x6f0 <4> [402.377903] ksys_ioctl+0x35/0x60 <4> [402.377906] __x64_sys_ioctl+0x11/0x20 <4> [402.377910] do_syscall_64+0x4f/0x210 <4> [402.377914] entry_SYSCALL_64_after_hwframe+0x49/0xbe <4> [402.377917] -> #0 (&kernel#2){+.+.}: <4> [402.377923] __lock_acquire+0x1328/0x15d0 <4> [402.377926] lock_acquire+0xa7/0x1c0 <4> [402.377930] __mutex_lock+0x9a/0x9d0 <4> [402.377977] i915_request_create+0x16/0x1c0 [i915] <4> [402.378013] intel_engine_flush_barriers+0x4c/0x100 [i915] <4> [402.378062] i915_ggtt_pin+0x7d/0x130 [i915] <4> [402.378108] gen6_ppgtt_pin+0x9c/0x110 [i915] <4> [402.378148] ring_context_pin+0x2e/0xc0 [i915] <4> [402.378183] __intel_context_do_pin+0x6b/0x190 [i915] <4> [402.378226] i915_gem_do_execbuffer+0x180c/0x26b0 [i915] <4> [402.378268] i915_gem_execbuffer2_ioctl+0x11b/0x460 [i915] <4> [402.378272] drm_ioctl_kernel+0xa7/0xf0 <4> [402.378275] drm_ioctl+0x2e1/0x390 <4> [402.378279] do_vfs_ioctl+0xa0/0x6f0 <4> [402.378282] ksys_ioctl+0x35/0x60 <4> [402.378286] __x64_sys_ioctl+0x11/0x20 <4> [402.378289] do_syscall_64+0x4f/0x210 <4> [402.378292] entry_SYSCALL_64_after_hwframe+0x49/0xbe <4> [402.378295] other info that might help us debug this: <4> [402.378299] Possible unsafe locking scenario: <4> [402.378302] CPU0 CPU1 <4> [402.378305] ---- ---- <4> [402.378307] lock(&ppgtt->pin_mutex); <4> [402.378310] lock(&kernel#2); <4> [402.378314] lock(&ppgtt->pin_mutex); <4> [402.378317] lock(&kernel#2); <4> [402.378320] Signed-off-by: Chris Wilson Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191206105527.1130413-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 9f1dc96b10a6..ae5cae1fe503 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1140,9 +1140,6 @@ static int emit_ppgtt_update(struct i915_request *rq, void *data) } *cs++ = MI_NOOP; intel_ring_advance(rq, cs); - } else { - /* ppGTT is not part of the legacy context image */ - gen6_ppgtt_pin(i915_vm_to_ppgtt(vm)); } return 0; @@ -1150,10 +1147,20 @@ static int emit_ppgtt_update(struct i915_request *rq, void *data) static bool skip_ppgtt_update(struct intel_context *ce, void *data) { + if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) + return true; + if (HAS_LOGICAL_RING_CONTEXTS(ce->engine->i915)) - return !ce->state; - else - return !atomic_read(&ce->pin_count); + return false; + + if (!atomic_read(&ce->pin_count)) + return true; + + /* ppGTT is not part of the legacy context image */ + if (gen6_ppgtt_pin(i915_vm_to_ppgtt(ce->vm))) + return true; + + return false; } static int set_ppgtt(struct drm_i915_file_private *file_priv, -- cgit v1.2.3 From a22198a934e67d461657cde8d79daa305441b9e3 Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Fri, 6 Dec 2019 17:00:33 -0800 Subject: drm/i915/guc: Update uncore access path in flush_ggtt_writes The preferred way to access the uncore is through the GT structure. Update the GuC function, flush_ggtt_writes, to use this path. Signed-off-by: Matthew Brost Signed-off-by: John Harrison Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191207010033.24667-1-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 6f94af7ad1de..4df296a5e7c7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -488,10 +488,9 @@ static void guc_add_request(struct intel_guc *guc, struct i915_request *rq) */ static void flush_ggtt_writes(struct i915_vma *vma) { - struct drm_i915_private *i915 = vma->vm->i915; - if (i915_vma_is_map_and_fenceable(vma)) - intel_uncore_posting_read_fw(&i915->uncore, GUC_STATUS); + intel_uncore_posting_read_fw(vma->vm->gt->uncore, + GUC_STATUS); } static void guc_submit(struct intel_engine_cs *engine, -- cgit v1.2.3 From 8b1c78e06e6167f49beb27be073faa2c6c5c6eff Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 6 Dec 2019 10:55:27 +0000 Subject: drm/i915: Avoid calling i915_gem_object_unbind holding object lock In the extreme case, we may wish to wait on an rcu-barrier to reap stale vm to purge the last of the object bindings. However, we are not allowed to use rcu_barrier() beneath the dma_resv (i.e. object) lock and do not take lightly the prospect of unlocking a mutex deep in the bowels of the routine. i915_gem_object_unbind() itself does not need the object lock, and it turns out the callers do not need to the unbind as part of a locked sequence around set-cache-level, so rearrange the code to avoid taking the object lock in the callers. <4> [186.816311] ====================================================== <4> [186.816313] WARNING: possible circular locking dependency detected <4> [186.816316] 5.4.0-rc8-CI-CI_DRM_7486+ #1 Tainted: G U <4> [186.816318] ------------------------------------------------------ <4> [186.816320] perf_pmu/1321 is trying to acquire lock: <4> [186.816322] ffff88849487c4d8 (&mm->mmap_sem#2){++++}, at: __might_fault+0x39/0x90 <4> [186.816331] but task is already holding lock: <4> [186.816333] ffffe8ffffa05008 (&cpuctx_mutex){+.+.}, at: perf_event_ctx_lock_nested+0xa9/0x1b0 <4> [186.816339] which lock already depends on the new lock. <4> [186.816341] the existing dependency chain (in reverse order) is: <4> [186.816343] -> #6 (&cpuctx_mutex){+.+.}: <4> [186.816349] __mutex_lock+0x9a/0x9d0 <4> [186.816352] perf_event_init_cpu+0xa4/0x140 <4> [186.816357] perf_event_init+0x19d/0x1cd <4> [186.816362] start_kernel+0x372/0x4f4 <4> [186.816365] secondary_startup_64+0xa4/0xb0 <4> [186.816381] -> #5 (pmus_lock){+.+.}: <4> [186.816385] __mutex_lock+0x9a/0x9d0 <4> [186.816387] perf_event_init_cpu+0x6b/0x140 <4> [186.816404] cpuhp_invoke_callback+0x9b/0x9d0 <4> [186.816406] _cpu_up+0xa2/0x140 <4> [186.816409] do_cpu_up+0x61/0xa0 <4> [186.816411] smp_init+0x57/0x96 <4> [186.816413] kernel_init_freeable+0xac/0x1c7 <4> [186.816416] kernel_init+0x5/0x100 <4> [186.816419] ret_from_fork+0x24/0x50 <4> [186.816421] -> #4 (cpu_hotplug_lock.rw_sem){++++}: <4> [186.816424] cpus_read_lock+0x34/0xd0 <4> [186.816427] rcu_barrier+0xaa/0x190 <4> [186.816429] kernel_init+0x21/0x100 <4> [186.816431] ret_from_fork+0x24/0x50 <4> [186.816433] -> #3 (rcu_state.barrier_mutex){+.+.}: <4> [186.816436] __mutex_lock+0x9a/0x9d0 <4> [186.816438] rcu_barrier+0x23/0x190 <4> [186.816502] i915_gem_object_unbind+0x3a6/0x400 [i915] <4> [186.816537] i915_gem_object_set_cache_level+0x32/0x90 [i915] <4> [186.816571] i915_gem_object_pin_to_display_plane+0x5d/0x160 [i915] <4> [186.816612] intel_pin_and_fence_fb_obj+0x9e/0x200 [i915] <4> [186.816679] intel_plane_pin_fb+0x3f/0xd0 [i915] <4> [186.816717] intel_prepare_plane_fb+0x130/0x520 [i915] <4> [186.816722] drm_atomic_helper_prepare_planes+0x85/0x110 <4> [186.816761] intel_atomic_commit+0xc6/0x350 [i915] <4> [186.816764] drm_atomic_helper_update_plane+0xed/0x110 <4> [186.816768] setplane_internal+0x97/0x190 <4> [186.816770] drm_mode_setplane+0xcd/0x190 <4> [186.816773] drm_ioctl_kernel+0xa7/0xf0 <4> [186.816775] drm_ioctl+0x2e1/0x390 <4> [186.816778] do_vfs_ioctl+0xa0/0x6f0 <4> [186.816780] ksys_ioctl+0x35/0x60 <4> [186.816782] __x64_sys_ioctl+0x11/0x20 <4> [186.816785] do_syscall_64+0x4f/0x210 <4> [186.816787] entry_SYSCALL_64_after_hwframe+0x49/0xbe <4> [186.816789] -> #2 (reservation_ww_class_mutex){+.+.}: <4> [186.816793] __ww_mutex_lock.constprop.15+0xc3/0x1090 <4> [186.816795] ww_mutex_lock+0x39/0x70 <4> [186.816798] dma_resv_lockdep+0x10e/0x1f7 <4> [186.816800] do_one_initcall+0x58/0x2ff <4> [186.816802] kernel_init_freeable+0x137/0x1c7 <4> [186.816804] kernel_init+0x5/0x100 <4> [186.816806] ret_from_fork+0x24/0x50 <4> [186.816808] -> #1 (reservation_ww_class_acquire){+.+.}: <4> [186.816811] dma_resv_lockdep+0xec/0x1f7 <4> [186.816813] do_one_initcall+0x58/0x2ff <4> [186.816815] kernel_init_freeable+0x137/0x1c7 <4> [186.816817] kernel_init+0x5/0x100 <4> [186.816819] ret_from_fork+0x24/0x50 <4> [186.816820] -> #0 (&mm->mmap_sem#2){++++}: <4> [186.816824] __lock_acquire+0x1328/0x15d0 <4> [186.816826] lock_acquire+0xa7/0x1c0 <4> [186.816828] __might_fault+0x63/0x90 <4> [186.816831] _copy_to_user+0x1e/0x80 <4> [186.816834] perf_read+0x200/0x2b0 <4> [186.816836] vfs_read+0x96/0x160 <4> [186.816838] ksys_read+0x9f/0xe0 <4> [186.816839] do_syscall_64+0x4f/0x210 <4> [186.816841] entry_SYSCALL_64_after_hwframe+0x49/0xbe <4> [186.816843] other info that might help us debug this: <4> [186.816846] Chain exists of: &mm->mmap_sem#2 --> pmus_lock --> &cpuctx_mutex <4> [186.816849] Possible unsafe locking scenario: <4> [186.816851] CPU0 CPU1 <4> [186.816853] ---- ---- <4> [186.816854] lock(&cpuctx_mutex); <4> [186.816856] lock(pmus_lock); <4> [186.816858] lock(&cpuctx_mutex); <4> [186.816860] lock(&mm->mmap_sem#2); <4> [186.816861] *** DEADLOCK *** Closes: https://gitlab.freedesktop.org/drm/intel/issues/728 Signed-off-by: Chris Wilson Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191206105527.1130413-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/display/intel_display.c | 12 ++++---- drivers/gpu/drm/i915/display/intel_overlay.c | 2 -- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 41 ++++++++-------------------- 3 files changed, 16 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a35ec8e027c7..37760a381402 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2165,19 +2165,18 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, * pin/unpin/fence and not more. */ wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); - i915_gem_object_lock(obj); atomic_inc(&dev_priv->gpu_error.pending_fb_pin); - pinctl = 0; - - /* Valleyview is definitely limited to scanning out the first + /* + * Valleyview is definitely limited to scanning out the first * 512MiB. Lets presume this behaviour was inherited from the * g4x display engine and that all earlier gen are similarly * limited. Testing suggests that it is a little more * complicated than this. For example, Cherryview appears quite * happy to scanout from anywhere within its global aperture. */ + pinctl = 0; if (HAS_GMCH(dev_priv)) pinctl |= PIN_MAPPABLE; @@ -2189,7 +2188,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, if (uses_fence && i915_vma_is_map_and_fenceable(vma)) { int ret; - /* Install a fence for tiled scan-out. Pre-i965 always needs a + /* + * Install a fence for tiled scan-out. Pre-i965 always needs a * fence, whereas 965+ only requires a fence if using * framebuffer compression. For simplicity, we always, when * possible, install a fence as the cost is not that onerous. @@ -2219,8 +2219,6 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, i915_vma_get(vma); err: atomic_dec(&dev_priv->gpu_error.pending_fb_pin); - - i915_gem_object_unlock(obj); intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); return vma; } diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 8cfb785e761c..2a44b3be2600 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -758,10 +758,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, atomic_inc(&dev_priv->gpu_error.pending_fb_pin); - i915_gem_object_lock(new_bo); vma = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL, PIN_MAPPABLE); - i915_gem_object_unlock(new_bo); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_pin_section; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 808eb327a29b..53e28e417cc9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -187,21 +187,23 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, { int ret; - assert_object_held(obj); - if (obj->cache_level == cache_level) return 0; - ret = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE); + ret = i915_gem_object_lock_interruptible(obj); if (ret) return ret; - /* The cache-level will be applied when each vma is rebound. */ + /* Always invalidate stale cachelines */ + if (obj->cache_level != cache_level) { + i915_gem_object_set_cache_coherency(obj, cache_level); + obj->cache_dirty = true; + } - i915_gem_object_set_cache_coherency(obj, cache_level); - obj->cache_dirty = true; /* Always invalidate stale cachelines */ + i915_gem_object_unlock(obj); - return 0; + /* The cache-level will be applied when each vma is rebound. */ + return i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE); } int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, @@ -282,20 +284,7 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, goto out; } - if (obj->cache_level == level) - goto out; - - ret = i915_gem_object_wait(obj, - I915_WAIT_INTERRUPTIBLE, - MAX_SCHEDULE_TIMEOUT); - if (ret) - goto out; - - ret = i915_gem_object_lock_interruptible(obj); - if (ret == 0) { - ret = i915_gem_object_set_cache_level(obj, level); - i915_gem_object_unlock(obj); - } + ret = i915_gem_object_set_cache_level(obj, level); out: i915_gem_object_put(obj); @@ -318,8 +307,6 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, struct i915_vma *vma; int ret; - assert_object_held(obj); - /* Frame buffer must be in LMEM (no migration yet) */ if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj)) return ERR_PTR(-EINVAL); @@ -362,13 +349,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, vma->display_alignment = max_t(u64, vma->display_alignment, alignment); - __i915_gem_object_flush_for_display(obj); - - /* - * It should now be out of any other write domains, and we can update - * the domain values for our changes. - */ - obj->read_domains |= I915_GEM_DOMAIN_GTT; + i915_gem_object_flush_if_display(obj); return vma; } -- cgit v1.2.3 From ca5930b181a446c58acfed2bd6cffe0b04455f83 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 7 Dec 2019 22:14:53 +0000 Subject: drm/i915/gtt: Account for preallocation in asserts Our asserts allow for the PDEs to be allocated concurrently, but we did not account for the aliasing-ppgtt to be preallocated on top. Testcase: igt/gem_ppgtt #bsw Signed-off-by: Chris Wilson Cc: Mika Kuoppala Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191207221453.2802627-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6a2183442fed..be36719e7987 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -53,6 +53,8 @@ #define DBG(...) #endif +#define NALLOC 3 /* 1 normal, 1 for concurrent threads, 1 for preallocation */ + /** * DOC: Global GTT views * @@ -793,7 +795,7 @@ __set_pd_entry(struct i915_page_directory * const pd, u64 (*encode)(const dma_addr_t, const enum i915_cache_level)) { /* Each thread pre-pins the pd, and we may have a thread per pde. */ - GEM_BUG_ON(atomic_read(px_used(pd)) > 2 * ARRAY_SIZE(pd->entry)); + GEM_BUG_ON(atomic_read(px_used(pd)) > NALLOC * ARRAY_SIZE(pd->entry)); atomic_inc(px_used(pd)); pd->entry[idx] = to; @@ -1128,7 +1130,7 @@ static int __gen8_ppgtt_alloc(struct i915_address_space * const vm, atomic_add(count, &pt->used); /* All other pdes may be simultaneously removed */ - GEM_BUG_ON(atomic_read(&pt->used) > 2 * I915_PDES); + GEM_BUG_ON(atomic_read(&pt->used) > NALLOC * I915_PDES); *start += count; } } while (idx++, --len); -- cgit v1.2.3 From d63411000741ebca84b147b3e79cb6b298ee07e9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Dec 2019 14:36:48 +0000 Subject: drm/i915/gt: Turn vm off then on again for gen7 mm switch "Have you tried switching it off and on again?" Set the size of the mm to 0 to disable all PD cachelines, before enabling the whole mm again. Let's see if that tricks the TLB into reloading. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191208143648.2986669-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index f66220f3c0e6..5c22ca6f998a 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1365,7 +1365,9 @@ static const struct intel_context_ops ring_context_ops = { .destroy = ring_context_destroy, }; -static int load_pd_dir(struct i915_request *rq, const struct i915_ppgtt *ppgtt) +static int load_pd_dir(struct i915_request *rq, + const struct i915_ppgtt *ppgtt, + u32 valid) { const struct intel_engine_cs * const engine = rq->engine; u32 *cs; @@ -1376,7 +1378,7 @@ static int load_pd_dir(struct i915_request *rq, const struct i915_ppgtt *ppgtt) *cs++ = MI_LOAD_REGISTER_IMM(1); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine->mmio_base)); - *cs++ = PP_DIR_DCLV_2G; + *cs++ = valid; *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine->mmio_base)); @@ -1395,7 +1397,7 @@ static int load_pd_dir(struct i915_request *rq, const struct i915_ppgtt *ppgtt) intel_ring_advance(rq, cs); - return 0; + return rq->engine->emit_flush(rq, EMIT_FLUSH); } static int flush_tlb(struct i915_request *rq) @@ -1599,8 +1601,6 @@ static int switch_context(struct i915_request *rq) GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); if (vm) { - int loops = 4; /* 2 for Haswell? 4 for Baytrail! */ - /* * Not only do we need a full barrier (post-sync write) after * invalidating the TLBs, but we need to wait a little bit @@ -1617,17 +1617,15 @@ static int switch_context(struct i915_request *rq) if (ret) return ret; - do { - ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm)); - if (ret) - return ret; - } while (--loops); + ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm), 0); + if (ret) + return ret; - ret = flush_tlb(rq); + ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm), PP_DIR_DCLV_2G); if (ret) return ret; - ret = rq->engine->emit_flush(rq, EMIT_FLUSH); + ret = flush_tlb(rq); if (ret) return ret; -- cgit v1.2.3 From 8d65859a4cbae92f441b9aec8780055a361cc3d0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 7 Dec 2019 22:26:44 +0000 Subject: drm/i915/gem: Comment on inability to check args.pad for MMAP_OFFSET Since we didn't check and insist that args.pad must be zero for MMAP_GTT historically, we cannot insert a check now as old userspace may be feeding in garbage. As such the lack of check is enshrined into the ABI, so add a comment to remind us we cannot add the check later. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191207222644.2830129-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 3a3f30bc8ac7..879fff8adc48 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -620,6 +620,15 @@ i915_gem_mmap_offset_ioctl(struct drm_device *dev, void *data, enum i915_mmap_type type; int err; + /* + * Historically we failed to check args.pad and args.offset + * and so we cannot use those fields for user input and we cannot + * add -EINVAL for them as the ABI is fixed, i.e. old userspace + * may be feeding in garbage in those fields. + * + * if (args->pad) return -EINVAL; is verbotten! + */ + err = i915_user_extensions(u64_to_user_ptr(args->extensions), NULL, 0, NULL); if (err) -- cgit v1.2.3 From 7240497850f76e698e27aca66664cd7ca4f1d5ff Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 7 Dec 2019 18:29:37 +0000 Subject: drm/i915: Flesh out device_info pretty printer Include all the number fields for describing the GT, as well as the current boolean flags, primarily for inclusion in error states. Signed-off-by: Chris Wilson Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191207182937.2583002-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 22 ++++++--------------- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/i915_gpu_error.c | 5 +++-- drivers/gpu/drm/i915/intel_device_info.c | 33 ++++++++++++++++++++++++++------ drivers/gpu/drm/i915/intel_device_info.h | 9 +++++---- 5 files changed, 43 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index eb80a2c4b55b..062e5bef637a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -61,24 +61,14 @@ static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node) static int i915_capabilities(struct seq_file *m, void *data) { - struct drm_i915_private *dev_priv = node_to_i915(m->private); - const struct intel_device_info *info = INTEL_INFO(dev_priv); + struct drm_i915_private *i915 = node_to_i915(m->private); struct drm_printer p = drm_seq_file_printer(m); - const char *msg; - seq_printf(m, "gen: %d\n", INTEL_GEN(dev_priv)); - seq_printf(m, "platform: %s\n", intel_platform_name(info->platform)); - seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv)); - - msg = "n/a"; -#ifdef CONFIG_INTEL_IOMMU - msg = enableddisabled(intel_iommu_gfx_mapped); -#endif - seq_printf(m, "iommu: %s\n", msg); + seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(i915)); - intel_device_info_dump_flags(info, &p); - intel_device_info_dump_runtime(RUNTIME_INFO(dev_priv), &p); - intel_driver_caps_print(&dev_priv->caps, &p); + intel_device_info_print_static(INTEL_INFO(i915), &p); + intel_device_info_print_runtime(RUNTIME_INFO(i915), &p); + intel_driver_caps_print(&i915->caps, &p); kernel_param_lock(THIS_MODULE); i915_params_dump(&i915_modparams, &p); @@ -2759,7 +2749,7 @@ static int i915_rcs_topology(struct seq_file *m, void *unused) struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_printer p = drm_seq_file_printer(m); - intel_device_info_dump_topology(&RUNTIME_INFO(dev_priv)->sseu, &p); + intel_device_info_print_topology(&RUNTIME_INFO(dev_priv)->sseu, &p); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5d7e11927729..1234bd64db2f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1397,8 +1397,8 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv) INTEL_INFO(dev_priv)->platform), INTEL_GEN(dev_priv)); - intel_device_info_dump_flags(INTEL_INFO(dev_priv), &p); - intel_device_info_dump_runtime(RUNTIME_INFO(dev_priv), &p); + intel_device_info_print_static(INTEL_INFO(dev_priv), &p); + intel_device_info_print_runtime(RUNTIME_INFO(dev_priv), &p); } if (IS_ENABLED(CONFIG_DRM_I915_DEBUG)) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 2b30a45fa25c..8374d50c0770 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -599,9 +599,10 @@ static void err_print_capabilities(struct drm_i915_error_state_buf *m, { struct drm_printer p = i915_error_printer(m); - intel_device_info_dump_flags(info, &p); + intel_device_info_print_static(info, &p); + intel_device_info_print_runtime(runtime, &p); + intel_device_info_print_topology(&runtime->sseu, &p); intel_driver_caps_print(caps, &p); - intel_device_info_dump_topology(&runtime->sseu, &p); } static void err_print_params(struct drm_i915_error_state_buf *m, diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index a5b571364cf6..2cde0bac27d3 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -73,9 +73,30 @@ const char *intel_platform_name(enum intel_platform platform) return platform_names[platform]; } -void intel_device_info_dump_flags(const struct intel_device_info *info, - struct drm_printer *p) +static const char *iommu_name(void) { + const char *msg = "n/a"; + +#ifdef CONFIG_INTEL_IOMMU + msg = enableddisabled(intel_iommu_gfx_mapped); +#endif + + return msg; +} + +void intel_device_info_print_static(const struct intel_device_info *info, + struct drm_printer *p) +{ + drm_printf(p, "engines: %x\n", info->engine_mask); + drm_printf(p, "gen: %d\n", info->gen); + drm_printf(p, "gt: %d\n", info->gt); + drm_printf(p, "iommu: %s\n", iommu_name()); + drm_printf(p, "memory-regions: %x\n", info->memory_regions); + drm_printf(p, "page-sizes: %x\n", info->page_sizes); + drm_printf(p, "platform: %s\n", intel_platform_name(info->platform)); + drm_printf(p, "ppgtt-size: %d\n", info->ppgtt_size); + drm_printf(p, "ppgtt-type: %d\n", info->ppgtt_type); + #define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name)); DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG @@ -106,8 +127,8 @@ static void sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p) drm_printf(p, "has EU power gating: %s\n", yesno(sseu->has_eu_pg)); } -void intel_device_info_dump_runtime(const struct intel_runtime_info *info, - struct drm_printer *p) +void intel_device_info_print_runtime(const struct intel_runtime_info *info, + struct drm_printer *p) { sseu_dump(&info->sseu, p); @@ -148,8 +169,8 @@ static void sseu_set_eus(struct sseu_dev_info *sseu, int slice, int subslice, } } -void intel_device_info_dump_topology(const struct sseu_dev_info *sseu, - struct drm_printer *p) +void intel_device_info_print_topology(const struct sseu_dev_info *sseu, + struct drm_printer *p) { int s, ss; diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 4bdf8a6cfb47..2725cb7fc169 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -230,12 +230,13 @@ const char *intel_platform_name(enum intel_platform platform); void intel_device_info_subplatform_init(struct drm_i915_private *dev_priv); void intel_device_info_runtime_init(struct drm_i915_private *dev_priv); -void intel_device_info_dump_flags(const struct intel_device_info *info, - struct drm_printer *p); -void intel_device_info_dump_runtime(const struct intel_runtime_info *info, + +void intel_device_info_print_static(const struct intel_device_info *info, struct drm_printer *p); -void intel_device_info_dump_topology(const struct sseu_dev_info *sseu, +void intel_device_info_print_runtime(const struct intel_runtime_info *info, struct drm_printer *p); +void intel_device_info_print_topology(const struct sseu_dev_info *sseu, + struct drm_printer *p); void intel_device_info_init_mmio(struct drm_i915_private *dev_priv); -- cgit v1.2.3 From 16c46fd505fbe33ee480f8bb67aa3807b3507c72 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Dec 2019 16:12:51 +0000 Subject: drm/i915/gem: Avoid rcu_barrier() from shrinker paths As i915_gem_object_unbind() waits on an rcu_barrier() to flush vm releases (and destruction of their bound vma), we have to be careful not to invoke that barrier from beneath the shrinker: <4> [430.222671] WARNING: possible circular locking dependency detected <4> [430.222673] 5.4.0-rc8-CI-CI_DRM_7508+ #1 Tainted: G U <4> [430.222675] ------------------------------------------------------ <4> [430.222677] gem_pwrite/2317 is trying to acquire lock: <4> [430.222678] ffffffff82248218 (rcu_state.barrier_mutex){+.+.}, at: rcu_barrier+0x23/0x190 <4> [430.222685] but task is already holding lock: <4> [430.222687] ffffffff82263a40 (fs_reclaim){+.+.}, at: fs_reclaim_acquire.part.117+0x0/0x30 <4> [430.222691] which lock already depends on the new lock. <4> [430.222693] the existing dependency chain (in reverse order) is: <4> [430.222695] -> #2 (fs_reclaim){+.+.}: <4> [430.222698] fs_reclaim_acquire.part.117+0x24/0x30 <4> [430.222702] kmem_cache_alloc_trace+0x2a/0x2c0 <4> [430.222705] intel_cpuc_prepare+0x37/0x1a0 <4> [430.222709] cpuhp_invoke_callback+0x9b/0x9d0 <4> [430.222712] _cpu_up+0xa2/0x140 <4> [430.222714] do_cpu_up+0x61/0xa0 <4> [430.222718] smp_init+0x57/0x96 <4> [430.222722] kernel_init_freeable+0xac/0x1c7 <4> [430.222725] kernel_init+0x5/0x100 <4> [430.222728] ret_from_fork+0x24/0x50 <4> [430.222729] -> #1 (cpu_hotplug_lock.rw_sem){++++}: <4> [430.222733] cpus_read_lock+0x34/0xd0 <4> [430.222734] rcu_barrier+0xaa/0x190 <4> [430.222736] kernel_init+0x21/0x100 <4> [430.222737] ret_from_fork+0x24/0x50 <4> [430.222739] -> #0 (rcu_state.barrier_mutex){+.+.}: <4> [430.222742] __lock_acquire+0x1328/0x15d0 <4> [430.222743] lock_acquire+0xa7/0x1c0 <4> [430.222746] __mutex_lock+0x9a/0x9d0 <4> [430.222747] rcu_barrier+0x23/0x190 <4> [430.222850] i915_gem_object_unbind+0x264/0x3d0 [i915] <4> [430.222882] i915_gem_shrink+0x297/0x5f0 [i915] <4> [430.222912] i915_gem_shrink_all+0x38/0x60 [i915] <4> [430.222934] i915_drop_caches_set+0x1f0/0x240 [i915] <4> [430.222938] simple_attr_write+0xb0/0xd0 <4> [430.222941] full_proxy_write+0x51/0x80 <4> [430.222943] vfs_write+0xb9/0x1d0 <4> [430.222944] ksys_write+0x9f/0xe0 <4> [430.222946] do_syscall_64+0x4f/0x210 <4> [430.222948] entry_SYSCALL_64_after_hwframe+0x49/0xbe <4> [430.222950] other info that might help us debug this: <4> [430.222952] Chain exists of: rcu_state.barrier_mutex --> cpu_hotplug_lock.rw_sem --> fs_reclaim <4> [430.222955] Possible unsafe locking scenario: <4> [430.222957] CPU0 CPU1 <4> [430.222958] ---- ---- <4> [430.222960] lock(fs_reclaim); <4> [430.222961] lock(cpu_hotplug_lock.rw_sem); <4> [430.222963] lock(fs_reclaim); <4> [430.222964] lock(rcu_state.barrier_mutex); <4> [430.222966] *** DEADLOCK *** <4> [430.222968] 3 locks held by gem_pwrite/2317: <4> [430.222969] #0: ffff88849e2d9408 (sb_writers#14){.+.+}, at: vfs_write+0x1a4/0x1d0 <4> [430.222973] #1: ffff888496976db0 (&attr->mutex){+.+.}, at: simple_attr_write+0x36/0xd0 <4> [430.222976] #2: ffffffff82263a40 (fs_reclaim){+.+.}, at: fs_reclaim_acquire.part.117+0x0/0x30 <4> [430.222980] stack backtrace: <4> [430.222982] CPU: 1 PID: 2317 Comm: gem_pwrite Tainted: G U 5.4.0-rc8-CI-CI_DRM_7508+ #1 <4> [430.222985] Hardware name: Intel Corporation Tiger Lake Client Platform/TigerLake U DDR4 SODIMM RVP, BIOS TGLSFWI1.R00.2321.A08.1909162051 09/16/2019 <4> [430.222989] Call Trace: <4> [430.222992] dump_stack+0x71/0x9b <4> [430.222995] check_noncircular+0x19b/0x1c0 <4> [430.222998] ? __lock_acquire+0x1328/0x15d0 <4> [430.222999] __lock_acquire+0x1328/0x15d0 <4> [430.223001] ? mark_held_locks+0x49/0x70 <4> [430.223003] lock_acquire+0xa7/0x1c0 <4> [430.223005] ? rcu_barrier+0x23/0x190 <4> [430.223008] __mutex_lock+0x9a/0x9d0 <4> [430.223009] ? rcu_barrier+0x23/0x190 <4> [430.223011] ? rcu_barrier+0x23/0x190 <4> [430.223013] ? find_held_lock+0x2d/0x90 <4> [430.223045] ? i915_gem_object_unbind+0x24a/0x3d0 [i915] <4> [430.223048] ? rcu_barrier+0x23/0x190 <4> [430.223049] rcu_barrier+0x23/0x190 <4> [430.223081] i915_gem_object_unbind+0x264/0x3d0 [i915] <4> [430.223119] i915_gem_shrink+0x297/0x5f0 [i915] Closes: https://gitlab.freedesktop.org/drm/intel/issues/743 Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191208161252.3015727-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 4 +++- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 53e28e417cc9..88ab7e71f36c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -203,7 +203,9 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, i915_gem_object_unlock(obj); /* The cache-level will be applied when each vma is rebound. */ - return i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE); + return i915_gem_object_unbind(obj, + I915_GEM_OBJECT_UNBIND_ACTIVE | + I915_GEM_OBJECT_UNBIND_BARRIER); } int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c3d8af28bfc1..bae97cd62cb9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1845,6 +1845,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, int i915_gem_object_unbind(struct drm_i915_gem_object *obj, unsigned long flags); #define I915_GEM_OBJECT_UNBIND_ACTIVE BIT(0) +#define I915_GEM_OBJECT_UNBIND_BARRIER BIT(1) void i915_gem_runtime_suspend(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 919d3a723c50..5eeef1ef7448 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -178,7 +178,7 @@ err_vm: list_splice_init(&still_in_list, &obj->vma.list); spin_unlock(&obj->vma.lock); - if (ret == -EAGAIN && flags & I915_GEM_OBJECT_UNBIND_ACTIVE) { + if (ret == -EAGAIN && flags & I915_GEM_OBJECT_UNBIND_BARRIER) { rcu_barrier(); /* flush the i915_vm_release() */ goto try_again; } -- cgit v1.2.3 From d3e483526cd3057936360503e3d7694d0bcb6eb2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Dec 2019 16:12:52 +0000 Subject: drm/i915: Change i915_vma_unbind() to report -EAGAIN on activity If someone else acquires the i915_vma before we complete our wait and unbind it, we currently error out with -EBUSY. Use -EAGAIN instead so that if necessary the caller is prepared to try again. Closes: https://gitlab.freedesktop.org/drm/intel/issues/683 Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191208161252.3015727-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 9ca6664c190c..6794c742fbbf 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1181,7 +1181,7 @@ int __i915_vma_unbind(struct i915_vma *vma) GEM_BUG_ON(i915_vma_is_active(vma)); if (i915_vma_is_pinned(vma)) { vma_print_allocator(vma, "is pinned"); - return -EBUSY; + return -EAGAIN; } GEM_BUG_ON(i915_vma_is_active(vma)); -- cgit v1.2.3 From 322d56aa3145a28445907ecc638a2c3aa3295c6b Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 6 Dec 2019 11:43:38 -0800 Subject: drm/i915/perf: Allow non-privileged access when OA buffer is not sampled SAMPLE_OA_REPORT enables sampling of OA reports from the OA buffer. Since reports from OA buffer had system wide visibility, collecting samples from the OA buffer was a privileged operation on previous platforms. Prior to TGL, it was also necessary to sample the OA buffer to normalize reports from MI REPORT PERF COUNT. TGL has a dedicated OAR unit to sample perf reports for a specific render context. This removes the necessity to sample OA buffer. - If not sampling the OA buffer, allow non-privileged access. An earlier patch allows the non-privilege access: https://patchwork.freedesktop.org/patch/337716/?series=68582&rev=1 - Clear up the path for non-privileged access in this patch Signed-off-by: Umesh Nerlige Ramappa Fixes: 00a7f0d7155c ("drm/i915/tgl: Add perf support on TGL") Reviewed-by: Lionel Landwerlin Signed-off-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20191206194339.31356-1-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index f20dda40b378..9fef7b57520f 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2722,7 +2722,8 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, return -EINVAL; } - if (!(props->sample_flags & SAMPLE_OA_REPORT)) { + if (!(props->sample_flags & SAMPLE_OA_REPORT) && + (INTEL_GEN(perf->i915) < 12 || !stream->ctx)) { DRM_DEBUG("Only OA report sampling supported\n"); return -EINVAL; } @@ -2754,7 +2755,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, format_size = perf->oa_formats[props->oa_format].size; - stream->sample_flags |= SAMPLE_OA_REPORT; + stream->sample_flags = props->sample_flags; stream->sample_size += format_size; stream->oa_buffer.format_size = format_size; -- cgit v1.2.3 From ccdeed497042676e13fc1625e2a341880eff5da5 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Fri, 6 Dec 2019 11:43:39 -0800 Subject: drm/i915/perf: Configure OAR for specific context Gen12 supports saving/restoring render counters per context. Apply OAR configuration only for the context that is passed in to perf. v2: - Fix OACTXCONTROL value to only stop/resume counters. - Remove gen12_update_reg_state_unlocked as power state is already applied by the caller. v3: (Lionel) - Move register initialization into the array - Assume a valid oa_config in enable_metric_set Signed-off-by: Umesh Nerlige Ramappa Fixes: 00a7f0d7155c ("drm/i915/tgl: Add perf support on TGL") Reviewed-by: Lionel Landwerlin Signed-off-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20191206194339.31356-2-umesh.nerlige.ramappa@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 199 ++++++++++++++++++++++----------------- 1 file changed, 112 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 9fef7b57520f..8d2e37949f46 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2082,20 +2082,12 @@ gen8_update_reg_state_unlocked(const struct intel_context *ce, u32 *reg_state = ce->lrc_reg_state; int i; - if (IS_GEN(stream->perf->i915, 12)) { - u32 format = stream->oa_buffer.format; + reg_state[ctx_oactxctrl + 1] = + (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) | + (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) | + GEN8_OA_COUNTER_RESUME; - reg_state[ctx_oactxctrl + 1] = - (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) | - (stream->oa_config ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0); - } else { - reg_state[ctx_oactxctrl + 1] = - (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) | - (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) | - GEN8_OA_COUNTER_RESUME; - } - - for (i = 0; !!ctx_flexeu0 && i < ARRAY_SIZE(flex_regs); i++) + for (i = 0; i < ARRAY_SIZE(flex_regs); i++) reg_state[ctx_flexeu0 + i * 2 + 1] = oa_config_flex_reg(stream->oa_config, flex_regs[i]); @@ -2228,34 +2220,51 @@ static int gen8_configure_context(struct i915_gem_context *ctx, return err; } -static int gen12_emit_oar_config(struct intel_context *ce, bool enable) +static int gen12_configure_oar_context(struct i915_perf_stream *stream, bool enable) { - struct i915_request *rq; - u32 *cs; - int err = 0; - - rq = i915_request_create(ce); - if (IS_ERR(rq)) - return PTR_ERR(rq); - - cs = intel_ring_begin(rq, 4); - if (IS_ERR(cs)) { - err = PTR_ERR(cs); - goto out; - } - - *cs++ = MI_LOAD_REGISTER_IMM(1); - *cs++ = i915_mmio_reg_offset(RING_CONTEXT_CONTROL(ce->engine->mmio_base)); - *cs++ = _MASKED_FIELD(GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE, - enable ? GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE : 0); - *cs++ = MI_NOOP; + int err; + struct intel_context *ce = stream->pinned_ctx; + u32 format = stream->oa_buffer.format; + struct flex regs_context[] = { + { + GEN8_OACTXCONTROL, + stream->perf->ctx_oactxctrl_offset + 1, + enable ? GEN8_OA_COUNTER_RESUME : 0, + }, + }; + /* Offsets in regs_lri are not used since this configuration is only + * applied using LRI. Initialize the correct offsets for posterity. + */ +#define GEN12_OAR_OACONTROL_OFFSET 0x5B0 + struct flex regs_lri[] = { + { + GEN12_OAR_OACONTROL, + GEN12_OAR_OACONTROL_OFFSET + 1, + (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) | + (enable ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0) + }, + { + RING_CONTEXT_CONTROL(ce->engine->mmio_base), + CTX_CONTEXT_CONTROL, + _MASKED_FIELD(GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE, + enable ? + GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE : + 0) + }, + }; - intel_ring_advance(rq, cs); + /* Modify the context image of pinned context with regs_context*/ + err = intel_context_lock_pinned(ce); + if (err) + return err; -out: - i915_request_add(rq); + err = gen8_modify_context(ce, regs_context, ARRAY_SIZE(regs_context)); + intel_context_unlock_pinned(ce); + if (err) + return err; - return err; + /* Apply regs_lri using LRI with pinned context */ + return gen8_modify_self(ce, regs_lri, ARRAY_SIZE(regs_lri)); } /* @@ -2281,53 +2290,16 @@ out: * per-context OA state. * * Note: it's only the RCS/Render context that has any OA state. + * Note: the first flex register passed must always be R_PWR_CLK_STATE */ -static int lrc_configure_all_contexts(struct i915_perf_stream *stream, - const struct i915_oa_config *oa_config) +static int oa_configure_all_contexts(struct i915_perf_stream *stream, + struct flex *regs, + size_t num_regs) { struct drm_i915_private *i915 = stream->perf->i915; - /* The MMIO offsets for Flex EU registers aren't contiguous */ - const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset; -#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1) - struct flex regs[] = { - { - GEN8_R_PWR_CLK_STATE, - CTX_R_PWR_CLK_STATE, - }, - { - IS_GEN(i915, 12) ? - GEN12_OAR_OACONTROL : GEN8_OACTXCONTROL, - stream->perf->ctx_oactxctrl_offset + 1, - }, - { EU_PERF_CNTL0, ctx_flexeuN(0) }, - { EU_PERF_CNTL1, ctx_flexeuN(1) }, - { EU_PERF_CNTL2, ctx_flexeuN(2) }, - { EU_PERF_CNTL3, ctx_flexeuN(3) }, - { EU_PERF_CNTL4, ctx_flexeuN(4) }, - { EU_PERF_CNTL5, ctx_flexeuN(5) }, - { EU_PERF_CNTL6, ctx_flexeuN(6) }, - }; -#undef ctx_flexeuN struct intel_engine_cs *engine; struct i915_gem_context *ctx, *cn; - size_t array_size = IS_GEN(i915, 12) ? 2 : ARRAY_SIZE(regs); - int i, err; - - if (IS_GEN(i915, 12)) { - u32 format = stream->oa_buffer.format; - - regs[1].value = - (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) | - (oa_config ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0); - } else { - regs[1].value = - (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) | - (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) | - GEN8_OA_COUNTER_RESUME; - } - - for (i = 2; !!ctx_flexeu0 && i < array_size; i++) - regs[i].value = oa_config_flex_reg(oa_config, regs[i].reg); + int err; lockdep_assert_held(&stream->perf->lock); @@ -2357,7 +2329,7 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream, spin_unlock(&i915->gem.contexts.lock); - err = gen8_configure_context(ctx, regs, array_size); + err = gen8_configure_context(ctx, regs, num_regs); if (err) { i915_gem_context_put(ctx); return err; @@ -2382,7 +2354,7 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream, regs[0].value = intel_sseu_make_rpcs(i915, &ce->sseu); - err = gen8_modify_self(ce, regs, array_size); + err = gen8_modify_self(ce, regs, num_regs); if (err) return err; } @@ -2390,6 +2362,56 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream, return 0; } +static int gen12_configure_all_contexts(struct i915_perf_stream *stream, + const struct i915_oa_config *oa_config) +{ + struct flex regs[] = { + { + GEN8_R_PWR_CLK_STATE, + CTX_R_PWR_CLK_STATE, + }, + }; + + return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs)); +} + +static int lrc_configure_all_contexts(struct i915_perf_stream *stream, + const struct i915_oa_config *oa_config) +{ + /* The MMIO offsets for Flex EU registers aren't contiguous */ + const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset; +#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1) + struct flex regs[] = { + { + GEN8_R_PWR_CLK_STATE, + CTX_R_PWR_CLK_STATE, + }, + { + GEN8_OACTXCONTROL, + stream->perf->ctx_oactxctrl_offset + 1, + }, + { EU_PERF_CNTL0, ctx_flexeuN(0) }, + { EU_PERF_CNTL1, ctx_flexeuN(1) }, + { EU_PERF_CNTL2, ctx_flexeuN(2) }, + { EU_PERF_CNTL3, ctx_flexeuN(3) }, + { EU_PERF_CNTL4, ctx_flexeuN(4) }, + { EU_PERF_CNTL5, ctx_flexeuN(5) }, + { EU_PERF_CNTL6, ctx_flexeuN(6) }, + }; +#undef ctx_flexeuN + int i; + + regs[1].value = + (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) | + (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) | + GEN8_OA_COUNTER_RESUME; + + for (i = 2; i < ARRAY_SIZE(regs); i++) + regs[i].value = oa_config_flex_reg(oa_config, regs[i].reg); + + return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs)); +} + static int gen8_enable_metric_set(struct i915_perf_stream *stream) { struct intel_uncore *uncore = stream->uncore; @@ -2473,7 +2495,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream) * to make sure all slices/subslices are ON before writing to NOA * registers. */ - ret = lrc_configure_all_contexts(stream, oa_config); + ret = gen12_configure_all_contexts(stream, oa_config); if (ret) return ret; @@ -2483,8 +2505,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream) * requested this. */ if (stream->ctx) { - ret = gen12_emit_oar_config(stream->pinned_ctx, - oa_config != NULL); + ret = gen12_configure_oar_context(stream, true); if (ret) return ret; } @@ -2518,11 +2539,11 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream) struct intel_uncore *uncore = stream->uncore; /* Reset all contexts' slices/subslices configurations. */ - lrc_configure_all_contexts(stream, NULL); + gen12_configure_all_contexts(stream, NULL); /* disable the context save/restore or OAR counters */ if (stream->ctx) - gen12_emit_oar_config(stream->pinned_ctx, false); + gen12_configure_oar_context(stream, false); /* Make sure we disable noa to save power. */ intel_uncore_rmw(uncore, RPM_CONFIG1, GEN10_GT_NOA_ENABLE, 0); @@ -2864,7 +2885,11 @@ void i915_oa_init_reg_state(const struct intel_context *ce, return; stream = engine->i915->perf.exclusive_stream; - if (stream) + /* + * For gen12, only CTX_R_PWR_CLK_STATE needs update, but the caller + * is already doing that, so nothing to be done for gen12 here. + */ + if (stream && INTEL_GEN(stream->perf->i915) < 12) gen8_update_reg_state_unlocked(ce, stream); } -- cgit v1.2.3 From cd8c021b36a66833cefe2c90a79a9e312a2a5690 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:09 +0200 Subject: drm/i915/fbc: Disable fbc by default on all glk+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're missing a workaround in the fbc code for all glk+ platforms which can cause corruption around the top of the screen. So enabling fbc by default is a bad idea. I'm not keen to backport the w/a so let's start by disabling fbc by default on all glk+. We'll lift the restriction once the w/a is in place. Cc: stable@vger.kernel.org Cc: Daniel Drake Cc: Paulo Zanoni Cc: Jian-Hong Pan Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-2-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 70c56abe1a83..f139cd545515 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1284,7 +1284,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) return 0; /* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */ - if (IS_GEMINILAKE(dev_priv)) + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) return 0; if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) -- cgit v1.2.3 From fb2d8e0cd4d76bdc4630defbd545de5ece594124 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:10 +0200 Subject: drm/i915/fbc: Nuke bogus single pipe fbc1 restriction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not sure where the single pipe only restriction came for fbc1. Nothing I can see that would prevent this. v2: Nuke no_fbc_on_multiple_pipes() too Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-3-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_display.c | 2 -- drivers/gpu/drm/i915/display/intel_fbc.c | 52 ---------------------------- drivers/gpu/drm/i915/display/intel_fbc.h | 1 - drivers/gpu/drm/i915/i915_drv.h | 1 - 4 files changed, 56 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 37760a381402..dbc487daec95 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17810,8 +17810,6 @@ intel_modeset_setup_hw_state(struct drm_device *dev, } intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); - - intel_fbc_init_pipe_state(dev_priv); } void intel_display_resume(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index f139cd545515..8fcd1ceaddc7 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -50,11 +50,6 @@ static inline bool fbc_supported(struct drm_i915_private *dev_priv) return HAS_FBC(dev_priv); } -static inline bool no_fbc_on_multiple_pipes(struct drm_i915_private *dev_priv) -{ - return INTEL_GEN(dev_priv) <= 3; -} - /* * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's @@ -419,25 +414,6 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv, fbc->no_fbc_reason = reason; } -static bool multiple_pipes_ok(struct intel_crtc *crtc, - const struct intel_plane_state *plane_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_fbc *fbc = &dev_priv->fbc; - enum pipe pipe = crtc->pipe; - - /* Don't even bother tracking anything we don't need. */ - if (!no_fbc_on_multiple_pipes(dev_priv)) - return true; - - if (plane_state->uapi.visible) - fbc->visible_pipes_mask |= (1 << pipe); - else - fbc->visible_pipes_mask &= ~(1 << pipe); - - return (fbc->visible_pipes_mask & ~(1 << pipe)) != 0; -} - static int find_compression_threshold(struct drm_i915_private *dev_priv, struct drm_mm_node *node, int size, @@ -867,18 +843,12 @@ void intel_fbc_pre_update(struct intel_crtc *crtc, mutex_lock(&fbc->lock); - if (!multiple_pipes_ok(crtc, plane_state)) { - reason = "more than one pipe active"; - goto deactivate; - } - if (!fbc->enabled || fbc->crtc != crtc) goto unlock; intel_fbc_update_state_cache(crtc, crtc_state, plane_state); fbc->flip_pending = true; -deactivate: intel_fbc_deactivate(dev_priv, reason); unlock: mutex_unlock(&fbc->lock); @@ -1244,28 +1214,6 @@ void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv) schedule_work(&fbc->underrun_work); } -/** - * intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking - * @dev_priv: i915 device instance - * - * The FBC code needs to track CRTC visibility since the older platforms can't - * have FBC enabled while multiple pipes are used. This function does the - * initial setup at driver load to make sure FBC is matching the real hardware. - */ -void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv) -{ - struct intel_crtc *crtc; - - /* Don't even bother tracking anything if we don't need. */ - if (!no_fbc_on_multiple_pipes(dev_priv)) - return; - - for_each_intel_crtc(&dev_priv->drm, crtc) - if (intel_crtc_active(crtc) && - crtc->base.primary->state->visible) - dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe); -} - /* * The DDX driver changes its behavior depending on the value it reads from * i915.enable_fbc, so sanitize it by translating the default value into either diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index f58b0b1e3c5c..3e7905003e4e 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -24,7 +24,6 @@ void intel_fbc_pre_update(struct intel_crtc *crtc, const struct intel_plane_state *plane_state); void intel_fbc_post_update(struct intel_crtc *crtc); void intel_fbc_init(struct drm_i915_private *dev_priv); -void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv); void intel_fbc_enable(struct intel_crtc *crtc, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bae97cd62cb9..d515a9d39e2e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -366,7 +366,6 @@ struct intel_fbc { unsigned threshold; unsigned int possible_framebuffer_bits; unsigned int busy_bits; - unsigned int visible_pipes_mask; struct intel_crtc *crtc; struct drm_mm_node compressed_fb; -- cgit v1.2.3 From 04da7b9f9af63fa2d3eaf2bd3ffab4624f02b449 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:11 +0200 Subject: drm/i915: Relocate intel_crtc_active() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move intel_crtc_active() next to its only remaining user (pre-g4x wm code). Reviewed-by: Lucas De Marchi Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-4-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_display.c | 19 ------------------- drivers/gpu/drm/i915/display/intel_display.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index dbc487daec95..538418b4889d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1045,25 +1045,6 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, NULL, best_clock); } -bool intel_crtc_active(struct intel_crtc *crtc) -{ - /* Be paranoid as we can arrive here with only partial - * state retrieved from the hardware during setup. - * - * We can ditch the adjusted_mode.crtc_clock check as soon - * as Haswell has gained clock readout/fastboot support. - * - * We can ditch the crtc->primary->state->fb check as soon as we can - * properly reconstruct framebuffers. - * - * FIXME: The intel_crtc->active here should be switched to - * crtc->state->active once we have proper CRTC states wired up - * for atomic. - */ - return crtc->active && crtc->base.primary->state->fb && - crtc->config->hw.adjusted_mode.crtc_clock; -} - enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 5ed716a986ad..c03a9675072f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -565,7 +565,6 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, struct dpll *best_clock); int chv_calc_dpll_params(int refclk, struct dpll *pll_clock); -bool intel_crtc_active(struct intel_crtc *crtc); bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state); void hsw_enable_ips(const struct intel_crtc_state *crtc_state); void hsw_disable_ips(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 669d45e6e6d7..7aa5824b15d2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -814,6 +814,25 @@ static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, return plane_state->uapi.visible; } +static bool intel_crtc_active(struct intel_crtc *crtc) +{ + /* Be paranoid as we can arrive here with only partial + * state retrieved from the hardware during setup. + * + * We can ditch the adjusted_mode.crtc_clock check as soon + * as Haswell has gained clock readout/fastboot support. + * + * We can ditch the crtc->primary->state->fb check as soon as we can + * properly reconstruct framebuffers. + * + * FIXME: The intel_crtc->active here should be switched to + * crtc->state->active once we have proper CRTC states wired up + * for atomic. + */ + return crtc->active && crtc->base.primary->state->fb && + crtc->config->hw.adjusted_mode.crtc_clock; +} + static struct intel_crtc *single_enabled_crtc(struct drm_i915_private *dev_priv) { struct intel_crtc *crtc, *enabled = NULL; -- cgit v1.2.3 From 644398586f00f82f91396f0590771c5d512c3061 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:12 +0200 Subject: drm/i915/fbc: Remove the FBC_RT_BASE setup for ILK/SNB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want to use the FBC hardware render tracking so let's not enable it. To use the hw tracking properly we'd anyway need to integrate this into the command submissing path as the register is context saved, and if rendering happens via the ppgtt we'd have to configure it with the ppgtt address instead of the ggtt address. Easier to use software tracking instead. Note that on pre-ilk we can't actually disable render tracking. However we can't rely on it because it requires that DSPSURF to match the render target address, and since we play tricks with DSPSURF that may not be the case. Hence we shall rely on software render tracking on all platforms. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-5-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 8fcd1ceaddc7..20e753749bf8 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -248,8 +248,6 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) } I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset); - I915_WRITE(ILK_FBC_RT_BASE, - i915_ggtt_offset(params->vma) | ILK_FBC_RT_VALID); /* enable it... */ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); -- cgit v1.2.3 From 6f745ba696fd4f34bb7533f92e58679e1f3ca57a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:13 +0200 Subject: drm/i915/fbc: Precompute gen9 cfb stride w/a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precompute the override cfb stride value so that we can check it when determining if flip nuke can be used or not. The hardware has 13 bits for this, so we can shrink the storage to u16 while at it. v2: Don't explode when crtc_state->enable_fbc lies to us Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-6-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 38 ++++++++++++++++++++------------ drivers/gpu/drm/i915/i915_drv.h | 3 ++- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 20e753749bf8..e579f78e4453 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -283,8 +283,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) val &= ~(FBC_STRIDE_OVERRIDE | FBC_STRIDE_MASK); - if (i915_gem_object_get_tiling(params->vma->obj) != - I915_TILING_X) + if (params->gen9_wa_cfb_stride) val |= FBC_STRIDE_OVERRIDE | params->gen9_wa_cfb_stride; I915_WRITE(CHICKEN_MISC_4, val); @@ -414,8 +413,8 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv, static int find_compression_threshold(struct drm_i915_private *dev_priv, struct drm_mm_node *node, - int size, - int fb_cpp) + unsigned int size, + unsigned int fb_cpp) { int compression_threshold = 1; int ret; @@ -461,18 +460,15 @@ again: } } -static int intel_fbc_alloc_cfb(struct intel_crtc *crtc) +static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, + unsigned int size, unsigned int fb_cpp) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; struct drm_mm_node *uninitialized_var(compressed_llb); - int size, fb_cpp, ret; + int ret; WARN_ON(drm_mm_node_allocated(&fbc->compressed_fb)); - size = intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache); - fb_cpp = fbc->state_cache.fb.format->cpp[0]; - ret = find_compression_threshold(dev_priv, &fbc->compressed_fb, size, fb_cpp); if (!ret) @@ -823,9 +819,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache); - if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv)) - params->gen9_wa_cfb_stride = DIV_ROUND_UP(cache->plane.src_w, - 32 * fbc->threshold) * 8; + params->gen9_wa_cfb_stride = cache->gen9_wa_cfb_stride; } void intel_fbc_pre_update(struct intel_crtc *crtc, @@ -1054,6 +1048,8 @@ void intel_fbc_enable(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; + struct intel_fbc_state_cache *cache = &fbc->state_cache; + const struct drm_framebuffer *fb = plane_state->hw.fb; if (!fbc_supported(dev_priv)) return; @@ -1076,11 +1072,25 @@ void intel_fbc_enable(struct intel_crtc *crtc, WARN_ON(fbc->crtc != NULL); intel_fbc_update_state_cache(crtc, crtc_state, plane_state); - if (intel_fbc_alloc_cfb(crtc)) { + + /* FIXME crtc_state->enable_fbc lies :( */ + if (!cache->plane.visible) + goto out; + + if (intel_fbc_alloc_cfb(dev_priv, + intel_fbc_calculate_cfb_size(dev_priv, cache), + fb->format->cpp[0])) { fbc->no_fbc_reason = "not enough stolen memory"; goto out; } + if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && + fb->modifier != I915_FORMAT_MOD_X_TILED) + cache->gen9_wa_cfb_stride = + DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->threshold) * 8; + else + cache->gen9_wa_cfb_stride = 0; + DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe)); fbc->no_fbc_reason = "FBC enabled but not active yet\n"; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d515a9d39e2e..2e99f5d48396 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -417,6 +417,7 @@ struct intel_fbc { const struct drm_format_info *format; unsigned int stride; } fb; + u16 gen9_wa_cfb_stride; } state_cache; /* @@ -442,7 +443,7 @@ struct intel_fbc { } fb; int cfb_size; - unsigned int gen9_wa_cfb_stride; + u16 gen9_wa_cfb_stride; } params; const char *no_fbc_reason; -- cgit v1.2.3 From 8bdbe1befd9d426455017edfaa17d44b387fea82 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:14 +0200 Subject: drm/i915/fbc: Track plane visibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the code (ab)uses cache->vma to indicate the plane visibility. I want to nuke that so let's add a dedicated boolean for this. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-7-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 21 ++++++++++----------- drivers/gpu/drm/i915/i915_drv.h | 1 + 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index e579f78e4453..957b9fb8fd9b 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -634,8 +634,9 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, struct intel_fbc_state_cache *cache = &fbc->state_cache; struct drm_framebuffer *fb = plane_state->hw.fb; - cache->vma = NULL; - cache->flags = 0; + cache->plane.visible = plane_state->uapi.visible; + if (!cache->plane.visible) + return; cache->crtc.mode_flags = crtc_state->hw.adjusted_mode.flags; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) @@ -649,16 +650,12 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, */ cache->plane.src_w = drm_rect_width(&plane_state->uapi.src) >> 16; cache->plane.src_h = drm_rect_height(&plane_state->uapi.src) >> 16; - cache->plane.visible = plane_state->uapi.visible; cache->plane.adjusted_x = plane_state->color_plane[0].x; cache->plane.adjusted_y = plane_state->color_plane[0].y; cache->plane.y = plane_state->uapi.src.y1 >> 16; cache->plane.pixel_blend_mode = plane_state->hw.pixel_blend_mode; - if (!cache->plane.visible) - return; - cache->fb.format = fb->format; cache->fb.stride = fb->pitches[0]; @@ -674,6 +671,11 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc_state_cache *cache = &fbc->state_cache; + if (!cache->plane.visible) { + fbc->no_fbc_reason = "primary plane not visible"; + return false; + } + /* We don't need to use a state cache here since this information is * global for all CRTC. */ @@ -682,11 +684,6 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) return false; } - if (!cache->vma) { - fbc->no_fbc_reason = "primary plane not visible"; - return false; - } - if (cache->crtc.mode_flags & DRM_MODE_FLAG_INTERLACE) { fbc->no_fbc_reason = "incompatible mode"; return false; @@ -820,6 +817,8 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache); params->gen9_wa_cfb_stride = cache->gen9_wa_cfb_stride; + + params->plane_visible = cache->plane.visible; } void intel_fbc_pre_update(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2e99f5d48396..0f318efb92ce 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -444,6 +444,7 @@ struct intel_fbc { int cfb_size; u16 gen9_wa_cfb_stride; + bool plane_visible; } params; const char *no_fbc_reason; -- cgit v1.2.3 From 97a978e2d3a09d261d813c6946d173988e68dcc2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:15 +0200 Subject: drm/i915/fbc: Store fence_id directly in fbc cache/params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than playing around with vma+flags let's just grab the fence id from within and stash that directly in the fbc cache/params. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-8-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 33 +++++++++++++++++--------------- drivers/gpu/drm/i915/i915_drv.h | 8 ++------ 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 957b9fb8fd9b..c198a59dc864 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -151,7 +151,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) if (IS_I945GM(dev_priv)) fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; - fbc_ctl |= params->vma->fence->id; + fbc_ctl |= params->fence_id; I915_WRITE(FBC_CONTROL, fbc_ctl); } @@ -171,8 +171,8 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv) else dpfc_ctl |= DPFC_CTL_LIMIT_1X; - if (params->flags & PLANE_HAS_FENCE) { - dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id; + if (params->fence_id >= 0) { + dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fence_id; I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset); } else { I915_WRITE(DPFC_FENCE_YOFF, 0); @@ -229,14 +229,14 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) break; } - if (params->flags & PLANE_HAS_FENCE) { + if (params->fence_id >= 0) { dpfc_ctl |= DPFC_CTL_FENCE_EN; if (IS_GEN(dev_priv, 5)) - dpfc_ctl |= params->vma->fence->id; + dpfc_ctl |= params->fence_id; if (IS_GEN(dev_priv, 6)) { I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | - params->vma->fence->id); + params->fence_id); I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset); } @@ -309,11 +309,11 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) break; } - if (params->flags & PLANE_HAS_FENCE) { + if (params->fence_id >= 0) { dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | - params->vma->fence->id); + params->fence_id); I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset); } else { I915_WRITE(SNB_DPFC_CTL_SA,0); @@ -659,10 +659,14 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->fb.format = fb->format; cache->fb.stride = fb->pitches[0]; - cache->vma = plane_state->vma; - cache->flags = plane_state->flags; - if (WARN_ON(cache->flags & PLANE_HAS_FENCE && !cache->vma->fence)) - cache->flags &= ~PLANE_HAS_FENCE; + WARN_ON(plane_state->flags & PLANE_HAS_FENCE && + !plane_state->vma->fence); + + if (plane_state->flags & PLANE_HAS_FENCE && + plane_state->vma->fence) + cache->fence_id = plane_state->vma->fence->id; + else + cache->fence_id = -1; } static bool intel_fbc_can_activate(struct intel_crtc *crtc) @@ -707,7 +711,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * For now this will effecively disable FBC with 90/270 degree * rotation. */ - if (!(cache->flags & PLANE_HAS_FENCE)) { + if (cache->fence_id < 0) { fbc->no_fbc_reason = "framebuffer not tiled or fenced"; return false; } @@ -804,8 +808,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, * zero. */ memset(params, 0, sizeof(*params)); - params->vma = cache->vma; - params->flags = cache->flags; + params->fence_id = cache->fence_id; params->crtc.pipe = crtc->pipe; params->crtc.i9xx_plane = to_intel_plane(crtc->base.primary)->i9xx_plane; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0f318efb92ce..4b2d0901bc9c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -386,9 +386,6 @@ struct intel_fbc { * these problems. */ struct intel_fbc_state_cache { - struct i915_vma *vma; - unsigned long flags; - struct { unsigned int mode_flags; u32 hsw_bdw_pixel_rate; @@ -418,6 +415,7 @@ struct intel_fbc { unsigned int stride; } fb; u16 gen9_wa_cfb_stride; + s8 fence_id; } state_cache; /* @@ -428,9 +426,6 @@ struct intel_fbc { * are supposed to read from it in order to program the registers. */ struct intel_fbc_reg_params { - struct i915_vma *vma; - unsigned long flags; - struct { enum pipe pipe; enum i9xx_plane_id i9xx_plane; @@ -444,6 +439,7 @@ struct intel_fbc { int cfb_size; u16 gen9_wa_cfb_stride; + s8 fence_id; bool plane_visible; } params; -- cgit v1.2.3 From 30016696c2e0c0ddfa1f56e26039978f666c8283 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:16 +0200 Subject: drm/i915/fbc: Make fence_id optional for i965gm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i965gm no longer needs the fence for scanout so we should be do what we do for ctg+ and only configure a fence for FBC when we have one. In theory this should do nothing atm on account of intel_fbc_can_activate() requiring the fence, but since we do this for g4x+ let's do it for i965gm as well. We may want to relax the requirements at some point and allow FBC without a fence. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-9-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index c198a59dc864..244afc15c7d1 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -138,8 +138,10 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) u32 fbc_ctl2; /* Set it up... */ - fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; + fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM; fbc_ctl2 |= FBC_CTL_PLANE(params->crtc.i9xx_plane); + if (params->fence_id >= 0) + fbc_ctl2 |= FBC_CTL_CPU_FENCE; I915_WRITE(FBC_CONTROL2, fbc_ctl2); I915_WRITE(FBC_FENCE_OFF, params->crtc.fence_y_offset); } @@ -151,7 +153,8 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) if (IS_I945GM(dev_priv)) fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; - fbc_ctl |= params->fence_id; + if (params->fence_id >= 0) + fbc_ctl |= params->fence_id; I915_WRITE(FBC_CONTROL, fbc_ctl); } -- cgit v1.2.3 From 31ce20c24721ae9ef5312ac81756163babc66e48 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:17 +0200 Subject: drm/i915/fbc: s/gen9 && !glk/gen9_bc || bxt/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the 'gen9 && !glk' with the slightly more obvious 'gen9_bc || bxt'. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-10-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 244afc15c7d1..79218a2dfc42 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -281,7 +281,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) int threshold = dev_priv->fbc.threshold; /* Display WA #0529: skl, kbl, bxt. */ - if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv)) { + if (IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) { u32 val = I915_READ(CHICKEN_MISC_4); val &= ~(FBC_STRIDE_OVERRIDE | FBC_STRIDE_MASK); @@ -1089,7 +1089,7 @@ void intel_fbc_enable(struct intel_crtc *crtc, goto out; } - if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && + if ((IS_GEN9_BC(dev_priv) || IS_BROXTON(dev_priv)) && fb->modifier != I915_FORMAT_MOD_X_TILED) cache->gen9_wa_cfb_stride = DIV_ROUND_UP(cache->plane.src_w, 32 * fbc->threshold) * 8; -- cgit v1.2.3 From c866a0e41640f7f9759b66b96c18d5d2bf35c24b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:18 +0200 Subject: drm/i915/fbc: Nuke fbc.enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fbc.enabled == (fbc.crtc != NULL), so let's just nuke fbc.enabled. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-11-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 23 +++++++++-------------- drivers/gpu/drm/i915/i915_drv.h | 1 - 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 79218a2dfc42..3ade7e67573a 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -840,7 +840,7 @@ void intel_fbc_pre_update(struct intel_crtc *crtc, mutex_lock(&fbc->lock); - if (!fbc->enabled || fbc->crtc != crtc) + if (fbc->crtc != crtc) goto unlock; intel_fbc_update_state_cache(crtc, crtc_state, plane_state); @@ -864,14 +864,13 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv) struct intel_crtc *crtc = fbc->crtc; WARN_ON(!mutex_is_locked(&fbc->lock)); - WARN_ON(!fbc->enabled); + WARN_ON(!fbc->crtc); WARN_ON(fbc->active); DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe)); __intel_fbc_cleanup_cfb(dev_priv); - fbc->enabled = false; fbc->crtc = NULL; } @@ -882,7 +881,7 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc) WARN_ON(!mutex_is_locked(&fbc->lock)); - if (!fbc->enabled || fbc->crtc != crtc) + if (fbc->crtc != crtc) return; fbc->flip_pending = false; @@ -922,7 +921,7 @@ void intel_fbc_post_update(struct intel_crtc *crtc) static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc) { - if (fbc->enabled) + if (fbc->crtc) return to_intel_plane(fbc->crtc->base.primary)->frontbuffer_bit; else return fbc->possible_framebuffer_bits; @@ -944,7 +943,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits; - if (fbc->enabled && fbc->busy_bits) + if (fbc->crtc && fbc->busy_bits) intel_fbc_deactivate(dev_priv, "frontbuffer write"); mutex_unlock(&fbc->lock); @@ -965,7 +964,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv, if (origin == ORIGIN_GTT || origin == ORIGIN_FLIP) goto out; - if (!fbc->busy_bits && fbc->enabled && + if (!fbc->busy_bits && fbc->crtc && (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) { if (fbc->active) intel_fbc_recompress(dev_priv); @@ -1061,8 +1060,7 @@ void intel_fbc_enable(struct intel_crtc *crtc, mutex_lock(&fbc->lock); - if (fbc->enabled) { - WARN_ON(fbc->crtc == NULL); + if (fbc->crtc) { if (fbc->crtc == crtc) { WARN_ON(!crtc_state->enable_fbc); WARN_ON(fbc->active); @@ -1074,7 +1072,6 @@ void intel_fbc_enable(struct intel_crtc *crtc, goto out; WARN_ON(fbc->active); - WARN_ON(fbc->crtc != NULL); intel_fbc_update_state_cache(crtc, crtc_state, plane_state); @@ -1099,7 +1096,6 @@ void intel_fbc_enable(struct intel_crtc *crtc, DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe)); fbc->no_fbc_reason = "FBC enabled but not active yet\n"; - fbc->enabled = true; fbc->crtc = crtc; out: mutex_unlock(&fbc->lock); @@ -1139,7 +1135,7 @@ void intel_fbc_global_disable(struct drm_i915_private *dev_priv) return; mutex_lock(&fbc->lock); - if (fbc->enabled) { + if (fbc->crtc) { WARN_ON(fbc->crtc->active); __intel_fbc_disable(dev_priv); } @@ -1155,7 +1151,7 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work) mutex_lock(&fbc->lock); /* Maybe we were scheduled twice. */ - if (fbc->underrun_detected || !fbc->enabled) + if (fbc->underrun_detected || !fbc->crtc) goto out; DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n"); @@ -1278,7 +1274,6 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn); mutex_init(&fbc->lock); - fbc->enabled = false; fbc->active = false; if (!drm_mm_initialized(&dev_priv->mm.stolen)) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4b2d0901bc9c..729f542d5de2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -373,7 +373,6 @@ struct intel_fbc { bool false_color; - bool enabled; bool active; bool flip_pending; -- cgit v1.2.3 From 6252bb78fcc30f3d5166e7af98a6f403fddc46cf Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:19 +0200 Subject: drm/i915/fbc: Start using flip nuke MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware automagically nukes the cfb on flip. We can use that whenever the plane/crtc configuration doesn't change too much. Let's hook that up. We'll need this for glk+ since we need to introduce an extra vblank wait after FBC disable. As we're currently disabling FBC around all plane updates we'd slow them down by an extra frame. Not a great user experience when your fps is always capped at vrefres/2. With flip nuke we don't need the extra vblank wait. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-12-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 50 +++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 3ade7e67573a..c6ab5a051883 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -68,7 +68,7 @@ static unsigned int get_crtc_fence_y_offset(struct intel_fbc *fbc) * write to the PLANE_SIZE register. For BDW-, the hardware looks at the value * we wrote to PIPESRC. */ -static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache, +static void intel_fbc_get_plane_source_size(const struct intel_fbc_state_cache *cache, int *width, int *height) { if (width) @@ -78,7 +78,7 @@ static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache, } static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv, - struct intel_fbc_state_cache *cache) + const struct intel_fbc_state_cache *cache) { int lines; @@ -827,6 +827,38 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->plane_visible = cache->plane.visible; } +static bool intel_fbc_can_flip_nuke(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_fbc *fbc = &dev_priv->fbc; + const struct intel_fbc_state_cache *cache = &fbc->state_cache; + const struct intel_fbc_reg_params *params = &fbc->params; + + if (drm_atomic_crtc_needs_modeset(&crtc_state->uapi)) + return false; + + if (!params->plane_visible) + return false; + + if (!intel_fbc_can_activate(crtc)) + return false; + + if (params->fb.format != cache->fb.format) + return false; + + if (params->fb.stride != cache->fb.stride) + return false; + + if (params->cfb_size != intel_fbc_calculate_cfb_size(dev_priv, cache)) + return false; + + if (params->gen9_wa_cfb_stride != cache->gen9_wa_cfb_stride) + return false; + + return true; +} + void intel_fbc_pre_update(struct intel_crtc *crtc, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) @@ -846,7 +878,8 @@ void intel_fbc_pre_update(struct intel_crtc *crtc, intel_fbc_update_state_cache(crtc, crtc_state, plane_state); fbc->flip_pending = true; - intel_fbc_deactivate(dev_priv, reason); + if (!intel_fbc_can_flip_nuke(crtc_state)) + intel_fbc_deactivate(dev_priv, reason); unlock: mutex_unlock(&fbc->lock); } @@ -885,7 +918,6 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc) return; fbc->flip_pending = false; - WARN_ON(fbc->active); if (!i915_modparams.enable_fbc) { intel_fbc_deactivate(dev_priv, "disabled at runtime per module param"); @@ -899,10 +931,9 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc) if (!intel_fbc_can_activate(crtc)) return; - if (!fbc->busy_bits) { - intel_fbc_deactivate(dev_priv, "FBC enabled (active or scheduled)"); + if (!fbc->busy_bits) intel_fbc_hw_activate(dev_priv); - } else + else intel_fbc_deactivate(dev_priv, "frontbuffer write"); } @@ -1061,10 +1092,7 @@ void intel_fbc_enable(struct intel_crtc *crtc, mutex_lock(&fbc->lock); if (fbc->crtc) { - if (fbc->crtc == crtc) { - WARN_ON(!crtc_state->enable_fbc); - WARN_ON(fbc->active); - } + WARN_ON(fbc->crtc == crtc && !crtc_state->enable_fbc); goto out; } -- cgit v1.2.3 From 07fd0df822cc1818fe8ef9760f9f51116789da5e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 28 Nov 2019 17:03:38 +0200 Subject: drm/i915/fbc: Wait for vblank after FBC disable on glk+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On glk+ the hardware gets confused if we disable FBC while it's recompressing and we perform a plane update during the same frame. The result is that top of the screen gets corrupted. We can avoid that by giving the hardware enough time to finish the FBC disable before we touch the plane registers. Ie. we need an extra vblank wait after FBC disable. v2: Don't do the vblank wait if we never activated FBC in hw Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191128150338.12490-1-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++++ drivers/gpu/drm/i915/display/intel_fbc.c | 29 +++++++++++++++++++++++++--- drivers/gpu/drm/i915/display/intel_fbc.h | 2 +- drivers/gpu/drm/i915/i915_drv.h | 1 + 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 538418b4889d..5c50b7d2db25 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6063,6 +6063,10 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state)) hsw_disable_ips(old_crtc_state); + if (new_primary_state && + intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state)) + intel_wait_for_vblank(dev_priv, pipe); + if (new_primary_state) intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index c6ab5a051883..68416e312e5c 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -362,6 +362,7 @@ static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv) struct intel_fbc *fbc = &dev_priv->fbc; fbc->active = true; + fbc->activated = true; if (INTEL_GEN(dev_priv) >= 7) gen7_fbc_activate(dev_priv); @@ -859,16 +860,17 @@ static bool intel_fbc_can_flip_nuke(const struct intel_crtc_state *crtc_state) return true; } -void intel_fbc_pre_update(struct intel_crtc *crtc, +bool intel_fbc_pre_update(struct intel_crtc *crtc, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_fbc *fbc = &dev_priv->fbc; const char *reason = "update pending"; + bool need_vblank_wait = false; if (!fbc_supported(dev_priv)) - return; + return need_vblank_wait; mutex_lock(&fbc->lock); @@ -878,10 +880,31 @@ void intel_fbc_pre_update(struct intel_crtc *crtc, intel_fbc_update_state_cache(crtc, crtc_state, plane_state); fbc->flip_pending = true; - if (!intel_fbc_can_flip_nuke(crtc_state)) + if (!intel_fbc_can_flip_nuke(crtc_state)) { intel_fbc_deactivate(dev_priv, reason); + + /* + * Display WA #1198: glk+ + * Need an extra vblank wait between FBC disable and most plane + * updates. Bspec says this is only needed for plane disable, but + * that is not true. Touching most plane registers will cause the + * corruption to appear. Also SKL/derivatives do not seem to be + * affected. + * + * TODO: could optimize this a bit by sampling the frame + * counter when we disable FBC (if it was already done earlier) + * and skipping the extra vblank wait before the plane update + * if at least one frame has already passed. + */ + if (fbc->activated && + (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))) + need_vblank_wait = true; + fbc->activated = false; + } unlock: mutex_unlock(&fbc->lock); + + return need_vblank_wait; } /** diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index 3e7905003e4e..c8a5e5098687 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -19,7 +19,7 @@ struct intel_plane_state; void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, struct intel_atomic_state *state); bool intel_fbc_is_active(struct drm_i915_private *dev_priv); -void intel_fbc_pre_update(struct intel_crtc *crtc, +bool intel_fbc_pre_update(struct intel_crtc *crtc, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); void intel_fbc_post_update(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 729f542d5de2..ce130e1f1e47 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -374,6 +374,7 @@ struct intel_fbc { bool false_color; bool active; + bool activated; bool flip_pending; bool underrun_detected; -- cgit v1.2.3 From 34cddbc03b13e3d18ba94ad59767768cf08f9e07 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:21 +0200 Subject: drm/i915/fbc: Enable fbc by default on glk+ once again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have the glk+ w/a for back to back fbc disable + plane update in place we can once more enable fbc on glk+ by default. Cc: Daniel Drake Cc: Paulo Zanoni Cc: Jian-Hong Pan Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-14-ville.syrjala@linux.intel.com Tested-by: Daniel Drake Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 68416e312e5c..3c50c1a79e81 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1291,10 +1291,6 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) if (!HAS_FBC(dev_priv)) return 0; - /* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */ - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) - return 0; - if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) return 1; -- cgit v1.2.3 From e10ad9c697463f0647fa684e5425aefc5fa611f4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 27 Nov 2019 22:12:22 +0200 Subject: drm/i915/fbc: Reallocate cfb if we need more of it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code assumes we can omit the cfb allocation once fbc has been enabled once. That's nonsense. Let's try to reallocate it if we need to. The code is still a mess, but maybe this is enough to get fbc going in some cases where it initially underallocates the cfb and there's no full modeset to fix it up. Cc: Daniel Drake Cc: Paulo Zanoni Cc: Jian-Hong Pan Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191127201222.16669-15-ville.syrjala@linux.intel.com Tested-by: Daniel Drake Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/display/intel_fbc.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 3c50c1a79e81..6f1d5c032681 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -673,6 +673,14 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->fence_id = -1; } +static bool intel_fbc_cfb_size_changed(struct drm_i915_private *dev_priv) +{ + struct intel_fbc *fbc = &dev_priv->fbc; + + return intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) > + fbc->compressed_fb.size * fbc->threshold; +} + static bool intel_fbc_can_activate(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -758,8 +766,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * we didn't get any invalidate/deactivate calls, but this would require * a lot of tracking just for a specific case. If we conclude it's an * important case, we can implement it later. */ - if (intel_fbc_calculate_cfb_size(dev_priv, &fbc->state_cache) > - fbc->compressed_fb.size * fbc->threshold) { + if (intel_fbc_cfb_size_changed(dev_priv)) { fbc->no_fbc_reason = "CFB requirements changed"; return false; } @@ -1115,12 +1122,12 @@ void intel_fbc_enable(struct intel_crtc *crtc, mutex_lock(&fbc->lock); if (fbc->crtc) { - WARN_ON(fbc->crtc == crtc && !crtc_state->enable_fbc); - goto out; - } + if (fbc->crtc != crtc || + !intel_fbc_cfb_size_changed(dev_priv)) + goto out; - if (!crtc_state->enable_fbc) - goto out; + __intel_fbc_disable(dev_priv); + } WARN_ON(fbc->active); @@ -1133,6 +1140,7 @@ void intel_fbc_enable(struct intel_crtc *crtc, if (intel_fbc_alloc_cfb(dev_priv, intel_fbc_calculate_cfb_size(dev_priv, cache), fb->format->cpp[0])) { + cache->plane.visible = false; fbc->no_fbc_reason = "not enough stolen memory"; goto out; } -- cgit v1.2.3 From 67e1d5ed85a83e232a9e0b995f5778a86722b96e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 4 Dec 2019 20:05:41 +0200 Subject: drm/i915/hdcp: Nuke intel_hdcp_transcoder_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_hdcp_transcoder_config() is clobbering some globally visible state in .compute_config(). That is a big no no as .compute_config() is supposed to have no visible side effects when either the commit fails or it's just a TEST_ONLY commit. Inline this stuff into intel_hdcp_enable() so that the state only gets modified when we actually commit the state to the hardware. Cc: Ramalingam C Cc: Jani Nikula Cc: Uma Shankar Fixes: 39e2df090c3c ("drm/i915/hdcp: update current transcoder into intel_hdcp") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191204180549.1267-2-ville.syrjala@linux.intel.com Reviewed-by: Ramalingam C --- drivers/gpu/drm/i915/display/intel_ddi.c | 5 ++++- drivers/gpu/drm/i915/display/intel_dp.c | 3 --- drivers/gpu/drm/i915/display/intel_hdcp.c | 26 ++++++++------------------ drivers/gpu/drm/i915/display/intel_hdcp.h | 5 ++--- drivers/gpu/drm/i915/display/intel_hdmi.c | 3 --- 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3cacb1e279c1..3e81c54c349e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4034,6 +4034,7 @@ static void intel_enable_ddi(struct intel_encoder *encoder, if (conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) intel_hdcp_enable(to_intel_connector(conn_state->connector), + crtc_state->cpu_transcoder, (u8)conn_state->hdcp_content_type); } @@ -4137,7 +4138,9 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder, if (conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED || content_protection_type_changed) - intel_hdcp_enable(connector, (u8)conn_state->hdcp_content_type); + intel_hdcp_enable(connector, + crtc_state->cpu_transcoder, + (u8)conn_state->hdcp_content_type); } static void diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6611119b9f9b..5b1a24432e85 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2425,9 +2425,6 @@ intel_dp_compute_config(struct intel_encoder *encoder, intel_psr_compute_config(intel_dp, pipe_config); - intel_hdcp_transcoder_config(intel_connector, - pipe_config->cpu_transcoder); - return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 001ce27d7029..0fdbd39f6641 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -1821,23 +1821,6 @@ enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } } -void intel_hdcp_transcoder_config(struct intel_connector *connector, - enum transcoder cpu_transcoder) -{ - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct intel_hdcp *hdcp = &connector->hdcp; - - if (!hdcp->shim) - return; - - if (INTEL_GEN(dev_priv) >= 12) { - mutex_lock(&hdcp->mutex); - hdcp->cpu_transcoder = cpu_transcoder; - hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder); - mutex_unlock(&hdcp->mutex); - } -} - static inline int initialize_hdcp_port_data(struct intel_connector *connector, const struct intel_hdcp_shim *shim) { @@ -1959,8 +1942,10 @@ int intel_hdcp_init(struct intel_connector *connector, return 0; } -int intel_hdcp_enable(struct intel_connector *connector, u8 content_type) +int intel_hdcp_enable(struct intel_connector *connector, + enum transcoder cpu_transcoder, u8 content_type) { + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; int ret = -EINVAL; @@ -1972,6 +1957,11 @@ int intel_hdcp_enable(struct intel_connector *connector, u8 content_type) WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); hdcp->content_type = content_type; + if (INTEL_GEN(dev_priv) >= 12) { + hdcp->cpu_transcoder = cpu_transcoder; + hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder); + } + /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h index 41c1053d9e38..f3c3272e712a 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp.h @@ -21,11 +21,10 @@ enum transcoder; void intel_hdcp_atomic_check(struct drm_connector *connector, struct drm_connector_state *old_state, struct drm_connector_state *new_state); -void intel_hdcp_transcoder_config(struct intel_connector *connector, - enum transcoder cpu_transcoder); int intel_hdcp_init(struct intel_connector *connector, const struct intel_hdcp_shim *hdcp_shim); -int intel_hdcp_enable(struct intel_connector *connector, u8 content_type); +int intel_hdcp_enable(struct intel_connector *connector, + enum transcoder cpu_transcoder, u8 content_type); int intel_hdcp_disable(struct intel_connector *connector); bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port); bool intel_hdcp_capable(struct intel_connector *connector); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 29a174af5314..a89a09b25260 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2490,9 +2490,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, return -EINVAL; } - intel_hdcp_transcoder_config(intel_hdmi->attached_connector, - pipe_config->cpu_transcoder); - return 0; } -- cgit v1.2.3 From d54dc6eede681e5fa81a69c51e97be07175e6011 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Thu, 5 Dec 2019 14:02:39 -0800 Subject: drm/i915/guc: Drop leftover preemption code Remove unused enums and ctx_save_restore_disabled() function, leftover from the legacy preemption removal. Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191205220243.27403-1-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 4df296a5e7c7..5975870667a6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -18,15 +18,6 @@ #include "i915_drv.h" #include "i915_trace.h" -enum { - GUC_PREEMPT_NONE = 0, - GUC_PREEMPT_INPROGRESS, - GUC_PREEMPT_FINISHED, -}; -#define GUC_PREEMPT_BREADCRUMB_DWORDS 0x8 -#define GUC_PREEMPT_BREADCRUMB_BYTES \ - (sizeof(u32) * GUC_PREEMPT_BREADCRUMB_DWORDS) - /** * DOC: GuC-based command submission * @@ -883,19 +874,6 @@ static void guc_client_free(struct intel_guc_client *client) kfree(client); } -static inline bool ctx_save_restore_disabled(struct intel_context *ce) -{ - u32 sr = ce->lrc_reg_state[CTX_CONTEXT_CONTROL + 1]; - -#define SR_DISABLED \ - _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | \ - CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT) - - return (sr & SR_DISABLED) == SR_DISABLED; - -#undef SR_DISABLED -} - static int guc_clients_create(struct intel_guc *guc) { struct intel_guc_client *client; -- cgit v1.2.3 From 18c094b304046335fc9a4bce8ec3a2ac33edab8e Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Thu, 5 Dec 2019 14:02:40 -0800 Subject: drm/i915/guc: add a helper to allocate and map guc vma We already have a couple of use-cases in the code and another one will come in one of the later patches in the series. v2: use the new function for the CT object as well Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: Chris Wilson #v1 Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20191205220243.27403-2-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 34 +++++++++++++++++++++++ drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 21 +++----------- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 25 ++++------------- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 22 +++++---------- 5 files changed, 52 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 3ee4a4e7689d..922a19635d20 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -704,3 +704,37 @@ err: i915_gem_object_put(obj); return vma; } + +/** + * intel_guc_allocate_and_map_vma() - Allocate and map VMA for GuC usage + * @guc: the guc + * @size: size of area to allocate (both virtual space and memory) + * @out_vma: return variable for the allocated vma pointer + * @out_vaddr: return variable for the obj mapping + * + * This wrapper calls intel_guc_allocate_vma() and then maps the allocated + * object with I915_MAP_WB. + * + * Return: 0 if successful, a negative errno code otherwise. + */ +int intel_guc_allocate_and_map_vma(struct intel_guc *guc, u32 size, + struct i915_vma **out_vma, void **out_vaddr) +{ + struct i915_vma *vma; + void *vaddr; + + vma = intel_guc_allocate_vma(guc, size); + if (IS_ERR(vma)) + return PTR_ERR(vma); + + vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); + if (IS_ERR(vaddr)) { + i915_vma_unpin_and_release(&vma, 0); + return PTR_ERR(vaddr); + } + + *out_vma = vma; + *out_vaddr = vaddr; + + return 0; +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index e6400204a2bd..bf438f820c35 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -149,6 +149,8 @@ int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset); int intel_guc_suspend(struct intel_guc *guc); int intel_guc_resume(struct intel_guc *guc); struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); +int intel_guc_allocate_and_map_vma(struct intel_guc *guc, u32 size, + struct i915_vma **out_vma, void **out_vaddr); static inline bool intel_guc_is_supported(struct intel_guc *guc) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 05ca90456a2c..101728006ae9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -136,32 +136,19 @@ static void __guc_ads_init(struct intel_guc *guc) int intel_guc_ads_create(struct intel_guc *guc) { const u32 size = PAGE_ALIGN(sizeof(struct __guc_ads_blob)); - struct i915_vma *vma; - void *blob; int ret; GEM_BUG_ON(guc->ads_vma); - vma = intel_guc_allocate_vma(guc, size); - if (IS_ERR(vma)) - return PTR_ERR(vma); + ret = intel_guc_allocate_and_map_vma(guc, size, &guc->ads_vma, + (void **)&guc->ads_blob); - blob = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); - if (IS_ERR(blob)) { - ret = PTR_ERR(blob); - goto err_vma; - } - - guc->ads_vma = vma; - guc->ads_blob = blob; + if (ret) + return ret; __guc_ads_init(guc); return 0; - -err_vma: - i915_vma_unpin_and_release(&guc->ads_vma, 0); - return ret; } void intel_guc_ads_destroy(struct intel_guc *guc) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index b49115517510..5fb7f957edf9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -125,7 +125,6 @@ static int guc_action_deregister_ct_buffer(struct intel_guc *guc, static int ctch_init(struct intel_guc *guc, struct intel_guc_ct_channel *ctch) { - struct i915_vma *vma; void *blob; int err; int i; @@ -154,20 +153,13 @@ static int ctch_init(struct intel_guc *guc, * other code will need updating as well. */ - /* allocate vma */ - vma = intel_guc_allocate_vma(guc, PAGE_SIZE); - if (IS_ERR(vma)) { - err = PTR_ERR(vma); - goto err_out; + err = intel_guc_allocate_and_map_vma(guc, PAGE_SIZE, &ctch->vma, &blob); + if (err) { + CT_DEBUG_DRIVER("CT: channel %d initialization failed; err=%d\n", + ctch->owner, err); + return err; } - ctch->vma = vma; - /* map first page */ - blob = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); - if (IS_ERR(blob)) { - err = PTR_ERR(blob); - goto err_vma; - } CT_DEBUG_DRIVER("CT: vma base=%#x\n", intel_guc_ggtt_offset(guc, ctch->vma)); @@ -179,13 +171,6 @@ static int ctch_init(struct intel_guc *guc, } return 0; - -err_vma: - i915_vma_unpin_and_release(&ctch->vma, 0); -err_out: - CT_DEBUG_DRIVER("CT: channel %d initialization failed; err=%d\n", - ctch->owner, err); - return err; } static void ctch_fini(struct intel_guc *guc, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 5975870667a6..bb3af8eb0cc0 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -308,23 +308,15 @@ static void guc_proc_desc_fini(struct intel_guc_client *client) static int guc_stage_desc_pool_create(struct intel_guc *guc) { - struct i915_vma *vma; - void *vaddr; - - vma = intel_guc_allocate_vma(guc, - PAGE_ALIGN(sizeof(struct guc_stage_desc) * - GUC_MAX_STAGE_DESCRIPTORS)); - if (IS_ERR(vma)) - return PTR_ERR(vma); + u32 size = PAGE_ALIGN(sizeof(struct guc_stage_desc) * + GUC_MAX_STAGE_DESCRIPTORS); + int ret; - vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); - if (IS_ERR(vaddr)) { - i915_vma_unpin_and_release(&vma, 0); - return PTR_ERR(vaddr); - } + ret = intel_guc_allocate_and_map_vma(guc, size, &guc->stage_desc_pool, + &guc->stage_desc_pool_vaddr); + if (ret) + return ret; - guc->stage_desc_pool = vma; - guc->stage_desc_pool_vaddr = vaddr; ida_init(&guc->stage_ids); return 0; -- cgit v1.2.3 From e9362e1336feb1e942da036aba9ec2aeffe9e4d2 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Thu, 5 Dec 2019 14:02:41 -0800 Subject: drm/i915/guc: kill doorbell code and selftests Instead of relying on the workqueue, the upcoming reworked GuC submission flow will offer the host driver indipendent control over the execution status of each context submitted to GuC. As part of this, the doorbell usage model has been reworked, with each doorbell being paired to a single lrc and a doorbell ring representing new work available for that specific context. This mechanism, however, limits the number of contexts that can be registered with GuC to the number of doorbells, which is an undesired limitation. To avoid this limitation, we requested the GuC team to also provide a H2G that will allow the host to notify the GuC of work available for a specified lrc, so we can use that mechanism instead of relying on the doorbells. We can therefore drop the doorbell code we currently have, also given the fact that in the unlikely case we'd want to switch back to using doorbells we'd have to heavily rework it. The workqueue will still have a use in the new interface to pass special commands, so that code has been retained for now. With the doorbells gone and the GuC client becoming even simpler, the existing GuC selftests don't give us any meaningful coverage so we can remove them as well. Some selftests might come with the new code, but they will look different from what we have now so if doesn't seem worth it to keep the file around in the meantime. v2: fix comments and commit message (John) Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20191205220243.27403-3-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 8 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 376 ++------------------- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h | 9 +- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 7 +- drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 299 ---------------- drivers/gpu/drm/i915/i915_debugfs.c | 11 +- .../gpu/drm/i915/selftests/i915_live_selftests.h | 1 - 8 files changed, 44 insertions(+), 669 deletions(-) delete mode 100644 drivers/gpu/drm/i915/gt/uc/selftest_guc.c diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index bf438f820c35..b2d1766e689a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -20,8 +20,8 @@ struct __guc_ads_blob; /* * Top level structure of GuC. It handles firmware loading and manages client - * pool and doorbells. intel_guc owns a intel_guc_client to replace the legacy - * ExecList submission. + * pool. intel_guc owns a intel_guc_client to replace the legacy ExecList + * submission. */ struct intel_guc { struct intel_uc_fw fw; @@ -50,10 +50,6 @@ struct intel_guc { struct intel_guc_client *execbuf_client; - DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS); - /* Cyclic counter mod pagesize */ - u32 db_cacheline; - /* Control params for fw initialization */ u32 params[GUC_CTL_MAX_DWORDS]; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index a26a85d50209..1e8e4af7d9ca 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -31,7 +31,7 @@ #define GUC_DOORBELL_INVALID 256 -#define GUC_DB_SIZE (PAGE_SIZE) +#define GUC_PD_SIZE (PAGE_SIZE) #define GUC_WQ_SIZE (PAGE_SIZE * 2) /* Work queue item header definitions */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index bb3af8eb0cc0..334bd4ded642 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -30,8 +30,8 @@ * GuC client: * A intel_guc_client refers to a submission path through GuC. Currently, there * is only one client, which is charged with all submissions to the GuC. This - * struct is the owner of a doorbell, a process descriptor and a workqueue (all - * of them inside a single gem object that contains all required pages for these + * struct is the owner of a process descriptor and a workqueue (both of them + * inside a single gem object that contains all required pages for these * elements). * * GuC stage descriptor: @@ -39,13 +39,13 @@ * descriptors, and shares them with the GuC. * Currently, there exists a 1:1 mapping between a intel_guc_client and a * guc_stage_desc (via the client's stage_id), so effectively only one - * gets used. This stage descriptor lets the GuC know about the doorbell, - * workqueue and process descriptor. Theoretically, it also lets the GuC - * know about our HW contexts (context ID, etc...), but we actually - * employ a kind of submission where the GuC uses the LRCA sent via the work - * item instead (the single guc_stage_desc associated to execbuf client - * contains information about the default kernel context only, but this is - * essentially unused). This is called a "proxy" submission. + * gets used. This stage descriptor lets the GuC know about the workqueue and + * process descriptor. Theoretically, it also lets the GuC know about our HW + * contexts (context ID, etc...), but we actually employ a kind of submission + * where the GuC uses the LRCA sent via the work item instead (the single + * guc_stage_desc associated to execbuf client contains information about the + * default kernel context only, but this is essentially unused). This is called + * a "proxy" submission. * * The Scratch registers: * There are 16 MMIO-based registers start from 0xC180. The kernel driver writes @@ -56,10 +56,6 @@ * then proceeds. * See intel_guc_send() * - * Doorbells: - * Doorbells are interrupts to uKernel. A doorbell is a single cache line (QW) - * mapped into process space. - * * Work Items: * There are several types of work items that the host may place into a * workqueue, each with its own requirements and limitations. Currently only @@ -81,78 +77,6 @@ static inline bool is_high_priority(struct intel_guc_client *client) client->priority == GUC_CLIENT_PRIORITY_HIGH); } -static int reserve_doorbell(struct intel_guc_client *client) -{ - unsigned long offset; - unsigned long end; - u16 id; - - GEM_BUG_ON(client->doorbell_id != GUC_DOORBELL_INVALID); - - /* - * The bitmap tracks which doorbell registers are currently in use. - * It is split into two halves; the first half is used for normal - * priority contexts, the second half for high-priority ones. - */ - offset = 0; - end = GUC_NUM_DOORBELLS / 2; - if (is_high_priority(client)) { - offset = end; - end += offset; - } - - id = find_next_zero_bit(client->guc->doorbell_bitmap, end, offset); - if (id == end) - return -ENOSPC; - - __set_bit(id, client->guc->doorbell_bitmap); - client->doorbell_id = id; - DRM_DEBUG_DRIVER("client %u (high prio=%s) reserved doorbell: %d\n", - client->stage_id, yesno(is_high_priority(client)), - id); - return 0; -} - -static bool has_doorbell(struct intel_guc_client *client) -{ - if (client->doorbell_id == GUC_DOORBELL_INVALID) - return false; - - return test_bit(client->doorbell_id, client->guc->doorbell_bitmap); -} - -static void unreserve_doorbell(struct intel_guc_client *client) -{ - GEM_BUG_ON(!has_doorbell(client)); - - __clear_bit(client->doorbell_id, client->guc->doorbell_bitmap); - client->doorbell_id = GUC_DOORBELL_INVALID; -} - -/* - * Tell the GuC to allocate or deallocate a specific doorbell - */ - -static int __guc_allocate_doorbell(struct intel_guc *guc, u32 stage_id) -{ - u32 action[] = { - INTEL_GUC_ACTION_ALLOCATE_DOORBELL, - stage_id - }; - - return intel_guc_send(guc, action, ARRAY_SIZE(action)); -} - -static int __guc_deallocate_doorbell(struct intel_guc *guc, u32 stage_id) -{ - u32 action[] = { - INTEL_GUC_ACTION_DEALLOCATE_DOORBELL, - stage_id - }; - - return intel_guc_send(guc, action, ARRAY_SIZE(action)); -} - static struct guc_stage_desc *__get_stage_desc(struct intel_guc_client *client) { struct guc_stage_desc *base = client->guc->stage_desc_pool_vaddr; @@ -160,118 +84,10 @@ static struct guc_stage_desc *__get_stage_desc(struct intel_guc_client *client) return &base[client->stage_id]; } -/* - * Initialise, update, or clear doorbell data shared with the GuC - * - * These functions modify shared data and so need access to the mapped - * client object which contains the page being used for the doorbell - */ - -static void __update_doorbell_desc(struct intel_guc_client *client, u16 new_id) -{ - struct guc_stage_desc *desc; - - /* Update the GuC's idea of the doorbell ID */ - desc = __get_stage_desc(client); - desc->db_id = new_id; -} - -static struct guc_doorbell_info *__get_doorbell(struct intel_guc_client *client) -{ - return client->vaddr + client->doorbell_offset; -} - -static bool __doorbell_valid(struct intel_guc *guc, u16 db_id) -{ - struct intel_uncore *uncore = guc_to_gt(guc)->uncore; - - GEM_BUG_ON(db_id >= GUC_NUM_DOORBELLS); - return intel_uncore_read(uncore, GEN8_DRBREGL(db_id)) & GEN8_DRB_VALID; -} - -static void __init_doorbell(struct intel_guc_client *client) -{ - struct guc_doorbell_info *doorbell; - - doorbell = __get_doorbell(client); - doorbell->db_status = GUC_DOORBELL_ENABLED; - doorbell->cookie = 0; -} - -static void __fini_doorbell(struct intel_guc_client *client) -{ - struct guc_doorbell_info *doorbell; - u16 db_id = client->doorbell_id; - - doorbell = __get_doorbell(client); - doorbell->db_status = GUC_DOORBELL_DISABLED; - - /* Doorbell release flow requires that we wait for GEN8_DRB_VALID bit - * to go to zero after updating db_status before we call the GuC to - * release the doorbell - */ - if (wait_for_us(!__doorbell_valid(client->guc, db_id), 10)) - WARN_ONCE(true, "Doorbell never became invalid after disable\n"); -} - -static int create_doorbell(struct intel_guc_client *client) -{ - int ret; - - if (WARN_ON(!has_doorbell(client))) - return -ENODEV; /* internal setup error, should never happen */ - - __update_doorbell_desc(client, client->doorbell_id); - __init_doorbell(client); - - ret = __guc_allocate_doorbell(client->guc, client->stage_id); - if (ret) { - __fini_doorbell(client); - __update_doorbell_desc(client, GUC_DOORBELL_INVALID); - DRM_DEBUG_DRIVER("Couldn't create client %u doorbell: %d\n", - client->stage_id, ret); - return ret; - } - - return 0; -} - -static int destroy_doorbell(struct intel_guc_client *client) -{ - int ret; - - GEM_BUG_ON(!has_doorbell(client)); - - __fini_doorbell(client); - ret = __guc_deallocate_doorbell(client->guc, client->stage_id); - if (ret) - DRM_ERROR("Couldn't destroy client %u doorbell: %d\n", - client->stage_id, ret); - - __update_doorbell_desc(client, GUC_DOORBELL_INVALID); - - return ret; -} - -static unsigned long __select_cacheline(struct intel_guc *guc) -{ - unsigned long offset; - - /* Doorbell uses a single cache line within a page */ - offset = offset_in_page(guc->db_cacheline); - - /* Moving to next cache line to reduce contention */ - guc->db_cacheline += cache_line_size(); - - DRM_DEBUG_DRIVER("reserved cacheline 0x%lx, next 0x%x, linesize %u\n", - offset, guc->db_cacheline, cache_line_size()); - return offset; -} - static inline struct guc_process_desc * __get_process_desc(struct intel_guc_client *client) { - return client->vaddr + client->proc_desc_offset; + return client->vaddr; } /* @@ -332,8 +148,8 @@ static void guc_stage_desc_pool_destroy(struct intel_guc *guc) * Initialise/clear the stage descriptor shared with the GuC firmware. * * This descriptor tells the GuC where (in GGTT space) to find the important - * data structures relating to this client (doorbell, process descriptor, - * write queue, etc). + * data structures relating to this client (process descriptor, write queue, + * etc). */ static void guc_stage_desc_init(struct intel_guc_client *client) { @@ -350,19 +166,14 @@ static void guc_stage_desc_init(struct intel_guc_client *client) desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT; desc->stage_id = client->stage_id; desc->priority = client->priority; - desc->db_id = client->doorbell_id; /* - * The doorbell, process descriptor, and workqueue are all parts - * of the client object, which the GuC will reference via the GGTT + * The process descriptor and workqueue are all parts of the client + * object, which the GuC will reference via the GGTT */ gfx_addr = intel_guc_ggtt_offset(guc, client->vma); - desc->db_trigger_phy = sg_dma_address(client->vma->pages->sgl) + - client->doorbell_offset; - desc->db_trigger_cpu = ptr_to_u64(__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 + GUC_DB_SIZE; + desc->process_desc = gfx_addr; + desc->wq_addr = gfx_addr + GUC_PD_SIZE; desc->wq_size = GUC_WQ_SIZE; desc->desc_private = ptr_to_u64(client); @@ -408,48 +219,23 @@ static void guc_wq_item_append(struct intel_guc_client *client, GUC_WQ_SIZE) < wqi_size); GEM_BUG_ON(wq_off & (wqi_size - 1)); - /* WQ starts from the page after doorbell / process_desc */ - wqi = client->vaddr + wq_off + GUC_DB_SIZE; - - if (I915_SELFTEST_ONLY(client->use_nop_wqi)) { - wqi->header = WQ_TYPE_NOOP | (wqi_len << WQ_LEN_SHIFT); - } else { - /* Now fill in the 4-word work queue item */ - wqi->header = WQ_TYPE_INORDER | - (wqi_len << WQ_LEN_SHIFT) | - (target_engine << WQ_TARGET_SHIFT) | - WQ_NO_WCFLUSH_WAIT; - wqi->context_desc = context_desc; - wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT; - GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX); - wqi->fence_id = fence_id; - } + /* WQ starts from the page after process_desc */ + wqi = client->vaddr + wq_off + GUC_PD_SIZE; + + /* Now fill in the 4-word work queue item */ + wqi->header = WQ_TYPE_INORDER | + (wqi_len << WQ_LEN_SHIFT) | + (target_engine << WQ_TARGET_SHIFT) | + WQ_NO_WCFLUSH_WAIT; + wqi->context_desc = context_desc; + wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT; + GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX); + wqi->fence_id = fence_id; /* Make the update visible to GuC */ WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1)); } -static void guc_ring_doorbell(struct intel_guc_client *client) -{ - struct guc_doorbell_info *db; - u32 cookie; - - lockdep_assert_held(&client->wq_lock); - - /* pointer of current doorbell cacheline */ - db = __get_doorbell(client); - - /* - * We're not expecting the doorbell cookie to change behind our back, - * we also need to treat 0 as a reserved value. - */ - cookie = READ_ONCE(db->cookie); - WARN_ON_ONCE(xchg(&db->cookie, cookie + 1 ?: cookie + 2) != cookie); - - /* XXX: doorbell was lost and need to acquire it again */ - GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED); -} - static void guc_add_request(struct intel_guc *guc, struct i915_request *rq) { struct intel_guc_client *client = guc->execbuf_client; @@ -459,7 +245,6 @@ static void guc_add_request(struct intel_guc *guc, struct i915_request *rq) guc_wq_item_append(client, engine->guc_id, ctx_desc, ring_tail, rq->fence.seqno); - guc_ring_doorbell(client); } /* @@ -743,36 +528,6 @@ static void guc_reset_finish(struct intel_engine_cs *engine) * path of guc_submit() above. */ -/* Check that a doorbell register is in the expected state */ -static bool doorbell_ok(struct intel_guc *guc, u16 db_id) -{ - bool valid; - - GEM_BUG_ON(db_id >= GUC_NUM_DOORBELLS); - - valid = __doorbell_valid(guc, db_id); - - if (test_bit(db_id, guc->doorbell_bitmap) == valid) - return true; - - DRM_DEBUG_DRIVER("Doorbell %u has unexpected state: valid=%s\n", - db_id, yesno(valid)); - - return false; -} - -static bool guc_verify_doorbells(struct intel_guc *guc) -{ - bool doorbells_ok = true; - u16 db_id; - - for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id) - if (!doorbell_ok(guc, db_id)) - doorbells_ok = false; - - return doorbells_ok; -} - /** * guc_client_alloc() - Allocate an intel_guc_client * @guc: the intel_guc structure @@ -797,7 +552,6 @@ guc_client_alloc(struct intel_guc *guc, u32 priority) client->guc = guc; client->priority = priority; - client->doorbell_id = GUC_DOORBELL_INVALID; spin_lock_init(&client->wq_lock); ret = ida_simple_get(&guc->stage_ids, 0, GUC_MAX_STAGE_DESCRIPTORS, @@ -807,8 +561,8 @@ guc_client_alloc(struct intel_guc *guc, u32 priority) client->stage_id = ret; - /* The first page is doorbell/proc_desc. Two followed pages are wq. */ - vma = intel_guc_allocate_vma(guc, GUC_DB_SIZE + GUC_WQ_SIZE); + /* The first page is proc_desc. Two following pages are wq. */ + vma = intel_guc_allocate_vma(guc, GUC_PD_SIZE + GUC_WQ_SIZE); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto err_id; @@ -824,31 +578,11 @@ guc_client_alloc(struct intel_guc *guc, u32 priority) } client->vaddr = vaddr; - ret = reserve_doorbell(client); - if (ret) - goto err_vaddr; - - client->doorbell_offset = __select_cacheline(guc); - - /* - * Since the doorbell only requires a single cacheline, we can save - * space by putting the application process descriptor in the same - * page. Use the half of the page that doesn't include the doorbell. - */ - if (client->doorbell_offset >= (GUC_DB_SIZE / 2)) - client->proc_desc_offset = 0; - else - client->proc_desc_offset = (GUC_DB_SIZE / 2); - DRM_DEBUG_DRIVER("new priority %u client %p: stage_id %u\n", priority, client, client->stage_id); - DRM_DEBUG_DRIVER("doorbell id %u, cacheline offset 0x%lx\n", - client->doorbell_id, client->doorbell_offset); return client; -err_vaddr: - i915_gem_object_unpin_map(client->vma->obj); err_vma: i915_vma_unpin_and_release(&client->vma, 0); err_id: @@ -860,7 +594,6 @@ err_client: static void guc_client_free(struct intel_guc_client *client) { - unreserve_doorbell(client); i915_vma_unpin_and_release(&client->vma, I915_VMA_RELEASE_MAP); ida_simple_remove(&client->guc->stage_ids, client->stage_id); kfree(client); @@ -891,44 +624,22 @@ static void guc_clients_destroy(struct intel_guc *guc) guc_client_free(client); } -static int __guc_client_enable(struct intel_guc_client *client) +static void __guc_client_enable(struct intel_guc_client *client) { - int ret; - guc_proc_desc_init(client); guc_stage_desc_init(client); - - ret = create_doorbell(client); - if (ret) - goto fail; - - return 0; - -fail: - guc_stage_desc_fini(client); - guc_proc_desc_fini(client); - return ret; } static void __guc_client_disable(struct intel_guc_client *client) { - /* - * By the time we're here, GuC may have already been reset. if that is - * the case, instead of trying (in vain) to communicate with it, let's - * just cleanup the doorbell HW and our internal state. - */ - if (intel_guc_is_running(client->guc)) - destroy_doorbell(client); - else - __fini_doorbell(client); - + /* Note: By the time we're here, GuC may have already been reset */ guc_stage_desc_fini(client); guc_proc_desc_fini(client); } -static int guc_clients_enable(struct intel_guc *guc) +static void guc_clients_enable(struct intel_guc *guc) { - return __guc_client_enable(guc->execbuf_client); + __guc_client_enable(guc->execbuf_client); } static void guc_clients_disable(struct intel_guc *guc) @@ -957,7 +668,6 @@ int intel_guc_submission_init(struct intel_guc *guc) */ GEM_BUG_ON(!guc->stage_desc_pool); - WARN_ON(!guc_verify_doorbells(guc)); ret = guc_clients_create(guc); if (ret) goto err_pool; @@ -972,7 +682,6 @@ err_pool: void intel_guc_submission_fini(struct intel_guc *guc) { guc_clients_destroy(guc); - WARN_ON(!guc_verify_doorbells(guc)); if (guc->stage_desc_pool) guc_stage_desc_pool_destroy(guc); @@ -1042,16 +751,11 @@ static void guc_set_default_submission(struct intel_engine_cs *engine) GEM_BUG_ON(engine->irq_enable || engine->irq_disable); } -int intel_guc_submission_enable(struct intel_guc *guc) +void intel_guc_submission_enable(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); struct intel_engine_cs *engine; enum intel_engine_id id; - int err; - - err = i915_inject_probe_error(gt->i915, -ENXIO); - if (err) - return err; /* * We're using GuC work items for submitting work through GuC. Since @@ -1068,9 +772,7 @@ int intel_guc_submission_enable(struct intel_guc *guc) GEM_BUG_ON(!guc->execbuf_client); - err = guc_clients_enable(guc); - if (err) - return err; + guc_clients_enable(guc); /* Take over from manual control of ELSP (execlists) */ guc_interrupts_capture(gt); @@ -1079,8 +781,6 @@ int intel_guc_submission_enable(struct intel_guc *guc) engine->set_default_submission = guc_set_default_submission; engine->set_default_submission(engine); } - - return 0; } void intel_guc_submission_disable(struct intel_guc *guc) @@ -1108,7 +808,3 @@ void intel_guc_submission_init_early(struct intel_guc *guc) { guc->submission_supported = __guc_submission_support(guc); } - -#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) -#include "selftest_guc.c" -#endif diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h index 54d716828352..e2deb4e6f42a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h @@ -44,21 +44,14 @@ struct intel_guc_client { /* bitmap of (host) engine ids */ u32 priority; u32 stage_id; - u32 proc_desc_offset; - - u16 doorbell_id; - unsigned long doorbell_offset; /* Protects GuC client's WQ access */ spinlock_t wq_lock; - - /* For testing purposes, use nop WQ items instead of real ones */ - I915_SELFTEST_DECLARE(bool use_nop_wqi); }; void intel_guc_submission_init_early(struct intel_guc *guc); int intel_guc_submission_init(struct intel_guc *guc); -int intel_guc_submission_enable(struct intel_guc *guc); +void intel_guc_submission_enable(struct intel_guc *guc); void intel_guc_submission_disable(struct intel_guc *guc); void intel_guc_submission_fini(struct intel_guc *guc); int intel_guc_preempt_work_create(struct intel_guc *guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 629b19377a29..c6519066a0f6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -486,11 +486,8 @@ int intel_uc_init_hw(struct intel_uc *uc) if (ret) goto err_communication; - if (intel_uc_supports_guc_submission(uc)) { - ret = intel_guc_submission_enable(guc); - if (ret) - goto err_communication; - } + if (intel_uc_supports_guc_submission(uc)) + intel_guc_submission_enable(guc); dev_info(i915->drm.dev, "%s firmware %s version %u.%u %s:%s\n", intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_GUC), guc->fw.path, diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c deleted file mode 100644 index d8a80388bd31..000000000000 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c +++ /dev/null @@ -1,299 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2017 Intel Corporation - */ - -#include "i915_selftest.h" -#include "gem/i915_gem_pm.h" - -/* max doorbell number + negative test for each client type */ -#define ATTEMPTS (GUC_NUM_DOORBELLS + GUC_CLIENT_PRIORITY_NUM) - -static struct intel_guc_client *clients[ATTEMPTS]; - -static bool available_dbs(struct intel_guc *guc, u32 priority) -{ - unsigned long offset; - unsigned long end; - u16 id; - - /* first half is used for normal priority, second half for high */ - offset = 0; - end = GUC_NUM_DOORBELLS / 2; - if (priority <= GUC_CLIENT_PRIORITY_HIGH) { - offset = end; - end += offset; - } - - id = find_next_zero_bit(guc->doorbell_bitmap, end, offset); - if (id < end) - return true; - - return false; -} - -static int check_all_doorbells(struct intel_guc *guc) -{ - u16 db_id; - - pr_info_once("Max number of doorbells: %d", GUC_NUM_DOORBELLS); - for (db_id = 0; db_id < GUC_NUM_DOORBELLS; ++db_id) { - if (!doorbell_ok(guc, db_id)) { - pr_err("doorbell %d, not ok\n", db_id); - return -EIO; - } - } - - return 0; -} - -static int ring_doorbell_nop(struct intel_guc_client *client) -{ - struct guc_process_desc *desc = __get_process_desc(client); - int err; - - client->use_nop_wqi = true; - - spin_lock_irq(&client->wq_lock); - - guc_wq_item_append(client, 0, 0, 0, 0); - guc_ring_doorbell(client); - - spin_unlock_irq(&client->wq_lock); - - client->use_nop_wqi = false; - - /* if there are no issues GuC will update the WQ head and keep the - * WQ in active status - */ - err = wait_for(READ_ONCE(desc->head) == READ_ONCE(desc->tail), 10); - if (err) { - pr_err("doorbell %u ring failed!\n", client->doorbell_id); - return -EIO; - } - - if (desc->wq_status != WQ_STATUS_ACTIVE) { - pr_err("doorbell %u ring put WQ in bad state (%u)!\n", - client->doorbell_id, desc->wq_status); - return -EIO; - } - - return 0; -} - -/* - * Basic client sanity check, handy to validate create_clients. - */ -static int validate_client(struct intel_guc_client *client, int client_priority) -{ - if (client->priority != client_priority || - client->doorbell_id == GUC_DOORBELL_INVALID) - return -EINVAL; - else - return 0; -} - -static bool client_doorbell_in_sync(struct intel_guc_client *client) -{ - return !client || doorbell_ok(client->guc, client->doorbell_id); -} - -/* - * Check that we're able to synchronize guc_clients with their doorbells - * - * We're creating clients and reserving doorbells once, at module load. During - * module lifetime, GuC, doorbell HW, and i915 state may go out of sync due to - * GuC being reset. In other words - GuC clients are still around, but the - * status of their doorbells may be incorrect. This is the reason behind - * validating that the doorbells status expected by the driver matches what the - * GuC/HW have. - */ -static int igt_guc_clients(void *arg) -{ - struct intel_gt *gt = arg; - struct intel_guc *guc = >->uc.guc; - intel_wakeref_t wakeref; - int err = 0; - - GEM_BUG_ON(!HAS_GT_UC(gt->i915)); - wakeref = intel_runtime_pm_get(gt->uncore->rpm); - - err = check_all_doorbells(guc); - if (err) - goto unlock; - - /* - * Get rid of clients created during driver load because the test will - * recreate them. - */ - guc_clients_disable(guc); - guc_clients_destroy(guc); - if (guc->execbuf_client) { - pr_err("guc_clients_destroy lied!\n"); - err = -EINVAL; - goto unlock; - } - - err = guc_clients_create(guc); - if (err) { - pr_err("Failed to create clients\n"); - goto unlock; - } - GEM_BUG_ON(!guc->execbuf_client); - - err = validate_client(guc->execbuf_client, - GUC_CLIENT_PRIORITY_KMD_NORMAL); - if (err) { - pr_err("execbug client validation failed\n"); - goto out; - } - - /* the client should now have reserved a doorbell */ - if (!has_doorbell(guc->execbuf_client)) { - pr_err("guc_clients_create didn't reserve doorbells\n"); - err = -EINVAL; - goto out; - } - - /* Now enable the clients */ - guc_clients_enable(guc); - - /* each client should now have received a doorbell */ - if (!client_doorbell_in_sync(guc->execbuf_client)) { - pr_err("failed to initialize the doorbells\n"); - err = -EINVAL; - goto out; - } - - /* - * Basic test - an attempt to reallocate a valid doorbell to the - * client it is currently assigned should not cause a failure. - */ - err = create_doorbell(guc->execbuf_client); - -out: - /* - * Leave clean state for other test, plus the driver always destroy the - * clients during unload. - */ - guc_clients_disable(guc); - guc_clients_destroy(guc); - guc_clients_create(guc); - guc_clients_enable(guc); -unlock: - intel_runtime_pm_put(gt->uncore->rpm, wakeref); - return err; -} - -/* - * Create as many clients as number of doorbells. Note that there's already - * client(s)/doorbell(s) created during driver load, but this test creates - * its own and do not interact with the existing ones. - */ -static int igt_guc_doorbells(void *arg) -{ - struct intel_gt *gt = arg; - struct intel_guc *guc = >->uc.guc; - intel_wakeref_t wakeref; - int i, err = 0; - u16 db_id; - - GEM_BUG_ON(!HAS_GT_UC(gt->i915)); - wakeref = intel_runtime_pm_get(gt->uncore->rpm); - - err = check_all_doorbells(guc); - if (err) - goto unlock; - - for (i = 0; i < ATTEMPTS; i++) { - clients[i] = guc_client_alloc(guc, i % GUC_CLIENT_PRIORITY_NUM); - - if (!clients[i]) { - pr_err("[%d] No guc client\n", i); - err = -EINVAL; - goto out; - } - - if (IS_ERR(clients[i])) { - if (PTR_ERR(clients[i]) != -ENOSPC) { - pr_err("[%d] unexpected error\n", i); - err = PTR_ERR(clients[i]); - goto out; - } - - if (available_dbs(guc, i % GUC_CLIENT_PRIORITY_NUM)) { - pr_err("[%d] non-db related alloc fail\n", i); - err = -EINVAL; - goto out; - } - - /* expected, ran out of dbs for this client type */ - continue; - } - - /* - * The check below is only valid because we keep a doorbell - * assigned during the whole life of the client. - */ - if (clients[i]->stage_id >= GUC_NUM_DOORBELLS) { - pr_err("[%d] more clients than doorbells (%d >= %d)\n", - i, clients[i]->stage_id, GUC_NUM_DOORBELLS); - err = -EINVAL; - goto out; - } - - err = validate_client(clients[i], i % GUC_CLIENT_PRIORITY_NUM); - if (err) { - pr_err("[%d] client_alloc sanity check failed!\n", i); - err = -EINVAL; - goto out; - } - - db_id = clients[i]->doorbell_id; - - err = __guc_client_enable(clients[i]); - if (err) { - pr_err("[%d] Failed to create a doorbell\n", i); - goto out; - } - - /* doorbell id shouldn't change, we are holding the mutex */ - if (db_id != clients[i]->doorbell_id) { - pr_err("[%d] doorbell id changed (%d != %d)\n", - i, db_id, clients[i]->doorbell_id); - err = -EINVAL; - goto out; - } - - err = check_all_doorbells(guc); - if (err) - goto out; - - err = ring_doorbell_nop(clients[i]); - if (err) - goto out; - } - -out: - for (i = 0; i < ATTEMPTS; i++) - if (!IS_ERR_OR_NULL(clients[i])) { - __guc_client_disable(clients[i]); - guc_client_free(clients[i]); - } -unlock: - intel_runtime_pm_put(gt->uncore->rpm, wakeref); - return err; -} - -int intel_guc_live_selftest(struct drm_i915_private *i915) -{ - static const struct i915_subtest tests[] = { - SUBTEST(igt_guc_clients), - SUBTEST(igt_guc_doorbells), - }; - - if (!USES_GUC_SUBMISSION(i915)) - return 0; - - return intel_gt_live_subtests(tests, &i915->gt); -} diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 062e5bef637a..3e563384e84d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1805,17 +1805,10 @@ static int i915_guc_info(struct seq_file *m, void *data) GEM_BUG_ON(!guc->execbuf_client); - seq_printf(m, "\nDoorbell map:\n"); - seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap); - seq_printf(m, "Doorbell next cacheline: 0x%x\n", guc->db_cacheline); - seq_printf(m, "\nGuC execbuf client @ %p:\n", client); - seq_printf(m, "\tPriority %d, GuC stage index: %u, PD offset 0x%x\n", + seq_printf(m, "\tPriority %d, GuC stage index: %u\n", 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); + client->stage_id); /* Add more as required ... */ return 0; diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index c7c50aac8708..476fba2ed8bb 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@ -37,7 +37,6 @@ selftest(reset, intel_reset_live_selftests) selftest(memory_region, intel_memory_region_live_selftests) selftest(hangcheck, intel_hangcheck_live_selftests) selftest(execlists, intel_execlists_live_selftests) -selftest(guc, intel_guc_live_selftest) selftest(perf, i915_perf_live_selftests) /* Here be dragons: keep last to run last! */ selftest(late_gt_pm, intel_gt_pm_late_selftests) -- cgit v1.2.3 From 3c9abe886a95d91b3d1e1cc16af4322a1abe31d5 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Thu, 5 Dec 2019 14:02:42 -0800 Subject: drm/i915/guc: kill the GuC client We now only use 1 client without any plan to add more. The client is also only holding information about the WQ and the process desc, so we can just move those in the intel_guc structure and always use stage_id 0. v2: fix comment (John) v3: fix the comment for real, fix kerneldoc Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20191205220243.27403-4-daniele.ceraolospurio@intel.com --- Documentation/gpu/i915.rst | 3 - drivers/gpu/drm/i915/gt/intel_reset.c | 6 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 8 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 1 - drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 276 ++++++---------------- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h | 45 +--- drivers/gpu/drm/i915/i915_debugfs.c | 11 - 7 files changed, 89 insertions(+), 261 deletions(-) diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index d0947c5c4ab8..e539c42a3e78 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -466,9 +466,6 @@ GuC-based command submission .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c :doc: GuC-based command submission -.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c - :internal: - HuC --- .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_huc.c diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 0e94b720c993..8408cb84e52c 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -21,6 +21,7 @@ #include "intel_reset.h" #include "uc/intel_guc.h" +#include "uc/intel_guc_submission.h" #define RESET_MAX_RETRIES 3 @@ -1085,6 +1086,7 @@ static inline int intel_gt_reset_engine(struct intel_engine_cs *engine) int intel_engine_reset(struct intel_engine_cs *engine, const char *msg) { struct intel_gt *gt = engine->gt; + bool uses_guc = intel_engine_in_guc_submission_mode(engine); int ret; GEM_TRACE("%s flags=%lx\n", engine->name, gt->reset.flags); @@ -1100,14 +1102,14 @@ int intel_engine_reset(struct intel_engine_cs *engine, const char *msg) "Resetting %s for %s\n", engine->name, msg); atomic_inc(&engine->i915->gpu_error.reset_engine_count[engine->uabi_class]); - if (!engine->gt->uc.guc.execbuf_client) + if (!uses_guc) ret = intel_gt_reset_engine(engine); else ret = intel_guc_reset_engine(&engine->gt->uc.guc, engine); if (ret) { /* If we fail here, we expect to fallback to a global reset */ DRM_DEBUG_DRIVER("%sFailed to reset %s, ret=%d\n", - engine->gt->uc.guc.execbuf_client ? "GuC " : "", + uses_guc ? "GuC " : "", engine->name, ret); goto out; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index b2d1766e689a..cd09c912e361 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -46,9 +46,13 @@ struct intel_guc { struct i915_vma *stage_desc_pool; void *stage_desc_pool_vaddr; - struct ida stage_ids; - struct intel_guc_client *execbuf_client; + struct i915_vma *workqueue; + void *workqueue_vaddr; + spinlock_t wq_lock; + + struct i915_vma *proc_desc; + void *proc_desc_vaddr; /* Control params for fw initialization */ u32 params[GUC_CTL_MAX_DWORDS]; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 1e8e4af7d9ca..a6b733c146c9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -31,7 +31,6 @@ #define GUC_DOORBELL_INVALID 256 -#define GUC_PD_SIZE (PAGE_SIZE) #define GUC_WQ_SIZE (PAGE_SIZE * 2) /* Work queue item header definitions */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 334bd4ded642..172220e83079 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -27,24 +27,13 @@ * code) matches the old submission model and will be updated as part of the * upgrade to the new flow. * - * GuC client: - * A intel_guc_client refers to a submission path through GuC. Currently, there - * is only one client, which is charged with all submissions to the GuC. This - * struct is the owner of a process descriptor and a workqueue (both of them - * inside a single gem object that contains all required pages for these - * elements). - * * GuC stage descriptor: * During initialization, the driver allocates a static pool of 1024 such - * descriptors, and shares them with the GuC. - * Currently, there exists a 1:1 mapping between a intel_guc_client and a - * guc_stage_desc (via the client's stage_id), so effectively only one - * gets used. This stage descriptor lets the GuC know about the workqueue and + * descriptors, and shares them with the GuC. Currently, we only use one + * descriptor. This stage descriptor lets the GuC know about the workqueue and * process descriptor. Theoretically, it also lets the GuC know about our HW * contexts (context ID, etc...), but we actually employ a kind of submission - * where the GuC uses the LRCA sent via the work item instead (the single - * guc_stage_desc associated to execbuf client contains information about the - * default kernel context only, but this is essentially unused). This is called + * where the GuC uses the LRCA sent via the work item instead. This is called * a "proxy" submission. * * The Scratch registers: @@ -71,33 +60,45 @@ static inline struct i915_priolist *to_priolist(struct rb_node *rb) return rb_entry(rb, struct i915_priolist, node); } -static inline bool is_high_priority(struct intel_guc_client *client) +static struct guc_stage_desc *__get_stage_desc(struct intel_guc *guc, u32 id) { - return (client->priority == GUC_CLIENT_PRIORITY_KMD_HIGH || - client->priority == GUC_CLIENT_PRIORITY_HIGH); + struct guc_stage_desc *base = guc->stage_desc_pool_vaddr; + + return &base[id]; } -static struct guc_stage_desc *__get_stage_desc(struct intel_guc_client *client) +static int guc_workqueue_create(struct intel_guc *guc) { - struct guc_stage_desc *base = client->guc->stage_desc_pool_vaddr; - - return &base[client->stage_id]; + return intel_guc_allocate_and_map_vma(guc, GUC_WQ_SIZE, &guc->workqueue, + &guc->workqueue_vaddr); } -static inline struct guc_process_desc * -__get_process_desc(struct intel_guc_client *client) +static void guc_workqueue_destroy(struct intel_guc *guc) { - return client->vaddr; + i915_vma_unpin_and_release(&guc->workqueue, I915_VMA_RELEASE_MAP); } /* * Initialise the process descriptor shared with the GuC firmware. */ -static void guc_proc_desc_init(struct intel_guc_client *client) +static int guc_proc_desc_create(struct intel_guc *guc) +{ + const u32 size = PAGE_ALIGN(sizeof(struct guc_process_desc)); + + return intel_guc_allocate_and_map_vma(guc, size, &guc->proc_desc, + &guc->proc_desc_vaddr); +} + +static void guc_proc_desc_destroy(struct intel_guc *guc) +{ + i915_vma_unpin_and_release(&guc->proc_desc, I915_VMA_RELEASE_MAP); +} + +static void guc_proc_desc_init(struct intel_guc *guc) { struct guc_process_desc *desc; - desc = memset(__get_process_desc(client), 0, sizeof(*desc)); + desc = memset(guc->proc_desc_vaddr, 0, sizeof(*desc)); /* * XXX: pDoorbell and WQVBaseAddress are pointers in process address @@ -108,39 +109,27 @@ static void guc_proc_desc_init(struct intel_guc_client *client) desc->wq_base_addr = 0; desc->db_base_addr = 0; - desc->stage_id = client->stage_id; desc->wq_size_bytes = GUC_WQ_SIZE; desc->wq_status = WQ_STATUS_ACTIVE; - desc->priority = client->priority; + desc->priority = GUC_CLIENT_PRIORITY_KMD_NORMAL; } -static void guc_proc_desc_fini(struct intel_guc_client *client) +static void guc_proc_desc_fini(struct intel_guc *guc) { - struct guc_process_desc *desc; - - desc = __get_process_desc(client); - memset(desc, 0, sizeof(*desc)); + memset(guc->proc_desc_vaddr, 0, sizeof(struct guc_process_desc)); } static int guc_stage_desc_pool_create(struct intel_guc *guc) { u32 size = PAGE_ALIGN(sizeof(struct guc_stage_desc) * GUC_MAX_STAGE_DESCRIPTORS); - int ret; - - ret = intel_guc_allocate_and_map_vma(guc, size, &guc->stage_desc_pool, - &guc->stage_desc_pool_vaddr); - if (ret) - return ret; - - ida_init(&guc->stage_ids); - return 0; + return intel_guc_allocate_and_map_vma(guc, size, &guc->stage_desc_pool, + &guc->stage_desc_pool_vaddr); } static void guc_stage_desc_pool_destroy(struct intel_guc *guc) { - ida_destroy(&guc->stage_ids); i915_vma_unpin_and_release(&guc->stage_desc_pool, I915_VMA_RELEASE_MAP); } @@ -148,58 +137,49 @@ static void guc_stage_desc_pool_destroy(struct intel_guc *guc) * Initialise/clear the stage descriptor shared with the GuC firmware. * * This descriptor tells the GuC where (in GGTT space) to find the important - * data structures relating to this client (process descriptor, write queue, + * data structures related to work submission (process descriptor, write queue, * etc). */ -static void guc_stage_desc_init(struct intel_guc_client *client) +static void guc_stage_desc_init(struct intel_guc *guc) { - struct intel_guc *guc = client->guc; struct guc_stage_desc *desc; - u32 gfx_addr; - desc = __get_stage_desc(client); + /* we only use 1 stage desc, so hardcode it to 0 */ + desc = __get_stage_desc(guc, 0); memset(desc, 0, sizeof(*desc)); desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | GUC_STAGE_DESC_ATTR_KERNEL; - if (is_high_priority(client)) - desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT; - desc->stage_id = client->stage_id; - desc->priority = client->priority; - /* - * The process descriptor and workqueue are all parts of the client - * object, which the GuC will reference via the GGTT - */ - gfx_addr = intel_guc_ggtt_offset(guc, client->vma); - desc->process_desc = gfx_addr; - desc->wq_addr = gfx_addr + GUC_PD_SIZE; - desc->wq_size = GUC_WQ_SIZE; + desc->stage_id = 0; + desc->priority = GUC_CLIENT_PRIORITY_KMD_NORMAL; - desc->desc_private = ptr_to_u64(client); + desc->process_desc = intel_guc_ggtt_offset(guc, guc->proc_desc); + desc->wq_addr = intel_guc_ggtt_offset(guc, guc->workqueue); + desc->wq_size = GUC_WQ_SIZE; } -static void guc_stage_desc_fini(struct intel_guc_client *client) +static void guc_stage_desc_fini(struct intel_guc *guc) { struct guc_stage_desc *desc; - desc = __get_stage_desc(client); + desc = __get_stage_desc(guc, 0); memset(desc, 0, sizeof(*desc)); } /* Construct a Work Item and append it to the GuC's Work Queue */ -static void guc_wq_item_append(struct intel_guc_client *client, +static void guc_wq_item_append(struct intel_guc *guc, u32 target_engine, u32 context_desc, u32 ring_tail, u32 fence_id) { /* 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; - struct guc_process_desc *desc = __get_process_desc(client); + struct guc_process_desc *desc = guc->proc_desc_vaddr; struct guc_wq_item *wqi; u32 wq_off; - lockdep_assert_held(&client->wq_lock); + lockdep_assert_held(&guc->wq_lock); /* 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 @@ -219,8 +199,7 @@ static void guc_wq_item_append(struct intel_guc_client *client, GUC_WQ_SIZE) < wqi_size); GEM_BUG_ON(wq_off & (wqi_size - 1)); - /* WQ starts from the page after process_desc */ - wqi = client->vaddr + wq_off + GUC_PD_SIZE; + wqi = guc->workqueue_vaddr + wq_off; /* Now fill in the 4-word work queue item */ wqi->header = WQ_TYPE_INORDER | @@ -238,12 +217,11 @@ static void guc_wq_item_append(struct intel_guc_client *client, static void guc_add_request(struct intel_guc *guc, struct i915_request *rq) { - struct intel_guc_client *client = guc->execbuf_client; struct intel_engine_cs *engine = rq->engine; u32 ctx_desc = lower_32_bits(rq->hw_context->lrc_desc); u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); - guc_wq_item_append(client, engine->guc_id, ctx_desc, + guc_wq_item_append(guc, engine->guc_id, ctx_desc, ring_tail, rq->fence.seqno); } @@ -266,9 +244,8 @@ static void guc_submit(struct intel_engine_cs *engine, struct i915_request **end) { struct intel_guc *guc = &engine->gt->uc.guc; - struct intel_guc_client *client = guc->execbuf_client; - spin_lock(&client->wq_lock); + spin_lock(&guc->wq_lock); do { struct i915_request *rq = *out++; @@ -277,7 +254,7 @@ static void guc_submit(struct intel_engine_cs *engine, guc_add_request(guc, rq); } while (out != end); - spin_unlock(&client->wq_lock); + spin_unlock(&guc->wq_lock); } static inline int rq_prio(const struct i915_request *rq) @@ -528,126 +505,6 @@ static void guc_reset_finish(struct intel_engine_cs *engine) * path of guc_submit() above. */ -/** - * guc_client_alloc() - Allocate an intel_guc_client - * @guc: the intel_guc structure - * @priority: four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW - * The kernel client to replace ExecList submission is created with - * NORMAL priority. Priority of a client for scheduler can be HIGH, - * while a preemption context can use CRITICAL. - * - * Return: An intel_guc_client object if success, else NULL. - */ -static struct intel_guc_client * -guc_client_alloc(struct intel_guc *guc, u32 priority) -{ - struct intel_guc_client *client; - struct i915_vma *vma; - void *vaddr; - int ret; - - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return ERR_PTR(-ENOMEM); - - client->guc = guc; - client->priority = priority; - spin_lock_init(&client->wq_lock); - - ret = ida_simple_get(&guc->stage_ids, 0, GUC_MAX_STAGE_DESCRIPTORS, - GFP_KERNEL); - if (ret < 0) - goto err_client; - - client->stage_id = ret; - - /* The first page is proc_desc. Two following pages are wq. */ - vma = intel_guc_allocate_vma(guc, GUC_PD_SIZE + GUC_WQ_SIZE); - if (IS_ERR(vma)) { - ret = PTR_ERR(vma); - goto err_id; - } - - /* We'll keep just the first (doorbell/proc) page permanently kmap'd. */ - client->vma = vma; - - vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); - if (IS_ERR(vaddr)) { - ret = PTR_ERR(vaddr); - goto err_vma; - } - client->vaddr = vaddr; - - DRM_DEBUG_DRIVER("new priority %u client %p: stage_id %u\n", - priority, client, client->stage_id); - - return client; - -err_vma: - i915_vma_unpin_and_release(&client->vma, 0); -err_id: - ida_simple_remove(&guc->stage_ids, client->stage_id); -err_client: - kfree(client); - return ERR_PTR(ret); -} - -static void guc_client_free(struct intel_guc_client *client) -{ - i915_vma_unpin_and_release(&client->vma, I915_VMA_RELEASE_MAP); - ida_simple_remove(&client->guc->stage_ids, client->stage_id); - kfree(client); -} - -static int guc_clients_create(struct intel_guc *guc) -{ - struct intel_guc_client *client; - - GEM_BUG_ON(guc->execbuf_client); - - client = guc_client_alloc(guc, GUC_CLIENT_PRIORITY_KMD_NORMAL); - if (IS_ERR(client)) { - DRM_ERROR("Failed to create GuC client for submission!\n"); - return PTR_ERR(client); - } - guc->execbuf_client = client; - - return 0; -} - -static void guc_clients_destroy(struct intel_guc *guc) -{ - struct intel_guc_client *client; - - client = fetch_and_zero(&guc->execbuf_client); - if (client) - guc_client_free(client); -} - -static void __guc_client_enable(struct intel_guc_client *client) -{ - guc_proc_desc_init(client); - guc_stage_desc_init(client); -} - -static void __guc_client_disable(struct intel_guc_client *client) -{ - /* Note: By the time we're here, GuC may have already been reset */ - guc_stage_desc_fini(client); - guc_proc_desc_fini(client); -} - -static void guc_clients_enable(struct intel_guc *guc) -{ - __guc_client_enable(guc->execbuf_client); -} - -static void guc_clients_disable(struct intel_guc *guc) -{ - if (guc->execbuf_client) - __guc_client_disable(guc->execbuf_client); -} - /* * Set up the memory resources to be shared with the GuC (via the GGTT) * at firmware loading time. @@ -668,12 +525,20 @@ int intel_guc_submission_init(struct intel_guc *guc) */ GEM_BUG_ON(!guc->stage_desc_pool); - ret = guc_clients_create(guc); + ret = guc_workqueue_create(guc); if (ret) goto err_pool; + ret = guc_proc_desc_create(guc); + if (ret) + goto err_workqueue; + + spin_lock_init(&guc->wq_lock); + return 0; +err_workqueue: + guc_workqueue_destroy(guc); err_pool: guc_stage_desc_pool_destroy(guc); return ret; @@ -681,10 +546,11 @@ err_pool: void intel_guc_submission_fini(struct intel_guc *guc) { - guc_clients_destroy(guc); - - if (guc->stage_desc_pool) + if (guc->stage_desc_pool) { + guc_proc_desc_destroy(guc); + guc_workqueue_destroy(guc); guc_stage_desc_pool_destroy(guc); + } } static void guc_interrupts_capture(struct intel_gt *gt) @@ -770,9 +636,8 @@ void intel_guc_submission_enable(struct intel_guc *guc) sizeof(struct guc_wq_item) * I915_NUM_ENGINES > GUC_WQ_SIZE); - GEM_BUG_ON(!guc->execbuf_client); - - guc_clients_enable(guc); + guc_proc_desc_init(guc); + guc_stage_desc_init(guc); /* Take over from manual control of ELSP (execlists) */ guc_interrupts_capture(gt); @@ -789,8 +654,12 @@ void intel_guc_submission_disable(struct intel_guc *guc) GEM_BUG_ON(gt->awake); /* GT should be parked first */ + /* Note: By the time we're here, GuC may have already been reset */ + guc_interrupts_release(gt); - guc_clients_disable(guc); + + guc_stage_desc_fini(guc); + guc_proc_desc_fini(guc); } static bool __guc_submission_support(struct intel_guc *guc) @@ -808,3 +677,8 @@ void intel_guc_submission_init_early(struct intel_guc *guc) { guc->submission_supported = __guc_submission_support(guc); } + +bool intel_engine_in_guc_submission_mode(const struct intel_engine_cs *engine) +{ + return engine->set_default_submission == guc_set_default_submission; +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h index e2deb4e6f42a..e402a2932592 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h @@ -6,48 +6,10 @@ #ifndef _INTEL_GUC_SUBMISSION_H_ #define _INTEL_GUC_SUBMISSION_H_ -#include +#include -#include "gt/intel_engine_types.h" - -#include "i915_gem.h" -#include "i915_selftest.h" - -struct drm_i915_private; - -/* - * This structure primarily describes the GEM object shared with the GuC. - * The specs sometimes refer to this object as a "GuC context", but we use - * the term "client" to avoid confusion with hardware contexts. This - * GEM object is held for the entire lifetime of our interaction with - * the GuC, being allocated before the GuC is loaded with its firmware. - * Because there's no way to update the address used by the GuC after - * initialisation, the shared object must stay pinned into the GGTT as - * long as the GuC is in use. We also keep the first page (only) mapped - * into kernel address space, as it includes shared data that must be - * updated on every request submission. - * - * The single GEM object described here is actually made up of several - * separate areas, as far as the GuC is concerned. The first page (kept - * kmap'd) includes the "process descriptor" which holds sequence data for - * the doorbell, and one cacheline which actually *is* the doorbell; a - * write to this will "ring the doorbell" (i.e. send an interrupt to the - * 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. - */ -struct intel_guc_client { - struct i915_vma *vma; - void *vaddr; - struct intel_guc *guc; - - /* bitmap of (host) engine ids */ - u32 priority; - u32 stage_id; - - /* Protects GuC client's WQ access */ - spinlock_t wq_lock; -}; +struct intel_guc; +struct intel_engine_cs; void intel_guc_submission_init_early(struct intel_guc *guc); int intel_guc_submission_init(struct intel_guc *guc); @@ -56,5 +18,6 @@ void intel_guc_submission_disable(struct intel_guc *guc); void intel_guc_submission_fini(struct intel_guc *guc); int intel_guc_preempt_work_create(struct intel_guc *guc); void intel_guc_preempt_work_destroy(struct intel_guc *guc); +bool intel_engine_in_guc_submission_mode(const struct intel_engine_cs *engine); #endif diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3e563384e84d..6cb149ba1905 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1792,23 +1792,12 @@ static void i915_guc_log_info(struct seq_file *m, static int i915_guc_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - const struct intel_guc *guc = &dev_priv->gt.uc.guc; - struct intel_guc_client *client = guc->execbuf_client; if (!USES_GUC(dev_priv)) return -ENODEV; i915_guc_log_info(m, dev_priv); - if (!USES_GUC_SUBMISSION(dev_priv)) - return 0; - - GEM_BUG_ON(!guc->execbuf_client); - - seq_printf(m, "\nGuC execbuf client @ %p:\n", client); - seq_printf(m, "\tPriority %d, GuC stage index: %u\n", - client->priority, - client->stage_id); /* Add more as required ... */ return 0; -- cgit v1.2.3 From 82c69bf58650e644c61aa2bf5100b63a1070fd2f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 9 Dec 2019 02:32:15 +0000 Subject: drm/i915/gt: Detect if we miss WaIdleLiteRestore In order to avoid confusing the HW, we must never submit an empty ring during lite-restore, that is we should always advance the RING_TAIL before submitting to stay ahead of the RING_HEAD. Normally this is prevented by keeping a couple of spare NOPs in the request->wa_tail so that on resubmission we can advance the tail. This relies on the request only being resubmitted once, which is the normal condition as it is seen once for ELSP[1] and then later in ELSP[0]. On preemption, the requests are unwound and the tail reset back to the normal end point (as we know the request is incomplete and therefore its RING_HEAD is even earlier). However, if this w/a should fail we would try and resubmit the request with the RING_TAIL already set to the location of this request's wa_tail potentially causing a GPU hang. We can spot when we do try and incorrectly resubmit without advancing the RING_TAIL and spare any embarrassment by forcing the context restore. In the case of preempt-to-busy, we leave the requests running on the HW while we unwind. As the ring is still live, we cannot rewind our rq->tail without forcing a reload so leave it set to rq->wa_tail and only force a reload if we resubmit after a lite-restore. (Normally, the forced reload will be a part of the preemption event.) Fixes: 22b7a426bbe1 ("drm/i915/execlists: Preempt-to-busy") Closes: https://gitlab.freedesktop.org/drm/intel/issues/673 Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Cc: stable@kernel.vger.org Link: https://patchwork.freedesktop.org/patch/msgid/20191209023215.3519970-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 46 +++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index c7ea8a055005..929f6bae4eba 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -845,12 +845,6 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine) } } -static void unwind_wa_tail(struct i915_request *rq) -{ - rq->tail = intel_ring_wrap(rq->ring, rq->wa_tail - WA_TAIL_BYTES); - assert_ring_tail_valid(rq->ring, rq->tail); -} - static struct i915_request * __unwind_incomplete_requests(struct intel_engine_cs *engine) { @@ -863,12 +857,10 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine) list_for_each_entry_safe_reverse(rq, rn, &engine->active.requests, sched.link) { - if (i915_request_completed(rq)) continue; /* XXX */ __i915_request_unsubmit(rq); - unwind_wa_tail(rq); /* * Push the request back into the queue for later resubmission. @@ -1216,13 +1208,29 @@ execlists_schedule_out(struct i915_request *rq) i915_request_put(rq); } -static u64 execlists_update_context(const struct i915_request *rq) +static u64 execlists_update_context(struct i915_request *rq) { struct intel_context *ce = rq->hw_context; - u64 desc; + u64 desc = ce->lrc_desc; + u32 tail; - ce->lrc_reg_state[CTX_RING_TAIL] = - intel_ring_set_tail(rq->ring, rq->tail); + /* + * WaIdleLiteRestore:bdw,skl + * + * We should never submit the context with the same RING_TAIL twice + * just in case we submit an empty ring, which confuses the HW. + * + * We append a couple of NOOPs (gen8_emit_wa_tail) after the end of + * the normal request to be able to always advance the RING_TAIL on + * subsequent resubmissions (for lite restore). Should that fail us, + * and we try and submit the same tail again, force the context + * reload. + */ + tail = intel_ring_set_tail(rq->ring, rq->tail); + if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail)) + desc |= CTX_DESC_FORCE_RESTORE; + ce->lrc_reg_state[CTX_RING_TAIL] = tail; + rq->tail = rq->wa_tail; /* * Make sure the context image is complete before we submit it to HW. @@ -1236,13 +1244,11 @@ static u64 execlists_update_context(const struct i915_request *rq) */ wmb(); - desc = ce->lrc_desc; - ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE; - /* Wa_1607138340:tgl */ if (IS_TGL_REVID(rq->i915, TGL_REVID_A0, TGL_REVID_A0)) desc |= CTX_DESC_FORCE_RESTORE; + ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE; return desc; } @@ -1776,16 +1782,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) return; } - - /* - * WaIdleLiteRestore:bdw,skl - * Apply the wa NOOPs to prevent - * ring:HEAD == rq:TAIL as we resubmit the - * request. See gen8_emit_fini_breadcrumb() for - * where we prepare the padding after the - * end of the request. - */ - last->tail = last->wa_tail; } } -- cgit v1.2.3 From 1805ec67b12a12c794aee7ed46bd577748ee2a2c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 10 Dec 2019 14:32:05 +0000 Subject: drm/i915/selftests: fix uninitialized variable sum when summing up values Currently the variable sum is not uninitialized and hence will cause an incorrect result in the summation values. Fix this by initializing sum to the first item in the summation. Addresses-Coverity: ("Uninitialized scalar variable") Fixes: 3c7a44bbbfa7 ("drm/i915/selftests: Perform some basic cycle counting of MI ops") Signed-off-by: Colin Ian King Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191210143205.338308-1-colin.king@canonical.com --- drivers/gpu/drm/i915/gt/selftest_engine_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c index 761d81f4bd68..f88e445a1cae 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c @@ -108,7 +108,7 @@ static u32 trifilter(u32 *a) sort(a, COUNT, sizeof(*a), cmp_u32, NULL); - sum += mul_u32_u32(a[2], 2); + sum = mul_u32_u32(a[2], 2); sum += a[1]; sum += a[3]; -- cgit v1.2.3 From 3fa01d642fa7fc8b2ee2833155048d2d107da2e8 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 5 Dec 2019 14:48:48 -0800 Subject: drm/i915/tgl: Program BW_BUDDY registers during display init Gen12 can improve bandwidth efficiency by pairing up memory requests with similar addresses. We need to program the BW_BUDDY1 and BW_BUDDY2 registers according to the memory configuration during display initialization to take advantage of this capability. The magic numbers we program here feel like something that could definitely change on future platforms, so let's use a table-based programming scheme to make this easy to extend in the future. v2: - Add separate table for Wa_1409767108. (Stan) - Reorder structure reduce size by a word. Page mask can still be up to 28 bits (even though current values are small) so we should keep it as a u32, but just using a u8 for DRAM type instead of the actual enum type saves space. (Lucas, Ville) - Rename function to tgl_bw_buddy_init() to be more precise about what it does. (Lucas) Bspec: 49189 Bspec: 49218 Bspec: 52890 Cc: Stanislav Lisovskiy Cc: Ville Syrjala Cc: Lucas De Marchi Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191205224848.76712-1-matthew.d.roper@intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_display_power.c | 54 ++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 8 ++++ 2 files changed, 62 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index ce1b64f4dd44..0b3dd2a3b94d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -4781,6 +4781,56 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) intel_combo_phy_uninit(dev_priv); } +struct buddy_page_mask { + u32 page_mask; + u8 type; + u8 num_channels; +}; + +static const struct buddy_page_mask tgl_buddy_page_masks[] = { + { .num_channels = 1, .type = INTEL_DRAM_LPDDR4, .page_mask = 0xE }, + { .num_channels = 1, .type = INTEL_DRAM_DDR4, .page_mask = 0xF }, + { .num_channels = 2, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x1C }, + { .num_channels = 2, .type = INTEL_DRAM_DDR4, .page_mask = 0x1F }, + {} +}; + +static const struct buddy_page_mask wa_1409767108_buddy_page_masks[] = { + { .num_channels = 1, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x1 }, + { .num_channels = 1, .type = INTEL_DRAM_DDR4, .page_mask = 0x1 }, + { .num_channels = 2, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x3 }, + { .num_channels = 2, .type = INTEL_DRAM_DDR4, .page_mask = 0x3 }, + {} +}; + +static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv) +{ + enum intel_dram_type type = dev_priv->dram_info.type; + u8 num_channels = dev_priv->dram_info.num_channels; + const struct buddy_page_mask *table; + int i; + + if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0)) + /* Wa_1409767108: tgl */ + table = wa_1409767108_buddy_page_masks; + else + table = tgl_buddy_page_masks; + + for (i = 0; table[i].page_mask != 0; i++) + if (table[i].num_channels == num_channels && + table[i].type == type) + break; + + if (table[i].page_mask == 0) { + DRM_DEBUG_DRIVER("Unknown memory configuration; disabling address buddy logic.\n"); + I915_WRITE(BW_BUDDY1_CTL, BW_BUDDY_DISABLE); + I915_WRITE(BW_BUDDY2_CTL, BW_BUDDY_DISABLE); + } else { + I915_WRITE(BW_BUDDY1_PAGE_MASK, table[i].page_mask); + I915_WRITE(BW_BUDDY2_PAGE_MASK, table[i].page_mask); + } +} + static void icl_display_core_init(struct drm_i915_private *dev_priv, bool resume) { @@ -4813,6 +4863,10 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, /* 6. Setup MBUS. */ icl_mbus_init(dev_priv); + /* 7. Program arbiter BW_BUDDY registers */ + if (INTEL_GEN(dev_priv) >= 12) + tgl_bw_buddy_init(dev_priv); + if (resume && dev_priv->csr.dmc_payload) intel_csr_load_program(dev_priv); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1a6376a97d48..082190c2dc48 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7765,6 +7765,14 @@ enum { #define GEN7_MSG_CTL _MMIO(0x45010) #define WAIT_FOR_PCH_RESET_ACK (1 << 1) #define WAIT_FOR_PCH_FLR_ACK (1 << 0) + +#define BW_BUDDY1_CTL _MMIO(0x45140) +#define BW_BUDDY2_CTL _MMIO(0x45150) +#define BW_BUDDY_DISABLE REG_BIT(31) + +#define BW_BUDDY1_PAGE_MASK _MMIO(0x45144) +#define BW_BUDDY2_PAGE_MASK _MMIO(0x45154) + #define HSW_NDE_RSTWRN_OPT _MMIO(0x46408) #define RESET_PCH_HANDSHAKE_ENABLE (1 << 4) -- cgit v1.2.3 From d1dad6f43334f8ea93b76953cef0703f8bf9d42e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:45 +0200 Subject: drm/i915/bios: pass devdata to parse_ddi_port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow accessing the parent structure later on. Drop const for allowing future modification as well. Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/3318b09aaccbbe141e233ca510d581b421259a2a.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 1aeecdd02293..307e347c4a17 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1554,9 +1554,10 @@ static enum port dvo_port_to_port(u8 dvo_port) } static void parse_ddi_port(struct drm_i915_private *dev_priv, - const struct child_device_config *child, + struct display_device_data *devdata, u8 bdb_version) { + const struct child_device_config *child = &devdata->child; struct ddi_vbt_port_info *info; bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; enum port port; @@ -1708,7 +1709,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, static void parse_ddi_ports(struct drm_i915_private *dev_priv, u8 bdb_version) { - const struct display_device_data *devdata; + struct display_device_data *devdata; if (!HAS_DDI(dev_priv) && !IS_CHERRYVIEW(dev_priv)) return; @@ -1717,7 +1718,7 @@ static void parse_ddi_ports(struct drm_i915_private *dev_priv, u8 bdb_version) return; list_for_each_entry(devdata, &dev_priv->vbt.display_devices, node) - parse_ddi_port(dev_priv, &devdata->child, bdb_version); + parse_ddi_port(dev_priv, devdata, bdb_version); } static void -- cgit v1.2.3 From 6e0d46e91efd4440e00a1c5380bf9a2f933529b8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:46 +0200 Subject: drm/i915/bios: parse compression parameters block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check for child devices that specify compression, and store the device specific compression parameters in the display device data struct for later use. Warn if compression is requested but not available. Use fairly rigid checks for compression data for starters. These can be made more dynamic later. Log about DSC presence in DDI port parse, though this is not universal across platforms or port types (DSI). v2: amended debug logging Bspec: 29885 Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/357d685ba047faf2285138c2f7014a8dee9a12b7.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 61 ++++++++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_vbt_defs.h | 2 +- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 307e347c4a17..726516ae17ba 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -61,6 +61,7 @@ /* Wrapper for VBT child device config */ struct display_device_data { struct child_device_config child; + struct dsc_compression_parameters_entry *dsc; struct list_head node; }; @@ -1366,6 +1367,57 @@ err: memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence)); } +static void +parse_compression_parameters(struct drm_i915_private *i915, + const struct bdb_header *bdb) +{ + const struct bdb_compression_parameters *params; + struct display_device_data *devdata; + const struct child_device_config *child; + u16 block_size; + int index; + + if (bdb->version < 198) + return; + + params = find_section(bdb, BDB_COMPRESSION_PARAMETERS); + if (params) { + /* Sanity checks */ + if (params->entry_size != sizeof(params->data[0])) { + DRM_DEBUG_KMS("VBT: unsupported compression param entry size\n"); + return; + } + + block_size = get_blocksize(params); + if (block_size < sizeof(*params)) { + DRM_DEBUG_KMS("VBT: expected 16 compression param entries\n"); + return; + } + } + + list_for_each_entry(devdata, &i915->vbt.display_devices, node) { + child = &devdata->child; + + if (!child->compression_enable) + continue; + + if (!params) { + DRM_DEBUG_KMS("VBT: compression params not available\n"); + continue; + } + + if (child->compression_method_cps) { + DRM_DEBUG_KMS("VBT: CPS compression not supported\n"); + continue; + } + + index = child->compression_structure_index; + + devdata->dsc = kmemdup(¶ms->data[index], + sizeof(*devdata->dsc), GFP_KERNEL); + } +} + static u8 translate_iboost(u8 val) { static const u8 mapping[] = { 1, 3, 7 }; /* See VBT spec */ @@ -1598,10 +1650,11 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, if (bdb_version >= 209) info->supports_tbt = child->tbt; - DRM_DEBUG_KMS("Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d LSPCON:%d USB-Type-C:%d TBT:%d\n", + DRM_DEBUG_KMS("Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d LSPCON:%d USB-Type-C:%d TBT:%d DSC:%d\n", port_name(port), is_crt, is_dvi, is_hdmi, is_dp, is_edp, HAS_LSPCON(dev_priv) && child->lspcon, - info->supports_typec_usb, info->supports_tbt); + info->supports_typec_usb, info->supports_tbt, + devdata->dsc != NULL); if (is_edp && is_dvi) DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n", @@ -2037,6 +2090,9 @@ void intel_bios_init(struct drm_i915_private *dev_priv) parse_mipi_config(dev_priv, bdb); parse_mipi_sequence(dev_priv, bdb); + /* Depends on child device list */ + parse_compression_parameters(dev_priv, bdb); + /* Further processing on pre-parsed data */ parse_sdvo_device_mapping(dev_priv, bdb->version); parse_ddi_ports(dev_priv, bdb->version); @@ -2060,6 +2116,7 @@ void intel_bios_driver_remove(struct drm_i915_private *dev_priv) list_for_each_entry_safe(devdata, n, &dev_priv->vbt.display_devices, node) { list_del(&devdata->node); + kfree(devdata->dsc); kfree(devdata); } diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index 98b71dc32d2a..4d0c23b29248 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -369,7 +369,7 @@ struct child_device_config { u16 dtd_buf_ptr; /* 161 */ u8 edidless_efp:1; /* 161 */ u8 compression_enable:1; /* 198 */ - u8 compression_method:1; /* 198 */ + u8 compression_method_cps:1; /* 198 */ u8 ganged_edp:1; /* 202 */ u8 reserved0:4; u8 compression_structure_index:4; /* 198 */ -- cgit v1.2.3 From 1bf2f3bf29a97037e695cc3e8695746fd8d2cde0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:47 +0200 Subject: drm/i915/bios: add support for querying DSC details for encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add function for retrieving the DSC data for an encoder. Initially, this is DSI specific, as DP does not use VBT settings for DSC at all. It's also not very pretty. In the future we might have a pointer from encoder to the child device, which would make the child device list query here so much more sensible. v3: - use crtc_state instead of pipe_config - return true by default from intel_bios_get_dsc_params() - expand the comment about rc_buffer_block_size and rc_buffer_size v2: - make more robust, debug log errors better Bspec: 29885 Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/b895c349d964d70e4cad26f12a629ea1898bfcc2.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 99 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_bios.h | 5 ++ 2 files changed, 104 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 726516ae17ba..bd674fd355b7 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -29,6 +29,7 @@ #include #include "display/intel_display.h" +#include "display/intel_display_types.h" #include "display/intel_gmbus.h" #include "i915_drv.h" @@ -2394,6 +2395,104 @@ bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, return false; } +static void fill_dsc(struct intel_crtc_state *crtc_state, + struct dsc_compression_parameters_entry *dsc, + int dsc_max_bpc) +{ + struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; + int bpc = 8; + + vdsc_cfg->dsc_version_major = dsc->version_major; + vdsc_cfg->dsc_version_minor = dsc->version_minor; + + if (dsc->support_12bpc && dsc_max_bpc >= 12) + bpc = 12; + else if (dsc->support_10bpc && dsc_max_bpc >= 10) + bpc = 10; + else if (dsc->support_8bpc && dsc_max_bpc >= 8) + bpc = 8; + else + DRM_DEBUG_KMS("VBT: Unsupported BPC %d for DCS\n", + dsc_max_bpc); + + crtc_state->pipe_bpp = bpc * 3; + + crtc_state->dsc.compressed_bpp = min(crtc_state->pipe_bpp, + VBT_DSC_MAX_BPP(dsc->max_bpp)); + + /* + * FIXME: This is ugly, and slice count should take DSC engine + * throughput etc. into account. + * + * Also, per spec DSI supports 1, 2, 3 or 4 horizontal slices. + */ + if (dsc->slices_per_line & BIT(2)) { + crtc_state->dsc.slice_count = 4; + } else if (dsc->slices_per_line & BIT(1)) { + crtc_state->dsc.slice_count = 2; + } else { + /* FIXME */ + if (!(dsc->slices_per_line & BIT(0))) + DRM_DEBUG_KMS("VBT: Unsupported DSC slice count for DSI\n"); + + crtc_state->dsc.slice_count = 1; + } + + if (crtc_state->hw.adjusted_mode.crtc_hdisplay % + crtc_state->dsc.slice_count != 0) + DRM_DEBUG_KMS("VBT: DSC hdisplay %d not divisible by slice count %d\n", + crtc_state->hw.adjusted_mode.crtc_hdisplay, + crtc_state->dsc.slice_count); + + /* + * FIXME: Use VBT rc_buffer_block_size and rc_buffer_size for the + * implementation specific physical rate buffer size. Currently we use + * the required rate buffer model size calculated in + * drm_dsc_compute_rc_parameters() according to VESA DSC Annex E. + * + * The VBT rc_buffer_block_size and rc_buffer_size definitions + * correspond to DP 1.4 DPCD offsets 0x62 and 0x63. The DP DSC + * implementation should also use the DPCD (or perhaps VBT for eDP) + * provided value for the buffer size. + */ + + /* FIXME: DSI spec says bpc + 1 for this one */ + vdsc_cfg->line_buf_depth = VBT_DSC_LINE_BUFFER_DEPTH(dsc->line_buffer_depth); + + vdsc_cfg->block_pred_enable = dsc->block_prediction_enable; + + vdsc_cfg->slice_height = dsc->slice_height; +} + +/* FIXME: initially DSI specific */ +bool intel_bios_get_dsc_params(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + int dsc_max_bpc) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + const struct display_device_data *devdata; + const struct child_device_config *child; + + list_for_each_entry(devdata, &i915->vbt.display_devices, node) { + child = &devdata->child; + + if (!(child->device_type & DEVICE_TYPE_MIPI_OUTPUT)) + continue; + + if (child->dvo_port - DVO_PORT_MIPIA == encoder->port) { + if (!devdata->dsc) + return false; + + if (crtc_state) + fill_dsc(crtc_state, devdata->dsc, dsc_max_bpc); + + return true; + } + } + + return false; +} + /** * intel_bios_is_port_hpd_inverted - is HPD inverted for %port * @i915: i915 device instance diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index 98f064828a57..d6a0c29d37ac 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -35,6 +35,8 @@ #include struct drm_i915_private; +struct intel_crtc_state; +struct intel_encoder; enum port; enum intel_backlight_type { @@ -242,5 +244,8 @@ bool intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915, bool intel_bios_is_lspcon_present(const struct drm_i915_private *i915, enum port port); enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv, enum port port); +bool intel_bios_get_dsc_params(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + int dsc_max_bpc); #endif /* _INTEL_BIOS_H_ */ -- cgit v1.2.3 From 7a7b5be96fb66febb50ef001c0e5d20d55c0c34b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:48 +0200 Subject: drm/i915/dsc: move DP specific compute params to intel_dp.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out future DSI specific parameters aren't workable with the approach of having the encoder specific functions in intel_vdsc.c. Make intel_dsc_compute_params() a helper that does the encoder independent parts, and have encoder code call it. Move intel_dsc_dp_compute_params() to intel_dp.c as intel_dp_dsc_compute_params(). No functional changes. v2: Rename pipe_config to crtc_state while at it. Cc: Manasi Navare Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/620688ec302f7f49cc539c6c1653bfaf6092fce0.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 47 +++++++++++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_vdsc.c | 48 +------------------------------ 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 5b1a24432e85..2b76d6f172a1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2046,6 +2046,51 @@ static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc) return 0; } +#define DSC_SUPPORTED_VERSION_MIN 1 + +static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; + u8 line_buf_depth; + int ret; + + ret = intel_dsc_compute_params(encoder, crtc_state); + if (ret) + return ret; + + vdsc_cfg->dsc_version_major = + (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & + DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT; + vdsc_cfg->dsc_version_minor = + min(DSC_SUPPORTED_VERSION_MIN, + (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & + DP_DSC_MINOR_MASK) >> DP_DSC_MINOR_SHIFT); + + vdsc_cfg->convert_rgb = intel_dp->dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & + DP_DSC_RGB; + + line_buf_depth = drm_dp_dsc_sink_line_buf_depth(intel_dp->dsc_dpcd); + if (!line_buf_depth) { + DRM_DEBUG_KMS("DSC Sink Line Buffer Depth invalid\n"); + return -EINVAL; + } + + if (vdsc_cfg->dsc_version_minor == 2) + vdsc_cfg->line_buf_depth = (line_buf_depth == DSC_1_2_MAX_LINEBUF_DEPTH_BITS) ? + DSC_1_2_MAX_LINEBUF_DEPTH_VAL : line_buf_depth; + else + vdsc_cfg->line_buf_depth = (line_buf_depth > DSC_1_1_MAX_LINEBUF_DEPTH_BITS) ? + DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth; + + vdsc_cfg->block_pred_enable = + intel_dp->dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & + DP_DSC_BLK_PREDICTION_IS_SUPPORTED; + + return drm_dsc_compute_rc_parameters(vdsc_cfg); +} + static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, @@ -2132,7 +2177,7 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, } } - ret = intel_dsc_compute_params(&dig_port->base, pipe_config); + ret = intel_dp_dsc_compute_params(&dig_port->base, pipe_config); if (ret < 0) { DRM_DEBUG_KMS("Cannot compute valid DSC parameters for Input Bpp = %d " "Compressed BPP = %d\n", diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index b23ba8d108db..834d665a47d2 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -30,8 +30,6 @@ enum COLUMN_INDEX_BPC { MAX_COLUMN_INDEX }; -#define DSC_SUPPORTED_VERSION_MIN 1 - /* From DSC_v1.11 spec, rc_parameter_Set syntax element typically constant */ static const u16 rc_buf_thresh[] = { 896, 1792, 2688, 3584, 4480, 5376, 6272, 6720, 7168, 7616, @@ -335,45 +333,6 @@ static const struct rc_parameters *get_rc_params(u16 compressed_bpp, return &rc_parameters[row_index][column_index]; } -/* Values filled from DSC Sink DPCD */ -static int intel_dsc_dp_compute_params(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) -{ - struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct drm_dsc_config *vdsc_cfg = &pipe_config->dsc.config; - u8 line_buf_depth; - - vdsc_cfg->dsc_version_major = - (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & - DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT; - vdsc_cfg->dsc_version_minor = - min(DSC_SUPPORTED_VERSION_MIN, - (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & - DP_DSC_MINOR_MASK) >> DP_DSC_MINOR_SHIFT); - - vdsc_cfg->convert_rgb = intel_dp->dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & - DP_DSC_RGB; - - line_buf_depth = drm_dp_dsc_sink_line_buf_depth(intel_dp->dsc_dpcd); - if (!line_buf_depth) { - DRM_DEBUG_KMS("DSC Sink Line Buffer Depth invalid\n"); - return -EINVAL; - } - - if (vdsc_cfg->dsc_version_minor == 2) - vdsc_cfg->line_buf_depth = (line_buf_depth == DSC_1_2_MAX_LINEBUF_DEPTH_BITS) ? - DSC_1_2_MAX_LINEBUF_DEPTH_VAL : line_buf_depth; - else - vdsc_cfg->line_buf_depth = (line_buf_depth > DSC_1_1_MAX_LINEBUF_DEPTH_BITS) ? - DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth; - - vdsc_cfg->block_pred_enable = - intel_dp->dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & - DP_DSC_BLK_PREDICTION_IS_SUPPORTED; - - return 0; -} - int intel_dsc_compute_params(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -381,7 +340,6 @@ int intel_dsc_compute_params(struct intel_encoder *encoder, u16 compressed_bpp = pipe_config->dsc.compressed_bpp; const struct rc_parameters *rc_params; u8 i = 0; - int ret; vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay; vdsc_cfg->pic_height = pipe_config->hw.adjusted_mode.crtc_vdisplay; @@ -470,11 +428,7 @@ int intel_dsc_compute_params(struct intel_encoder *encoder, vdsc_cfg->initial_scale_value = (vdsc_cfg->rc_model_size << 3) / (vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset); - ret = intel_dsc_dp_compute_params(encoder, pipe_config); - if (ret) - return ret; - - return drm_dsc_compute_rc_parameters(vdsc_cfg); + return 0; } enum intel_display_power_domain -- cgit v1.2.3 From c42c38ec307b6fb81c5cb213a8f082e03ffbe166 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:49 +0200 Subject: drm/i915/dsc: move slice height calculation to encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out this isn't compatible with DSI, where we use the value from VBT. No functional changes. Cc: Manasi Navare Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/3dd689688a51daff26088eaf6feac27f8b9f5ebc.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 12 ++++++++++++ drivers/gpu/drm/i915/display/intel_vdsc.c | 11 ----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 2b76d6f172a1..0d98ba7e98c0 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2060,6 +2060,18 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder, if (ret) return ret; + /* + * Slice Height of 8 works for all currently available panels. So start + * with that if pic_height is an integral multiple of 8. Eventually add + * logic to try multiple slice heights. + */ + if (vdsc_cfg->pic_height % 8 == 0) + vdsc_cfg->slice_height = 8; + else if (vdsc_cfg->pic_height % 4 == 0) + vdsc_cfg->slice_height = 4; + else + vdsc_cfg->slice_height = 2; + vdsc_cfg->dsc_version_major = (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 834d665a47d2..c53024dfb1ec 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -345,17 +345,6 @@ int intel_dsc_compute_params(struct intel_encoder *encoder, vdsc_cfg->pic_height = pipe_config->hw.adjusted_mode.crtc_vdisplay; vdsc_cfg->slice_width = DIV_ROUND_UP(vdsc_cfg->pic_width, pipe_config->dsc.slice_count); - /* - * Slice Height of 8 works for all currently available panels. So start - * with that if pic_height is an integral multiple of 8. - * Eventually add logic to try multiple slice heights. - */ - if (vdsc_cfg->pic_height % 8 == 0) - vdsc_cfg->slice_height = 8; - else if (vdsc_cfg->pic_height % 4 == 0) - vdsc_cfg->slice_height = 4; - else - vdsc_cfg->slice_height = 2; /* Gen 11 does not support YCbCr */ vdsc_cfg->simple_422 = false; -- cgit v1.2.3 From 2d15f3925a4b508b6ad10078bd324da1e95960a7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:50 +0200 Subject: drm/i915/dsc: add support for computing and writing PPS for DSI encoders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add DSI specific computation and transmission to display of PPS. With hopes that this approach will work for both DP and DSI encoders. Cc: Manasi Navare Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/461db10b1f4d76625625a9f2b1e3d932fff42799.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index c53024dfb1ec..7bd727129a8f 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -10,6 +10,7 @@ #include "i915_drv.h" #include "intel_display_types.h" +#include "intel_dsi.h" #include "intel_vdsc.h" enum ROW_INDEX_BPP { @@ -844,6 +845,25 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, } } +static void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + struct mipi_dsi_device *dsi; + struct drm_dsc_picture_parameter_set pps; + enum port port; + + drm_dsc_pps_payload_pack(&pps, vdsc_cfg); + + for_each_dsi_port(port, intel_dsi->ports) { + dsi = intel_dsi->dsi_hosts[port]->device; + + mipi_dsi_picture_parameter_set(dsi, &pps); + mipi_dsi_compression_mode(dsi, true); + } +} + static void intel_dsc_dp_pps_write(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { @@ -882,7 +902,10 @@ void intel_dsc_enable(struct intel_encoder *encoder, intel_dsc_pps_configure(encoder, crtc_state); - intel_dsc_dp_pps_write(encoder, crtc_state); + if (encoder->type == INTEL_OUTPUT_DSI) + intel_dsc_dsi_pps_write(encoder, crtc_state); + else + intel_dsc_dp_pps_write(encoder, crtc_state); if (crtc_state->cpu_transcoder == TRANSCODER_EDP) { dss_ctl1_reg = DSS_CTL1; -- cgit v1.2.3 From deaaff49198d04c197a95bceac95efc8534f6c04 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:51 +0200 Subject: drm/i915/dsc: make DSC source support helper generic Move intel_dp_source_supports_dsc() from intel_dp.c as intel_dsc_source_support() in intel_vdsc.c. The DSC source support is more about DSC than about DP, and will be needed for DP independent code. Cc: Manasi Navare Cc: Vandita Kulkarni Reviewed-by: Manasi Navare Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/6c9f646090913290fb00efd46a4332421bf95930.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 27 +++++---------------------- drivers/gpu/drm/i915/display/intel_vdsc.c | 19 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_vdsc.h | 4 ++++ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0d98ba7e98c0..fe31bbfd6c62 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1889,32 +1889,15 @@ static bool intel_dp_supports_fec(struct intel_dp *intel_dp, drm_dp_sink_supports_fec(intel_dp->fec_capable); } -static bool intel_dp_source_supports_dsc(struct intel_dp *intel_dp, - const struct intel_crtc_state *pipe_config) -{ - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - - if (!INTEL_INFO(dev_priv)->display.has_dsc) - return false; - - /* On TGL, DSC is supported on all Pipes */ - if (INTEL_GEN(dev_priv) >= 12) - return true; - - if (INTEL_GEN(dev_priv) >= 10 && - pipe_config->cpu_transcoder != TRANSCODER_A) - return true; - - return false; -} - static bool intel_dp_supports_dsc(struct intel_dp *intel_dp, - const struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *crtc_state) { - if (!intel_dp_is_edp(intel_dp) && !pipe_config->fec_enable) + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + + if (!intel_dp_is_edp(intel_dp) && !crtc_state->fec_enable) return false; - return intel_dp_source_supports_dsc(intel_dp, pipe_config) && + return intel_dsc_source_support(encoder, crtc_state) && drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd); } diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 7bd727129a8f..a1b0f7cf1a96 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -334,6 +334,25 @@ static const struct rc_parameters *get_rc_params(u16 compressed_bpp, return &rc_parameters[row_index][column_index]; } +bool intel_dsc_source_support(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + if (!INTEL_INFO(i915)->display.has_dsc) + return false; + + /* On TGL, DSC is supported on all Pipes */ + if (INTEL_GEN(i915) >= 12) + return true; + + if (INTEL_GEN(i915) >= 10 && + crtc_state->cpu_transcoder != TRANSCODER_A) + return true; + + return false; +} + int intel_dsc_compute_params(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h index 4ed2256750c3..88c6c17903c1 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc.h @@ -6,9 +6,13 @@ #ifndef __INTEL_VDSC_H__ #define __INTEL_VDSC_H__ +#include + struct intel_encoder; struct intel_crtc_state; +bool intel_dsc_source_support(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); void intel_dsc_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_dsc_disable(const struct intel_crtc_state *crtc_state); -- cgit v1.2.3 From fbacb15ea814e7badb57ebc4015d6542290d0ff8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:52 +0200 Subject: drm/i915/dsc: add basic hardware state readout support Add basic hardware state readout for DSC, and check the most relevant details in the state checker. v2: - check for DSC power before reading its state - check if source supports DSC at all As a side effect, this should also get the power domains for the enabled DSC on takeover, and subsequently disable DSC if it's not needed. Cc: Manasi Navare Cc: Vandita Kulkarni Reviewed-by: Manasi Navare Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/3fb018cf9bd9a4c275aab389b6ec0f2a4e938bb9.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 ++ drivers/gpu/drm/i915/display/intel_display.c | 4 +++ drivers/gpu/drm/i915/display/intel_vdsc.c | 49 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_vdsc.h | 2 ++ 4 files changed, 57 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3e81c54c349e..5b6f32517c75 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4294,6 +4294,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, if (WARN_ON(transcoder_is_dsi(cpu_transcoder))) return; + intel_dsc_get_config(encoder, pipe_config); + temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) flags |= DRM_MODE_FLAG_PHSYNC; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5c50b7d2db25..9c47454b3ac7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -13301,6 +13301,10 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(sync_mode_slaves_mask); PIPE_CONF_CHECK_I(master_transcoder); + PIPE_CONF_CHECK_I(dsc.compression_enable); + PIPE_CONF_CHECK_I(dsc.dsc_split); + PIPE_CONF_CHECK_I(dsc.compressed_bpp); + #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I #undef PIPE_CONF_CHECK_BOOL diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index a1b0f7cf1a96..ed9048140937 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -864,6 +864,55 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, } } +void intel_dsc_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + enum pipe pipe = crtc->pipe; + enum intel_display_power_domain power_domain; + intel_wakeref_t wakeref; + u32 dss_ctl1, dss_ctl2, val; + + if (!intel_dsc_source_support(encoder, crtc_state)) + return; + + power_domain = intel_dsc_power_domain(crtc_state); + + wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); + if (!wakeref) + return; + + if (crtc_state->cpu_transcoder == TRANSCODER_EDP) { + dss_ctl1 = I915_READ(DSS_CTL1); + dss_ctl2 = I915_READ(DSS_CTL2); + } else { + dss_ctl1 = I915_READ(ICL_PIPE_DSS_CTL1(pipe)); + dss_ctl2 = I915_READ(ICL_PIPE_DSS_CTL2(pipe)); + } + + crtc_state->dsc.compression_enable = dss_ctl2 & LEFT_BRANCH_VDSC_ENABLE; + if (!crtc_state->dsc.compression_enable) + goto out; + + crtc_state->dsc.dsc_split = (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE) && + (dss_ctl1 & JOINER_ENABLE); + + /* FIXME: add more state readout as needed */ + + /* PPS1 */ + if (cpu_transcoder == TRANSCODER_EDP) + val = I915_READ(DSCA_PICTURE_PARAMETER_SET_1); + else + val = I915_READ(ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe)); + vdsc_cfg->bits_per_pixel = val; + crtc_state->dsc.compressed_bpp = vdsc_cfg->bits_per_pixel >> 4; +out: + intel_display_power_put(dev_priv, power_domain, wakeref); +} + static void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h index 88c6c17903c1..e56a3254c214 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc.h @@ -18,6 +18,8 @@ void intel_dsc_enable(struct intel_encoder *encoder, void intel_dsc_disable(const struct intel_crtc_state *crtc_state); int intel_dsc_compute_params(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); +void intel_dsc_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state); enum intel_display_power_domain intel_dsc_power_domain(const struct intel_crtc_state *crtc_state); -- cgit v1.2.3 From 50003bf50d32f3ff8ead40d6d68ee5e91a693e20 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:53 +0200 Subject: drm/i915/dsi: set pipe_bpp on ICL configure config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ICL DSI pipe_bpp currently comes from compute_baseline_pipe_bpp(). Fix it. Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/191f5c4fa5f4af29d4bf7e30bb35f45ce05b33f0.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index f688207932e0..ef53ed6d3ecf 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1286,6 +1286,11 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, else pipe_config->cpu_transcoder = TRANSCODER_DSI_0; + if (intel_dsi->pixel_format == MIPI_DSI_FMT_RGB888) + pipe_config->pipe_bpp = 24; + else + pipe_config->pipe_bpp = 18; + pipe_config->clock_set = true; pipe_config->port_clock = intel_dsi_bitrate(intel_dsi) / 5; -- cgit v1.2.3 From 54ed6902cabc58ae58643b7d06cafa4ed5540e6d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:54 +0200 Subject: drm/i915/dsi: abstract afe_clk calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll make more use of it in the future. Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/0341fdc13260625150315b0b57a4227eb766c50f.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index ef53ed6d3ecf..de3743233dcb 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -301,18 +301,26 @@ static void configure_dual_link_mode(struct intel_encoder *encoder, I915_WRITE(DSS_CTL1, dss_ctl1); } +/* aka DSI 8X clock */ +static int afe_clk(struct intel_encoder *encoder) +{ + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + int bpp; + + bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); + + return DIV_ROUND_CLOSEST(intel_dsi->pclk * bpp, intel_dsi->lane_count); +} + static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; - u32 bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); - u32 afe_clk_khz; /* 8X Clock */ + int afe_clk_khz; u32 esc_clk_div_m; - afe_clk_khz = DIV_ROUND_CLOSEST(intel_dsi->pclk * bpp, - intel_dsi->lane_count); - + afe_clk_khz = afe_clk(encoder); esc_clk_div_m = DIV_ROUND_UP(afe_clk_khz, DSI_MAX_ESC_CLK); for_each_dsi_port(port, intel_dsi->ports) { -- cgit v1.2.3 From adf1bd3dfbaedf7100b542b92fb085f89222a349 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:55 +0200 Subject: drm/i915/dsi: use afe_clk() instead of intel_dsi_bitrate() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll be expanding afe_clk() to take DSC into account. Switch to using it where DSC matters. Which is really everywhere that intel_dsi_bitrate() is currently used in ICL DSI code. The functional difference is that we round the result closest instead of down. Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/b6c52b320daa8aaa0d79618ce714170f8f04ff67.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index de3743233dcb..d576f29cef75 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -539,7 +539,7 @@ static void gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder) * leave all fields at HW default values. */ if (IS_GEN(dev_priv, 11)) { - if (intel_dsi_bitrate(intel_dsi) <= 800000) { + if (afe_clk(encoder) <= 800000) { for_each_dsi_port(port, intel_dsi->ports) { tmp = I915_READ(DPHY_TA_TIMING_PARAM(port)); tmp &= ~TA_SURE_MASK; @@ -649,7 +649,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, tmp |= EOTP_DISABLED; /* enable link calibration if freq > 1.5Gbps */ - if (intel_dsi_bitrate(intel_dsi) >= 1500 * 1000) { + if (afe_clk(encoder) >= 1500 * 1000) { tmp &= ~LINK_CALIBRATION_MASK; tmp |= CALIBRATION_ENABLED_INITIAL_ONLY; } @@ -930,7 +930,7 @@ static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder) * TIME_NS = (BYTE_CLK_COUNT * 8 * 10^6)/ Bitrate * ESCAPE_CLK_COUNT = TIME_NS/ESC_CLK_NS */ - divisor = intel_dsi_tlpx_ns(intel_dsi) * intel_dsi_bitrate(intel_dsi) * 1000; + divisor = intel_dsi_tlpx_ns(intel_dsi) * afe_clk(encoder) * 1000; mul = 8 * 1000000; hs_tx_timeout = DIV_ROUND_UP(intel_dsi->hs_tx_timeout * mul, divisor); @@ -1300,7 +1300,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = 18; pipe_config->clock_set = true; - pipe_config->port_clock = intel_dsi_bitrate(intel_dsi) / 5; + pipe_config->port_clock = afe_clk(encoder) / 5; return 0; } -- cgit v1.2.3 From 0486513935ef95a3ce429323cac8148d58057913 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:56 +0200 Subject: drm/i915/dsi: take compression into account in afe_clk() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass crtc_state to afe_clk() to be able to take compression into account in the computation. Once we enable compression, that is. Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/a698780362b8d6955d115ef8bb6cf1f7aabbee00.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 40 ++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index d576f29cef75..5149a28a874b 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -302,17 +302,22 @@ static void configure_dual_link_mode(struct intel_encoder *encoder, } /* aka DSI 8X clock */ -static int afe_clk(struct intel_encoder *encoder) +static int afe_clk(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); int bpp; - bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); + if (crtc_state->dsc.compression_enable) + bpp = crtc_state->dsc.compressed_bpp; + else + bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); return DIV_ROUND_CLOSEST(intel_dsi->pclk * bpp, intel_dsi->lane_count); } -static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder) +static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -320,7 +325,7 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder) int afe_clk_khz; u32 esc_clk_div_m; - afe_clk_khz = afe_clk(encoder); + afe_clk_khz = afe_clk(encoder, crtc_state); esc_clk_div_m = DIV_ROUND_UP(afe_clk_khz, DSI_MAX_ESC_CLK); for_each_dsi_port(port, intel_dsi->ports) { @@ -498,7 +503,9 @@ static void gen11_dsi_enable_ddi_buffer(struct intel_encoder *encoder) } } -static void gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder) +static void +gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -539,7 +546,7 @@ static void gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder) * leave all fields at HW default values. */ if (IS_GEN(dev_priv, 11)) { - if (afe_clk(encoder) <= 800000) { + if (afe_clk(encoder, crtc_state) <= 800000) { for_each_dsi_port(port, intel_dsi->ports) { tmp = I915_READ(DPHY_TA_TIMING_PARAM(port)); tmp &= ~TA_SURE_MASK; @@ -649,7 +656,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, tmp |= EOTP_DISABLED; /* enable link calibration if freq > 1.5Gbps */ - if (afe_clk(encoder) >= 1500 * 1000) { + if (afe_clk(encoder, pipe_config) >= 1500 * 1000) { tmp &= ~LINK_CALIBRATION_MASK; tmp |= CALIBRATION_ENABLED_INITIAL_ONLY; } @@ -915,7 +922,8 @@ static void gen11_dsi_enable_transcoder(struct intel_encoder *encoder) } } -static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder) +static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -930,7 +938,7 @@ static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder) * TIME_NS = (BYTE_CLK_COUNT * 8 * 10^6)/ Bitrate * ESCAPE_CLK_COUNT = TIME_NS/ESC_CLK_NS */ - divisor = intel_dsi_tlpx_ns(intel_dsi) * afe_clk(encoder) * 1000; + divisor = intel_dsi_tlpx_ns(intel_dsi) * afe_clk(encoder, crtc_state) * 1000; mul = 8 * 1000000; hs_tx_timeout = DIV_ROUND_UP(intel_dsi->hs_tx_timeout * mul, divisor); @@ -966,7 +974,7 @@ static void gen11_dsi_setup_timeouts(struct intel_encoder *encoder) static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -983,13 +991,13 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, gen11_dsi_enable_ddi_buffer(encoder); /* setup D-PHY timings */ - gen11_dsi_setup_dphy_timings(encoder); + gen11_dsi_setup_dphy_timings(encoder, crtc_state); /* step 4h: setup DSI protocol timeouts */ - gen11_dsi_setup_timeouts(encoder); + gen11_dsi_setup_timeouts(encoder, crtc_state); /* Step (4h, 4i, 4j, 4k): Configure transcoder */ - gen11_dsi_configure_transcoder(encoder, pipe_config); + gen11_dsi_configure_transcoder(encoder, crtc_state); /* Step 4l: Gate DDI clocks */ if (IS_GEN(dev_priv, 11)) @@ -1036,14 +1044,14 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) } static void gen11_dsi_pre_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, + const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { /* step2: enable IO power */ gen11_dsi_enable_io_power(encoder); /* step3: enable DSI PLL */ - gen11_dsi_program_esc_clk_div(encoder); + gen11_dsi_program_esc_clk_div(encoder, crtc_state); } static void gen11_dsi_pre_enable(struct intel_encoder *encoder, @@ -1300,7 +1308,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = 18; pipe_config->clock_set = true; - pipe_config->port_clock = afe_clk(encoder) / 5; + pipe_config->port_clock = afe_clk(encoder, pipe_config) / 5; return 0; } -- cgit v1.2.3 From 38b898810ae92b2e78b47f513fe66bdd5687ed54 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:57 +0200 Subject: drm/i915/dsi: use compressed pixel format with DSC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compression is enabled, configure the DSI transcoder to use compressed format. Suggested-by: Vandita Kulkarni Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/0e58022ce5425560b3b31062c41de385a736c8b1.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 36 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 5149a28a874b..460759913708 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -682,22 +682,26 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, /* select pixel format */ tmp &= ~PIX_FMT_MASK; - switch (intel_dsi->pixel_format) { - default: - MISSING_CASE(intel_dsi->pixel_format); - /* fallthrough */ - case MIPI_DSI_FMT_RGB565: - tmp |= PIX_FMT_RGB565; - break; - case MIPI_DSI_FMT_RGB666_PACKED: - tmp |= PIX_FMT_RGB666_PACKED; - break; - case MIPI_DSI_FMT_RGB666: - tmp |= PIX_FMT_RGB666_LOOSE; - break; - case MIPI_DSI_FMT_RGB888: - tmp |= PIX_FMT_RGB888; - break; + if (pipe_config->dsc.compression_enable) { + tmp |= PIX_FMT_COMPRESSED; + } else { + switch (intel_dsi->pixel_format) { + default: + MISSING_CASE(intel_dsi->pixel_format); + /* fallthrough */ + case MIPI_DSI_FMT_RGB565: + tmp |= PIX_FMT_RGB565; + break; + case MIPI_DSI_FMT_RGB666_PACKED: + tmp |= PIX_FMT_RGB666_PACKED; + break; + case MIPI_DSI_FMT_RGB666: + tmp |= PIX_FMT_RGB666_LOOSE; + break; + case MIPI_DSI_FMT_RGB888: + tmp |= PIX_FMT_RGB888; + break; + } } if (INTEL_GEN(dev_priv) >= 12) { -- cgit v1.2.3 From 53693f02d80e0a909e76c2a25f8aac8515f959db Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:58 +0200 Subject: drm/i915/dsi: account for DSC in horizontal timings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When DSC is enabled, we need to adjust the horizontal timings to account for the compressed (and therefore reduced) link speed. The compressed frequency ratio simplifies down to the ratio between compressed and non-compressed bpp. Bspec: 49263 Suggested-by: Vandita Kulkarni Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/fecebdc2719dd0c78eaf8f4d3225bb185956d7db.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 460759913708..caa477c4b1af 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -785,12 +785,12 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, static void gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); const struct drm_display_mode *adjusted_mode = - &pipe_config->hw.adjusted_mode; + &crtc_state->hw.adjusted_mode; enum port port; enum transcoder dsi_trans; /* horizontal timings */ @@ -798,11 +798,25 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder, u16 hback_porch; /* vertical timings */ u16 vtotal, vactive, vsync_start, vsync_end, vsync_shift; + int mul = 1, div = 1; + + /* + * Adjust horizontal timings (htotal, hsync_start, hsync_end) to account + * for slower link speed if DSC is enabled. + * + * The compression frequency ratio is the ratio between compressed and + * non-compressed link speeds, and simplifies down to the ratio between + * compressed and non-compressed bpp. + */ + if (crtc_state->dsc.compression_enable) { + mul = crtc_state->dsc.compressed_bpp; + div = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); + } hactive = adjusted_mode->crtc_hdisplay; - htotal = adjusted_mode->crtc_htotal; - hsync_start = adjusted_mode->crtc_hsync_start; - hsync_end = adjusted_mode->crtc_hsync_end; + htotal = DIV_ROUND_UP(adjusted_mode->crtc_htotal * mul, div); + hsync_start = DIV_ROUND_UP(adjusted_mode->crtc_hsync_start * mul, div); + hsync_end = DIV_ROUND_UP(adjusted_mode->crtc_hsync_end * mul, div); hsync_size = hsync_end - hsync_start; hback_porch = (adjusted_mode->crtc_htotal - adjusted_mode->crtc_hsync_end); -- cgit v1.2.3 From c2bb35e99f4b426efdd28011655bd67ca86749b5 Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Tue, 10 Dec 2019 12:50:59 +0200 Subject: drm/i915/dsi: Fix state mismatch warns for horizontal timings with DSC When DSC is enabled consider the compression ratio that was used during horizontal timing calculations. This may still lead to warns due to rounding errors in the round-trip. v2 by Jani: - rebase on top of the more generic dsc state readout Signed-off-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/c2481aaf67ea396aa4698cd2d8e23d19ec4f4ecf.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index caa477c4b1af..b1d775d834d4 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1255,6 +1255,18 @@ static void gen11_dsi_get_timings(struct intel_encoder *encoder, struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; + if (pipe_config->dsc.compressed_bpp) { + int div = pipe_config->dsc.compressed_bpp; + int mul = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); + + adjusted_mode->crtc_htotal = + DIV_ROUND_UP(adjusted_mode->crtc_htotal * mul, div); + adjusted_mode->crtc_hsync_start = + DIV_ROUND_UP(adjusted_mode->crtc_hsync_start * mul, div); + adjusted_mode->crtc_hsync_end = + DIV_ROUND_UP(adjusted_mode->crtc_hsync_end * mul, div); + } + if (intel_dsi->dual_link) { adjusted_mode->crtc_hdisplay *= 2; if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) -- cgit v1.2.3 From 2b68392e638dfa5cf4f7b558f62e3ea4def2e605 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:51:00 +0200 Subject: drm/i915/dsi: add support for DSC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable DSC for DSI, if specified in VBT. This still lacks DSC aware get config implementation, and therefore state checker will fail. Also mode valid is not there yet. v5: - add dsc get config call v4: - convert_rgb = true (Vandita) - ignore max cdclock check (Vandita) - rename pipe_config to crtc_state v3: - take compressed bpp into account v2: - Nuke conn_state->max_requested_bpc, it's not used on DSI Bspec: 49263 Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/e0136299e03c582238523189f6951eeb08daed98.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 69 ++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index b1d775d834d4..03aa92d317a2 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -34,6 +34,7 @@ #include "intel_ddi.h" #include "intel_dsi.h" #include "intel_panel.h" +#include "intel_vdsc.h" static inline int header_credits_available(struct drm_i915_private *dev_priv, enum transcoder dsi_trans) @@ -1087,6 +1088,8 @@ static void gen11_dsi_pre_enable(struct intel_encoder *encoder, /* step5: program and powerup panel */ gen11_dsi_powerup_panel(encoder); + intel_dsc_enable(encoder, pipe_config); + /* step6c: configure transcoder timings */ gen11_dsi_set_transcoder_timings(encoder, pipe_config); @@ -1248,6 +1251,13 @@ static void gen11_dsi_disable(struct intel_encoder *encoder, gen11_dsi_disable_io_power(encoder); } +static enum drm_mode_status gen11_dsi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + /* FIXME: DSC? */ + return intel_dsi_mode_valid(connector, mode); +} + static void gen11_dsi_get_timings(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -1294,6 +1304,8 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + intel_dsc_get_config(encoder, pipe_config); + /* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */ pipe_config->port_clock = cnl_calc_wrpll_link(dev_priv, &pipe_config->dpll_hw_state); @@ -1307,6 +1319,48 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = bdw_get_pipemisc_bpp(crtc); } +static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; + int dsc_max_bpc = INTEL_GEN(dev_priv) >= 12 ? 12 : 10; + bool use_dsc; + int ret; + + use_dsc = intel_bios_get_dsc_params(encoder, crtc_state, dsc_max_bpc); + if (!use_dsc) + return 0; + + if (crtc_state->pipe_bpp < 8 * 3) + return -EINVAL; + + /* FIXME: split only when necessary */ + if (crtc_state->dsc.slice_count > 1) + crtc_state->dsc.dsc_split = true; + + vdsc_cfg->convert_rgb = true; + + ret = intel_dsc_compute_params(encoder, crtc_state); + if (ret) + return ret; + + /* DSI specific sanity checks on the common code */ + WARN_ON(vdsc_cfg->vbr_enable); + WARN_ON(vdsc_cfg->simple_422); + WARN_ON(vdsc_cfg->pic_width % vdsc_cfg->slice_width); + WARN_ON(vdsc_cfg->slice_height < 8); + WARN_ON(vdsc_cfg->pic_height % vdsc_cfg->slice_height); + + ret = drm_dsc_compute_rc_parameters(vdsc_cfg); + if (ret) + return ret; + + crtc_state->dsc.compression_enable = true; + + return 0; +} + static int gen11_dsi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -1338,6 +1392,10 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = 18; pipe_config->clock_set = true; + + if (gen11_dsi_dsc_compute_config(encoder, pipe_config)) + DRM_DEBUG_KMS("Attempting to use DSC failed\n"); + pipe_config->port_clock = afe_clk(encoder, pipe_config) / 5; return 0; @@ -1346,8 +1404,13 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, static void gen11_dsi_get_power_domains(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { - get_dsi_io_power_domains(to_i915(encoder->base.dev), - enc_to_intel_dsi(&encoder->base)); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + get_dsi_io_power_domains(i915, enc_to_intel_dsi(&encoder->base)); + + if (crtc_state->dsc.compression_enable) + intel_display_power_get(i915, + intel_dsc_power_domain(crtc_state)); } static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder, @@ -1417,7 +1480,7 @@ static const struct drm_connector_funcs gen11_dsi_connector_funcs = { static const struct drm_connector_helper_funcs gen11_dsi_connector_helper_funcs = { .get_modes = intel_dsi_get_modes, - .mode_valid = intel_dsi_mode_valid, + .mode_valid = gen11_dsi_mode_valid, .atomic_check = intel_digital_connector_atomic_check, }; -- cgit v1.2.3 From d04a661a2c7169b48782aa5e9d85d4b4383d562e Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Thu, 5 Dec 2019 18:05:13 +0530 Subject: drm/i915/dsb: Fix in mmio offset calculation of DSB instance As the current usage is restricted to first DSB instance per pipe, so existing code could not catch the issue to calculate the mmio offset of different DSB instance per pipe. Corrected the offset calculation. Fixes: a6e58d9a2e04 ("drm/i915/dsb: Check DSB engine status.") Signed-off-by: Animesh Manna Reviewed-by: Anshuman Gupta Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191205123513.22603-1-animesh.manna@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 082190c2dc48..17f9dd3bda72 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -12084,7 +12084,7 @@ enum skl_power_gate { /* This register controls the Display State Buffer (DSB) engines. */ #define _DSBSL_INSTANCE_BASE 0x70B00 #define DSBSL_INSTANCE(pipe, id) (_DSBSL_INSTANCE_BASE + \ - (pipe) * 0x1000 + (id) * 100) + (pipe) * 0x1000 + (id) * 0x100) #define DSB_HEAD(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x0) #define DSB_TAIL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x4) #define DSB_CTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x8) -- cgit v1.2.3 From c81471f5e95c79c55687282ff6800f112b5d560b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 10 Dec 2019 15:13:32 +0000 Subject: drm/i915: Copy across scheduler behaviour flags across submit fences We want the bonded request to have the same scheduler properties as its master so that it is placed at the same depth in the queue. For example, consider we have requests A, B and B', where B & B' are a bonded pair to run in parallel on two engines. A -> B \- B' B will run after A and so may be scheduled on an idle engine and wait on A using a semaphore. B' sees B being executed and so enters the queue on the same engine as A. As B' did not inherit the semaphore-chain from B, it may have higher precedence than A and so preempts execution. However, B' then sits on a semaphore waiting for B, who is waiting for A, who is blocked by B. Ergo B' needs to inherit the scheduler properties from B (i.e. the semaphore chain) so that it is scheduled with the same priority as B and will not be executed ahead of Bs dependencies. Furthermore, to prevent the priorities changing via the expose fence on B', we need to couple in the dependencies for PI. This requires us to relax our sanity-checks that dependencies are strictly in order. v2: Synchronise (B, B') execution on all platforms, regardless of using a scheduler, any no-op syncs should be elided. Fixes: ee1136908e9b ("drm/i915/execlists: Virtual engine bonding") Closes: https://gitlab.freedesktop.org/drm/intel/issues/464 Testcase: igt/gem_exec_balancer/bonded-chain Testcase: igt/gem_exec_balancer/bonded-semaphore Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191210151332.3902215-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_request.c | 114 ++++++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_scheduler.c | 1 - 2 files changed, 89 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index ddc6c311349c..a6238c626a16 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -300,11 +300,11 @@ void i915_request_retire_upto(struct i915_request *rq) } static int -__i915_request_await_execution(struct i915_request *rq, - struct i915_request *signal, - void (*hook)(struct i915_request *rq, - struct dma_fence *signal), - gfp_t gfp) +__await_execution(struct i915_request *rq, + struct i915_request *signal, + void (*hook)(struct i915_request *rq, + struct dma_fence *signal), + gfp_t gfp) { struct execute_cb *cb; @@ -341,6 +341,8 @@ __i915_request_await_execution(struct i915_request *rq, } spin_unlock_irq(&signal->lock); + /* Copy across semaphore status as we need the same behaviour */ + rq->sched.flags |= signal->sched.flags; return 0; } @@ -824,31 +826,21 @@ already_busywaiting(struct i915_request *rq) } static int -emit_semaphore_wait(struct i915_request *to, - struct i915_request *from, - gfp_t gfp) +__emit_semaphore_wait(struct i915_request *to, + struct i915_request *from, + u32 seqno) { const int has_token = INTEL_GEN(to->i915) >= 12; u32 hwsp_offset; - int len; + int len, err; u32 *cs; GEM_BUG_ON(INTEL_GEN(to->i915) < 8); - /* Just emit the first semaphore we see as request space is limited. */ - if (already_busywaiting(to) & from->engine->mask) - goto await_fence; - - if (i915_request_await_start(to, from) < 0) - goto await_fence; - - /* Only submit our spinner after the signaler is running! */ - if (__i915_request_await_execution(to, from, NULL, gfp)) - goto await_fence; - /* We need to pin the signaler's HWSP until we are finished reading. */ - if (intel_timeline_read_hwsp(from, to, &hwsp_offset)) - goto await_fence; + err = intel_timeline_read_hwsp(from, to, &hwsp_offset); + if (err) + return err; len = 4; if (has_token) @@ -871,7 +863,7 @@ emit_semaphore_wait(struct i915_request *to, MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_GTE_SDD) + has_token; - *cs++ = from->fence.seqno; + *cs++ = seqno; *cs++ = hwsp_offset; *cs++ = 0; if (has_token) { @@ -880,6 +872,28 @@ emit_semaphore_wait(struct i915_request *to, } intel_ring_advance(to, cs); + return 0; +} + +static int +emit_semaphore_wait(struct i915_request *to, + struct i915_request *from, + gfp_t gfp) +{ + /* Just emit the first semaphore we see as request space is limited. */ + if (already_busywaiting(to) & from->engine->mask) + goto await_fence; + + if (i915_request_await_start(to, from) < 0) + goto await_fence; + + /* Only submit our spinner after the signaler is running! */ + if (__await_execution(to, from, NULL, gfp)) + goto await_fence; + + if (__emit_semaphore_wait(to, from, from->fence.seqno)) + goto await_fence; + to->sched.semaphores |= from->engine->mask; to->sched.flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN; return 0; @@ -995,6 +1009,57 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence) return 0; } +static bool intel_timeline_sync_has_start(struct intel_timeline *tl, + struct dma_fence *fence) +{ + return __intel_timeline_sync_is_later(tl, + fence->context, + fence->seqno - 1); +} + +static int intel_timeline_sync_set_start(struct intel_timeline *tl, + const struct dma_fence *fence) +{ + return __intel_timeline_sync_set(tl, fence->context, fence->seqno - 1); +} + +static int +__i915_request_await_execution(struct i915_request *to, + struct i915_request *from, + void (*hook)(struct i915_request *rq, + struct dma_fence *signal)) +{ + int err; + + /* Submit both requests at the same time */ + err = __await_execution(to, from, hook, I915_FENCE_GFP); + if (err) + return err; + + /* Squash repeated depenendices to the same timelines */ + if (intel_timeline_sync_has_start(i915_request_timeline(to), + &from->fence)) + return 0; + + /* Ensure both start together [after all semaphores in signal] */ + if (intel_engine_has_semaphores(to->engine)) + err = __emit_semaphore_wait(to, from, from->fence.seqno - 1); + else + err = i915_request_await_start(to, from); + if (err < 0) + return err; + + /* Couple the dependency tree for PI on this exposed to->fence */ + if (to->engine->schedule) { + err = i915_sched_node_add_dependency(&to->sched, &from->sched); + if (err < 0) + return err; + } + + return intel_timeline_sync_set_start(i915_request_timeline(to), + &from->fence); +} + int i915_request_await_execution(struct i915_request *rq, struct dma_fence *fence, @@ -1030,8 +1095,7 @@ i915_request_await_execution(struct i915_request *rq, if (dma_fence_is_i915(fence)) ret = __i915_request_await_execution(rq, to_request(fence), - hook, - I915_FENCE_GFP); + hook); else ret = i915_sw_fence_await_dma_fence(&rq->submit, fence, I915_FENCE_TIMEOUT, diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index 1937a26d412f..2bc2aa46a1b9 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.c +++ b/drivers/gpu/drm/i915/i915_scheduler.c @@ -484,7 +484,6 @@ void i915_sched_node_fini(struct i915_sched_node *node) * so we may be called out-of-order. */ list_for_each_entry_safe(dep, tmp, &node->signalers_list, signal_link) { - GEM_BUG_ON(!node_signaled(dep->signaler)); GEM_BUG_ON(!list_empty(&dep->dfs_link)); list_del(&dep->wait_link); -- cgit v1.2.3 From 00aff3f6d8e2c0e24f015280eedad6ac60f0594a Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 9 Dec 2019 12:23:14 +0000 Subject: drm/i915: Improve execbuf debug Convert i915_gem_check_execbuffer to return the error code instead of a boolean so our neat EINVAL debugging trick works within this function. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191209122314.16289-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 34044c6203a5..5003e616a1ad 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1915,15 +1915,15 @@ err_skip: return err; } -static bool i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) +static int i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) { if (exec->flags & __I915_EXEC_ILLEGAL_FLAGS) - return false; + return -EINVAL; /* Kernel clipping was a DRI1 misfeature */ if (!(exec->flags & I915_EXEC_FENCE_ARRAY)) { if (exec->num_cliprects || exec->cliprects_ptr) - return false; + return -EINVAL; } if (exec->DR4 == 0xffffffff) { @@ -1931,12 +1931,12 @@ static bool i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) exec->DR4 = 0; } if (exec->DR1 || exec->DR4) - return false; + return -EINVAL; if ((exec->batch_start_offset | exec->batch_len) & 0x7) - return false; + return -EINVAL; - return true; + return 0; } static int i915_reset_gen7_sol_offsets(struct i915_request *rq) @@ -2768,8 +2768,9 @@ i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, exec2.flags = I915_EXEC_RENDER; i915_execbuffer2_set_context_id(exec2, 0); - if (!i915_gem_check_execbuffer(&exec2)) - return -EINVAL; + err = i915_gem_check_execbuffer(&exec2); + if (err) + return err; /* Copy in the exec list from userland */ exec_list = kvmalloc_array(count, sizeof(*exec_list), @@ -2846,8 +2847,9 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, return -EINVAL; } - if (!i915_gem_check_execbuffer(args)) - return -EINVAL; + err = i915_gem_check_execbuffer(args); + if (err) + return err; /* Allocate an extra slot for use by the command parser */ exec2_list = kvmalloc_array(count + 1, eb_element_size(), -- cgit v1.2.3 From c0168a3ee6208e72050f47473d9b63fa248ca582 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 10 Dec 2019 15:36:20 +0000 Subject: drm/i915/gt: Check we are the Ironlake IPS provider before deregistering Check that we own the global pointer before deregistering. Reported-by: Venkata Sandeep Dhanalakota Signed-off-by: Chris Wilson Cc: Venkata Sandeep Dhanalakota Cc: Andi Shyti Reviewed-by: Venkata Sandeep Dhanalakota Link: https://patchwork.freedesktop.org/patch/msgid/20191210153620.3929372-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rps.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 08a38a3b90b0..fd01e4100fc1 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1715,6 +1715,7 @@ void intel_rps_driver_register(struct intel_rps *rps) * set up, to avoid intel-ips sneaking in and reading bogus values. */ if (IS_GEN(gt->i915, 5)) { + GEM_BUG_ON(ips_mchdev); rcu_assign_pointer(ips_mchdev, gt->i915); ips_ping_for_i915_load(); } @@ -1722,7 +1723,8 @@ void intel_rps_driver_register(struct intel_rps *rps) void intel_rps_driver_unregister(struct intel_rps *rps) { - rcu_assign_pointer(ips_mchdev, NULL); + if (ips_mchdev == rps_to_i915(rps)) + rcu_assign_pointer(ips_mchdev, NULL); } static struct drm_i915_private *mchdev_get(void) -- cgit v1.2.3 From 93e89ac8537bad2cd560c64b70dbb87e68714e54 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 10 Dec 2019 13:37:19 +0000 Subject: drm/i915/gem: Wait on unbind barriers when invalidating userptr When we are told we have to drop all references to userptr, wait for any barriers required for unbinding. <4> [2055.808787] WARNING: CPU: 3 PID: 6239 at mm/mmu_notifier.c:472 __mmu_notifier_invalidate_range_start+0x1f2/0x250 <4> [2055.808792] Modules linked in: vgem mei_hdcp snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic x86_pkg_temp_thermal coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel r8169 lpc_ich realtek i915 snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hwdep snd_hda_core pinctrl_broxton snd_pcm pinctrl_intel mei_me intel_lpss_pci mei prime_numbers [last unloaded: vgem] <4> [2055.808834] CPU: 3 PID: 6239 Comm: gem_userptr_bli Tainted: G U 5.5.0-rc1-CI-CI_DRM_7522+ #1 <4> [2055.808839] Hardware name: /NUC6CAYB, BIOS AYAPLCEL.86A.0049.2018.0508.1356 05/08/2018 <4> [2055.808847] RIP: 0010:__mmu_notifier_invalidate_range_start+0x1f2/0x250 <4> [2055.808853] Code: c2 48 c7 c7 70 17 2e 82 44 89 45 d4 48 8b 70 28 e8 ec 01 ef ff 41 f6 46 20 01 44 8b 45 d4 75 0a 41 83 f8 f5 44 89 7d d4 74 89 <0f> 0b 44 89 45 d4 eb 81 0f 0b 49 8b 46 18 49 8b 76 10 4c 89 ff 48 <4> [2055.808858] RSP: 0018:ffffc90002937d40 EFLAGS: 00010202 <4> [2055.808865] RAX: 0000000000000061 RBX: ffff8882703a33e0 RCX: 0000000000000001 <4> [2055.808870] RDX: 0000000000000000 RSI: ffff888277da8cb8 RDI: 00000000ffffffff <4> [2055.808874] RBP: ffffc90002937d70 R08: 00000000fffffff5 R09: 0000000000000000 <4> [2055.808879] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000001 <4> [2055.808884] R13: ffffffff822e1716 R14: ffffc90002937d80 R15: 00000000fffffff5 <4> [2055.808890] FS: 00007fda75004e40(0000) GS:ffff888277d80000(0000) knlGS:0000000000000000 <4> [2055.808895] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4> [2055.808900] CR2: 000055ad72ec3000 CR3: 00000002697b2000 CR4: 00000000003406e0 <4> [2055.808904] Call Trace: <4> [2055.808920] unmap_vmas+0x13e/0x150 <4> [2055.808937] unmap_region+0xa3/0x100 <4> [2055.808964] __do_munmap+0x26d/0x490 <4> [2055.808980] __vm_munmap+0x66/0xc0 <4> [2055.808994] __x64_sys_munmap+0x12/0x20 <4> [2055.809001] do_syscall_64+0x4f/0x220 Closes: https://gitlab.freedesktop.org/drm/intel/issues/771 Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191210133719.3874455-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index 54ebc7ab71bc..f7f66c62cf0e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -129,7 +129,8 @@ userptr_mn_invalidate_range_start(struct mmu_notifier *_mn, spin_unlock(&mn->lock); ret = i915_gem_object_unbind(obj, - I915_GEM_OBJECT_UNBIND_ACTIVE); + I915_GEM_OBJECT_UNBIND_ACTIVE | + I915_GEM_OBJECT_UNBIND_BARRIER); if (ret == 0) ret = __i915_gem_object_put_pages(obj); i915_gem_object_put(obj); -- cgit v1.2.3 From 5de34ed13787c47f34b73d69b3d0bbaf2245d534 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 10 Dec 2019 11:55:02 +0000 Subject: drm/i915/selftests: Show the i915_active on failure Print the i915_active state on selftest failure, with a hope it helps illuminate the cause of the failure. References: https://gitlab.freedesktop.org/drm/intel/issues/765 Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191210115502.3767070-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/i915_active.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/i915_active.c b/drivers/gpu/drm/i915/selftests/i915_active.c index 6c1db3ded446..ef572a0c2566 100644 --- a/drivers/gpu/drm/i915/selftests/i915_active.c +++ b/drivers/gpu/drm/i915/selftests/i915_active.c @@ -155,7 +155,11 @@ static int live_active_wait(void *arg) i915_active_wait(&active->base); if (!READ_ONCE(active->retired)) { + struct drm_printer p = drm_err_printer(__func__); + pr_err("i915_active not retired after waiting!\n"); + i915_active_print(&active->base, &p); + err = -EINVAL; } @@ -184,7 +188,11 @@ static int live_active_retire(void *arg) err = -EIO; if (!READ_ONCE(active->retired)) { + struct drm_printer p = drm_err_printer(__func__); + pr_err("i915_active not retired after flushing!\n"); + i915_active_print(&active->base, &p); + err = -EINVAL; } -- cgit v1.2.3 From a722146b5f52f514aabf0d04c3dbdd39850d0a8c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Nov 2019 18:38:11 +0200 Subject: drm/i915: ELiminate intel_pipe_to_cpu_transcoder() from assert_fdi_tx() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's start to eliminate intel_pipe_to_cpu_transcoder() so that we can get rid of one more crtc->config usage (which we will want to nuke as well). In the case of assert_fdi_tx() we know that we're never dealing with the EDP transcoder so we can simply replace this with a cast. v2: Fix poor English in comment Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191112163812.22075-3-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9c47454b3ac7..e5f725bcca51 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1146,11 +1146,15 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { bool cur_state; - enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, - pipe); if (HAS_DDI(dev_priv)) { - /* DDI does not have a specific FDI_TX register */ + /* + * DDI does not have a specific FDI_TX register. + * + * FDI is never fed from EDP transcoder + * so pipe->transcoder cast is fine here. + */ + enum transcoder cpu_transcoder = (enum transcoder)pipe; u32 val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); cur_state = !!(val & TRANS_DDI_FUNC_ENABLE); } else { -- cgit v1.2.3 From b104e8b200974f9d1a431d1ce15f0e6d547dc859 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 12 Nov 2019 18:38:12 +0200 Subject: drm/i915: Pass cpu transcoder to assert_pipe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to eliminate intel_pipe_to_cpu_transcoder() (and its crtc->config usage) let's pass the cpu transcoder to assert_pipe() so we don't have to do the pipe->cpu transcoder lookup on HSW+. On VLV/CHV this can get called during eDP init, which happens before crtc->config->cpu_transcoder is even populated. So currently we're always reading PIPECONF(A) there even if we're trying to check the state of some other pipe. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191112163812.22075-4-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 36 +++++++++++----------------- drivers/gpu/drm/i915/display/intel_display.h | 9 ++++--- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e5f725bcca51..d0d37a979737 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1045,14 +1045,6 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, NULL, best_clock); } -enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); - - return crtc->config->cpu_transcoder; -} - static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, enum pipe pipe) { @@ -1271,11 +1263,9 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) } void assert_pipe(struct drm_i915_private *dev_priv, - enum pipe pipe, bool state) + enum transcoder cpu_transcoder, bool state) { bool cur_state; - enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, - pipe); enum intel_display_power_domain power_domain; intel_wakeref_t wakeref; @@ -1295,8 +1285,9 @@ void assert_pipe(struct drm_i915_private *dev_priv, } I915_STATE_WARN(cur_state != state, - "pipe %c assertion failure (expected %s, current %s)\n", - pipe_name(pipe), onoff(state), onoff(cur_state)); + "transcoder %s assertion failure (expected %s, current %s)\n", + transcoder_name(cpu_transcoder), + onoff(state), onoff(cur_state)); } static void assert_plane(struct intel_plane *plane, bool state) @@ -1423,7 +1414,7 @@ static void vlv_enable_pll(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - assert_pipe_disabled(dev_priv, pipe); + assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder); /* PLL is protected by panel, make sure we can write it */ assert_panel_unlocked(dev_priv, pipe); @@ -1472,7 +1463,7 @@ static void chv_enable_pll(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - assert_pipe_disabled(dev_priv, pipe); + assert_pipe_disabled(dev_priv, pipe_config->cpu_transcoder); /* PLL is protected by panel, make sure we can write it */ assert_panel_unlocked(dev_priv, pipe); @@ -1519,7 +1510,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc, u32 dpll = crtc_state->dpll_hw_state.dpll; int i; - assert_pipe_disabled(dev_priv, crtc->pipe); + assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder); /* PLL is protected by panel, make sure we can write it */ if (i9xx_has_pps(dev_priv)) @@ -1568,7 +1559,7 @@ static void i9xx_disable_pll(const struct intel_crtc_state *crtc_state) return; /* Make sure the pipe isn't still relying on us */ - assert_pipe_disabled(dev_priv, pipe); + assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder); I915_WRITE(DPLL(pipe), DPLL_VGA_MODE_DIS); POSTING_READ(DPLL(pipe)); @@ -1579,7 +1570,7 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) u32 val; /* Make sure the pipe isn't still relying on us */ - assert_pipe_disabled(dev_priv, pipe); + assert_pipe_disabled(dev_priv, (enum transcoder)pipe); val = DPLL_INTEGRATED_REF_CLK_VLV | DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; @@ -1596,7 +1587,7 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) u32 val; /* Make sure the pipe isn't still relying on us */ - assert_pipe_disabled(dev_priv, pipe); + assert_pipe_disabled(dev_priv, (enum transcoder)pipe); val = DPLL_SSC_REF_CLK_CHV | DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; @@ -4660,7 +4651,7 @@ static void ironlake_fdi_link_train(struct intel_crtc *crtc, u32 temp, tries; /* FDI needs bits from pipe first */ - assert_pipe_enabled(dev_priv, pipe); + assert_pipe_enabled(dev_priv, crtc_state->cpu_transcoder); /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit for train result */ @@ -6793,7 +6784,7 @@ static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) * according to register description and PRM. */ WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE); - assert_pipe_disabled(dev_priv, crtc->pipe); + assert_pipe_disabled(dev_priv, crtc_state->cpu_transcoder); I915_WRITE(PFIT_PGM_RATIOS, crtc_state->gmch_pfit.pgm_ratios); I915_WRITE(PFIT_CONTROL, crtc_state->gmch_pfit.control); @@ -7099,7 +7090,7 @@ static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->gmch_pfit.control) return; - assert_pipe_disabled(dev_priv, crtc->pipe); + assert_pipe_disabled(dev_priv, old_crtc_state->cpu_transcoder); DRM_DEBUG_KMS("disabling pfit, current: 0x%08x\n", I915_READ(PFIT_CONTROL)); @@ -8110,6 +8101,7 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe, return -ENOMEM; pipe_config->uapi.crtc = &crtc->base; + pipe_config->cpu_transcoder = (enum transcoder)pipe; pipe_config->pixel_multiplier = 1; pipe_config->dpll = *dpll; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index c03a9675072f..327376810f66 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -517,8 +517,6 @@ enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port); int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, - enum pipe pipe); u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc); int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp); @@ -620,9 +618,10 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true) #define assert_fdi_rx_pll_disabled(d, p) assert_fdi_rx_pll(d, p, false) -void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); -#define assert_pipe_enabled(d, p) assert_pipe(d, p, true) -#define assert_pipe_disabled(d, p) assert_pipe(d, p, false) +void assert_pipe(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder, bool state); +#define assert_pipe_enabled(d, t) assert_pipe(d, t, true) +#define assert_pipe_disabled(d, t) assert_pipe(d, t, false) /* 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 From 7b0bcead187fb3afb45fd052316f9eb967ef1986 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 10 Dec 2019 14:45:35 +0000 Subject: drm/i915/display: remove duplicated assignment to pointer crtc_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pointer crtc_state is being assigned twice, one of these is redundant and can be removed. Addresses-Coverity: ("Evaluation order violation") Signed-off-by: Colin Ian King Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191210144535.341977-1-colin.king@canonical.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d0d37a979737..0e5a33969d77 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17751,7 +17751,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev, for_each_intel_crtc(&dev_priv->drm, crtc) { struct intel_crtc_state *crtc_state = - crtc_state = to_intel_crtc_state(crtc->base.state); + to_intel_crtc_state(crtc->base.state); intel_sanitize_crtc(crtc, ctx); intel_dump_pipe_config(crtc_state, NULL, "[setup_hw_state]"); -- cgit v1.2.3 From f3417d703f18b2bfe180e28cd65f44b540546d29 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 10 Dec 2019 14:23:49 +0000 Subject: drm/i915: remove redundant checks for a null fb pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A prior check and return when pointer fb is null makes subsequent null checks on fb redundant. Remove the redundant null checks. Addresses-Coverity: ("Logically dead code") Signed-off-by: Colin Ian King Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191210142349.333171-1-colin.king@canonical.com --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6cb149ba1905..9cd5ce5bc93b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2582,8 +2582,8 @@ static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane) plane_state->hw.rotation); seq_printf(m, "\t\thw: fb=%d,%s,%dx%d, visible=%s, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", - fb ? fb->base.id : 0, fb ? format_name.str : "n/a", - fb ? fb->width : 0, fb ? fb->height : 0, + fb->base.id, format_name.str, + fb->width, fb->height, yesno(plane_state->uapi.visible), DRM_RECT_FP_ARG(&plane_state->uapi.src), DRM_RECT_ARG(&plane_state->uapi.dst), -- cgit v1.2.3 From 65c29dbb19b2451990c5c477fef7ada3b8218f05 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Dec 2019 15:02:04 +0000 Subject: drm/i915: Use the i915_device name for identifying our request fences Use the dev_name(i915) to identify the requests for debugging, so we can tell different device timelines apart. Signed-off-by: Chris Wilson Cc: Venkata Sandeep Dhanalakota Reviewed-by: Venkata Sandeep Dhanalakota Link: https://patchwork.freedesktop.org/patch/msgid/20191211150204.133471-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_request.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index a6238c626a16..51bb8a0812a1 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -57,7 +57,7 @@ static struct i915_global_request { static const char *i915_fence_get_driver_name(struct dma_fence *fence) { - return "i915"; + return dev_name(to_request(fence)->i915->drm.dev); } static const char *i915_fence_get_timeline_name(struct dma_fence *fence) @@ -74,7 +74,7 @@ static const char *i915_fence_get_timeline_name(struct dma_fence *fence) if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) return "signaled"; - return to_request(fence)->gem_context->name ?: "[i915]"; + return to_request(fence)->gem_context->name ?: "[" DRIVER_NAME "]"; } static bool i915_fence_signaled(struct dma_fence *fence) -- cgit v1.2.3 From cb1b7ad08c22c771500bdd842b01bc12ffcfbb50 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 11 Dec 2019 12:45:47 +0000 Subject: drm/i915/uc: Drop explicit i915 param in some uc_fw functions There is no need to pass explicit i915 since we already have a debug trick to get parent gt from uc_fw, we only need to make this trick available on non-debug builds. Signed-off-by: Michal Wajdeczko Cc: Daniele Ceraolo Spurio Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191211124549.59516-2-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 5 ++--- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 15 +++++++-------- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index c6519066a0f6..f42952403c0b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -267,18 +267,17 @@ static void guc_disable_communication(struct intel_guc *guc) void intel_uc_fetch_firmwares(struct intel_uc *uc) { - struct drm_i915_private *i915 = uc_to_gt(uc)->i915; int err; if (!intel_uc_uses_guc(uc)) return; - err = intel_uc_fw_fetch(&uc->guc.fw, i915); + err = intel_uc_fw_fetch(&uc->guc.fw); if (err) return; if (intel_uc_uses_huc(uc)) - intel_uc_fw_fetch(&uc->huc.fw, i915); + intel_uc_fw_fetch(&uc->huc.fw); } void intel_uc_cleanup_firmwares(struct intel_uc *uc) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 66a30ab7044a..512ee012fd05 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -11,7 +11,6 @@ #include "intel_uc_fw_abi.h" #include "i915_drv.h" -#ifdef CONFIG_DRM_I915_DEBUG_GUC static inline struct intel_gt *__uc_fw_to_gt(struct intel_uc_fw *uc_fw) { GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED); @@ -22,6 +21,7 @@ static inline struct intel_gt *__uc_fw_to_gt(struct intel_uc_fw *uc_fw) return container_of(uc_fw, struct intel_gt, uc.huc.fw); } +#ifdef CONFIG_DRM_I915_DEBUG_GUC void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, enum intel_uc_fw_status status) { @@ -219,10 +219,9 @@ void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED); } -static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, - struct drm_i915_private *i915, - int e) +static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e) { + struct drm_i915_private *i915 = __uc_fw_to_gt(uc_fw)->i915; bool user = e == -EINVAL; if (i915_inject_probe_error(i915, e)) { @@ -260,14 +259,14 @@ static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, /** * intel_uc_fw_fetch - fetch uC firmware * @uc_fw: uC firmware - * @i915: device private * * Fetch uC firmware into GEM obj. * * Return: 0 on success, a negative errno code on failure. */ -int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw, struct drm_i915_private *i915) +int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) { + struct drm_i915_private *i915 = __uc_fw_to_gt(uc_fw)->i915; struct device *dev = i915->drm.dev; struct drm_i915_gem_object *obj; const struct firmware *fw = NULL; @@ -282,8 +281,8 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw, struct drm_i915_private *i915) if (err) return err; - __force_fw_fetch_failures(uc_fw, i915, -EINVAL); - __force_fw_fetch_failures(uc_fw, i915, -ESTALE); + __force_fw_fetch_failures(uc_fw, -EINVAL); + __force_fw_fetch_failures(uc_fw, -ESTALE); err = request_firmware(&fw, uc_fw->path, dev); if (err) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h index 7a0a5989afc9..ddf2b34139c1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h @@ -229,7 +229,7 @@ static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw) void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type, bool supported, enum intel_platform platform, u8 rev); -int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw, struct drm_i915_private *i915); +int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw); void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw); int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, struct intel_gt *gt, u32 wopcm_offset, u32 dma_flags); -- cgit v1.2.3 From 3a1e3c483584762c794fb21795ed02982c8cdcf7 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 11 Dec 2019 12:45:48 +0000 Subject: drm/i915/uc: Drop explicit gt param in some uc_fw functions There is no need to pass explicit gt since we already have a trick to get parent gt from uc_fw, we only need to use it. Signed-off-by: Michal Wajdeczko Cc: Daniele Ceraolo Spurio Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191211124549.59516-3-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 29 +++++++++++++---------------- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h | 3 +-- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 5528224448f6..3a1c47d600ea 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -149,7 +149,7 @@ int intel_guc_fw_upload(struct intel_guc *guc) * Current uCode expects the code to be loaded at 8k; locations below * this are used for the stack. */ - ret = intel_uc_fw_upload(&guc->fw, gt, 0x2000, UOS_MOVE); + ret = intel_uc_fw_upload(&guc->fw, 0x2000, UOS_MOVE); if (ret) goto out; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c index d654340d4d03..eee193bf2cc4 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c @@ -39,5 +39,5 @@ void intel_huc_fw_init_early(struct intel_huc *huc) int intel_huc_fw_upload(struct intel_huc *huc) { /* HW doesn't look at destination address for HuC, so set it to 0 */ - return intel_uc_fw_upload(&huc->fw, huc_to_gt(huc), 0, HUC_UKERNEL); + return intel_uc_fw_upload(&huc->fw, 0, HUC_UKERNEL); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 512ee012fd05..380f36f9c3b1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -400,11 +400,10 @@ static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw, struct i915_ggtt *ggtt) return lower_32_bits(node->start); } -static void intel_uc_fw_ggtt_bind(struct intel_uc_fw *uc_fw, - struct intel_gt *gt) +static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw) { struct drm_i915_gem_object *obj = uc_fw->obj; - struct i915_ggtt *ggtt = gt->ggtt; + struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; struct i915_vma dummy = { .node.start = uc_fw_ggtt_offset(uc_fw, ggtt), .node.size = obj->base.size, @@ -421,19 +420,18 @@ static void intel_uc_fw_ggtt_bind(struct intel_uc_fw *uc_fw, ggtt->vm.insert_entries(&ggtt->vm, &dummy, I915_CACHE_NONE, 0); } -static void intel_uc_fw_ggtt_unbind(struct intel_uc_fw *uc_fw, - struct intel_gt *gt) +static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw) { struct drm_i915_gem_object *obj = uc_fw->obj; - struct i915_ggtt *ggtt = gt->ggtt; + struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; u64 start = uc_fw_ggtt_offset(uc_fw, ggtt); ggtt->vm.clear_range(&ggtt->vm, start, obj->base.size); } -static int uc_fw_xfer(struct intel_uc_fw *uc_fw, struct intel_gt *gt, - u32 wopcm_offset, u32 dma_flags) +static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags) { + struct intel_gt *gt = __uc_fw_to_gt(uc_fw); struct intel_uncore *uncore = gt->uncore; u64 offset; int ret; @@ -451,7 +449,7 @@ static int uc_fw_xfer(struct intel_uc_fw *uc_fw, struct intel_gt *gt, intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset)); /* Set the DMA destination */ - intel_uncore_write_fw(uncore, DMA_ADDR_1_LOW, wopcm_offset); + intel_uncore_write_fw(uncore, DMA_ADDR_1_LOW, dst_offset); intel_uncore_write_fw(uncore, DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM); /* @@ -483,17 +481,16 @@ static int uc_fw_xfer(struct intel_uc_fw *uc_fw, struct intel_gt *gt, /** * intel_uc_fw_upload - load uC firmware using custom loader * @uc_fw: uC firmware - * @gt: the intel_gt structure - * @wopcm_offset: destination offset in wopcm + * @dst_offset: destination offset * @dma_flags: flags for flags for dma ctrl * * Loads uC firmware and updates internal flags. * * Return: 0 on success, non-zero on failure. */ -int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, struct intel_gt *gt, - u32 wopcm_offset, u32 dma_flags) +int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags) { + struct intel_gt *gt = __uc_fw_to_gt(uc_fw); int err; /* make sure the status was cleared the last time we reset the uc */ @@ -507,9 +504,9 @@ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, struct intel_gt *gt, return -ENOEXEC; /* Call custom loader */ - intel_uc_fw_ggtt_bind(uc_fw, gt); - err = uc_fw_xfer(uc_fw, gt, wopcm_offset, dma_flags); - intel_uc_fw_ggtt_unbind(uc_fw, gt); + uc_fw_bind_ggtt(uc_fw); + err = uc_fw_xfer(uc_fw, dst_offset, dma_flags); + uc_fw_unbind_ggtt(uc_fw); if (err) goto fail; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h index ddf2b34139c1..1f30543d0d2d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h @@ -231,8 +231,7 @@ void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw, enum intel_platform platform, u8 rev); int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw); void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw); -int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, struct intel_gt *gt, - u32 wopcm_offset, u32 dma_flags); +int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 offset, u32 dma_flags); int intel_uc_fw_init(struct intel_uc_fw *uc_fw); void intel_uc_fw_fini(struct intel_uc_fw *uc_fw); size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len); -- cgit v1.2.3 From 220a9d45c6709127cd56430caef07034f1ec5030 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Wed, 11 Dec 2019 12:45:49 +0000 Subject: drm/i915/uc: Drop explicit ggtt param in some uc_fw functions There is no need to pass explicit ggtt since we already have a trick to get parent gt from uc_fw, we only need to use it. Signed-off-by: Michal Wajdeczko Cc: Daniele Ceraolo Spurio Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191211124549.59516-4-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 380f36f9c3b1..b6aedee46f9e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -389,8 +389,9 @@ fail: return err; } -static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw, struct i915_ggtt *ggtt) +static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw) { + struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; struct drm_mm_node *node = &ggtt->uc_fw; GEM_BUG_ON(!drm_mm_node_allocated(node)); @@ -405,7 +406,7 @@ static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw) struct drm_i915_gem_object *obj = uc_fw->obj; struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; struct i915_vma dummy = { - .node.start = uc_fw_ggtt_offset(uc_fw, ggtt), + .node.start = uc_fw_ggtt_offset(uc_fw), .node.size = obj->base.size, .pages = obj->mm.pages, .vm = &ggtt->vm, @@ -424,7 +425,7 @@ static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw) { struct drm_i915_gem_object *obj = uc_fw->obj; struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; - u64 start = uc_fw_ggtt_offset(uc_fw, ggtt); + u64 start = uc_fw_ggtt_offset(uc_fw); ggtt->vm.clear_range(&ggtt->vm, start, obj->base.size); } @@ -443,7 +444,7 @@ static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags) intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); /* Set the source address for the uCode */ - offset = uc_fw_ggtt_offset(uc_fw, gt->ggtt); + offset = uc_fw_ggtt_offset(uc_fw); GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000); intel_uncore_write_fw(uncore, DMA_ADDR_0_LOW, lower_32_bits(offset)); intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset)); -- cgit v1.2.3 From 972745fd577044ea153ec6d7899dcf9bb3c806e5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 10 Dec 2019 18:01:11 +0000 Subject: drm/i915/gt: Disable manual rc6 for Braswell/Baytrail The initial investigated showed that while the PCU on Braswell/Baytrail controlled RC6 itself. setting the software RC6 request made no difference. Further testing reveals though that it causes a delay in the PCU on enabling RC6. Closes: https://gitlab.freedesktop.org/drm/intel/issues/763 Fixes: 730eaeb52426 ("drm/i915/gt: Manual rc6 entry upon parking") Testcase: igt/perf/rc6-disable Signed-off-by: Chris Wilson Cc: Andi Shyti Cc: Mika Kuoppala Cc: Imre Deak Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191210180111.3958558-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rc6.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 4dc82196b285..8ec2b7725141 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -612,6 +612,9 @@ void intel_rc6_park(struct intel_rc6 *rc6) return; } + if (!(rc6->ctl_enable & GEN6_RC_CTL_RC6_ENABLE)) + return; + /* Turn off the HW timers and go directly to rc6 */ set(uncore, GEN6_RC_CONTROL, GEN6_RC_CTL_RC6_ENABLE); set(uncore, GEN6_RC_STATE, 0x4 << RC_SW_TARGET_STATE_SHIFT); -- cgit v1.2.3 From 8f1ada252028853f1c405fde28a13f641d7280f6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Dec 2019 11:04:33 +0000 Subject: drm/i915: Fix cmdparser drm.debug The cmdparser rejection debug is not for driver development, but for the user, for which we use a plain DRM_DEBUG(). Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191211110437.4082687-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_cmd_parser.c | 55 +++++++++++++++++----------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 2ed497e7c9fd..7b7061973c5e 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -731,7 +731,7 @@ static u32 gen7_render_get_cmd_length_mask(u32 cmd_header) return 0xFF; } - DRM_DEBUG_DRIVER("CMD: Abnormal rcs cmd length! 0x%08X\n", cmd_header); + DRM_DEBUG("CMD: Abnormal rcs cmd length! 0x%08X\n", cmd_header); return 0; } @@ -754,7 +754,7 @@ static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header) return 0xFF; } - DRM_DEBUG_DRIVER("CMD: Abnormal bsd cmd length! 0x%08X\n", cmd_header); + DRM_DEBUG("CMD: Abnormal bsd cmd length! 0x%08X\n", cmd_header); return 0; } @@ -767,7 +767,7 @@ static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header) else if (client == INSTR_BC_CLIENT) return 0xFF; - DRM_DEBUG_DRIVER("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header); + DRM_DEBUG("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header); return 0; } @@ -778,7 +778,7 @@ static u32 gen9_blt_get_cmd_length_mask(u32 cmd_header) if (client == INSTR_MI_CLIENT || client == INSTR_BC_CLIENT) return 0xFF; - DRM_DEBUG_DRIVER("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header); + DRM_DEBUG("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header); return 0; } @@ -1211,7 +1211,7 @@ static bool check_cmd(const struct intel_engine_cs *engine, return true; if (desc->flags & CMD_DESC_REJECT) { - DRM_DEBUG_DRIVER("CMD: Rejected command: 0x%08X\n", *cmd); + DRM_DEBUG("CMD: Rejected command: 0x%08X\n", *cmd); return false; } @@ -1231,8 +1231,8 @@ static bool check_cmd(const struct intel_engine_cs *engine, find_reg(engine, reg_addr); if (!reg) { - DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (%s)\n", - reg_addr, *cmd, engine->name); + DRM_DEBUG("CMD: Rejected register 0x%08X in command: 0x%08X (%s)\n", + reg_addr, *cmd, engine->name); return false; } @@ -1242,22 +1242,22 @@ static bool check_cmd(const struct intel_engine_cs *engine, */ if (reg->mask) { if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { - DRM_DEBUG_DRIVER("CMD: Rejected LRM to masked register 0x%08X\n", - reg_addr); + DRM_DEBUG("CMD: Rejected LRM to masked register 0x%08X\n", + reg_addr); return false; } if (desc->cmd.value == MI_LOAD_REGISTER_REG) { - DRM_DEBUG_DRIVER("CMD: Rejected LRR to masked register 0x%08X\n", - reg_addr); + DRM_DEBUG("CMD: Rejected LRR to masked register 0x%08X\n", + reg_addr); return false; } if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) && (offset + 2 > length || (cmd[offset + 1] & reg->mask) != reg->value)) { - DRM_DEBUG_DRIVER("CMD: Rejected LRI to masked register 0x%08X\n", - reg_addr); + DRM_DEBUG("CMD: Rejected LRI to masked register 0x%08X\n", + reg_addr); return false; } } @@ -1284,8 +1284,8 @@ static bool check_cmd(const struct intel_engine_cs *engine, } if (desc->bits[i].offset >= length) { - DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X, too short to check bitmask (%s)\n", - *cmd, engine->name); + DRM_DEBUG("CMD: Rejected command 0x%08X, too short to check bitmask (%s)\n", + *cmd, engine->name); return false; } @@ -1293,11 +1293,11 @@ static bool check_cmd(const struct intel_engine_cs *engine, desc->bits[i].mask; if (dword != desc->bits[i].expected) { - DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X for bitmask 0x%08X (exp=0x%08X act=0x%08X) (%s)\n", - *cmd, - desc->bits[i].mask, - desc->bits[i].expected, - dword, engine->name); + DRM_DEBUG("CMD: Rejected command 0x%08X for bitmask 0x%08X (exp=0x%08X act=0x%08X) (%s)\n", + *cmd, + desc->bits[i].mask, + desc->bits[i].expected, + dword, engine->name); return false; } } @@ -1425,7 +1425,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, batch_start_offset, batch_len, &needs_clflush_after); if (IS_ERR(cmd)) { - DRM_DEBUG_DRIVER("CMD: Failed to copy batch\n"); + DRM_DEBUG("CMD: Failed to copy batch\n"); return PTR_ERR(cmd); } @@ -1446,8 +1446,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, desc = find_cmd(engine, *cmd, desc, &default_desc); if (!desc) { - DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n", - *cmd); + DRM_DEBUG("CMD: Unrecognized command: 0x%08X\n", *cmd); ret = -EINVAL; goto err; } @@ -1458,10 +1457,10 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, length = ((*cmd & desc->length.mask) + LENGTH_BIAS); if ((batch_end - cmd) < length) { - DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%u batchlen=%td\n", - *cmd, - length, - batch_end - cmd); + DRM_DEBUG("CMD: Command length exceeds batch length: 0x%08X length=%u batchlen=%td\n", + *cmd, + length, + batch_end - cmd); ret = -EINVAL; goto err; } @@ -1488,7 +1487,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, cmd += length; offset += length; if (cmd >= batch_end) { - DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); + DRM_DEBUG("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); ret = -EINVAL; goto err; } -- cgit v1.2.3 From 755bf8a8c9850f418e9a585f067e431677219260 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Dec 2019 11:04:34 +0000 Subject: drm/i915: Remove redundant parameters from intel_engine_cmd_parser Declutter the calling interface by reducing the parameters to the i915_vma and associated offsets. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191211110437.4082687-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 33 +------- drivers/gpu/drm/i915/gt/intel_gpu_commands.h | 21 +++++ drivers/gpu/drm/i915/i915_cmd_parser.c | 106 +++++++++++++------------ drivers/gpu/drm/i915/i915_drv.h | 10 +-- 4 files changed, 82 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 5003e616a1ad..796ed5340741 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -276,25 +276,6 @@ struct i915_execbuffer { #define exec_entry(EB, VMA) (&(EB)->exec[(VMA)->exec_flags - (EB)->flags]) -/* - * Used to convert any address to canonical form. - * Starting from gen8, some commands (e.g. STATE_BASE_ADDRESS, - * MI_LOAD_REGISTER_MEM and others, see Broadwell PRM Vol2a) require the - * addresses to be in a canonical form: - * "GraphicsAddress[63:48] are ignored by the HW and assumed to be in correct - * canonical form [63:48] == [47]." - */ -#define GEN8_HIGH_ADDRESS_BIT 47 -static inline u64 gen8_canonical_addr(u64 address) -{ - return sign_extend64(address, GEN8_HIGH_ADDRESS_BIT); -} - -static inline u64 gen8_noncanonical_addr(u64 address) -{ - return address & GENMASK_ULL(GEN8_HIGH_ADDRESS_BIT, 0); -} - static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) { return intel_engine_requires_cmd_parser(eb->engine) || @@ -2005,8 +1986,6 @@ static struct i915_vma *eb_parse(struct i915_execbuffer *eb) { struct intel_engine_pool_node *pool; struct i915_vma *vma; - u64 batch_start; - u64 shadow_batch_start; int err; pool = intel_engine_get_pool(eb->engine, eb->batch_len); @@ -2017,19 +1996,11 @@ static struct i915_vma *eb_parse(struct i915_execbuffer *eb) if (IS_ERR(vma)) goto err; - batch_start = gen8_canonical_addr(eb->batch->node.start) + - eb->batch_start_offset; - - shadow_batch_start = gen8_canonical_addr(vma->node.start); - err = intel_engine_cmd_parser(eb->engine, - eb->batch->obj, - batch_start, + eb->batch, eb->batch_start_offset, eb->batch_len, - pool->obj, - shadow_batch_start); - + vma); if (err) { i915_vma_unpin(vma); diff --git a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h index 4294f146f13c..c68c0e033f30 100644 --- a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h +++ b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h @@ -7,6 +7,8 @@ #ifndef _INTEL_GPU_COMMANDS_H_ #define _INTEL_GPU_COMMANDS_H_ +#include + /* * Target address alignments required for GPU access e.g. * MI_STORE_DWORD_IMM. @@ -319,4 +321,23 @@ #define COLOR_BLT ((0x2<<29)|(0x40<<22)) #define SRC_COPY_BLT ((0x2<<29)|(0x43<<22)) +/* + * Used to convert any address to canonical form. + * Starting from gen8, some commands (e.g. STATE_BASE_ADDRESS, + * MI_LOAD_REGISTER_MEM and others, see Broadwell PRM Vol2a) require the + * addresses to be in a canonical form: + * "GraphicsAddress[63:48] are ignored by the HW and assumed to be in correct + * canonical form [63:48] == [47]." + */ +#define GEN8_HIGH_ADDRESS_BIT 47 +static inline u64 gen8_canonical_addr(u64 address) +{ + return sign_extend64(address, GEN8_HIGH_ADDRESS_BIT); +} + +static inline u64 gen8_noncanonical_addr(u64 address) +{ + return address & GENMASK_ULL(GEN8_HIGH_ADDRESS_BIT, 0); +} + #endif /* _INTEL_GPU_COMMANDS_H_ */ diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 7b7061973c5e..2f5811d3707e 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1127,8 +1127,7 @@ find_reg(const struct intel_engine_cs *engine, u32 addr) /* Returns a vmap'd pointer to dst_obj, which the caller must unmap */ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, struct drm_i915_gem_object *src_obj, - u32 batch_start_offset, - u32 batch_len, + u32 offset, u32 length, bool *needs_clflush_after) { unsigned int src_needs_clflush; @@ -1153,22 +1152,21 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, src = ERR_PTR(-ENODEV); if (src_needs_clflush && - i915_can_memcpy_from_wc(NULL, batch_start_offset, 0)) { + i915_can_memcpy_from_wc(NULL, offset, 0)) { src = i915_gem_object_pin_map(src_obj, I915_MAP_WC); if (!IS_ERR(src)) { i915_memcpy_from_wc(dst, - src + batch_start_offset, - ALIGN(batch_len, 16)); + src + offset, + ALIGN(length, 16)); i915_gem_object_unpin_map(src_obj); } } if (IS_ERR(src)) { void *ptr; - int offset, n; + int x, n; - offset = offset_in_page(batch_start_offset); - - /* We can avoid clflushing partial cachelines before the write + /* + * We can avoid clflushing partial cachelines before the write * if we only every write full cache-lines. Since we know that * both the source and destination are in multiples of * PAGE_SIZE, we can simply round up to the next cacheline. @@ -1176,22 +1174,23 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, * validate up to the end of the batch. */ if (dst_needs_clflush & CLFLUSH_BEFORE) - batch_len = roundup(batch_len, - boot_cpu_data.x86_clflush_size); + length = round_up(length, + boot_cpu_data.x86_clflush_size); ptr = dst; - for (n = batch_start_offset >> PAGE_SHIFT; batch_len; n++) { - int len = min_t(int, batch_len, PAGE_SIZE - offset); + x = offset_in_page(offset); + for (n = offset >> PAGE_SHIFT; length; n++) { + int len = min_t(int, length, PAGE_SIZE - x); src = kmap_atomic(i915_gem_object_get_page(src_obj, n)); if (src_needs_clflush) - drm_clflush_virt_range(src + offset, len); - memcpy(ptr, src + offset, len); + drm_clflush_virt_range(src + x, len); + memcpy(ptr, src + x, len); kunmap_atomic(src); ptr += len; - batch_len -= len; - offset = 0; + length -= len; + x = 0; } } @@ -1307,9 +1306,9 @@ static bool check_cmd(const struct intel_engine_cs *engine, } static int check_bbstart(u32 *cmd, u32 offset, u32 length, - u32 batch_len, - u64 batch_start, - u64 shadow_batch_start, + u32 batch_length, + u64 batch_addr, + u64 shadow_addr, const unsigned long *jump_whitelist) { u64 jump_offset, jump_target; @@ -1327,14 +1326,14 @@ static int check_bbstart(u32 *cmd, u32 offset, u32 length, return -EINVAL; } - jump_target = *(u64*)(cmd+1); - jump_offset = jump_target - batch_start; + jump_target = *(u64 *)(cmd + 1); + jump_offset = jump_target - batch_addr; /* * Any underflow of jump_target is guaranteed to be outside the range * of a u32, so >= test catches both too large and too small */ - if (jump_offset >= batch_len) { + if (jump_offset >= batch_length) { DRM_DEBUG("CMD: BB_START to 0x%llx jumps out of BB\n", jump_target); return -EINVAL; @@ -1342,12 +1341,12 @@ static int check_bbstart(u32 *cmd, u32 offset, u32 length, /* * This cannot overflow a u32 because we already checked jump_offset - * is within the BB, and the batch_len is a u32 + * is within the BB, and the batch_length is a u32 */ target_cmd_offset = lower_32_bits(jump_offset); target_cmd_index = target_cmd_offset / sizeof(u32); - *(u64*)(cmd + 1) = shadow_batch_start + target_cmd_offset; + *(u64 *)(cmd + 1) = shadow_addr + target_cmd_offset; if (target_cmd_index == offset) return 0; @@ -1365,12 +1364,12 @@ static int check_bbstart(u32 *cmd, u32 offset, u32 length, } static unsigned long * -alloc_whitelist(struct drm_i915_private *i915, u32 batch_len) +alloc_whitelist(struct drm_i915_private *i915, u32 batch_length) { unsigned long *jmp; /* - * We expect batch_len to be less than 256KiB for known users, + * We expect batch_length to be less than 256KiB for known users, * i.e. we need at most an 8KiB bitmap allocation which should be * reasonably cheap due to kmalloc caches. */ @@ -1379,7 +1378,7 @@ alloc_whitelist(struct drm_i915_private *i915, u32 batch_len) return NULL; /* Prefer to report transient allocation failure rather than hit oom */ - jmp = bitmap_zalloc(DIV_ROUND_UP(batch_len, sizeof(u32)), + jmp = bitmap_zalloc(DIV_ROUND_UP(batch_length, sizeof(u32)), GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); if (!jmp) return ERR_PTR(-ENOMEM); @@ -1390,14 +1389,12 @@ alloc_whitelist(struct drm_i915_private *i915, u32 batch_len) #define LENGTH_BIAS 2 /** - * i915_parse_cmds() - parse a submitted batch buffer for privilege violations + * intel_engine_cmd_parser() - parse a batch buffer for privilege violations * @engine: the engine on which the batch is to execute - * @batch_obj: the batch buffer in question - * @batch_start: Canonical base address of batch - * @batch_start_offset: byte offset in the batch at which execution starts - * @batch_len: length of the commands in batch_obj - * @shadow_batch_obj: copy of the batch buffer in question - * @shadow_batch_start: Canonical base address of shadow_batch_obj + * @batch: the batch buffer in question + * @batch_offset: byte offset in the batch at which execution starts + * @batch_length: length of the commands in batch_obj + * @shadow: validated copy of the batch buffer in question * * Parses the specified batch buffer looking for privilege violations as * described in the overview. @@ -1407,22 +1404,27 @@ alloc_whitelist(struct drm_i915_private *i915, u32 batch_len) */ int intel_engine_cmd_parser(struct intel_engine_cs *engine, - struct drm_i915_gem_object *batch_obj, - u64 batch_start, - u32 batch_start_offset, - u32 batch_len, - struct drm_i915_gem_object *shadow_batch_obj, - u64 shadow_batch_start) + struct i915_vma *batch, + u32 batch_offset, + u32 batch_length, + struct i915_vma *shadow) { u32 *cmd, *batch_end, offset = 0; struct drm_i915_cmd_descriptor default_desc = noop_desc; const struct drm_i915_cmd_descriptor *desc = &default_desc; bool needs_clflush_after = false; unsigned long *jump_whitelist; + u64 batch_addr, shadow_addr; int ret = 0; - cmd = copy_batch(shadow_batch_obj, batch_obj, - batch_start_offset, batch_len, + GEM_BUG_ON(!IS_ALIGNED(batch_offset, sizeof(*cmd))); + GEM_BUG_ON(!IS_ALIGNED(batch_length, sizeof(*cmd))); + GEM_BUG_ON(range_overflows_t(u64, batch_offset, batch_length, + batch->size)); + GEM_BUG_ON(!batch_length); + + cmd = copy_batch(shadow->obj, batch->obj, + batch_offset, batch_length, &needs_clflush_after); if (IS_ERR(cmd)) { DRM_DEBUG("CMD: Failed to copy batch\n"); @@ -1430,14 +1432,17 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, } /* Defer failure until attempted use */ - jump_whitelist = alloc_whitelist(engine->i915, batch_len); + jump_whitelist = alloc_whitelist(engine->i915, batch_length); + + shadow_addr = gen8_canonical_addr(shadow->node.start); + batch_addr = gen8_canonical_addr(batch->node.start + batch_offset); /* * We use the batch length as size because the shadow object is as * large or larger and copy_batch() will write MI_NOPs to the extra * space. Parsing should be faster in some cases this way. */ - batch_end = cmd + (batch_len / sizeof(*batch_end)); + batch_end = cmd + batch_length / sizeof(*batch_end); do { u32 length; @@ -1454,7 +1459,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, if (desc->flags & CMD_DESC_FIXED) length = desc->length.fixed; else - length = ((*cmd & desc->length.mask) + LENGTH_BIAS); + length = (*cmd & desc->length.mask) + LENGTH_BIAS; if ((batch_end - cmd) < length) { DRM_DEBUG("CMD: Command length exceeds batch length: 0x%08X length=%u batchlen=%td\n", @@ -1471,9 +1476,8 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, } if (desc->cmd.value == MI_BATCH_BUFFER_START) { - ret = check_bbstart(cmd, offset, length, - batch_len, batch_start, - shadow_batch_start, + ret = check_bbstart(cmd, offset, length, batch_length, + batch_addr, shadow_addr, jump_whitelist); if (ret) @@ -1494,7 +1498,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, } while (1); if (needs_clflush_after) { - void *ptr = page_mask_bits(shadow_batch_obj->mm.mapping); + void *ptr = page_mask_bits(shadow->obj->mm.mapping); drm_clflush_virt_range(ptr, (void *)(cmd + 1) - ptr); } @@ -1502,7 +1506,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, err: if (!IS_ERR_OR_NULL(jump_whitelist)) kfree(jump_whitelist); - i915_gem_object_unpin_map(shadow_batch_obj); + i915_gem_object_unpin_map(shadow->obj); return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ce130e1f1e47..45f31197b390 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1946,12 +1946,10 @@ int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv); void intel_engine_init_cmd_parser(struct intel_engine_cs *engine); void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine); int intel_engine_cmd_parser(struct intel_engine_cs *engine, - struct drm_i915_gem_object *batch_obj, - u64 user_batch_start, - u32 batch_start_offset, - u32 batch_len, - struct drm_i915_gem_object *shadow_batch_obj, - u64 shadow_batch_start); + struct i915_vma *batch, + u32 batch_offset, + u32 batch_length, + struct i915_vma *shadow); /* intel_device_info.c */ static inline struct intel_device_info * -- cgit v1.2.3 From 37d1151ce75ea2a9ca7274cb0c93f21db9ab431a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Dec 2019 11:04:35 +0000 Subject: drm/i915: Simplify error escape from cmdparser We need to flush the destination buffer, even on error, to maintain consistent cache state. Thereby removing the jump on error past the clear, and reducing the loop-escape mechanism to a mere break. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191211110437.4082687-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_cmd_parser.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 2f5811d3707e..b692c40348a1 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1453,7 +1453,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, if (!desc) { DRM_DEBUG("CMD: Unrecognized command: 0x%08X\n", *cmd); ret = -EINVAL; - goto err; + break; } if (desc->flags & CMD_DESC_FIXED) @@ -1467,21 +1467,18 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, length, batch_end - cmd); ret = -EINVAL; - goto err; + break; } if (!check_cmd(engine, desc, cmd, length)) { ret = -EACCES; - goto err; + break; } if (desc->cmd.value == MI_BATCH_BUFFER_START) { ret = check_bbstart(cmd, offset, length, batch_length, batch_addr, shadow_addr, jump_whitelist); - - if (ret) - goto err; break; } @@ -1493,7 +1490,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, if (cmd >= batch_end) { DRM_DEBUG("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); ret = -EINVAL; - goto err; + break; } } while (1); @@ -1503,7 +1500,6 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, drm_clflush_virt_range(ptr, (void *)(cmd + 1) - ptr); } -err: if (!IS_ERR_OR_NULL(jump_whitelist)) kfree(jump_whitelist); i915_gem_object_unpin_map(shadow->obj); -- cgit v1.2.3 From 51696691aba3d1a3e74a9ad9e615abd06532a11e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Dec 2019 11:04:36 +0000 Subject: drm/i915/gem: Tidy up error handling for eb_parse() As the caller no longer uses the i915_vma result, stop returning it and just return the error code instead. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191211110437.4082687-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 39 ++++++++++++-------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 796ed5340741..13f88fc536c7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1982,19 +1982,24 @@ shadow_batch_pin(struct i915_execbuffer *eb, struct drm_i915_gem_object *obj) return vma; } -static struct i915_vma *eb_parse(struct i915_execbuffer *eb) +static int eb_parse(struct i915_execbuffer *eb) { struct intel_engine_pool_node *pool; struct i915_vma *vma; int err; + if (!eb_use_cmdparser(eb)) + return 0; + pool = intel_engine_get_pool(eb->engine, eb->batch_len); if (IS_ERR(pool)) - return ERR_CAST(pool); + return PTR_ERR(pool); vma = shadow_batch_pin(eb, pool->obj); - if (IS_ERR(vma)) + if (IS_ERR(vma)) { + err = PTR_ERR(vma); goto err; + } err = intel_engine_cmd_parser(eb->engine, eb->batch, @@ -2002,8 +2007,6 @@ static struct i915_vma *eb_parse(struct i915_execbuffer *eb) eb->batch_len, vma); if (err) { - i915_vma_unpin(vma); - /* * Unsafe GGTT-backed buffers can still be submitted safely * as non-secure. @@ -2011,11 +2014,9 @@ static struct i915_vma *eb_parse(struct i915_execbuffer *eb) * reject unsafe buffers */ if (i915_vma_is_ggtt(vma) && err == -EACCES) - /* Execute original buffer non-secure */ - vma = NULL; - else - vma = ERR_PTR(err); - goto err; + err = 0; + + goto err_unpin; } eb->vma[eb->buffer_count] = i915_vma_get(vma); @@ -2033,11 +2034,13 @@ static struct i915_vma *eb_parse(struct i915_execbuffer *eb) /* eb->batch_len unchanged */ vma->private = pool; - return vma; + return 0; +err_unpin: + i915_vma_unpin(vma); err: intel_engine_pool_put(pool); - return vma; + return err; } static void @@ -2558,15 +2561,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (eb.batch_len == 0) eb.batch_len = eb.batch->size - eb.batch_start_offset; - if (eb_use_cmdparser(&eb)) { - struct i915_vma *vma; - - vma = eb_parse(&eb); - if (IS_ERR(vma)) { - err = PTR_ERR(vma); - goto err_vma; - } - } + err = eb_parse(&eb); + if (err) + goto err_vma; /* * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure -- cgit v1.2.3 From 6aacb5a3b0bccfa207ef2710f106020c1d749f1d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Dec 2019 11:04:37 +0000 Subject: drm/i915: Align start for memcpy_from_wc The movntqda requires 16-byte alignment for the source pointer. Avoid falling back to clflush if the source pointer is misaligned by doing the doing a small uncached memcpy to fixup the alignments. v2: Turn the unaligned copy into a genuine helper Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191211110437.4082687-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_cmd_parser.c | 9 ++-- drivers/gpu/drm/i915/i915_memcpy.c | 75 ++++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_memcpy.h | 2 + 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index b692c40348a1..ddc8bf5175d9 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1151,13 +1151,12 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, } src = ERR_PTR(-ENODEV); - if (src_needs_clflush && - i915_can_memcpy_from_wc(NULL, offset, 0)) { + if (src_needs_clflush && i915_has_memcpy_from_wc()) { src = i915_gem_object_pin_map(src_obj, I915_MAP_WC); if (!IS_ERR(src)) { - i915_memcpy_from_wc(dst, - src + offset, - ALIGN(length, 16)); + i915_unaligned_memcpy_from_wc(dst, + src + offset, + length); i915_gem_object_unpin_map(src_obj); } } diff --git a/drivers/gpu/drm/i915/i915_memcpy.c b/drivers/gpu/drm/i915/i915_memcpy.c index 07b04b0acb77..fdd550405fd3 100644 --- a/drivers/gpu/drm/i915/i915_memcpy.c +++ b/drivers/gpu/drm/i915/i915_memcpy.c @@ -27,6 +27,12 @@ #include "i915_memcpy.h" +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG) +#define CI_BUG_ON(expr) BUG_ON(expr) +#else +#define CI_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) +#endif + static DEFINE_STATIC_KEY_FALSE(has_movntdqa); #ifdef CONFIG_AS_MOVNTDQA @@ -34,7 +40,6 @@ static void __memcpy_ntdqa(void *dst, const void *src, unsigned long len) { kernel_fpu_begin(); - len >>= 4; while (len >= 4) { asm("movntdqa (%0), %%xmm0\n" "movntdqa 16(%0), %%xmm1\n" @@ -59,6 +64,38 @@ static void __memcpy_ntdqa(void *dst, const void *src, unsigned long len) kernel_fpu_end(); } + +static void __memcpy_ntdqu(void *dst, const void *src, unsigned long len) +{ + kernel_fpu_begin(); + + while (len >= 4) { + asm("movntdqa (%0), %%xmm0\n" + "movntdqa 16(%0), %%xmm1\n" + "movntdqa 32(%0), %%xmm2\n" + "movntdqa 48(%0), %%xmm3\n" + "movups %%xmm0, (%1)\n" + "movups %%xmm1, 16(%1)\n" + "movups %%xmm2, 32(%1)\n" + "movups %%xmm3, 48(%1)\n" + :: "r" (src), "r" (dst) : "memory"); + src += 64; + dst += 64; + len -= 4; + } + while (len--) { + asm("movntdqa (%0), %%xmm0\n" + "movups %%xmm0, (%1)\n" + :: "r" (src), "r" (dst) : "memory"); + src += 16; + dst += 16; + } + + kernel_fpu_end(); +} +#else +static void __memcpy_ntdqa(void *dst, const void *src, unsigned long len) {} +static void __memcpy_ntdqu(void *dst, const void *src, unsigned long len) {} #endif /** @@ -83,17 +120,47 @@ bool i915_memcpy_from_wc(void *dst, const void *src, unsigned long len) if (unlikely(((unsigned long)dst | (unsigned long)src | len) & 15)) return false; -#ifdef CONFIG_AS_MOVNTDQA if (static_branch_likely(&has_movntdqa)) { if (likely(len)) - __memcpy_ntdqa(dst, src, len); + __memcpy_ntdqa(dst, src, len >> 4); return true; } -#endif return false; } +/** + * i915_unaligned_memcpy_from_wc: perform a mostly accelerated read from WC + * @dst: destination pointer + * @src: source pointer + * @len: how many bytes to copy + * + * Like i915_memcpy_from_wc(), the unaligned variant copies @len bytes from + * @src to @dst using * non-temporal instructions where available, but + * accepts that its arguments may not be aligned, but are valid for the + * potential 16-byte read past the end. + */ +void i915_unaligned_memcpy_from_wc(void *dst, void *src, unsigned long len) +{ + unsigned long addr; + + CI_BUG_ON(!i915_has_memcpy_from_wc()); + + addr = (unsigned long)src; + if (!IS_ALIGNED(addr, 16)) { + unsigned long x = min(ALIGN(addr, 16) - addr, len); + + memcpy(dst, src, x); + + len -= x; + dst += x; + src += x; + } + + if (likely(len)) + __memcpy_ntdqu(dst, src, DIV_ROUND_UP(len, 16)); +} + void i915_memcpy_init_early(struct drm_i915_private *dev_priv) { /* diff --git a/drivers/gpu/drm/i915/i915_memcpy.h b/drivers/gpu/drm/i915/i915_memcpy.h index 970d84b16987..e36d30edd987 100644 --- a/drivers/gpu/drm/i915/i915_memcpy.h +++ b/drivers/gpu/drm/i915/i915_memcpy.h @@ -11,7 +11,9 @@ struct drm_i915_private; void i915_memcpy_init_early(struct drm_i915_private *i915); + bool i915_memcpy_from_wc(void *dst, const void *src, unsigned long len); +void i915_unaligned_memcpy_from_wc(void *dst, void *src, unsigned long len); /* The movntdqa instructions used for memcpy-from-wc require 16-byte alignment, * as well as SSE4.1 support. i915_memcpy_from_wc() will report if it cannot -- cgit v1.2.3 From 7d929989bb7c476b3ef01dc5cd111622e42e78ea Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 12 Dec 2019 07:27:37 +0000 Subject: drm/i915/gt: Only ignore rc6 parking for PCU on byt/bsw An oversight in that we use rc6->ctl_enable to disable rc6 on gen9 and so it does not simply indicate indirect control via a PCU. Switch the rc6->ctl_enable check for a platform-based check. Fixes: 972745fd5770 ("drm/i915/gt: Disable manual rc6 for Braswell/Baytrail") Signed-off-by: Chris Wilson Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191212072737.884335-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rc6.c | 3 ++- drivers/gpu/drm/i915/gt/intel_rc6_types.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 8ec2b7725141..9e303c29d6e3 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -576,6 +576,7 @@ void intel_rc6_enable(struct intel_rc6 *rc6) else if (INTEL_GEN(i915) >= 6) gen6_rc6_enable(rc6); + rc6->manual = rc6->ctl_enable & GEN6_RC_CTL_RC6_ENABLE; if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) rc6->ctl_enable = 0; @@ -612,7 +613,7 @@ void intel_rc6_park(struct intel_rc6 *rc6) return; } - if (!(rc6->ctl_enable & GEN6_RC_CTL_RC6_ENABLE)) + if (!rc6->manual) return; /* Turn off the HW timers and go directly to rc6 */ diff --git a/drivers/gpu/drm/i915/gt/intel_rc6_types.h b/drivers/gpu/drm/i915/gt/intel_rc6_types.h index 60decae1abc9..bfbb623f7a4f 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6_types.h +++ b/drivers/gpu/drm/i915/gt/intel_rc6_types.h @@ -24,6 +24,7 @@ struct intel_rc6 { bool supported : 1; bool enabled : 1; + bool manual : 1; bool wakeref : 1; }; -- cgit v1.2.3 From 32d94048b988469f8bd62cdc6d934f9f58c2b7c5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Dec 2019 23:08:56 +0000 Subject: drm/i915/gem: Prepare gen7 cmdparser for async execution The gen7 cmdparser is primarily a promotion-based system to allow access to additional registers beyond the HW validation, and allows fallback to normal execution of the user batch buffer if valid and requires chaining. In the next patch, we will do the cmdparser validation in the pipeline asynchronously and so at the point of request construction we will not know if we want to execute the privileged and validated batch, or the original user batch. The solution employed here is to execute both batches, one with raised privileges and one as normal. This is because the gen7 MI_BATCH_BUFFER_START command cannot change privilege level within a batch and must strictly use the current privilege level (or undefined behaviour kills the GPU). So in order to execute the original batch, we need a second non-priviledged batch buffer chain from the ring, i.e. we need to emit two batches for each user batch. Inside the two batches we determine which one should actually execute, we provide a conditional trampoline to call the original batch. Implementation-wise, we create a single buffer and write the shadow and the trampoline inside it at different offsets; and bind the buffer into both the kernel GGTT for the privileged execution of the shadow and into the user ppGTT for the non-privileged execution of the trampoline and original batch. One buffer, two batches and two vma. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191211230858.599030-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 117 ++++++++++++++----------- drivers/gpu/drm/i915/gt/intel_gpu_commands.h | 8 ++ drivers/gpu/drm/i915/i915_cmd_parser.c | 57 ++++++++++-- drivers/gpu/drm/i915/i915_drv.h | 4 +- 4 files changed, 127 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 13f88fc536c7..4e546b6fff8e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -228,6 +228,7 @@ struct i915_execbuffer { struct i915_request *request; /** our request to build */ struct i915_vma *batch; /** identity of the batch obj/vma */ + struct i915_vma *trampoline; /** trampoline used for chaining */ /** actual size of execobj[] as we may extend it for the cmdparser */ unsigned int buffer_count; @@ -1946,31 +1947,13 @@ static int i915_reset_gen7_sol_offsets(struct i915_request *rq) } static struct i915_vma * -shadow_batch_pin(struct i915_execbuffer *eb, struct drm_i915_gem_object *obj) +shadow_batch_pin(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + unsigned int flags) { - struct i915_address_space *vm; struct i915_vma *vma; - u64 flags; int err; - /* - * PPGTT backed shadow buffers must be mapped RO, to prevent - * post-scan tampering - */ - if (CMDPARSER_USES_GGTT(eb->i915)) { - vm = &eb->engine->gt->ggtt->vm; - flags = PIN_GLOBAL; - } else { - vm = eb->context->vm; - if (!vm->has_read_only) { - DRM_DEBUG("Cannot prevent post-scan tampering without RO capable vm\n"); - return ERR_PTR(-EINVAL); - } - - i915_gem_object_set_readonly(obj); - flags = PIN_USER; - } - vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) return vma; @@ -1985,59 +1968,80 @@ shadow_batch_pin(struct i915_execbuffer *eb, struct drm_i915_gem_object *obj) static int eb_parse(struct i915_execbuffer *eb) { struct intel_engine_pool_node *pool; - struct i915_vma *vma; + struct i915_vma *shadow, *trampoline; + unsigned int len; int err; if (!eb_use_cmdparser(eb)) return 0; - pool = intel_engine_get_pool(eb->engine, eb->batch_len); + len = eb->batch_len; + if (!CMDPARSER_USES_GGTT(eb->i915)) { + /* + * ppGTT backed shadow buffers must be mapped RO, to prevent + * post-scan tampering + */ + if (!eb->context->vm->has_read_only) { + DRM_DEBUG("Cannot prevent post-scan tampering without RO capable vm\n"); + return -EINVAL; + } + } else { + len += I915_CMD_PARSER_TRAMPOLINE_SIZE; + } + + pool = intel_engine_get_pool(eb->engine, len); if (IS_ERR(pool)) return PTR_ERR(pool); - vma = shadow_batch_pin(eb, pool->obj); - if (IS_ERR(vma)) { - err = PTR_ERR(vma); + shadow = shadow_batch_pin(pool->obj, eb->context->vm, PIN_USER); + if (IS_ERR(shadow)) { + err = PTR_ERR(shadow); goto err; } + i915_gem_object_set_readonly(shadow->obj); + + trampoline = NULL; + if (CMDPARSER_USES_GGTT(eb->i915)) { + trampoline = shadow; + + shadow = shadow_batch_pin(pool->obj, + &eb->engine->gt->ggtt->vm, + PIN_GLOBAL); + if (IS_ERR(shadow)) { + err = PTR_ERR(shadow); + shadow = trampoline; + goto err_shadow; + } + + eb->batch_flags |= I915_DISPATCH_SECURE; + } err = intel_engine_cmd_parser(eb->engine, eb->batch, eb->batch_start_offset, eb->batch_len, - vma); - if (err) { - /* - * Unsafe GGTT-backed buffers can still be submitted safely - * as non-secure. - * For PPGTT backing however, we have no choice but to forcibly - * reject unsafe buffers - */ - if (i915_vma_is_ggtt(vma) && err == -EACCES) - err = 0; - - goto err_unpin; - } + shadow, trampoline); + if (err) + goto err_trampoline; - eb->vma[eb->buffer_count] = i915_vma_get(vma); + eb->vma[eb->buffer_count] = i915_vma_get(shadow); eb->flags[eb->buffer_count] = __EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_REF; - vma->exec_flags = &eb->flags[eb->buffer_count]; + shadow->exec_flags = &eb->flags[eb->buffer_count]; eb->buffer_count++; + eb->trampoline = trampoline; eb->batch_start_offset = 0; - eb->batch = vma; - - if (i915_vma_is_ggtt(vma)) - eb->batch_flags |= I915_DISPATCH_SECURE; - - /* eb->batch_len unchanged */ + eb->batch = shadow; - vma->private = pool; + shadow->private = pool; return 0; -err_unpin: - i915_vma_unpin(vma); +err_trampoline: + if (trampoline) + i915_vma_unpin(trampoline); +err_shadow: + i915_vma_unpin(shadow); err: intel_engine_pool_put(pool); return err; @@ -2089,6 +2093,16 @@ static int eb_submit(struct i915_execbuffer *eb) if (err) return err; + if (eb->trampoline) { + GEM_BUG_ON(eb->batch_start_offset); + err = eb->engine->emit_bb_start(eb->request, + eb->trampoline->node.start + + eb->batch_len, + 0, 0); + if (err) + return err; + } + if (i915_gem_context_nopreempt(eb->gem_context)) eb->request->flags |= I915_REQUEST_NOPREEMPT; @@ -2470,6 +2484,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.buffer_count = args->buffer_count; eb.batch_start_offset = args->batch_start_offset; eb.batch_len = args->batch_len; + eb.trampoline = NULL; eb.batch_flags = 0; if (args->flags & I915_EXEC_SECURE) { @@ -2667,6 +2682,8 @@ err_batch_unpin: err_vma: if (eb.exec) eb_release_vmas(&eb); + if (eb.trampoline) + i915_vma_unpin(eb.trampoline); mutex_unlock(&dev->struct_mutex); err_engine: eb_unpin_engine(&eb); diff --git a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h index c68c0e033f30..51b8718513bc 100644 --- a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h +++ b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h @@ -340,4 +340,12 @@ static inline u64 gen8_noncanonical_addr(u64 address) return address & GENMASK_ULL(GEN8_HIGH_ADDRESS_BIT, 0); } +static inline u32 *__gen6_emit_bb_start(u32 *cs, u32 addr, unsigned int flags) +{ + *cs++ = MI_BATCH_BUFFER_START | flags; + *cs++ = addr; + + return cs; +} + #endif /* _INTEL_GPU_COMMANDS_H_ */ diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index ddc8bf5175d9..34b0ea403a96 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1362,8 +1362,7 @@ static int check_bbstart(u32 *cmd, u32 offset, u32 length, return 0; } -static unsigned long * -alloc_whitelist(struct drm_i915_private *i915, u32 batch_length) +static unsigned long *alloc_whitelist(u32 batch_length) { unsigned long *jmp; @@ -1373,9 +1372,6 @@ alloc_whitelist(struct drm_i915_private *i915, u32 batch_length) * reasonably cheap due to kmalloc caches. */ - if (CMDPARSER_USES_GGTT(i915)) - return NULL; - /* Prefer to report transient allocation failure rather than hit oom */ jmp = bitmap_zalloc(DIV_ROUND_UP(batch_length, sizeof(u32)), GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); @@ -1394,6 +1390,7 @@ alloc_whitelist(struct drm_i915_private *i915, u32 batch_length) * @batch_offset: byte offset in the batch at which execution starts * @batch_length: length of the commands in batch_obj * @shadow: validated copy of the batch buffer in question + * @trampoline: whether to emit a conditional trampoline at the end of the batch * * Parses the specified batch buffer looking for privilege violations as * described in the overview. @@ -1406,7 +1403,8 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, struct i915_vma *batch, u32 batch_offset, u32 batch_length, - struct i915_vma *shadow) + struct i915_vma *shadow, + bool trampoline) { u32 *cmd, *batch_end, offset = 0; struct drm_i915_cmd_descriptor default_desc = noop_desc; @@ -1430,8 +1428,10 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, return PTR_ERR(cmd); } - /* Defer failure until attempted use */ - jump_whitelist = alloc_whitelist(engine->i915, batch_length); + jump_whitelist = NULL; + if (!trampoline) + /* Defer failure until attempted use */ + jump_whitelist = alloc_whitelist(batch_length); shadow_addr = gen8_canonical_addr(shadow->node.start); batch_addr = gen8_canonical_addr(batch->node.start + batch_offset); @@ -1493,6 +1493,47 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, } } while (1); + if (trampoline) { + /* + * With the trampoline, the shadow is executed twice. + * + * 1 - starting at offset 0, in privileged mode + * 2 - starting at offset batch_len, as non-privileged + * + * Only if the batch is valid and safe to execute, do we + * allow the first privileged execution to proceed. If not, + * we terminate the first batch and use the second batchbuffer + * entry to chain to the original unsafe non-privileged batch, + * leaving it to the HW to validate. + */ + *batch_end = MI_BATCH_BUFFER_END; + + if (ret) { + /* Batch unsafe to execute with privileges, cancel! */ + cmd = page_mask_bits(shadow->obj->mm.mapping); + *cmd = MI_BATCH_BUFFER_END; + + /* If batch is unsafe but valid, jump to the original */ + if (ret == -EACCES) { + unsigned int flags; + + flags = MI_BATCH_NON_SECURE_I965; + if (IS_HASWELL(engine->i915)) + flags = MI_BATCH_NON_SECURE_HSW; + + GEM_BUG_ON(!IS_GEN_RANGE(engine->i915, 6, 7)); + __gen6_emit_bb_start(batch_end, + batch_addr, + flags); + + ret = 0; /* allow execution */ + } + } + + if (needs_clflush_after) + drm_clflush_virt_range(batch_end, 8); + } + if (needs_clflush_after) { void *ptr = page_mask_bits(shadow->obj->mm.mapping); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 45f31197b390..0781b6326b8c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1949,7 +1949,9 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, struct i915_vma *batch, u32 batch_offset, u32 batch_length, - struct i915_vma *shadow); + struct i915_vma *shadow, + bool trampoline); +#define I915_CMD_PARSER_TRAMPOLINE_SIZE 8 /* intel_device_info.c */ static inline struct intel_device_info * -- cgit v1.2.3 From 686c7c35abc2201535e6921f9f5610a0b3c9194a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Dec 2019 23:08:57 +0000 Subject: drm/i915/gem: Asynchronous cmdparser Execute the cmdparser asynchronously as part of the submission pipeline. Using our dma-fences, we can schedule execution after an asynchronous piece of work, so we move the cmdparser out from under the struct_mutex inside execbuf as run it as part of the submission pipeline. The same security rules apply, we copy the user batch before validation and userspace cannot touch the validation shadow. The only caveat is that we will do request construction before we complete cmdparsing and so we cannot know the outcome of the validation step until later -- so the execbuf ioctl does not report -EINVAL directly, but we must cancel execution of the request and flag the error on the out-fence. Closes: https://gitlab.freedesktop.org/drm/intel/issues/611 Closes: https://gitlab.freedesktop.org/drm/intel/issues/412 Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191211230858.599030-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 90 +++++++++++++++++++++++--- drivers/gpu/drm/i915/i915_cmd_parser.c | 41 ++++++------ 2 files changed, 99 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 4e546b6fff8e..81eaf812c9da 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -25,6 +25,7 @@ #include "i915_gem_clflush.h" #include "i915_gem_context.h" #include "i915_gem_ioctls.h" +#include "i915_sw_fence_work.h" #include "i915_trace.h" enum { @@ -1223,10 +1224,6 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, if (unlikely(!cache->rq)) { int err; - /* If we need to copy for the cmdparser, we will stall anyway */ - if (eb_use_cmdparser(eb)) - return ERR_PTR(-EWOULDBLOCK); - if (!intel_engine_can_store_dword(eb->engine)) return ERR_PTR(-ENODEV); @@ -1965,6 +1962,85 @@ shadow_batch_pin(struct drm_i915_gem_object *obj, return vma; } +struct eb_parse_work { + struct dma_fence_work base; + struct intel_engine_cs *engine; + struct i915_vma *batch; + struct i915_vma *shadow; + struct i915_vma *trampoline; + unsigned int batch_offset; + unsigned int batch_length; +}; + +static int __eb_parse(struct dma_fence_work *work) +{ + struct eb_parse_work *pw = container_of(work, typeof(*pw), base); + + return intel_engine_cmd_parser(pw->engine, + pw->batch, + pw->batch_offset, + pw->batch_length, + pw->shadow, + pw->trampoline); +} + +static const struct dma_fence_work_ops eb_parse_ops = { + .name = "eb_parse", + .work = __eb_parse, +}; + +static int eb_parse_pipeline(struct i915_execbuffer *eb, + struct i915_vma *shadow, + struct i915_vma *trampoline) +{ + struct eb_parse_work *pw; + int err; + + pw = kzalloc(sizeof(*pw), GFP_KERNEL); + if (!pw) + return -ENOMEM; + + dma_fence_work_init(&pw->base, &eb_parse_ops); + + pw->engine = eb->engine; + pw->batch = eb->batch; + pw->batch_offset = eb->batch_start_offset; + pw->batch_length = eb->batch_len; + pw->shadow = shadow; + pw->trampoline = trampoline; + + dma_resv_lock(pw->batch->resv, NULL); + + err = dma_resv_reserve_shared(pw->batch->resv, 1); + if (err) + goto err_batch_unlock; + + /* Wait for all writes (and relocs) into the batch to complete */ + err = i915_sw_fence_await_reservation(&pw->base.chain, + pw->batch->resv, NULL, false, + 0, I915_FENCE_GFP); + if (err < 0) + goto err_batch_unlock; + + /* Keep the batch alive and unwritten as we parse */ + dma_resv_add_shared_fence(pw->batch->resv, &pw->base.dma); + + dma_resv_unlock(pw->batch->resv); + + /* Force execution to wait for completion of the parser */ + dma_resv_lock(shadow->resv, NULL); + dma_resv_add_excl_fence(shadow->resv, &pw->base.dma); + dma_resv_unlock(shadow->resv); + + dma_fence_work_commit(&pw->base); + return 0; + +err_batch_unlock: + dma_resv_unlock(pw->batch->resv); + kfree(pw); + return err; +} + static int eb_parse(struct i915_execbuffer *eb) { struct intel_engine_pool_node *pool; @@ -2016,11 +2092,7 @@ static int eb_parse(struct i915_execbuffer *eb) eb->batch_flags |= I915_DISPATCH_SECURE; } - err = intel_engine_cmd_parser(eb->engine, - eb->batch, - eb->batch_start_offset, - eb->batch_len, - shadow, trampoline); + err = eb_parse_pipeline(eb, shadow, trampoline); if (err) goto err_trampoline; diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 34b0ea403a96..7fcdcf31dc76 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1127,31 +1127,27 @@ find_reg(const struct intel_engine_cs *engine, u32 addr) /* Returns a vmap'd pointer to dst_obj, which the caller must unmap */ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, struct drm_i915_gem_object *src_obj, - u32 offset, u32 length, - bool *needs_clflush_after) + u32 offset, u32 length) { - unsigned int src_needs_clflush; - unsigned int dst_needs_clflush; + bool needs_clflush; void *dst, *src; int ret; - ret = i915_gem_object_prepare_write(dst_obj, &dst_needs_clflush); - if (ret) - return ERR_PTR(ret); - dst = i915_gem_object_pin_map(dst_obj, I915_MAP_FORCE_WB); - i915_gem_object_finish_access(dst_obj); if (IS_ERR(dst)) return dst; - ret = i915_gem_object_prepare_read(src_obj, &src_needs_clflush); + ret = i915_gem_object_pin_pages(src_obj); if (ret) { i915_gem_object_unpin_map(dst_obj); return ERR_PTR(ret); } + needs_clflush = + !(src_obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ); + src = ERR_PTR(-ENODEV); - if (src_needs_clflush && i915_has_memcpy_from_wc()) { + if (needs_clflush && i915_has_memcpy_from_wc()) { src = i915_gem_object_pin_map(src_obj, I915_MAP_WC); if (!IS_ERR(src)) { i915_unaligned_memcpy_from_wc(dst, @@ -1172,7 +1168,7 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, * We don't care about copying too much here as we only * validate up to the end of the batch. */ - if (dst_needs_clflush & CLFLUSH_BEFORE) + if (!(dst_obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ)) length = round_up(length, boot_cpu_data.x86_clflush_size); @@ -1182,7 +1178,7 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, int len = min_t(int, length, PAGE_SIZE - x); src = kmap_atomic(i915_gem_object_get_page(src_obj, n)); - if (src_needs_clflush) + if (needs_clflush) drm_clflush_virt_range(src + x, len); memcpy(ptr, src + x, len); kunmap_atomic(src); @@ -1193,11 +1189,9 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, } } - i915_gem_object_finish_access(src_obj); + i915_gem_object_unpin_pages(src_obj); /* dst_obj is returned with vmap pinned */ - *needs_clflush_after = dst_needs_clflush & CLFLUSH_AFTER; - return dst; } @@ -1383,6 +1377,11 @@ static unsigned long *alloc_whitelist(u32 batch_length) #define LENGTH_BIAS 2 +static bool shadow_needs_clflush(struct drm_i915_gem_object *obj) +{ + return !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE); +} + /** * intel_engine_cmd_parser() - parse a batch buffer for privilege violations * @engine: the engine on which the batch is to execute @@ -1398,7 +1397,6 @@ static unsigned long *alloc_whitelist(u32 batch_length) * Return: non-zero if the parser finds violations or otherwise fails; -EACCES * if the batch appears legal but should use hardware parsing */ - int intel_engine_cmd_parser(struct intel_engine_cs *engine, struct i915_vma *batch, u32 batch_offset, @@ -1409,7 +1407,6 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, u32 *cmd, *batch_end, offset = 0; struct drm_i915_cmd_descriptor default_desc = noop_desc; const struct drm_i915_cmd_descriptor *desc = &default_desc; - bool needs_clflush_after = false; unsigned long *jump_whitelist; u64 batch_addr, shadow_addr; int ret = 0; @@ -1420,9 +1417,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, batch->size)); GEM_BUG_ON(!batch_length); - cmd = copy_batch(shadow->obj, batch->obj, - batch_offset, batch_length, - &needs_clflush_after); + cmd = copy_batch(shadow->obj, batch->obj, batch_offset, batch_length); if (IS_ERR(cmd)) { DRM_DEBUG("CMD: Failed to copy batch\n"); return PTR_ERR(cmd); @@ -1530,11 +1525,11 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, } } - if (needs_clflush_after) + if (shadow_needs_clflush(shadow->obj)) drm_clflush_virt_range(batch_end, 8); } - if (needs_clflush_after) { + if (shadow_needs_clflush(shadow->obj)) { void *ptr = page_mask_bits(shadow->obj->mm.mapping); drm_clflush_virt_range(ptr, (void *)(cmd + 1) - ptr); -- cgit v1.2.3 From b58a8813ee6d65e98ee02b3d3036c6a75ac7e694 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Thu, 12 Dec 2019 12:19:03 +0000 Subject: drm/i915: Improve i915_inject_probe_error macro On non-debug builds we were not using i915 param and thus we may cause "unused variable" warning/error if caller was not using i915 elsewhere. Let compiler see this param. Signed-off-by: Michal Wajdeczko Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191212121903.72524-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/i915_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 04139ba1191e..b0ade76bec90 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -69,7 +69,7 @@ bool i915_error_injected(void); #else -#define i915_inject_probe_error(_i915, _err) 0 +#define i915_inject_probe_error(i915, e) ({ BUILD_BUG_ON_INVALID(i915); 0; }) #define i915_error_injected() false #endif -- cgit v1.2.3 From 1bc9865d8df3e1c6857a27c4b2b8a9ce8f027349 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 12 Dec 2019 15:42:24 +0000 Subject: drm/i915: Set fence_work.ops before dma_fence_init Since dma_fence_init may call ops (because of a meaningless trace_dma_fence), we need to set the worker ops prior to that call. Reported-by: Vince Weaver Fixes: 8e458fe2ee05 ("drm/i915: Generalise the clflush dma-worker") Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: Vince Weaver Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191212154224.1631531-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_sw_fence_work.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.c b/drivers/gpu/drm/i915/i915_sw_fence_work.c index 07552cd544f2..8538ee7a521d 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence_work.c +++ b/drivers/gpu/drm/i915/i915_sw_fence_work.c @@ -78,12 +78,11 @@ static const struct dma_fence_ops fence_ops = { void dma_fence_work_init(struct dma_fence_work *f, const struct dma_fence_work_ops *ops) { + f->ops = ops; spin_lock_init(&f->lock); dma_fence_init(&f->dma, &fence_ops, &f->lock, 0, 0); i915_sw_fence_init(&f->chain, fence_notify); INIT_WORK(&f->work, fence_work); - - f->ops = ops; } int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal) -- cgit v1.2.3 From ad3662e239fcb0ad5e04a51d59f4f39dea7a13a7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 12 Dec 2019 14:04:33 +0000 Subject: drm/i915/gt: Mark up ips_mchdev pointer access drivers/gpu/drm/i915/gt/intel_rps.c:1726:24: error: incompatible types in comparison expression (different address spaces): drivers/gpu/drm/i915/gt/intel_rps.c:1726:24: struct drm_i915_private [noderef] * drivers/gpu/drm/i915/gt/intel_rps.c:1726:24: struct drm_i915_private * Signed-off-by: Chris Wilson Reviewed-by: Venkata Sandeep Dhanalakota Link: https://patchwork.freedesktop.org/patch/msgid/20191212140459.1307617-7-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index fd01e4100fc1..106c9fce9d6c 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1723,7 +1723,7 @@ void intel_rps_driver_register(struct intel_rps *rps) void intel_rps_driver_unregister(struct intel_rps *rps) { - if (ips_mchdev == rps_to_i915(rps)) + if (rcu_access_pointer(ips_mchdev) == rps_to_i915(rps)) rcu_assign_pointer(ips_mchdev, NULL); } -- cgit v1.2.3 From b6a8781a447c71894d9f87f340b6ded00ea546c7 Mon Sep 17 00:00:00 2001 From: Lee Shawn C Date: Tue, 10 Dec 2019 23:04:14 +0800 Subject: drm/i915/cml: Remove unsupport PCI ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 'a7b4deeb02b9 ("drm/i915/cml: Add CML PCI IDS)' introduced new PCI ID that CML support. But some PCI IDs were removed in BSpec for CML. This patch is used to eliminate the unsed ID. Cc: Rodrigo Vivi Cc: Jani Nikula Cc: Anusha Srivatsa Cc: Cooper Chiou Signed-off-by: Lee Shawn C Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191210150415.10705-1-shawn.c.lee@intel.com --- include/drm/i915_pciids.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 3e26a9178aaf..92873c3957c8 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -448,9 +448,7 @@ #define INTEL_CML_GT1_IDS(info) \ INTEL_VGA_DEVICE(0x9B21, info), \ INTEL_VGA_DEVICE(0x9BAA, info), \ - INTEL_VGA_DEVICE(0x9BAB, info), \ INTEL_VGA_DEVICE(0x9BAC, info), \ - INTEL_VGA_DEVICE(0x9BA0, info), \ INTEL_VGA_DEVICE(0x9BA5, info), \ INTEL_VGA_DEVICE(0x9BA8, info), \ INTEL_VGA_DEVICE(0x9BA4, info), \ @@ -460,9 +458,7 @@ #define INTEL_CML_GT2_IDS(info) \ INTEL_VGA_DEVICE(0x9B41, info), \ INTEL_VGA_DEVICE(0x9BCA, info), \ - INTEL_VGA_DEVICE(0x9BCB, info), \ INTEL_VGA_DEVICE(0x9BCC, info), \ - INTEL_VGA_DEVICE(0x9BC0, info), \ INTEL_VGA_DEVICE(0x9BC5, info), \ INTEL_VGA_DEVICE(0x9BC8, info), \ INTEL_VGA_DEVICE(0x9BC4, info), \ -- cgit v1.2.3 From 8717c6b7414ffb890672276dccc284c23078ac0e Mon Sep 17 00:00:00 2001 From: Lee Shawn C Date: Tue, 10 Dec 2019 23:04:15 +0800 Subject: drm/i915/cml: Separate U series pci id from origianl list. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit U series device need different DDI buffer setup for eDP and DP. If driver did not recognize ULT id proerply. The setting for H and S series would be used. Cc: Rodrigo Vivi Cc: Jani Nikula Cc: Anusha Srivatsa Cc: Cooper Chiou Signed-off-by: Lee Shawn C Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191210150415.10705-2-shawn.c.lee@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 2 ++ drivers/gpu/drm/i915/intel_device_info.c | 2 ++ include/drm/i915_pciids.h | 20 +++++++++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index bba6b50e6beb..877560b1031e 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -897,6 +897,8 @@ static const struct pci_device_id pciidlist[] = { INTEL_WHL_U_GT3_IDS(&intel_coffeelake_gt3_info), INTEL_CML_GT1_IDS(&intel_coffeelake_gt1_info), INTEL_CML_GT2_IDS(&intel_coffeelake_gt2_info), + INTEL_CML_U_GT1_IDS(&intel_coffeelake_gt1_info), + INTEL_CML_U_GT2_IDS(&intel_coffeelake_gt2_info), INTEL_CNL_IDS(&intel_cannonlake_info), INTEL_ICL_11_IDS(&intel_icelake_11_info), INTEL_EHL_IDS(&intel_elkhartlake_info), diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 2cde0bac27d3..1acb5db77431 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -829,6 +829,8 @@ static const u16 subplatform_ult_ids[] = { INTEL_WHL_U_GT1_IDS(0), INTEL_WHL_U_GT2_IDS(0), INTEL_WHL_U_GT3_IDS(0), + INTEL_CML_U_GT1_IDS(0), + INTEL_CML_U_GT2_IDS(0), }; static const u16 subplatform_ulx_ids[] = { diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 92873c3957c8..1d2c12219f44 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -446,19 +446,18 @@ /* CML GT1 */ #define INTEL_CML_GT1_IDS(info) \ - INTEL_VGA_DEVICE(0x9B21, info), \ - INTEL_VGA_DEVICE(0x9BAA, info), \ - INTEL_VGA_DEVICE(0x9BAC, info), \ INTEL_VGA_DEVICE(0x9BA5, info), \ INTEL_VGA_DEVICE(0x9BA8, info), \ INTEL_VGA_DEVICE(0x9BA4, info), \ INTEL_VGA_DEVICE(0x9BA2, info) +#define INTEL_CML_U_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x9B21, info), \ + INTEL_VGA_DEVICE(0x9BAA, info), \ + INTEL_VGA_DEVICE(0x9BAC, info) + /* CML GT2 */ #define INTEL_CML_GT2_IDS(info) \ - INTEL_VGA_DEVICE(0x9B41, info), \ - INTEL_VGA_DEVICE(0x9BCA, info), \ - INTEL_VGA_DEVICE(0x9BCC, info), \ INTEL_VGA_DEVICE(0x9BC5, info), \ INTEL_VGA_DEVICE(0x9BC8, info), \ INTEL_VGA_DEVICE(0x9BC4, info), \ @@ -467,6 +466,11 @@ INTEL_VGA_DEVICE(0x9BE6, info), \ INTEL_VGA_DEVICE(0x9BF6, info) +#define INTEL_CML_U_GT2_IDS(info) \ + INTEL_VGA_DEVICE(0x9B41, info), \ + INTEL_VGA_DEVICE(0x9BCA, info), \ + INTEL_VGA_DEVICE(0x9BCC, info) + #define INTEL_KBL_IDS(info) \ INTEL_KBL_GT1_IDS(info), \ INTEL_KBL_GT2_IDS(info), \ @@ -532,7 +536,9 @@ INTEL_WHL_U_GT3_IDS(info), \ INTEL_AML_CFL_GT2_IDS(info), \ INTEL_CML_GT1_IDS(info), \ - INTEL_CML_GT2_IDS(info) + INTEL_CML_GT2_IDS(info), \ + INTEL_CML_U_GT1_IDS(info), \ + INTEL_CML_U_GT2_IDS(info) /* CNL */ #define INTEL_CNL_PORT_F_IDS(info) \ -- cgit v1.2.3 From 601a9ee0f0c71efdd36b7fe7b053e2fb42187c7e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Dec 2019 16:41:02 +0200 Subject: drm/i915: Streamline skl_commit_modeset_enables() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skl_commit_modeset_enables() is a bit of mess. Let's streamline it by simply tracking which pipes still need to be updated. As a bonus we get rid of the state->wm_results.dirty_pipes usage. v2: Rebase due to port sync Cc: José Roberto de Souza Reviewed-by: Stanislav Lisovskiy #v1 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191210144105.3239-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 48 ++++++++++++---------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0e5a33969d77..b995094dafe1 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14553,17 +14553,19 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc *crtc; struct intel_crtc_state *old_crtc_state, *new_crtc_state; - unsigned int updated = 0; - bool progress; - int i; u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices; u8 required_slices = state->wm_results.ddb.enabled_slices; struct skl_ddb_entry entries[I915_MAX_PIPES] = {}; + u8 dirty_pipes = 0; + int i; - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { /* ignore allocations for crtc's that have been turned off. */ if (!needs_modeset(new_crtc_state) && new_crtc_state->hw.active) entries[i] = old_crtc_state->wm.skl.ddb; + if (new_crtc_state->hw.active) + dirty_pipes |= BIT(crtc->pipe); + } /* If 2nd DBuf slice required, enable it here */ if (INTEL_GEN(dev_priv) >= 11 && required_slices > hw_enabled_slices) @@ -14575,15 +14577,13 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) * never overlap with eachother inbetween CRTC updates. Otherwise we'll * cause pipe underruns and other bad stuff. */ - do { - progress = false; - - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + while (dirty_pipes) { + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { enum pipe pipe = crtc->pipe; - bool vbl_wait = false; bool modeset = needs_modeset(new_crtc_state); - if (updated & BIT(crtc->pipe) || !new_crtc_state->hw.active) + if ((dirty_pipes & BIT(pipe)) == 0) continue; if (skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb, @@ -14591,20 +14591,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) INTEL_NUM_PIPES(dev_priv), i)) continue; - updated |= BIT(pipe); entries[i] = new_crtc_state->wm.skl.ddb; - - /* - * If this is an already active pipe, it's DDB changed, - * and this isn't the last pipe that needs updating - * then we need to wait for a vblank to pass for the - * new ddb allocation to take effect. - */ - if (!skl_ddb_entry_equal(&new_crtc_state->wm.skl.ddb, - &old_crtc_state->wm.skl.ddb) && - !modeset && - state->wm_results.dirty_pipes != updated) - vbl_wait = true; + dirty_pipes &= ~BIT(pipe); if (modeset && is_trans_port_sync_mode(new_crtc_state)) { if (is_trans_port_sync_master(new_crtc_state)) @@ -14619,12 +14607,18 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) new_crtc_state); } - if (vbl_wait) + /* + * If this is an already active pipe, it's DDB changed, + * and this isn't the last pipe that needs updating + * then we need to wait for a vblank to pass for the + * new ddb allocation to take effect. + */ + if (!skl_ddb_entry_equal(&new_crtc_state->wm.skl.ddb, + &old_crtc_state->wm.skl.ddb) && + !modeset && dirty_pipes) intel_wait_for_vblank(dev_priv, pipe); - - progress = true; } - } while (progress); + } /* If 2nd DBuf slice is no more required disable it */ if (INTEL_GEN(dev_priv) >= 11 && required_slices < hw_enabled_slices) -- cgit v1.2.3 From 8c8a854d6f43aacfaba49c116c426913bf416419 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 12 Dec 2019 12:11:30 +0300 Subject: drm/i915/bios: fix off by one in parse_generic_dtd() The "num_dtd" variable is the number of elements in the generic_dtd->dtd[] array so the > needs to be >= to prevent reading one element beyond the end of the array. Fixes: 33ef6d4fd8df ("drm/i915/vbt: Handle generic DTD block") Reviewed-by: Matt Roper Signed-off-by: Dan Carpenter Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191212091130.zf2g53njf5u24wk6@kili.mountain --- drivers/gpu/drm/i915/display/intel_bios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index bd674fd355b7..54c02debeddf 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -340,7 +340,7 @@ parse_generic_dtd(struct drm_i915_private *dev_priv, num_dtd = (get_blocksize(generic_dtd) - sizeof(struct bdb_generic_dtd)) / generic_dtd->gdtd_size; - if (dev_priv->vbt.panel_type > num_dtd) { + if (dev_priv->vbt.panel_type >= num_dtd) { DRM_ERROR("Panel type %d not found in table of %d DTD's\n", dev_priv->vbt.panel_type, num_dtd); return; -- cgit v1.2.3 From 86ca2bf2f9d3941c0ee6087604a3f6cc3efd12ae Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 13 Dec 2019 13:50:50 +0300 Subject: drm/i915/selftests: remove a condition We know that "err" is non-zero so there is no need to check. Signed-off-by: Dan Carpenter Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191213105050.y2v5nylsuxvc44jj@kili.mountain --- drivers/gpu/drm/i915/selftests/i915_request.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 99c94b4f69fb..71a4ca38fbac 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -1086,8 +1086,7 @@ static int __live_parallel_engine1(void *arg) rq = i915_request_create(engine->kernel_context); if (IS_ERR(rq)) { err = PTR_ERR(rq); - if (err) - break; + break; } i915_request_get(rq); -- cgit v1.2.3 From e8ab8d669d046a8e9b07707d2f00b9ba3e25d0ae Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 12 Dec 2019 16:15:09 -0800 Subject: drm/i915/ehl: Define EHL powerwells independently of ICL Outputs C and D on EHL are combo PHY outputs and thus should not be using the same TC AUX power well handlers as ICL. And even though icl_combo_phy_aux_power_well_ops works okay for EHL/JSL combo PHYs none of its special handling is actually necessary for this platform: * EHL/JSL don't actually need to program PORT_CL_DW12 * Display WA #1178 does not apply to EHL/JSL Thus we can simply drop back to using our standard "hsw-style" power well ops for EHL AUX power wells. Bspec: 4301 Fixes: f722b8c1e2a2 ("drm/i915/ehl: All EHL ports are combo phys") Cc: Jose Souza Cc: Bob Paauwe Cc: Vivek Kasireddy Cc: Lucas De Marchi Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191213001511.678070-2-matthew.d.roper@intel.com Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/i915/display/intel_display_power.c | 147 +++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 0b3dd2a3b94d..cf34427cc840 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -3688,6 +3688,151 @@ static const struct i915_power_well_desc icl_power_wells[] = { }, }; +static const struct i915_power_well_desc ehl_power_wells[] = { + { + .name = "always-on", + .always_on = true, + .domains = POWER_DOMAIN_MASK, + .ops = &i9xx_always_on_power_well_ops, + .id = DISP_PW_ID_NONE, + }, + { + .name = "power well 1", + /* Handled by the DMC firmware */ + .always_on = true, + .domains = 0, + .ops = &hsw_power_well_ops, + .id = SKL_DISP_PW_1, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_1, + .hsw.has_fuses = true, + }, + }, + { + .name = "DC off", + .domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS, + .ops = &gen9_dc_off_power_well_ops, + .id = SKL_DISP_DC_OFF, + }, + { + .name = "power well 2", + .domains = ICL_PW_2_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = SKL_DISP_PW_2, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_2, + .hsw.has_fuses = true, + }, + }, + { + .name = "power well 3", + .domains = ICL_PW_3_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_3, + .hsw.irq_pipe_mask = BIT(PIPE_B), + .hsw.has_vga = true, + .hsw.has_fuses = true, + }, + }, + { + .name = "DDI A IO", + .domains = ICL_DDI_IO_A_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_A, + }, + }, + { + .name = "DDI B IO", + .domains = ICL_DDI_IO_B_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_B, + }, + }, + { + .name = "DDI C IO", + .domains = ICL_DDI_IO_C_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_C, + }, + }, + { + .name = "DDI D IO", + .domains = ICL_DDI_IO_D_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_ddi_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_DDI_D, + }, + }, + { + .name = "AUX A", + .domains = ICL_AUX_A_IO_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_A, + }, + }, + { + .name = "AUX B", + .domains = ICL_AUX_B_IO_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_B, + }, + }, + { + .name = "AUX C", + .domains = ICL_AUX_C_TC1_IO_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_C, + }, + }, + { + .name = "AUX D", + .domains = ICL_AUX_D_TC2_IO_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &icl_aux_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_AUX_D, + }, + }, + { + .name = "power well 4", + .domains = ICL_PW_4_POWER_DOMAINS, + .ops = &hsw_power_well_ops, + .id = DISP_PW_ID_NONE, + { + .hsw.regs = &hsw_power_well_regs, + .hsw.idx = ICL_PW_CTL_IDX_PW_4, + .hsw.has_fuses = true, + .hsw.irq_pipe_mask = BIT(PIPE_C), + }, + }, +}; + static const struct i915_power_well_desc tgl_power_wells[] = { { .name = "always-on", @@ -4162,6 +4307,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) */ if (IS_GEN(dev_priv, 12)) { err = set_power_wells(power_domains, tgl_power_wells); + } else if (IS_ELKHARTLAKE(dev_priv)) { + err = set_power_wells(power_domains, ehl_power_wells); } else if (IS_GEN(dev_priv, 11)) { err = set_power_wells(power_domains, icl_power_wells); } else if (IS_CANNONLAKE(dev_priv)) { -- cgit v1.2.3 From ab3402581d0fa58e63e36875995f43ab02b4d0a0 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 12 Dec 2019 16:15:10 -0800 Subject: drm/i915/tgl: Drop Wa#1178 The TGL workaround database no longer shows Wa #1178 (or anything similar under different workaround names/numbers) so we should be able to drop it. In fact Swati just discovered that applying this workaround is the root cause of some power well enable failures we've been seeing in CI (gitlab issue 498). Once we stop applying this WA, TGL no longer utilizes any of the special handling provided by icl_combo_phy_aux_power_well_ops so we can just drop back to using the standard hsw-style power well ops instead. v3: Drop now-unused _TGL_AUX_ANAOVRD1_C definition too. (Lucas) Closes: https://gitlab.freedesktop.org/drm/intel/issues/498 Fixes: deea06b47574 ("drm/i915/tgl: apply Display WA #1178 to fix type C dongles") Cc: Lucas De Marchi Cc: Swati Sharma Cc: Imre Deak Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20191213001511.678070-3-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 6 +++--- drivers/gpu/drm/i915/i915_reg.h | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index cf34427cc840..52f2332e0ab8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -3977,7 +3977,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = { { .name = "AUX A", .domains = TGL_AUX_A_IO_POWER_DOMAINS, - .ops = &icl_combo_phy_aux_power_well_ops, + .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { .hsw.regs = &icl_aux_power_well_regs, @@ -3987,7 +3987,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = { { .name = "AUX B", .domains = TGL_AUX_B_IO_POWER_DOMAINS, - .ops = &icl_combo_phy_aux_power_well_ops, + .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { .hsw.regs = &icl_aux_power_well_regs, @@ -3997,7 +3997,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = { { .name = "AUX C", .domains = TGL_AUX_C_IO_POWER_DOMAINS, - .ops = &icl_combo_phy_aux_power_well_ops, + .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { .hsw.regs = &icl_aux_power_well_regs, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 17f9dd3bda72..cbb4689af432 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9437,11 +9437,9 @@ enum skl_power_gate { #define _ICL_AUX_REG_IDX(pw_idx) ((pw_idx) - ICL_PW_CTL_IDX_AUX_A) #define _ICL_AUX_ANAOVRD1_A 0x162398 #define _ICL_AUX_ANAOVRD1_B 0x6C398 -#define _TGL_AUX_ANAOVRD1_C 0x160398 #define ICL_AUX_ANAOVRD1(pw_idx) _MMIO(_PICK(_ICL_AUX_REG_IDX(pw_idx), \ _ICL_AUX_ANAOVRD1_A, \ - _ICL_AUX_ANAOVRD1_B, \ - _TGL_AUX_ANAOVRD1_C)) + _ICL_AUX_ANAOVRD1_B)) #define ICL_AUX_ANAOVRD1_LDO_BYPASS (1 << 7) #define ICL_AUX_ANAOVRD1_ENABLE (1 << 0) -- cgit v1.2.3 From b69fa3610b15497e487a6a35786de9600ee60932 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 12 Dec 2019 17:06:00 -0800 Subject: drm/i915/icl: Cleanup combo PHY aux power well handlers Now that the combo PHY aux power well handlers are used exclusively on Icelake, we can drop a bunch of the extra tests. v2: Don't try to use intel_uncore_rmw for register updates yet; there's pending display uncore patches that need to land first. (Lucas) v3: Drop the combo phy assertion. It was backward before, but doesn't seem terribly necessary. I'm keeping the IS_ICELAKE assertion though since we often copy/paste/modify the power well tables when defining new platforms and it's too easy to cargo cult the ICL-specific handling to new platforms that shouldn't use it. (Lucas) v4: Fix build; forgot to commit all the changes. (CI) Cc: Lucas De Marchi Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191213010600.701315-1-matthew.d.roper@intel.com Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/i915/display/intel_display_power.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 52f2332e0ab8..679457156797 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -418,7 +418,8 @@ icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, int pw_idx = power_well->desc->hsw.idx; enum phy phy = ICL_AUX_PW_TO_PHY(pw_idx); u32 val; - int wa_idx_max; + + WARN_ON(!IS_ICELAKE(dev_priv)); val = I915_READ(regs->driver); I915_WRITE(regs->driver, val | HSW_PWR_WELL_CTL_REQ(pw_idx)); @@ -430,14 +431,8 @@ icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, hsw_wait_for_power_well_enable(dev_priv, power_well); - /* Display WA #1178: icl, tgl */ - if (IS_TIGERLAKE(dev_priv)) - wa_idx_max = ICL_PW_CTL_IDX_AUX_C; - else - wa_idx_max = ICL_PW_CTL_IDX_AUX_B; - - if (!IS_ELKHARTLAKE(dev_priv) && - pw_idx >= ICL_PW_CTL_IDX_AUX_A && pw_idx <= wa_idx_max && + /* Display WA #1178: icl */ + if (pw_idx >= ICL_PW_CTL_IDX_AUX_A && pw_idx <= ICL_PW_CTL_IDX_AUX_B && !intel_bios_is_port_edp(dev_priv, (enum port)phy)) { val = I915_READ(ICL_AUX_ANAOVRD1(pw_idx)); val |= ICL_AUX_ANAOVRD1_ENABLE | ICL_AUX_ANAOVRD1_LDO_BYPASS; @@ -454,10 +449,10 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, enum phy phy = ICL_AUX_PW_TO_PHY(pw_idx); u32 val; - if (INTEL_GEN(dev_priv) < 12) { - val = I915_READ(ICL_PORT_CL_DW12(phy)); - I915_WRITE(ICL_PORT_CL_DW12(phy), val & ~ICL_LANE_ENABLE_AUX); - } + WARN_ON(!IS_ICELAKE(dev_priv)); + + val = I915_READ(ICL_PORT_CL_DW12(phy)); + I915_WRITE(ICL_PORT_CL_DW12(phy), val & ~ICL_LANE_ENABLE_AUX); val = I915_READ(regs->driver); I915_WRITE(regs->driver, val & ~HSW_PWR_WELL_CTL_REQ(pw_idx)); -- cgit v1.2.3 From 3dc716fd3cfddfaabf919f5337d5ff8b199b1cb4 Mon Sep 17 00:00:00 2001 From: Venkata Sandeep Dhanalakota Date: Fri, 13 Dec 2019 07:51:51 -0800 Subject: drm/i915/perf: Register sysctl path globally We do not require to register the sysctl paths per instance, so making registration global. v2: make sysctl path register and unregister function driver specific (Tvrtko and Lucas). Cc: Sudeep Dutt Cc: Rodrigo Vivi Cc: Daniel Vetter Cc: Chris Wilson Cc: Jani Nikula Signed-off-by: Venkata Sandeep Dhanalakota Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191213155152.69182-1-venkata.s.dhanalakota@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 9 ++++++++- drivers/gpu/drm/i915/i915_perf.c | 17 +++++++++++++---- drivers/gpu/drm/i915/i915_perf.h | 2 ++ drivers/gpu/drm/i915/i915_perf_types.h | 1 - 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 877560b1031e..9571611b4b16 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -30,6 +30,7 @@ #include "display/intel_fbdev.h" #include "i915_drv.h" +#include "i915_perf.h" #include "i915_globals.h" #include "i915_selftest.h" @@ -1053,7 +1054,12 @@ static int __init i915_init(void) return 0; } - return pci_register_driver(&i915_pci_driver); + err = pci_register_driver(&i915_pci_driver); + if (err) + return err; + + i915_perf_sysctl_register(); + return 0; } static void __exit i915_exit(void) @@ -1061,6 +1067,7 @@ static void __exit i915_exit(void) if (!i915_pci_driver.driver.owner) return; + i915_perf_sysctl_unregister(); pci_unregister_driver(&i915_pci_driver); i915_globals_exit(); } diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 8d2e37949f46..3c163a9d69a9 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -387,6 +387,8 @@ struct i915_oa_config_bo { struct i915_vma *vma; }; +static struct ctl_table_header *sysctl_header; + static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer); void i915_oa_config_release(struct kref *ref) @@ -4228,7 +4230,7 @@ static struct ctl_table dev_root[] = { }; /** - * i915_perf_init - initialize i915-perf state on module load + * i915_perf_init - initialize i915-perf state on module bind * @i915: i915 device instance * * Initializes i915-perf state without exposing anything to userspace. @@ -4345,7 +4347,6 @@ void i915_perf_init(struct drm_i915_private *i915) oa_sample_rate_hard_limit = 1000 * (RUNTIME_INFO(i915)->cs_timestamp_frequency_khz / 2); - perf->sysctl_header = register_sysctl_table(dev_root); mutex_init(&perf->metrics_lock); idr_init(&perf->metrics_idr); @@ -4381,6 +4382,16 @@ static int destroy_config(int id, void *p, void *data) return 0; } +void i915_perf_sysctl_register(void) +{ + sysctl_header = register_sysctl_table(dev_root); +} + +void i915_perf_sysctl_unregister(void) +{ + unregister_sysctl_table(sysctl_header); +} + /** * i915_perf_fini - Counter part to i915_perf_init() * @i915: i915 device instance @@ -4395,8 +4406,6 @@ void i915_perf_fini(struct drm_i915_private *i915) idr_for_each(&perf->metrics_idr, destroy_config, perf); idr_destroy(&perf->metrics_idr); - unregister_sysctl_table(perf->sysctl_header); - memset(&perf->ops, 0, sizeof(perf->ops)); perf->i915 = NULL; } diff --git a/drivers/gpu/drm/i915/i915_perf.h b/drivers/gpu/drm/i915/i915_perf.h index 4ceebce72060..882fdd0a7680 100644 --- a/drivers/gpu/drm/i915/i915_perf.h +++ b/drivers/gpu/drm/i915/i915_perf.h @@ -23,6 +23,8 @@ void i915_perf_fini(struct drm_i915_private *i915); void i915_perf_register(struct drm_i915_private *i915); void i915_perf_unregister(struct drm_i915_private *i915); int i915_perf_ioctl_version(void); +void i915_perf_sysctl_register(void); +void i915_perf_sysctl_unregister(void); int i915_perf_open_ioctl(struct drm_device *dev, void *data, struct drm_file *file); diff --git a/drivers/gpu/drm/i915/i915_perf_types.h b/drivers/gpu/drm/i915/i915_perf_types.h index 74ddc20a0d37..45e581455f5d 100644 --- a/drivers/gpu/drm/i915/i915_perf_types.h +++ b/drivers/gpu/drm/i915/i915_perf_types.h @@ -380,7 +380,6 @@ struct i915_perf { struct drm_i915_private *i915; struct kobject *metrics_kobj; - struct ctl_table_header *sysctl_header; /* * Lock associated with adding/modifying/removing OA configs -- cgit v1.2.3 From 639f2f24895fb37dd67dfecabd2c74019ed64140 Mon Sep 17 00:00:00 2001 From: Venkata Sandeep Dhanalakota Date: Fri, 13 Dec 2019 07:51:52 -0800 Subject: drm/i915: Introduce new macros for tracing New macros ENGINE_TRACE(), CE_TRACE(), RQ_TRACE() and GT_TRACE() are introduce to tag device name and engine name with contexts and requests tracing in i915. Cc: Sudeep Dutt Cc: Rodrigo Vivi Cc: Daniel Vetter Cc: Chris Wilson Cc: Jani Nikula Signed-off-by: Venkata Sandeep Dhanalakota Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191213155152.69182-2-venkata.s.dhanalakota@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_pm.c | 4 +- drivers/gpu/drm/i915/gt/intel_context.c | 11 +-- drivers/gpu/drm/i915/gt/intel_context.h | 7 ++ drivers/gpu/drm/i915/gt/intel_engine.h | 7 ++ drivers/gpu/drm/i915/gt/intel_engine_cs.c | 6 +- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 6 +- drivers/gpu/drm/i915/gt/intel_gt.h | 6 ++ drivers/gpu/drm/i915/gt/intel_gt_pm.c | 15 ++- drivers/gpu/drm/i915/gt/intel_lrc.c | 108 ++++++++++------------ drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 13 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 +- drivers/gpu/drm/i915/i915_request.c | 23 +---- drivers/gpu/drm/i915/i915_request.h | 7 ++ 14 files changed, 112 insertions(+), 111 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c index f88ee1317bb4..3671a4e7e1cb 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c @@ -13,7 +13,7 @@ void i915_gem_suspend(struct drm_i915_private *i915) { - GEM_TRACE("\n"); + GEM_TRACE("%s\n", dev_name(i915->drm.dev)); intel_wakeref_auto(&i915->ggtt.userfault_wakeref, 0); flush_workqueue(i915->wq); @@ -99,7 +99,7 @@ void i915_gem_suspend_late(struct drm_i915_private *i915) void i915_gem_resume(struct drm_i915_private *i915) { - GEM_TRACE("\n"); + GEM_TRACE("%s\n", dev_name(i915->drm.dev)); intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL); diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 61c39e943f69..b1e346d2d35f 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -68,9 +68,8 @@ int __intel_context_do_pin(struct intel_context *ce) if (err) goto err; - GEM_TRACE("%s context:%llx pin ring:{head:%04x, tail:%04x}\n", - ce->engine->name, ce->timeline->fence_context, - ce->ring->head, ce->ring->tail); + CE_TRACE(ce, "pin ring:{head:%04x, tail:%04x}\n", + ce->ring->head, ce->ring->tail); i915_gem_context_get(ce->gem_context); /* for ctx->ppgtt */ @@ -98,8 +97,7 @@ void intel_context_unpin(struct intel_context *ce) mutex_lock_nested(&ce->pin_mutex, SINGLE_DEPTH_NESTING); if (likely(atomic_dec_and_test(&ce->pin_count))) { - GEM_TRACE("%s context:%llx retire\n", - ce->engine->name, ce->timeline->fence_context); + CE_TRACE(ce, "retire\n"); ce->ops->unpin(ce); @@ -141,8 +139,7 @@ static void __intel_context_retire(struct i915_active *active) { struct intel_context *ce = container_of(active, typeof(*ce), active); - GEM_TRACE("%s context:%llx retire\n", - ce->engine->name, ce->timeline->fence_context); + CE_TRACE(ce, "retire\n"); set_bit(CONTEXT_VALID_BIT, &ce->flags); if (ce->state) diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index 68b3d317d959..b39eb1fcfbca 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -15,6 +15,13 @@ #include "intel_ring_types.h" #include "intel_timeline_types.h" +#define CE_TRACE(ce, fmt, ...) do { \ + const struct intel_context *ce__ = (ce); \ + ENGINE_TRACE(ce__->engine, "context:%llx" fmt, \ + ce__->timeline->fence_context, \ + ##__VA_ARGS__); \ +} while (0) + void intel_context_init(struct intel_context *ce, struct i915_gem_context *ctx, struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index c294ea80605e..0926ecea9147 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -29,6 +29,13 @@ struct intel_gt; #define CACHELINE_BYTES 64 #define CACHELINE_DWORDS (CACHELINE_BYTES / sizeof(u32)) +#define ENGINE_TRACE(e, fmt, ...) do { \ + const struct intel_engine_cs *e__ __maybe_unused = (e); \ + GEM_TRACE("%s %s: " fmt, \ + dev_name(e__->i915->drm.dev), e__->name, \ + ##__VA_ARGS__); \ +} while (0) + /* * The register defines to be used with the following macros need to accept a * base param, e.g: diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 49473c25916c..3d1d48bf90cf 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -912,7 +912,7 @@ int intel_engine_stop_cs(struct intel_engine_cs *engine) if (INTEL_GEN(engine->i915) < 3) return -ENODEV; - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); intel_uncore_write_fw(uncore, mode, _MASKED_BIT_ENABLE(STOP_RING)); @@ -921,7 +921,7 @@ int intel_engine_stop_cs(struct intel_engine_cs *engine) mode, MODE_IDLE, MODE_IDLE, 1000, stop_timeout(engine), NULL)) { - GEM_TRACE("%s: timed out on STOP_RING -> IDLE\n", engine->name); + ENGINE_TRACE(engine, "timed out on STOP_RING -> IDLE\n"); err = -ETIMEDOUT; } @@ -933,7 +933,7 @@ int intel_engine_stop_cs(struct intel_engine_cs *engine) void intel_engine_cancel_stop_cs(struct intel_engine_cs *engine) { - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); ENGINE_WRITE_FW(engine, RING_MI_MODE, _MASKED_BIT_DISABLE(STOP_RING)); } diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 889eb37e386a..bcbda8e52d41 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -21,7 +21,7 @@ static int __engine_unpark(struct intel_wakeref *wf) container_of(wf, typeof(*engine), wakeref); void *map; - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); intel_gt_pm_get(engine->gt); @@ -80,7 +80,7 @@ __queue_and_release_pm(struct i915_request *rq, { struct intel_gt_timelines *timelines = &engine->gt->timelines; - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); /* * We have to serialise all potential retirement paths with our @@ -204,7 +204,7 @@ static int __engine_park(struct intel_wakeref *wf) if (!switch_to_kernel_context(engine)) return -EBUSY; - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); call_idle_barriers(engine); /* cleanup after wedging */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index 5436f8c30708..9d9e8831daeb 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -12,6 +12,12 @@ struct drm_i915_private; +#define GT_TRACE(gt__, fmt, ...) do { \ + typecheck(struct intel_gt, *(gt__)); \ + GEM_TRACE("%s " fmt, dev_name(gt->i915->drm.dev), \ + ##__VA_ARGS__); \ +} while (0) + static inline struct intel_gt *uc_to_gt(struct intel_uc *uc) { return container_of(uc, struct intel_gt, uc); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index ecde67a75e32..bb57e3443a50 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -43,7 +43,7 @@ static int __gt_unpark(struct intel_wakeref *wf) struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref); struct drm_i915_private *i915 = gt->i915; - GEM_TRACE("\n"); + GT_TRACE(gt, "\n"); i915_globals_unpark(); @@ -76,7 +76,7 @@ static int __gt_park(struct intel_wakeref *wf) intel_wakeref_t wakeref = fetch_and_zero(>->awake); struct drm_i915_private *i915 = gt->i915; - GEM_TRACE("\n"); + GT_TRACE(gt, "\n"); intel_gt_park_requests(gt); @@ -141,7 +141,7 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force) enum intel_engine_id id; intel_wakeref_t wakeref; - GEM_TRACE("force:%s\n", yesno(force)); + GT_TRACE(gt, "force:%s", yesno(force)); /* Use a raw wakeref to avoid calling intel_display_power_get early */ wakeref = intel_runtime_pm_get(gt->uncore->rpm); @@ -188,7 +188,7 @@ int intel_gt_resume(struct intel_gt *gt) enum intel_engine_id id; int err = 0; - GEM_TRACE("\n"); + GT_TRACE(gt, "\n"); /* * After resume, we may need to poke into the pinned kernel @@ -301,20 +301,19 @@ void intel_gt_suspend_late(struct intel_gt *gt) intel_gt_sanitize(gt, false); - GEM_TRACE("\n"); + GT_TRACE(gt, "\n"); } void intel_gt_runtime_suspend(struct intel_gt *gt) { intel_uc_runtime_suspend(>->uc); - GEM_TRACE("\n"); + GT_TRACE(gt, "\n"); } int intel_gt_runtime_resume(struct intel_gt *gt) { - GEM_TRACE("\n"); - + GT_TRACE(gt, "\n"); intel_gt_init_swizzling(gt); return intel_uc_runtime_resume(>->uc); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 929f6bae4eba..4ebfecd95032 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1069,8 +1069,8 @@ static void reset_active(struct i915_request *rq, * remain correctly ordered. And we defer to __i915_request_submit() * so that all asynchronous waits are correctly handled. */ - GEM_TRACE("%s(%s): { rq=%llx:%lld }\n", - __func__, engine->name, rq->fence.context, rq->fence.seqno); + ENGINE_TRACE(engine, "{ rq=%llx:%lld }\n", + rq->fence.context, rq->fence.seqno); /* On resubmission of the active request, payload will be scrubbed */ if (i915_request_completed(rq)) @@ -1274,15 +1274,14 @@ trace_ports(const struct intel_engine_execlists *execlists, if (!ports[0]) return; - GEM_TRACE("%s: %s { %llx:%lld%s, %llx:%lld }\n", - engine->name, msg, - ports[0]->fence.context, - ports[0]->fence.seqno, - i915_request_completed(ports[0]) ? "!" : - i915_request_started(ports[0]) ? "*" : - "", - ports[1] ? ports[1]->fence.context : 0, - ports[1] ? ports[1]->fence.seqno : 0); + ENGINE_TRACE(engine, "%s { %llx:%lld%s, %llx:%lld }\n", msg, + ports[0]->fence.context, + ports[0]->fence.seqno, + i915_request_completed(ports[0]) ? "!" : + i915_request_started(ports[0]) ? "*" : + "", + ports[1] ? ports[1]->fence.context : 0, + ports[1] ? ports[1]->fence.seqno : 0); } static __maybe_unused bool @@ -1700,12 +1699,12 @@ static void execlists_dequeue(struct intel_engine_cs *engine) last = last_active(execlists); if (last) { if (need_preempt(engine, last, rb)) { - GEM_TRACE("%s: preempting last=%llx:%lld, prio=%d, hint=%d\n", - engine->name, - last->fence.context, - last->fence.seqno, - last->sched.attr.priority, - execlists->queue_priority_hint); + ENGINE_TRACE(engine, + "preempting last=%llx:%lld, prio=%d, hint=%d\n", + last->fence.context, + last->fence.seqno, + last->sched.attr.priority, + execlists->queue_priority_hint); record_preemption(execlists); /* @@ -1735,12 +1734,12 @@ static void execlists_dequeue(struct intel_engine_cs *engine) last = NULL; } else if (need_timeslice(engine, last) && timer_expired(&engine->execlists.timer)) { - GEM_TRACE("%s: expired last=%llx:%lld, prio=%d, hint=%d\n", - engine->name, - last->fence.context, - last->fence.seqno, - last->sched.attr.priority, - execlists->queue_priority_hint); + ENGINE_TRACE(engine, + "expired last=%llx:%lld, prio=%d, hint=%d\n", + last->fence.context, + last->fence.seqno, + last->sched.attr.priority, + execlists->queue_priority_hint); ring_set_paused(engine, 1); defer_active(engine); @@ -1817,14 +1816,14 @@ static void execlists_dequeue(struct intel_engine_cs *engine) return; /* leave this for another */ } - GEM_TRACE("%s: virtual rq=%llx:%lld%s, new engine? %s\n", - engine->name, - rq->fence.context, - rq->fence.seqno, - i915_request_completed(rq) ? "!" : - i915_request_started(rq) ? "*" : - "", - yesno(engine != ve->siblings[0])); + ENGINE_TRACE(engine, + "virtual rq=%llx:%lld%s, new engine? %s\n", + rq->fence.context, + rq->fence.seqno, + i915_request_completed(rq) ? "!" : + i915_request_started(rq) ? "*" : + "", + yesno(engine != ve->siblings[0])); ve->request = NULL; ve->base.execlists.queue_priority_hint = INT_MIN; @@ -1980,9 +1979,6 @@ done: * interrupt for secondary ports). */ execlists->queue_priority_hint = queue_prio(execlists); - GEM_TRACE("%s: queue_priority_hint:%d, submit:%s\n", - engine->name, execlists->queue_priority_hint, - yesno(submit)); if (submit) { *port = execlists_schedule_in(last, port - execlists->pending); @@ -2131,7 +2127,7 @@ static void process_csb(struct intel_engine_cs *engine) */ head = execlists->csb_head; tail = READ_ONCE(*execlists->csb_write); - GEM_TRACE("%s cs-irq head=%d, tail=%d\n", engine->name, head, tail); + ENGINE_TRACE(engine, "cs-irq head=%d, tail=%d\n", head, tail); if (unlikely(head == tail)) return; @@ -2169,9 +2165,8 @@ static void process_csb(struct intel_engine_cs *engine) * status notifier. */ - GEM_TRACE("%s csb[%d]: status=0x%08x:0x%08x\n", - engine->name, head, - buf[2 * head + 0], buf[2 * head + 1]); + ENGINE_TRACE(engine, "csb[%d]: status=0x%08x:0x%08x\n", + head, buf[2 * head + 0], buf[2 * head + 1]); if (INTEL_GEN(engine->i915) >= 12) promote = gen12_csb_parse(execlists, buf + 2 * head); @@ -2262,10 +2257,9 @@ static noinline void preempt_reset(struct intel_engine_cs *engine) /* Mark this tasklet as disabled to avoid waiting for it to complete */ tasklet_disable_nosync(&engine->execlists.tasklet); - GEM_TRACE("%s: preempt timeout %lu+%ums\n", - engine->name, - READ_ONCE(engine->props.preempt_timeout_ms), - jiffies_to_msecs(jiffies - engine->execlists.preempt.expires)); + ENGINE_TRACE(engine, "preempt timeout %lu+%ums\n", + READ_ONCE(engine->props.preempt_timeout_ms), + jiffies_to_msecs(jiffies - engine->execlists.preempt.expires)); intel_engine_reset(engine, "preemption time out"); tasklet_enable(&engine->execlists.tasklet); @@ -2971,8 +2965,8 @@ static void execlists_reset_prepare(struct intel_engine_cs *engine) struct intel_engine_execlists * const execlists = &engine->execlists; unsigned long flags; - GEM_TRACE("%s: depth<-%d\n", engine->name, - atomic_read(&execlists->tasklet.count)); + ENGINE_TRACE(engine, "depth<-%d\n", + atomic_read(&execlists->tasklet.count)); /* * Prevent request submission to the hardware until we have @@ -3134,8 +3128,8 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled) restore_default_state(ce, engine); out_replay: - GEM_TRACE("%s replay {head:%04x, tail:%04x}\n", - engine->name, ce->ring->head, ce->ring->tail); + ENGINE_TRACE(engine, "replay {head:%04x, tail:%04x}\n", + ce->ring->head, ce->ring->tail); intel_ring_update_space(ce->ring); __execlists_reset_reg_state(ce, engine); __execlists_update_reg_state(ce, engine); @@ -3151,7 +3145,7 @@ static void execlists_reset(struct intel_engine_cs *engine, bool stalled) { unsigned long flags; - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); spin_lock_irqsave(&engine->active.lock, flags); @@ -3172,7 +3166,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) struct rb_node *rb; unsigned long flags; - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); /* * Before we call engine->cancel_requests(), we should have exclusive @@ -3259,8 +3253,8 @@ static void execlists_reset_finish(struct intel_engine_cs *engine) if (__tasklet_enable(&execlists->tasklet)) /* And kick in case we missed a new request submission. */ tasklet_hi_schedule(&execlists->tasklet); - GEM_TRACE("%s: depth->%d\n", engine->name, - atomic_read(&execlists->tasklet.count)); + ENGINE_TRACE(engine, "depth->%d\n", + atomic_read(&execlists->tasklet.count)); } static int gen8_emit_bb_start(struct i915_request *rq, @@ -4309,10 +4303,9 @@ static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve) mask = ve->siblings[0]->mask; } - GEM_TRACE("%s: rq=%llx:%lld, mask=%x, prio=%d\n", - ve->base.name, - rq->fence.context, rq->fence.seqno, - mask, ve->base.execlists.queue_priority_hint); + ENGINE_TRACE(&ve->base, "rq=%llx:%lld, mask=%x, prio=%d\n", + rq->fence.context, rq->fence.seqno, + mask, ve->base.execlists.queue_priority_hint); return mask; } @@ -4403,10 +4396,9 @@ static void virtual_submit_request(struct i915_request *rq) struct i915_request *old; unsigned long flags; - GEM_TRACE("%s: rq=%llx:%lld\n", - ve->base.name, - rq->fence.context, - rq->fence.seqno); + ENGINE_TRACE(&ve->base, "rq=%llx:%lld\n", + rq->fence.context, + rq->fence.seqno); GEM_BUG_ON(ve->base.submit_request != virtual_submit_request); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 8408cb84e52c..f5b2e7c7e6c8 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1089,7 +1089,7 @@ int intel_engine_reset(struct intel_engine_cs *engine, const char *msg) bool uses_guc = intel_engine_in_guc_submission_mode(engine); int ret; - GEM_TRACE("%s flags=%lx\n", engine->name, gt->reset.flags); + ENGINE_TRACE(engine, "flags=%lx\n", gt->reset.flags); GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, >->reset.flags)); if (!intel_engine_pm_get_if_awake(engine)) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 5c22ca6f998a..30ba67c9abe9 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -632,8 +632,8 @@ static int xcs_resume(struct intel_engine_cs *engine) struct intel_ring *ring = engine->legacy.ring; int ret = 0; - GEM_TRACE("%s: ring:{HEAD:%04x, TAIL:%04x}\n", - engine->name, ring->head, ring->tail); + ENGINE_TRACE(engine, "ring:{HEAD:%04x, TAIL:%04x}\n", + ring->head, ring->tail); intel_uncore_forcewake_get(engine->uncore, FORCEWAKE_ALL); @@ -746,10 +746,10 @@ static void reset_prepare(struct intel_engine_cs *engine) * * FIXME: Wa for more modern gens needs to be validated */ - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); if (intel_engine_stop_cs(engine)) - GEM_TRACE("%s: timed out on STOP_RING\n", engine->name); + ENGINE_TRACE(engine, "timed out on STOP_RING\n"); intel_uncore_write_fw(uncore, RING_HEAD(base), @@ -765,9 +765,8 @@ static void reset_prepare(struct intel_engine_cs *engine) /* Check acts as a post */ if (intel_uncore_read_fw(uncore, RING_HEAD(base))) - GEM_TRACE("%s: ring head [%x] not parked\n", - engine->name, - intel_uncore_read_fw(uncore, RING_HEAD(base))); + ENGINE_TRACE(engine, "ring head [%x] not parked\n", + intel_uncore_read_fw(uncore, RING_HEAD(base))); } static void reset_ring(struct intel_engine_cs *engine, bool stalled) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 172220e83079..af04ed6e48d9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -375,7 +375,7 @@ static void guc_reset_prepare(struct intel_engine_cs *engine) { struct intel_engine_execlists * const execlists = &engine->execlists; - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); /* * Prevent request submission to the hardware until we have @@ -434,7 +434,7 @@ static void guc_cancel_requests(struct intel_engine_cs *engine) struct rb_node *rb; unsigned long flags; - GEM_TRACE("%s\n", engine->name); + ENGINE_TRACE(engine, "\n"); /* * Before we call engine->cancel_requests(), we should have exclusive @@ -495,8 +495,8 @@ static void guc_reset_finish(struct intel_engine_cs *engine) /* And kick in case we missed a new request submission. */ tasklet_hi_schedule(&execlists->tasklet); - GEM_TRACE("%s: depth->%d\n", engine->name, - atomic_read(&execlists->tasklet.count)); + ENGINE_TRACE(engine, "depth->%d\n", + atomic_read(&execlists->tasklet.count)); } /* diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 51bb8a0812a1..c6d59d263550 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -223,10 +223,7 @@ bool i915_request_retire(struct i915_request *rq) if (!i915_request_completed(rq)) return false; - GEM_TRACE("%s fence %llx:%lld, current %d\n", - rq->engine->name, - rq->fence.context, rq->fence.seqno, - hwsp_seqno(rq)); + RQ_TRACE(rq, "\n"); GEM_BUG_ON(!i915_sw_fence_signaled(&rq->submit)); trace_i915_request_retire(rq); @@ -287,10 +284,7 @@ void i915_request_retire_upto(struct i915_request *rq) struct intel_timeline * const tl = i915_request_timeline(rq); struct i915_request *tmp; - GEM_TRACE("%s fence %llx:%lld, current %d\n", - rq->engine->name, - rq->fence.context, rq->fence.seqno, - hwsp_seqno(rq)); + RQ_TRACE(rq, "\n"); GEM_BUG_ON(!i915_request_completed(rq)); @@ -351,10 +345,7 @@ bool __i915_request_submit(struct i915_request *request) struct intel_engine_cs *engine = request->engine; bool result = false; - GEM_TRACE("%s fence %llx:%lld, current %d\n", - engine->name, - request->fence.context, request->fence.seqno, - hwsp_seqno(request)); + RQ_TRACE(request, "\n"); GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->active.lock); @@ -443,10 +434,7 @@ void __i915_request_unsubmit(struct i915_request *request) { struct intel_engine_cs *engine = request->engine; - GEM_TRACE("%s fence %llx:%lld, current %d\n", - engine->name, - request->fence.context, request->fence.seqno, - hwsp_seqno(request)); + RQ_TRACE(request, "\n"); GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->active.lock); @@ -1261,8 +1249,7 @@ struct i915_request *__i915_request_commit(struct i915_request *rq) struct intel_ring *ring = rq->ring; u32 *cs; - GEM_TRACE("%s fence %llx:%lld\n", - engine->name, rq->fence.context, rq->fence.seqno); + RQ_TRACE(rq, "\n"); /* * To ensure that this call will not fail, space for its emissions diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 96991d64759c..a561b8efe869 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -49,6 +49,13 @@ struct i915_capture_list { struct i915_vma *vma; }; +#define RQ_TRACE(rq, fmt, ...) do { \ + const struct i915_request *rq__ = (rq); \ + ENGINE_TRACE(rq__->engine, "fence %llx:%lld, current %d" fmt, \ + rq__->fence.context, rq__->fence.seqno, \ + hwsp_seqno(rq__), ##__VA_ARGS__); \ +} while (0) + enum { /* * I915_FENCE_FLAG_ACTIVE - this request is currently submitted to HW. -- cgit v1.2.3 From f1925f3309d13d431f70e7b6b72ba59cae90fdff Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 13 Dec 2019 16:03:47 +0000 Subject: drm/i915: Use EAGAIN for trylock failures While not good behaviour, it is, however, established behaviour that we can punt EAGAIN to userspace if we need to retry the ioctl. When trying to acquire a mutex, prefer to use EAGAIN to propagate losing the race so that if it does end up back in userspace, we try again. Fixes: c81471f5e95c ("drm/i915: Copy across scheduler behaviour flags across submit fences") Closes: https://gitlab.freedesktop.org/drm/intel/issues/800 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191213160347.1789004-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_timeline.c | 2 +- drivers/gpu/drm/i915/i915_request.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 038e05a6336c..d71aafb66d6e 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -527,7 +527,7 @@ int intel_timeline_read_hwsp(struct i915_request *from, GEM_BUG_ON(rcu_access_pointer(to->timeline) == tl); - err = -EBUSY; + err = -EAGAIN; if (mutex_trylock(&tl->mutex)) { struct intel_timeline_cacheline *cl = from->hwsp_cacheline; diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index c6d59d263550..af2f78e040d7 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -771,7 +771,7 @@ i915_request_await_start(struct i915_request *rq, struct i915_request *signal) if (!tl) /* already started or maybe even completed */ return 0; - fence = ERR_PTR(-EBUSY); + fence = ERR_PTR(-EAGAIN); if (mutex_trylock(&tl->mutex)) { fence = NULL; if (!i915_request_started(signal) && -- cgit v1.2.3 From e03512edd2b8d01fe9d34b8c66cc21933e4a68f6 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Fri, 13 Dec 2019 20:37:35 +0200 Subject: drm/i915/rps: Add frequency translation helpers Add two helpers that for reading the actual GT's frequency. The two helpers are: - intel_rps_read_cagf: reads the frequency and returns it not normalized - intel_rps_read_actual_frequency: provides the frequency in Hz. Use the above helpers in sysfs and debugfs. Signed-off-by: Andi Shyti Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191213183736.31992-2-andi@etezian.org --- drivers/gpu/drm/i915/gt/intel_rps.c | 36 +++++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/gt/intel_rps.h | 3 ++- drivers/gpu/drm/i915/i915_debugfs.c | 19 ++----------------- drivers/gpu/drm/i915/i915_pmu.c | 2 +- drivers/gpu/drm/i915/i915_sysfs.c | 31 ++++++++----------------------- 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 106c9fce9d6c..5f5a000c801d 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1667,19 +1667,49 @@ void intel_rps_init(struct intel_rps *rps) rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; } -u32 intel_get_cagf(struct intel_rps *rps, u32 rpstat) +u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat) { struct drm_i915_private *i915 = rps_to_i915(rps); u32 cagf; - if (INTEL_GEN(i915) >= 9) + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + cagf = (rpstat >> 8) & 0xff; + else if (INTEL_GEN(i915) >= 9) cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; else cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; - return cagf; + return cagf; +} + +static u32 read_cagf(struct intel_rps *rps) +{ + struct drm_i915_private *i915 = rps_to_i915(rps); + u32 freq; + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + vlv_punit_get(i915); + freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + vlv_punit_put(i915); + } else { + freq = intel_uncore_read(rps_to_gt(rps)->uncore, GEN6_RPSTAT1); + } + + return intel_rps_get_cagf(rps, freq); +} + +u32 intel_rps_read_actual_frequency(struct intel_rps *rps) +{ + struct intel_runtime_pm *rpm = rps_to_gt(rps)->uncore->rpm; + intel_wakeref_t wakeref; + u32 freq = 0; + + with_intel_runtime_pm_if_in_use(rpm, wakeref) + freq = intel_gpu_freq(rps, read_cagf(rps)); + + return freq; } /* External interface for intel_ips.ko */ diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index 9518c66c9792..dfa98194f3b2 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -29,7 +29,8 @@ void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive); int intel_gpu_freq(struct intel_rps *rps, int val); int intel_freq_opcode(struct intel_rps *rps, int val); -u32 intel_get_cagf(struct intel_rps *rps, u32 rpstat1); +u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1); +u32 intel_rps_read_actual_frequency(struct intel_rps *rps); void gen5_rps_irq_handler(struct intel_rps *rps); void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9cd5ce5bc93b..d28468eaed57 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -881,7 +881,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK; rpcurdown = I915_READ(GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK; rpprevdown = I915_READ(GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK; - cagf = intel_gpu_freq(rps, intel_get_cagf(rps, rpstat)); + cagf = intel_rps_read_actual_frequency(rps); intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); @@ -1623,21 +1623,6 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_rps *rps = &dev_priv->gt.rps; - u32 act_freq = rps->cur_freq; - intel_wakeref_t wakeref; - - with_intel_runtime_pm_if_in_use(&dev_priv->runtime_pm, wakeref) { - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - vlv_punit_get(dev_priv); - act_freq = vlv_punit_read(dev_priv, - PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(dev_priv); - act_freq = (act_freq >> 8) & 0xff; - } else { - act_freq = intel_get_cagf(rps, - I915_READ(GEN6_RPSTAT1)); - } - } seq_printf(m, "RPS enabled? %d\n", rps->enabled); seq_printf(m, "GPU busy? %s\n", yesno(dev_priv->gt.awake)); @@ -1646,7 +1631,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) seq_printf(m, "Interactive? %d\n", READ_ONCE(rps->power.interactive)); seq_printf(m, "Frequency requested %d, actual %d\n", intel_gpu_freq(rps, rps->cur_freq), - intel_gpu_freq(rps, act_freq)); + intel_rps_read_actual_frequency(rps)); seq_printf(m, " min hard:%d, soft:%d; max soft:%d, hard:%d\n", intel_gpu_freq(rps, rps->min_freq), intel_gpu_freq(rps, rps->min_freq_softlimit), diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index eaad9c97d031..5f2adfbf85be 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -406,7 +406,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns) */ val = intel_uncore_read_fw(uncore, GEN6_RPSTAT1); if (val) - val = intel_get_cagf(rps, val); + val = intel_rps_get_cagf(rps, val); else val = rps->cur_freq; diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 65476909d1bf..ad2b1b833d7b 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -259,33 +259,18 @@ static const struct bin_attribute dpf_attrs_1 = { static ssize_t gt_act_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &dev_priv->gt.rps; - intel_wakeref_t wakeref; - u32 freq; - - wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - vlv_punit_get(dev_priv); - freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); - vlv_punit_put(dev_priv); - - freq = (freq >> 8) & 0xff; - } else { - freq = intel_get_cagf(rps, I915_READ(GEN6_RPSTAT1)); - } - - intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); + struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); + struct intel_rps *rps = &i915->gt.rps; - return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(rps, freq)); + return snprintf(buf, PAGE_SIZE, "%d\n", + intel_rps_read_actual_frequency(rps)); } static ssize_t gt_cur_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &dev_priv->gt.rps; + struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); + struct intel_rps *rps = &i915->gt.rps; return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(rps, rps->cur_freq)); @@ -293,8 +278,8 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev, static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &dev_priv->gt.rps; + struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); + struct intel_rps *rps = &i915->gt.rps; return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(rps, rps->boost_freq)); -- cgit v1.2.3 From f9b3b8c6be47d0df31528fa2de6cf6265570a6d8 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 6 Dec 2019 11:05:52 -0800 Subject: drm/i915/bios: remove extra debug messages Just like in commit 523e0cc89b83 ("drm/i915/tgl: allow DVI/HDMI on port A"), the port checks when reading the VBT can easily not match what the platform really exposes. However here we only have some additional debug messages that are not adding much value: in the previous debug message we already print everything we know about the VBT. Instead of keep fixing the possible port assignments according to the platform, just nuke the additional messages. Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191206190552.8818-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 54c02debeddf..8beac06e3f10 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1657,22 +1657,6 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, info->supports_typec_usb, info->supports_tbt, devdata->dsc != NULL); - if (is_edp && is_dvi) - DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n", - port_name(port)); - if (is_crt && port != PORT_E) - DRM_DEBUG_KMS("Port %c is analog\n", port_name(port)); - if (is_crt && (is_dvi || is_dp)) - DRM_DEBUG_KMS("Analog port %c is also DP or TMDS compatible\n", - port_name(port)); - if (is_dvi && (port == PORT_A || port == PORT_E)) - DRM_DEBUG_KMS("Port %c is TMDS compatible\n", port_name(port)); - if (!is_dvi && !is_dp && !is_crt) - DRM_DEBUG_KMS("Port %c is not DP/TMDS/CRT compatible\n", - port_name(port)); - if (is_edp && (port == PORT_B || port == PORT_C || port == PORT_E)) - DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); - if (is_dvi) { u8 ddc_pin; -- cgit v1.2.3 From 9c569784a422e9eaa1c6f61e46a41011391e4d1d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 11 Dec 2019 13:08:44 +0200 Subject: drm/i915/dsi: fix pipe D readout for DSI transcoders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 4d89adc7b56f ("drm/i915/display/dsi: Add support to pipe D") added pipe D support for DSI, but failed to update the state readout. Fixes: 4d89adc7b56f ("drm/i915/display/dsi: Add support to pipe D") Cc: Lucas De Marchi Cc: José Roberto de Souza Cc: Vandita Kulkarni Signed-off-by: Jani Nikula Reviewed-by: José Roberto de Souza Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20191211110844.2996-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b995094dafe1..8b69a7947cbe 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10427,6 +10427,9 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, case TRANS_DDI_EDP_INPUT_C_ONOFF: trans_pipe = PIPE_C; break; + case TRANS_DDI_EDP_INPUT_D_ONOFF: + trans_pipe = PIPE_D; + break; } if (trans_pipe == crtc->pipe) { -- cgit v1.2.3 From 7a90f89904afe66ff029bd784679aa293baacb72 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 13 Dec 2019 22:31:40 +0000 Subject: drm/i915/gem: Serialise object before changing cache-level Wait for the object to be idle before changing its cache-level and unbinding. This was dropped as supposedly superfluous from commit 8b1c78e06e61 ("drm/i915: Avoid calling i915_gem_object_unbind holding object lock"), but it turns out to prevent some cache dirt escaping. Smells like papering over a race... Closes: https://gitlab.freedesktop.org/drm/intel/issues/820 Fixes: 8b1c78e06e61 ("drm/i915: Avoid calling i915_gem_object_unbind holding object lock") Signed-off-by: Chris Wilson Cc: Andi Shyti Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191213223140.1830738-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 88ab7e71f36c..65f1851e2863 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -190,6 +190,13 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, if (obj->cache_level == cache_level) return 0; + ret = i915_gem_object_wait(obj, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_ALL, + MAX_SCHEDULE_TIMEOUT); + if (ret) + return ret; + ret = i915_gem_object_lock_interruptible(obj); if (ret) return ret; -- cgit v1.2.3 From 6fb0a14fac871af24829f307ba0ab082726e40b8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Dec 2019 21:48:28 +0100 Subject: drm/i915: opregion: set opregion chpd value to indicate the driver handles hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to both the old acpi_igd_opregion_spec_0.pdf and the newer skl_opregion_rev0p5.pdf opregion specification documents, if a driver handles hotplug events itself, it should set the opregion CHPD field to 1 to indicate this and the firmware should respond to this by no longer sending ACPI 0x00 notification events on e.g. lid-state changes. Specifically skl_opregion_rev0p5.pdf states thid in the documentation of the CHPD word: "Re-enumeration trigger logic in System BIOS MUST be disabled for all the Operating Systems supporting Hot-Plug (e.g., Windows* Longhorn and above)." Note the MUST in there. We ignore these notifications, so this should not be a problem but many recent DSTDs seem to all have the same copy-pasted bug in the GNOT() AML function which is used to send these notifications. Windows likely does not hit this bug as it presumably correcty sets CHPD to 1. Here is an example of the broken GNOT() method: Method (GNOT, 2, NotSerialized) { ... CEVT = Arg0 CSTS = 0x03 If (((CHPD == Zero) && (Arg1 == Zero))) { If (((OSYS > 0x07D0) || (OSYS < 0x07D6))) { Notify (PCI0, Arg1) } Else { Notify (GFX0, Arg1) } } ... Notice that the condition for the If is always true I believe that the || like needs to be an &&, but there is nothing we can do about this and in my own DSDT archive 55 of the 93 DSDTs have this issue. When the if is true the notification gets send to the PCI root instead of only to the GFX0 device. This causes Linux to re-enumerate PCI devices whenever the LID opens / closes, leading to unexpected messages in dmesg: Suspend through lid close: [ 313.598199] intel_atomisp2_pm 0000:00:03.0: Refused to change power state, currently in D3 [ 313.664453] intel_atomisp2_pm 0000:00:03.0: Refused to change power state, currently in D3 [ 313.737982] pci_bus 0000:01: Allocating resources [ 313.738036] pcieport 0000:00:1c.0: bridge window [io 0x1000-0x0fff] to [bus 01] add_size 1000 [ 313.738051] pcieport 0000:00:1c.0: bridge window [mem 0x00100000-0x000fffff 64bit pref] to [bus 01] add_size 200000 add_align 100000 [ 313.738111] pcieport 0000:00:1c.0: BAR 15: assigned [mem 0x91000000-0x911fffff 64bit pref] [ 313.738128] pcieport 0000:00:1c.0: BAR 13: assigned [io 0x1000-0x1fff] Resume: [ 813.623894] pci 0000:00:03.0: [8086:22b8] type 00 class 0x048000 [ 813.623955] pci 0000:00:03.0: reg 0x10: [mem 0x00000000-0x003fffff] [ 813.630477] pci 0000:00:03.0: BAR 0: assigned [mem 0x91c00000-0x91ffffff] [ 854.579101] intel_atomisp2_pm 0000:00:03.0: Refused to change power state, currently in D3 And more importantly this re-enumeration races with suspend/resume causing enumeration to not be complete when assert_isp_power_gated() from drivers/gpu/drm/i915/display/intel_display_power.c runs. This causes the !pci_dev_present(isp_ids) check in assert_isp_power_gated() to fail making the condition for the WARN true, leading to: [ 813.327886] ------------[ cut here ]------------ [ 813.327898] ISP not power gated [ 813.328028] WARNING: CPU: 2 PID: 2317 at drivers/gpu/drm/i915/display/intel_display_power.c:4870 intel_display_print_error_state+0x2b98/0x3a80 [i915] ... [ 813.328599] ---[ end trace f01e81b599596774 ]--- This commit fixes the unwanted ACPI notification on the PCI root device by setting CHPD to 1, so that the broken if condition in the AML never gets checked as notifications of type 0x00 are disabled altogether. Reviewed-by: Ville Syrjälä Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191212204828.191288-1-hdegoede@redhat.com --- drivers/gpu/drm/i915/display/intel_opregion.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index 969ade623691..e59b4992ba1b 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -941,6 +941,13 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) if (mboxes & MBOX_ACPI) { DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); opregion->acpi = base + OPREGION_ACPI_OFFSET; + /* + * Indicate we handle monitor hotplug events ourselves so we do + * not need ACPI notifications for them. Disabling these avoids + * triggering the AML code doing the notifation, which may be + * broken as Windows also seems to disable these. + */ + opregion->acpi->chpd = 1; } if (mboxes & MBOX_SWSCI) { -- cgit v1.2.3 From 4ba487019d1a196051feefab57f4a393815733b4 Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Mon, 16 Dec 2019 13:36:19 +0530 Subject: drm/i915: Fix WARN_ON condition for cursor plane ddb allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some cases like latency[level]==0, wm[level].res_lines>31, min_ddb_alloc can be U16_MAX, exclude it from the WARN_ON. v2: Specify the cases in which we hit U16_MAX, indentation (Ville) Fixes: 10a7e07b68b9 ("drm/i915: Make sure cursor has enough ddb for the selected wm level") Suggested-by: Ville Syrjälä Signed-off-by: Vandita Kulkarni Reviewed-by: Ville Syrjälä Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191216080619.10945-1-vandita.kulkarni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7aa5824b15d2..00f9f5187669 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4312,8 +4312,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state, &crtc_state->wm.skl.optimal.planes[plane_id]; if (plane_id == PLANE_CURSOR) { - if (WARN_ON(wm->wm[level].min_ddb_alloc > - total[PLANE_CURSOR])) { + if (wm->wm[level].min_ddb_alloc > total[PLANE_CURSOR]) { + WARN_ON(wm->wm[level].min_ddb_alloc != U16_MAX); blocks = U32_MAX; break; } -- cgit v1.2.3 From 8b4f2925cb1eaa704b39d7a5452290b1d8c3bdf1 Mon Sep 17 00:00:00 2001 From: zhengbin Date: Mon, 16 Dec 2019 11:44:05 +0800 Subject: drm/i915: Remove unneeded semicolon Fixes coccicheck warning: drivers/gpu/drm/i915/gem/i915_gem_region.c:88:2-3: Unneeded semicolon drivers/gpu/drm/i915/gvt/gtt.c:1285:2-3: Unneeded semicolon Reported-by: Hulk Robot Signed-off-by: zhengbin Acked-by: Zhenyu Wang Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/1576467845-60920-1-git-send-email-zhengbin13@huawei.com --- drivers/gpu/drm/i915/gem/i915_gem_region.c | 2 +- drivers/gpu/drm/i915/gvt/gtt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c index 2f7bcfb9c964..d50adac12249 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_region.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c @@ -85,7 +85,7 @@ i915_gem_object_get_pages_buddy(struct drm_i915_gem_object *obj) } prev_end = offset + block_size; - }; + } sg_page_sizes |= sg->length; sg_mark_end(sg); diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 4b04af569c05..34cb404ba4b7 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1282,7 +1282,7 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu, return -EINVAL; default: GEM_BUG_ON(1); - }; + } /* direct shadow */ ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn, page_size, -- cgit v1.2.3 From 884054403393a46ae88f24b0d76581278222f5ce Mon Sep 17 00:00:00 2001 From: Venkata Sandeep Dhanalakota Date: Mon, 16 Dec 2019 10:53:32 -0800 Subject: drm/i915: Fix typecheck macro in GT_TRACE typecheck() macro creates an huge stack size causing issues with static analysis with coverity, addressing this with creating a local pointer. Fixes: 639f2f24895f ("drm/i915: Introduce new macros for tracing") Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Daniel Vetter Cc: Chris Wilson Cc: Jani Nikula Signed-off-by: Venkata Sandeep Dhanalakota Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191216185332.83289-1-venkata.s.dhanalakota@intel.com --- drivers/gpu/drm/i915/gt/intel_gt.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index 9d9e8831daeb..2355cf129e9c 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -12,9 +12,9 @@ struct drm_i915_private; -#define GT_TRACE(gt__, fmt, ...) do { \ - typecheck(struct intel_gt, *(gt__)); \ - GEM_TRACE("%s " fmt, dev_name(gt->i915->drm.dev), \ +#define GT_TRACE(gt, fmt, ...) do { \ + const struct intel_gt *gt__ __maybe_unused = (gt); \ + GEM_TRACE("%s " fmt, dev_name(gt__->i915->drm.dev), \ ##__VA_ARGS__); \ } while (0) -- cgit v1.2.3 From 0a9a5532d2962a74004e041eeb2217de930f8c27 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Dec 2019 12:26:03 +0000 Subject: drm/i915/gem: Apply lmem size restriction to get_pages When creating a handle, it is just that, an abstract handle. The fact that we cannot currently support a handle larger than the size of the backing storage is an artifact of our whole-object-at-a-time handling in get_pages() and being an implementation limitation is best handled at that point -- similar to shmem, where we only barf when asked to populate the whole object if larger than RAM. (Pinning the whole object at a time is major hindrance that we are likely to have to overcome in the near future.) In the case of the buddy allocator, the late check is preferable as the request size may often be smaller than the required size. Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: Joonas Lahtinen Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191216122603.2598155-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_lmem.c | 3 --- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- drivers/gpu/drm/i915/intel_memory_region.c | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c index 0e2bf6b7e143..520cc9cac471 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c @@ -79,9 +79,6 @@ __i915_gem_lmem_object_create(struct intel_memory_region *mem, struct drm_i915_private *i915 = mem->i915; struct drm_i915_gem_object *obj; - if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size) - return ERR_PTR(-E2BIG); - obj = i915_gem_object_alloc(); if (!obj) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 3f992491f537..497c367a79ca 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1420,7 +1420,7 @@ try_again: err = i915_gem_object_pin_pages(obj); if (err) { - if (err == -ENXIO) { + if (err == -ENXIO || err == -E2BIG) { i915_gem_object_put(obj); size >>= 1; goto try_again; diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index baaeaecc64af..e24c280e5930 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -73,6 +73,9 @@ __intel_memory_region_get_pages_buddy(struct intel_memory_region *mem, min_order = ilog2(size) - ilog2(mem->mm.chunk_size); } + if (size > BIT(mem->mm.max_order) * mem->mm.chunk_size) + return -E2BIG; + n_pages = size >> ilog2(mem->mm.chunk_size); mutex_lock(&mem->mm_lock); -- cgit v1.2.3 From 902eb748e5c3d32ad955eef439e0911905758166 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Dec 2019 14:24:09 +0000 Subject: drm/i915/gt: Tidy up full-ppgtt on Ivybridge With a couple more memory barriers dotted around the place we can significantly reduce the MTBF on Ivybridge. Still doesn't really help Haswell though. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191216142409.2605211-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 110 +++++++++--------------- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 + 2 files changed, 43 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 30ba67c9abe9..00d1fb582e95 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -362,6 +362,12 @@ gen7_render_ring_flush(struct i915_request *rq, u32 mode) */ flags |= PIPE_CONTROL_CS_STALL; + /* + * CS_STALL suggests at least a post-sync write. + */ + flags |= PIPE_CONTROL_QW_WRITE; + flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; + /* Just flush everything. Experiments have shown that reducing the * number of bits based on the write domains has little performance * impact. @@ -380,13 +386,6 @@ gen7_render_ring_flush(struct i915_request *rq, u32 mode) flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; - /* - * TLB invalidate requires a post-sync write. - */ - flags |= PIPE_CONTROL_QW_WRITE; - flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; - - flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; /* Workaround: we must issue a pipe_control with CS-stall bit * set before a pipe_control command that has the state cache @@ -1371,50 +1370,26 @@ static int load_pd_dir(struct i915_request *rq, const struct intel_engine_cs * const engine = rq->engine; u32 *cs; - cs = intel_ring_begin(rq, 12); + cs = intel_ring_begin(rq, 10); if (IS_ERR(cs)) return PTR_ERR(cs); - *cs++ = MI_LOAD_REGISTER_IMM(1); + *cs++ = MI_LOAD_REGISTER_IMM(3); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine->mmio_base)); *cs++ = valid; - - *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; - *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine->mmio_base)); - *cs++ = intel_gt_scratch_offset(rq->engine->gt, - INTEL_GT_SCRATCH_FIELD_DEFAULT); - - *cs++ = MI_LOAD_REGISTER_IMM(1); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine->mmio_base)); *cs++ = px_base(ppgtt->pd)->ggtt_offset << 10; + *cs++ = i915_mmio_reg_offset(RING_INSTPM(engine->mmio_base)); + *cs++ = _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE); /* Stall until the page table load is complete? */ *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine->mmio_base)); - *cs++ = intel_gt_scratch_offset(rq->engine->gt, + *cs++ = intel_gt_scratch_offset(engine->gt, INTEL_GT_SCRATCH_FIELD_DEFAULT); intel_ring_advance(rq, cs); - return rq->engine->emit_flush(rq, EMIT_FLUSH); -} - -static int flush_tlb(struct i915_request *rq) -{ - const struct intel_engine_cs * const engine = rq->engine; - u32 *cs; - - cs = intel_ring_begin(rq, 4); - if (IS_ERR(cs)) - return PTR_ERR(cs); - - *cs++ = MI_LOAD_REGISTER_IMM(1); - *cs++ = i915_mmio_reg_offset(RING_INSTPM(engine->mmio_base)); - *cs++ = _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE); - - *cs++ = MI_NOOP; - intel_ring_advance(rq, cs); - return 0; } @@ -1590,52 +1565,49 @@ static int remap_l3(struct i915_request *rq) return 0; } -static int switch_context(struct i915_request *rq) +static int switch_mm(struct i915_request *rq, struct i915_address_space *vm) { - struct intel_context *ce = rq->hw_context; - struct i915_address_space *vm = vm_alias(ce); - u32 hw_flags = 0; int ret; - GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); + if (!vm) + return 0; - if (vm) { - /* - * Not only do we need a full barrier (post-sync write) after - * invalidating the TLBs, but we need to wait a little bit - * longer. Whether this is merely delaying us, or the - * subsequent flush is a key part of serialising with the - * post-sync op, this extra pass appears vital before a - * mm switch! - */ - ret = rq->engine->emit_flush(rq, EMIT_INVALIDATE); - if (ret) - return ret; + ret = rq->engine->emit_flush(rq, EMIT_FLUSH); + if (ret) + return ret; - ret = flush_tlb(rq); - if (ret) - return ret; + /* + * Not only do we need a full barrier (post-sync write) after + * invalidating the TLBs, but we need to wait a little bit + * longer. Whether this is merely delaying us, or the + * subsequent flush is a key part of serialising with the + * post-sync op, this extra pass appears vital before a + * mm switch! + */ + ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm), PP_DIR_DCLV_2G); + if (ret) + return ret; - ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm), 0); - if (ret) - return ret; + return rq->engine->emit_flush(rq, EMIT_FLUSH); +} - ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm), PP_DIR_DCLV_2G); - if (ret) - return ret; +static int switch_context(struct i915_request *rq) +{ + struct intel_context *ce = rq->hw_context; + int ret; - ret = flush_tlb(rq); - if (ret) - return ret; + GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); - ret = rq->engine->emit_flush(rq, EMIT_INVALIDATE); - if (ret) - return ret; - } + ret = switch_mm(rq, vm_alias(ce)); + if (ret) + return ret; if (ce->state) { + u32 hw_flags; + GEM_BUG_ON(rq->engine->id != RCS0); + hw_flags = 0; if (!test_bit(CONTEXT_VALID_BIT, &ce->flags)) hw_flags = MI_RESTORE_INHIBIT; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index be36719e7987..d9a2f58a620a 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1709,8 +1709,10 @@ static void gen6_flush_pd(struct gen6_ppgtt *ppgtt, u64 start, u64 end) gen6_for_each_pde(pt, pd, start, end, pde) gen6_write_pde(ppgtt, pde, pt); + mb(); ioread32(ppgtt->pd_addr + pde - 1); gen6_ggtt_invalidate(ppgtt->base.vm.gt->ggtt); + mb(); mutex_unlock(&ppgtt->flush); } -- cgit v1.2.3 From f8b7487734ceae5f593e7b50368f98bc3eb3d068 Mon Sep 17 00:00:00 2001 From: Maya Rashish Date: Fri, 13 Dec 2019 10:26:30 +0000 Subject: Correct function name in comment Signed-off-by: Maya Rashish Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191213102630.GA24082@SDF.ORG --- drivers/gpu/drm/i915/i915_cmd_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 7fcdcf31dc76..a0e437aa65b7 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -235,7 +235,7 @@ static const struct drm_i915_cmd_descriptor gen7_common_cmds[] = { /* * MI_BATCH_BUFFER_START requires some special handling. It's not * really a 'skip' action but it doesn't seem like it's worth adding - * a new action. See i915_parse_cmds(). + * a new action. See intel_engine_cmd_parser(). */ CMD( MI_BATCH_BUFFER_START, SMI, !F, 0xFF, S ), }; -- cgit v1.2.3 From 9ddc8ec027a39759c946c3f4944d3e0c5a007ccd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Dec 2019 16:53:17 +0000 Subject: drm/i915: Eliminate the trylock for awaiting an earlier request We currently use an error-prone mutex_trylock to grab another timeline to find an earlier request along it. However, with a bit of a sleight-of-hand, we can reduce the mutex_trylock to a spin_lock on the immediate request and careful pointer chasing to acquire a reference on the previous request. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191216165317.2742896-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_request.c | 39 ++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index af2f78e040d7..a59b803aef92 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -756,34 +756,37 @@ err_unlock: static int i915_request_await_start(struct i915_request *rq, struct i915_request *signal) { - struct intel_timeline *tl; struct dma_fence *fence; int err; GEM_BUG_ON(i915_request_timeline(rq) == rcu_access_pointer(signal->timeline)); + fence = NULL; rcu_read_lock(); - tl = rcu_dereference(signal->timeline); - if (i915_request_started(signal) || !kref_get_unless_zero(&tl->kref)) - tl = NULL; - rcu_read_unlock(); - if (!tl) /* already started or maybe even completed */ - return 0; + spin_lock_irq(&signal->lock); + if (!i915_request_started(signal) && + !list_is_first(&signal->link, + &rcu_dereference(signal->timeline)->requests)) { + struct i915_request *prev = list_prev_entry(signal, link); - fence = ERR_PTR(-EAGAIN); - if (mutex_trylock(&tl->mutex)) { - fence = NULL; - if (!i915_request_started(signal) && - !list_is_first(&signal->link, &tl->requests)) { - signal = list_prev_entry(signal, link); - fence = dma_fence_get(&signal->fence); + /* + * Peek at the request before us in the timeline. That + * request will only be valid before it is retired, so + * after acquiring a reference to it, confirm that it is + * still part of the signaler's timeline. + */ + if (i915_request_get_rcu(prev)) { + if (list_next_entry(prev, link) == signal) + fence = &prev->fence; + else + i915_request_put(prev); } - mutex_unlock(&tl->mutex); } - intel_timeline_put(tl); - if (IS_ERR_OR_NULL(fence)) - return PTR_ERR_OR_ZERO(fence); + spin_unlock_irq(&signal->lock); + rcu_read_unlock(); + if (!fence) + return 0; err = 0; if (intel_timeline_sync_is_later(i915_request_timeline(rq), fence)) -- cgit v1.2.3 From 796ef2eff3cc4b4e032761710ddd8aa510e5cf3b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 17 Dec 2019 09:13:28 +0000 Subject: drm/i915/gt: Avoid multi-LRI on Sandybridge Sandybridge is the gen that didn't handle multiple registers in a single LRI packet. Don't forget it! Fixes: 902eb748e5c3 ("drm/i915/gt: Tidy up full-ppgtt on Ivybridge") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Tested-by: Tomi Sarvela Acked-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20191217091328.3093551-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 00d1fb582e95..b14d69d60e00 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1370,17 +1370,17 @@ static int load_pd_dir(struct i915_request *rq, const struct intel_engine_cs * const engine = rq->engine; u32 *cs; - cs = intel_ring_begin(rq, 10); + cs = intel_ring_begin(rq, 12); if (IS_ERR(cs)) return PTR_ERR(cs); - *cs++ = MI_LOAD_REGISTER_IMM(3); + *cs++ = MI_LOAD_REGISTER_IMM(1); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_DCLV(engine->mmio_base)); *cs++ = valid; + + *cs++ = MI_LOAD_REGISTER_IMM(1); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine->mmio_base)); *cs++ = px_base(ppgtt->pd)->ggtt_offset << 10; - *cs++ = i915_mmio_reg_offset(RING_INSTPM(engine->mmio_base)); - *cs++ = _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE); /* Stall until the page table load is complete? */ *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; @@ -1388,6 +1388,10 @@ static int load_pd_dir(struct i915_request *rq, *cs++ = intel_gt_scratch_offset(engine->gt, INTEL_GT_SCRATCH_FIELD_DEFAULT); + *cs++ = MI_LOAD_REGISTER_IMM(1); + *cs++ = i915_mmio_reg_offset(RING_INSTPM(engine->mmio_base)); + *cs++ = _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE); + intel_ring_advance(rq, cs); return 0; -- cgit v1.2.3 From b2147a3a4fc6ddbff7f72984837b4137d088793b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Dec 2019 21:29:04 +0100 Subject: ACPI / LPSS: Rename pwm_backlight pwm-lookup to pwm_soc_backlight At least Bay Trail (BYT) and Cherry Trail (CHT) devices can use 1 of 2 different PWM controllers for controlling the LCD's backlight brightness. Either the one integrated into the PMIC or the one integrated into the SoC (the 1st LPSS PWM controller). So far in the LPSS code on BYT we have skipped registering the LPSS PWM controller "pwm_backlight" lookup entry when a Crystal Cove PMIC is present, assuming that in this case the PMIC PWM controller will be used. On CHT we have been relying on only 1 of the 2 PWM controllers being enabled in the DSDT at the same time; and always registered the lookup. So far this has been working, but the correct way to determine which PWM controller needs to be used is by checking a bit in the VBT table and recently I've learned about 2 different BYT devices: Point of View MOBII TAB-P800W Acer Switch 10 SW5-012 Which use a Crystal Cove PMIC, yet the LCD is connected to the SoC/LPSS PWM controller (and the VBT correctly indicates this), so here our old heuristics fail. Since only the i915 driver has access to the VBT, this commit renames the "pwm_backlight" lookup entries for the 1st BYT/CHT LPSS PWM controller to "pwm_soc_backlight" so that the i915 driver can do a pwm_get() for the right controller depending on the VBT bit, instead of the i915 driver relying on a "pwm_backlight" lookup getting registered which magically points to the right controller. Acked-by: Jani Nikula Reviewed-by: Andy Shevchenko Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191216202906.1662893-2-hdegoede@redhat.com --- drivers/acpi/acpi_lpss.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 70f740b09684..db18df6cb330 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -69,10 +69,6 @@ ACPI_MODULE_NAME("acpi_lpss"); #define LPSS_SAVE_CTX BIT(4) #define LPSS_NO_D3_DELAY BIT(5) -/* Crystal Cove PMIC shares same ACPI ID between different platforms */ -#define BYT_CRC_HRV 2 -#define CHT_CRC_HRV 3 - struct lpss_private_data; struct lpss_device_desc { @@ -158,7 +154,7 @@ static void lpss_deassert_reset(struct lpss_private_data *pdata) */ static struct pwm_lookup byt_pwm_lookup[] = { PWM_LOOKUP_WITH_MODULE("80860F09:00", 0, "0000:00:02.0", - "pwm_backlight", 0, PWM_POLARITY_NORMAL, + "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, "pwm-lpss-platform"), }; @@ -170,8 +166,7 @@ static void byt_pwm_setup(struct lpss_private_data *pdata) if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1")) return; - if (!acpi_dev_present("INT33FD", NULL, BYT_CRC_HRV)) - pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup)); + pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup)); } #define LPSS_I2C_ENABLE 0x6c @@ -204,7 +199,7 @@ static void byt_i2c_setup(struct lpss_private_data *pdata) /* BSW PWM used for backlight control by the i915 driver */ static struct pwm_lookup bsw_pwm_lookup[] = { PWM_LOOKUP_WITH_MODULE("80862288:00", 0, "0000:00:02.0", - "pwm_backlight", 0, PWM_POLARITY_NORMAL, + "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, "pwm-lpss-platform"), }; -- cgit v1.2.3 From 2f093958397b14bd4e1ed82ccd8a1bbacc1691d0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Dec 2019 21:29:05 +0100 Subject: mfd: intel_soc_pmic: Rename pwm_backlight pwm-lookup to pwm_pmic_backlight At least Bay Trail (BYT) and Cherry Trail (CHT) devices can use 1 of 2 different PWM controllers for controlling the LCD's backlight brightness. Either the one integrated into the PMIC or the one integrated into the SoC (the 1st LPSS PWM controller). So far in the LPSS code on BYT we have skipped registering the LPSS PWM controller "pwm_backlight" lookup entry when a Crystal Cove PMIC is present, assuming that in this case the PMIC PWM controller will be used. On CHT we have been relying on only 1 of the 2 PWM controllers being enabled in the DSDT at the same time; and always registered the lookup. So far this has been working, but the correct way to determine which PWM controller needs to be used is by checking a bit in the VBT table and recently I've learned about 2 different BYT devices: Point of View MOBII TAB-P800W Acer Switch 10 SW5-012 Which use a Crystal Cove PMIC, yet the LCD is connected to the SoC/LPSS PWM controller (and the VBT correctly indicates this), so here our old heuristics fail. Since only the i915 driver has access to the VBT, this commit renames the "pwm_backlight" lookup entries for the Crystal Cove PMIC's PWM controller to "pwm_pmic_backlight" so that the i915 driver can do a pwm_get() for the right controller depending on the VBT bit, instead of the i915 driver relying on a "pwm_backlight" lookup getting registered which magically points to the right controller. Acked-by: Jani Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Acked-by: Lee Jones Link: https://patchwork.freedesktop.org/patch/msgid/20191216202906.1662893-3-hdegoede@redhat.com --- drivers/mfd/intel_soc_pmic_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c index c9f35378d391..47188df3080d 100644 --- a/drivers/mfd/intel_soc_pmic_core.c +++ b/drivers/mfd/intel_soc_pmic_core.c @@ -38,7 +38,7 @@ static struct gpiod_lookup_table panel_gpio_table = { /* PWM consumed by the Intel GFX */ static struct pwm_lookup crc_pwm_lookup[] = { - PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_backlight", 0, PWM_POLARITY_NORMAL), + PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_pmic_backlight", 0, PWM_POLARITY_NORMAL), }; static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, -- cgit v1.2.3 From b69413110207058b915c85834339c04b1557e92b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 16 Dec 2019 21:29:06 +0100 Subject: drm/i915: DSI: select correct PWM controller to use based on the VBT At least Bay Trail (BYT) and Cherry Trail (CHT) devices can use 1 of 2 different PWM controllers for controlling the LCD's backlight brightness. Either the one integrated into the PMIC or the one integrated into the SoC (the 1st LPSS PWM controller). So far in the LPSS code on BYT we have skipped registering the LPSS PWM controller "pwm_backlight" lookup entry when a Crystal Cove PMIC is present, assuming that in this case the PMIC PWM controller will be used. On CHT we have been relying on only 1 of the 2 PWM controllers being enabled in the DSDT at the same time; and always registered the lookup. So far this has been working, but the correct way to determine which PWM controller needs to be used is by checking a bit in the VBT table and recently I've learned about 2 different BYT devices: Point of View MOBII TAB-P800W Acer Switch 10 SW5-012 Which use a Crystal Cove PMIC, yet the LCD is connected to the SoC/LPSS PWM controller (and the VBT correctly indicates this), so here our old heuristics fail. This commit fixes using the wrong PWM controller on these devices by calling pwm_get() for the right PWM controller based on the VBT dsi.config.pwm_blc bit. Note this is part of a series which contains 2 other patches which renames the PWM lookup for the 1st SoC/LPSS PWM from "pwm_backlight" to "pwm_pmic_backlight" and the PWM lookup for the Crystal Cove PMIC PWM from "pwm_backlight" to "pwm_pmic_backlight". Acked-by: Jani Nikula Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191216202906.1662893-4-hdegoede@redhat.com --- drivers/gpu/drm/i915/display/intel_panel.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 6f3eaae3761f..7b3ec6eb3382 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -1840,13 +1840,22 @@ static int pwm_setup_backlight(struct intel_connector *connector, enum pipe pipe) { struct drm_device *dev = connector->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_panel *panel = &connector->panel; + const char *desc; int retval; - /* Get the PWM chip for backlight control */ - panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight"); + /* Get the right PWM chip for DSI backlight according to VBT */ + if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { + panel->backlight.pwm = pwm_get(dev->dev, "pwm_pmic_backlight"); + desc = "PMIC"; + } else { + panel->backlight.pwm = pwm_get(dev->dev, "pwm_soc_backlight"); + desc = "SoC"; + } + if (IS_ERR(panel->backlight.pwm)) { - DRM_ERROR("Failed to own the pwm chip\n"); + DRM_ERROR("Failed to get the %s PWM chip\n", desc); panel->backlight.pwm = NULL; return -ENODEV; } @@ -1873,6 +1882,7 @@ static int pwm_setup_backlight(struct intel_connector *connector, CRC_PMIC_PWM_PERIOD_NS); panel->backlight.enabled = panel->backlight.level != 0; + DRM_INFO("Using %s PWM for LCD backlight control\n", desc); return 0; } -- cgit v1.2.3 From e14177f19739d74839eb496a27f5f5d958beaa5b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 17 Dec 2019 13:47:29 +0000 Subject: drm/i915/gem: Keep request alive while attaching fences Since commit e5dadff4b093 ("drm/i915: Protect request retirement with timeline->mutex"), the request retirement can happen outside of the struct_mutex serialised only by the timeline->mutex. We drop the timeline->mutex on submitting the request (i915_request_add) so after that point, it is liable to be freed. Make sure our local reference is kept alive until we have finished attaching it to the signalers. (Note that this erodes the argument that i915_request_add should consume the reference, but that is a slightly larger patch!) Fixes: e5dadff4b093 ("drm/i915: Protect request retirement with timeline->mutex") Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: Tvrtko Ursulin Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20191217134729.3297818-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 81eaf812c9da..7d07131aa3f7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2730,6 +2730,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, err = eb_submit(&eb); err_request: add_to_client(eb.request, file); + i915_request_get(eb.request); i915_request_add(eb.request); if (fences) @@ -2745,6 +2746,7 @@ err_request: fput(out_fence->file); } } + i915_request_put(eb.request); err_batch_unpin: if (eb.batch_flags & I915_DISPATCH_SECURE) -- cgit v1.2.3 From 85bedbf191e82aac0d7f05623bccfeccdcd91cea Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 17 Dec 2019 01:16:59 +0000 Subject: drm/i915/gt: Eliminate the trylock for reading a timeline's hwsp As we stash a pointer to the HWSP cacheline on the request, when reading it we only need confirm that the cacheline is still valid by checking that the request and timeline are still intact. v2: Protect hwsp_cachline with RCU Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191217011659.3092130-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_timeline.c | 64 ++++++++++---------------- drivers/gpu/drm/i915/gt/intel_timeline_types.h | 12 ++++- drivers/gpu/drm/i915/i915_request.c | 4 +- drivers/gpu/drm/i915/i915_request.h | 5 +- 4 files changed, 39 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index d71aafb66d6e..ee5dc4fbdeb9 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -15,6 +15,9 @@ #define ptr_set_bit(ptr, bit) ((typeof(ptr))((unsigned long)(ptr) | BIT(bit))) #define ptr_test_bit(ptr, bit) ((unsigned long)(ptr) & BIT(bit)) +#define CACHELINE_BITS 6 +#define CACHELINE_FREE CACHELINE_BITS + struct intel_timeline_hwsp { struct intel_gt *gt; struct intel_gt_timelines *gt_timelines; @@ -23,14 +26,6 @@ struct intel_timeline_hwsp { u64 free_bitmap; }; -struct intel_timeline_cacheline { - struct i915_active active; - struct intel_timeline_hwsp *hwsp; - void *vaddr; -#define CACHELINE_BITS 6 -#define CACHELINE_FREE CACHELINE_BITS -}; - static struct i915_vma *__hwsp_alloc(struct intel_gt *gt) { struct drm_i915_private *i915 = gt->i915; @@ -133,7 +128,7 @@ static void __idle_cacheline_free(struct intel_timeline_cacheline *cl) __idle_hwsp_free(cl->hwsp, ptr_unmask_bits(cl->vaddr, CACHELINE_BITS)); i915_active_fini(&cl->active); - kfree(cl); + kfree_rcu(cl, rcu); } __i915_active_call @@ -514,46 +509,35 @@ int intel_timeline_read_hwsp(struct i915_request *from, struct i915_request *to, u32 *hwsp) { - struct intel_timeline *tl; + struct intel_timeline_cacheline *cl; int err; + GEM_BUG_ON(!rcu_access_pointer(from->hwsp_cacheline)); + rcu_read_lock(); - tl = rcu_dereference(from->timeline); - if (i915_request_completed(from) || !kref_get_unless_zero(&tl->kref)) - tl = NULL; + cl = rcu_dereference(from->hwsp_cacheline); + if (unlikely(!i915_active_acquire_if_busy(&cl->active))) + goto unlock; /* seqno wrapped and completed! */ + if (unlikely(i915_request_completed(from))) + goto release; rcu_read_unlock(); - if (!tl) /* already completed */ - return 1; - GEM_BUG_ON(rcu_access_pointer(to->timeline) == tl); - - err = -EAGAIN; - if (mutex_trylock(&tl->mutex)) { - struct intel_timeline_cacheline *cl = from->hwsp_cacheline; - - if (i915_request_completed(from)) { - err = 1; - goto unlock; - } + err = cacheline_ref(cl, to); + if (err) + goto out; - err = cacheline_ref(cl, to); - if (err) - goto unlock; + *hwsp = i915_ggtt_offset(cl->hwsp->vma) + + ptr_unmask_bits(cl->vaddr, CACHELINE_BITS) * CACHELINE_BYTES; - if (likely(cl == tl->hwsp_cacheline)) { - *hwsp = tl->hwsp_offset; - } else { /* across a seqno wrap, recover the original offset */ - *hwsp = i915_ggtt_offset(cl->hwsp->vma) + - ptr_unmask_bits(cl->vaddr, CACHELINE_BITS) * - CACHELINE_BYTES; - } +out: + i915_active_release(&cl->active); + return err; +release: + i915_active_release(&cl->active); unlock: - mutex_unlock(&tl->mutex); - } - intel_timeline_put(tl); - - return err; + rcu_read_unlock(); + return 1; } void intel_timeline_unpin(struct intel_timeline *tl) diff --git a/drivers/gpu/drm/i915/gt/intel_timeline_types.h b/drivers/gpu/drm/i915/gt/intel_timeline_types.h index aaf15cbe1ce1..24d040f14e89 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline_types.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline_types.h @@ -10,14 +10,15 @@ #include #include #include +#include #include #include "i915_active_types.h" struct drm_i915_private; struct i915_vma; -struct intel_timeline_cacheline; struct i915_syncmap; +struct intel_timeline_hwsp; struct intel_timeline { u64 fence_context; @@ -87,4 +88,13 @@ struct intel_timeline { struct rcu_head rcu; }; +struct intel_timeline_cacheline { + struct i915_active active; + + struct intel_timeline_hwsp *hwsp; + void *vaddr; + + struct rcu_head rcu; +}; + #endif /* __I915_TIMELINE_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index a59b803aef92..269470d3527a 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -655,9 +655,9 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp) rq->execution_mask = ce->engine->mask; rq->flags = 0; - rcu_assign_pointer(rq->timeline, tl); + RCU_INIT_POINTER(rq->timeline, tl); + RCU_INIT_POINTER(rq->hwsp_cacheline, tl->hwsp_cacheline); rq->hwsp_seqno = tl->hwsp_seqno; - rq->hwsp_cacheline = tl->hwsp_cacheline; rq->rcustate = get_state_synchronize_rcu(); /* acts as smp_mb() */ diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index a561b8efe869..aa38290eea3d 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -30,6 +30,7 @@ #include "gt/intel_context_types.h" #include "gt/intel_engine_types.h" +#include "gt/intel_timeline_types.h" #include "i915_gem.h" #include "i915_scheduler.h" @@ -41,8 +42,6 @@ struct drm_file; struct drm_i915_gem_object; struct i915_request; -struct intel_timeline; -struct intel_timeline_cacheline; struct i915_capture_list { struct i915_capture_list *next; @@ -183,7 +182,7 @@ struct i915_request { * inside the timeline's HWSP vma, but it is only valid while this * request has not completed and guarded by the timeline mutex. */ - struct intel_timeline_cacheline *hwsp_cacheline; + struct intel_timeline_cacheline __rcu *hwsp_cacheline; /** Position in the ring of the start of the request */ u32 head; -- cgit v1.2.3 From ba16a48af797db124ac100417f9229b1650ce1fb Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 17 Dec 2019 17:09:33 +0000 Subject: drm/i915: Fix pid leak with banned clients Get_pid_task() needs to be paired with a put_pid or we leak a pid reference every time a banned client tries to create a context. v2: * task_pid_nr helper exists! (Chris) Signed-off-by: Tvrtko Ursulin Fixes: b083a0870c79 ("drm/i915: Add per client max context ban limit") Cc: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191217170933.8108-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 46b4d1d643f8..6618c0c6506c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -2194,8 +2194,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, ext_data.fpriv = file->driver_priv; if (client_is_banned(ext_data.fpriv)) { DRM_DEBUG("client %s[%d] banned from creating ctx\n", - current->comm, - pid_nr(get_task_pid(current, PIDTYPE_PID))); + current->comm, task_pid_nr(current)); return -EIO; } -- cgit v1.2.3 From e627ad50a2d787dcd8d1e7755a995ec31efa0e44 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 16 Dec 2019 17:23:10 -0800 Subject: drm/i915/guc: Merge communication_stop and communication_disable The only difference from the GuC POV between guc_communication_stop and guc_communication_disable is that the former can be called after GuC has been reset. Instead of having two separate paths, we can just skip the call into GuC in the disabling path and re-use that. Note that by using the disable() path instead of the stop() one there are two additional changes in SW side for the stop path: - interrupts are now disabled before disabling the CT, which is ok because we do not want interrupts with CT disabled; - guc_get_mmio_msg() is called in the stop case as well, which is ok because if there are errors before the reset we do want to record them. Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20191217012316.13271-1-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 14 ++++++++------ drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 5 ----- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 18 ++---------------- 3 files changed, 10 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 5fb7f957edf9..f74ba4750a94 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -241,12 +241,14 @@ static void ctch_disable(struct intel_guc *guc, ctch->enabled = false; - guc_action_deregister_ct_buffer(guc, - ctch->owner, - INTEL_GUC_CT_BUFFER_TYPE_SEND); - guc_action_deregister_ct_buffer(guc, - ctch->owner, - INTEL_GUC_CT_BUFFER_TYPE_RECV); + if (intel_guc_is_running(guc)) { + guc_action_deregister_ct_buffer(guc, + ctch->owner, + INTEL_GUC_CT_BUFFER_TYPE_SEND); + guc_action_deregister_ct_buffer(guc, + ctch->owner, + INTEL_GUC_CT_BUFFER_TYPE_RECV); + } } static u32 ctch_get_next_fence(struct intel_guc_ct_channel *ctch) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h index 7c24d83f5c24..77c80d6cc25d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h @@ -81,11 +81,6 @@ void intel_guc_ct_fini(struct intel_guc_ct *ct); int intel_guc_ct_enable(struct intel_guc_ct *ct); void intel_guc_ct_disable(struct intel_guc_ct *ct); -static inline void intel_guc_ct_stop(struct intel_guc_ct *ct) -{ - ct->host_channel.enabled = false; -} - int intel_guc_send_ct(struct intel_guc *guc, const u32 *action, u32 len, u32 *response_buf, u32 response_buf_size); void intel_guc_to_host_event_handler_ct(struct intel_guc *guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index f42952403c0b..6e17e449e0a8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -224,7 +224,7 @@ static int guc_enable_communication(struct intel_guc *guc) return 0; } -static void __guc_stop_communication(struct intel_guc *guc) +static void guc_disable_communication(struct intel_guc *guc) { /* * Events generated during or after CT disable are logged by guc in @@ -237,20 +237,6 @@ static void __guc_stop_communication(struct intel_guc *guc) guc->send = intel_guc_send_nop; guc->handler = intel_guc_to_host_event_handler_nop; -} - -static void guc_stop_communication(struct intel_guc *guc) -{ - intel_guc_ct_stop(&guc->ct); - - __guc_stop_communication(guc); - - DRM_INFO("GuC communication stopped\n"); -} - -static void guc_disable_communication(struct intel_guc *guc) -{ - __guc_stop_communication(guc); intel_guc_ct_disable(&guc->ct); @@ -556,7 +542,7 @@ void intel_uc_reset_prepare(struct intel_uc *uc) if (!intel_guc_is_running(guc)) return; - guc_stop_communication(guc); + guc_disable_communication(guc); __uc_sanitize(uc); } -- cgit v1.2.3 From 7f5390c433876a6baef1ee09c5442160ae03cde0 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 16 Dec 2019 17:23:11 -0800 Subject: drm/i915/guc/ct: Drop guards in enable/disable calls We track the status of the GuC much more closely now and we expect the enable/disable functions to be correctly called only once. If this isn't true we do want to flag it as a flow failure (via the BUG_ON in the ctch functions) and not silently ignore the call. Suggested-by: Michal Wajdeczko Signed-off-by: Daniele Ceraolo Spurio Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20191217012316.13271-2-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index f74ba4750a94..b23b46619742 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -862,9 +862,6 @@ int intel_guc_ct_enable(struct intel_guc_ct *ct) struct intel_guc *guc = ct_to_guc(ct); struct intel_guc_ct_channel *ctch = &ct->host_channel; - if (ctch->enabled) - return 0; - return ctch_enable(guc, ctch); } @@ -877,8 +874,5 @@ void intel_guc_ct_disable(struct intel_guc_ct *ct) struct intel_guc *guc = ct_to_guc(ct); struct intel_guc_ct_channel *ctch = &ct->host_channel; - if (!ctch->enabled) - return; - ctch_disable(guc, ctch); } -- cgit v1.2.3 From 9ab28cd20c92bc121dbed64a11b75c5e68cb684b Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 16 Dec 2019 17:23:12 -0800 Subject: drm/i915/guc/ct: Stop expecting multiple CT channels The GuC supports having multiple CT buffer pairs and we designed our implementation with that in mind. However, the different channels are not processed in parallel within the GuC, so there is very little advantage in having multiple channels (independent locks?), compared to the drawbacks (one channel can starve the other if messages keep being submitted to it). Given this, it is unlikely we'll ever add a second channel and therefore we can simplify our code by removing the flexibility. v2: split substructure grouping to separate patch, improve docs (Michal) Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20191217012316.13271-3-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 219 +++++++++++------------------- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 43 ++---- 2 files changed, 90 insertions(+), 172 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index b23b46619742..4e20f6c48a4f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -37,9 +37,6 @@ static void ct_incoming_request_worker_func(struct work_struct *w); */ void intel_guc_ct_init_early(struct intel_guc_ct *ct) { - /* we're using static channel owners */ - ct->host_channel.owner = CTB_OWNER_HOST; - spin_lock_init(&ct->lock); INIT_LIST_HEAD(&ct->pending_requests); INIT_LIST_HEAD(&ct->incoming_requests); @@ -64,14 +61,13 @@ static inline const char *guc_ct_buffer_type_to_str(u32 type) } static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc, - u32 cmds_addr, u32 size, u32 owner) + u32 cmds_addr, u32 size) { - CT_DEBUG_DRIVER("CT: desc %p init addr=%#x size=%u owner=%u\n", - desc, cmds_addr, size, owner); + CT_DEBUG_DRIVER("CT: init addr=%#x size=%u\n", cmds_addr, size); memset(desc, 0, sizeof(*desc)); desc->addr = cmds_addr; desc->size = size; - desc->owner = owner; + desc->owner = CTB_OWNER_HOST; } static void guc_ct_buffer_desc_reset(struct guc_ct_buffer_desc *desc) @@ -104,12 +100,11 @@ static int guc_action_register_ct_buffer(struct intel_guc *guc, } static int guc_action_deregister_ct_buffer(struct intel_guc *guc, - u32 owner, u32 type) { u32 action[] = { INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER, - owner, + CTB_OWNER_HOST, type }; int err; @@ -117,19 +112,27 @@ static int guc_action_deregister_ct_buffer(struct intel_guc *guc, /* Can't use generic send(), CT deregistration must go over MMIO */ err = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); if (err) - DRM_ERROR("CT: deregister %s buffer failed; owner=%d err=%d\n", - guc_ct_buffer_type_to_str(type), owner, err); + DRM_ERROR("CT: deregister %s buffer failed; err=%d\n", + guc_ct_buffer_type_to_str(type), err); return err; } -static int ctch_init(struct intel_guc *guc, - struct intel_guc_ct_channel *ctch) +/** + * intel_guc_ct_init - Init buffer-based communication + * @ct: pointer to CT struct + * + * Allocate memory required for buffer-based communication. + * + * Return: 0 on success, a negative errno code on failure. + */ +int intel_guc_ct_init(struct intel_guc_ct *ct) { + struct intel_guc *guc = ct_to_guc(ct); void *blob; int err; int i; - GEM_BUG_ON(ctch->vma); + GEM_BUG_ON(ct->vma); /* We allocate 1 page to hold both descriptors and both buffers. * ___________..................... @@ -153,57 +156,65 @@ static int ctch_init(struct intel_guc *guc, * other code will need updating as well. */ - err = intel_guc_allocate_and_map_vma(guc, PAGE_SIZE, &ctch->vma, &blob); + err = intel_guc_allocate_and_map_vma(guc, PAGE_SIZE, &ct->vma, &blob); if (err) { - CT_DEBUG_DRIVER("CT: channel %d initialization failed; err=%d\n", - ctch->owner, err); + DRM_ERROR("CT: channel allocation failed; err=%d\n", err); return err; } CT_DEBUG_DRIVER("CT: vma base=%#x\n", - intel_guc_ggtt_offset(guc, ctch->vma)); + intel_guc_ggtt_offset(guc, ct->vma)); /* store pointers to desc and cmds */ - for (i = 0; i < ARRAY_SIZE(ctch->ctbs); i++) { - GEM_BUG_ON((i != CTB_SEND) && (i != CTB_RECV)); - ctch->ctbs[i].desc = blob + PAGE_SIZE/4 * i; - ctch->ctbs[i].cmds = blob + PAGE_SIZE/4 * i + PAGE_SIZE/2; + for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) { + GEM_BUG_ON((i != CTB_SEND) && (i != CTB_RECV)); + ct->ctbs[i].desc = blob + PAGE_SIZE/4 * i; + ct->ctbs[i].cmds = blob + PAGE_SIZE/4 * i + PAGE_SIZE/2; } return 0; } -static void ctch_fini(struct intel_guc *guc, - struct intel_guc_ct_channel *ctch) +/** + * intel_guc_ct_fini - Fini buffer-based communication + * @ct: pointer to CT struct + * + * Deallocate memory required for buffer-based communication. + */ +void intel_guc_ct_fini(struct intel_guc_ct *ct) { - GEM_BUG_ON(ctch->enabled); + GEM_BUG_ON(ct->enabled); - i915_vma_unpin_and_release(&ctch->vma, I915_VMA_RELEASE_MAP); + i915_vma_unpin_and_release(&ct->vma, I915_VMA_RELEASE_MAP); } -static int ctch_enable(struct intel_guc *guc, - struct intel_guc_ct_channel *ctch) +/** + * intel_guc_ct_enable - Enable buffer based command transport. + * @ct: pointer to CT struct + * + * Return: 0 on success, a negative errno code on failure. + */ +int intel_guc_ct_enable(struct intel_guc_ct *ct) { + struct intel_guc *guc = ct_to_guc(ct); u32 base; int err; int i; - GEM_BUG_ON(!ctch->vma); - - GEM_BUG_ON(ctch->enabled); + GEM_BUG_ON(ct->enabled); /* vma should be already allocated and map'ed */ - base = intel_guc_ggtt_offset(guc, ctch->vma); + GEM_BUG_ON(!ct->vma); + base = intel_guc_ggtt_offset(guc, ct->vma); /* (re)initialize descriptors * cmds buffers are in the second half of the blob page */ - for (i = 0; i < ARRAY_SIZE(ctch->ctbs); i++) { + for (i = 0; i < ARRAY_SIZE(ct->ctbs); i++) { GEM_BUG_ON((i != CTB_SEND) && (i != CTB_RECV)); - guc_ct_buffer_desc_init(ctch->ctbs[i].desc, + guc_ct_buffer_desc_init(ct->ctbs[i].desc, base + PAGE_SIZE/4 * i + PAGE_SIZE/2, - PAGE_SIZE/4, - ctch->owner); + PAGE_SIZE/4); } /* register buffers, starting wirh RECV buffer @@ -221,40 +232,42 @@ static int ctch_enable(struct intel_guc *guc, if (unlikely(err)) goto err_deregister; - ctch->enabled = true; + ct->enabled = true; return 0; err_deregister: guc_action_deregister_ct_buffer(guc, - ctch->owner, INTEL_GUC_CT_BUFFER_TYPE_RECV); err_out: - DRM_ERROR("CT: can't open channel %d; err=%d\n", ctch->owner, err); + DRM_ERROR("CT: can't open channel; err=%d\n", err); return err; } -static void ctch_disable(struct intel_guc *guc, - struct intel_guc_ct_channel *ctch) +/** + * intel_guc_ct_disable - Disable buffer based command transport. + * @ct: pointer to CT struct + */ +void intel_guc_ct_disable(struct intel_guc_ct *ct) { - GEM_BUG_ON(!ctch->enabled); + struct intel_guc *guc = ct_to_guc(ct); - ctch->enabled = false; + GEM_BUG_ON(!ct->enabled); + + ct->enabled = false; if (intel_guc_is_running(guc)) { guc_action_deregister_ct_buffer(guc, - ctch->owner, INTEL_GUC_CT_BUFFER_TYPE_SEND); guc_action_deregister_ct_buffer(guc, - ctch->owner, INTEL_GUC_CT_BUFFER_TYPE_RECV); } } -static u32 ctch_get_next_fence(struct intel_guc_ct_channel *ctch) +static u32 ct_get_next_fence(struct intel_guc_ct *ct) { /* For now it's trivial */ - return ++ctch->next_fence; + return ++ct->next_fence; } /** @@ -427,27 +440,26 @@ static int wait_for_ct_request_update(struct ct_request *req, u32 *status) return err; } -static int ctch_send(struct intel_guc_ct *ct, - struct intel_guc_ct_channel *ctch, - const u32 *action, - u32 len, - u32 *response_buf, - u32 response_buf_size, - u32 *status) +static int ct_send(struct intel_guc_ct *ct, + const u32 *action, + u32 len, + u32 *response_buf, + u32 response_buf_size, + u32 *status) { - struct intel_guc_ct_buffer *ctb = &ctch->ctbs[CTB_SEND]; + struct intel_guc_ct_buffer *ctb = &ct->ctbs[CTB_SEND]; struct guc_ct_buffer_desc *desc = ctb->desc; struct ct_request request; unsigned long flags; u32 fence; int err; - GEM_BUG_ON(!ctch->enabled); + GEM_BUG_ON(!ct->enabled); GEM_BUG_ON(!len); GEM_BUG_ON(len & ~GUC_CT_MSG_LEN_MASK); GEM_BUG_ON(!response_buf && response_buf_size); - fence = ctch_get_next_fence(ctch); + fence = ct_get_next_fence(ct); request.fence = fence; request.status = 0; request.response_len = response_buf_size; @@ -502,14 +514,12 @@ int intel_guc_send_ct(struct intel_guc *guc, const u32 *action, u32 len, u32 *response_buf, u32 response_buf_size) { struct intel_guc_ct *ct = &guc->ct; - struct intel_guc_ct_channel *ctch = &ct->host_channel; u32 status = ~0; /* undefined */ int ret; mutex_lock(&guc->send_mutex); - ret = ctch_send(ct, ctch, action, len, response_buf, response_buf_size, - &status); + ret = ct_send(ct, action, len, response_buf, response_buf_size, &status); if (unlikely(ret < 0)) { DRM_ERROR("CT: send action %#X failed; err=%d status=%#X\n", action[0], ret, status); @@ -772,14 +782,18 @@ static int ct_handle_request(struct intel_guc_ct *ct, const u32 *msg) return 0; } -static void ct_process_host_channel(struct intel_guc_ct *ct) +/* + * When we're communicating with the GuC over CT, GuC uses events + * to notify us about new messages being posted on the RECV buffer. + */ +void intel_guc_to_host_event_handler_ct(struct intel_guc *guc) { - struct intel_guc_ct_channel *ctch = &ct->host_channel; - struct intel_guc_ct_buffer *ctb = &ctch->ctbs[CTB_RECV]; + struct intel_guc_ct *ct = &guc->ct; + struct intel_guc_ct_buffer *ctb = &ct->ctbs[CTB_RECV]; u32 msg[GUC_CT_MSG_LEN_MASK + 1]; /* one extra dw for the header */ int err = 0; - if (!ctch->enabled) + if (!ct->enabled) return; do { @@ -799,80 +813,3 @@ static void ct_process_host_channel(struct intel_guc_ct *ct) } } -/* - * When we're communicating with the GuC over CT, GuC uses events - * to notify us about new messages being posted on the RECV buffer. - */ -void intel_guc_to_host_event_handler_ct(struct intel_guc *guc) -{ - struct intel_guc_ct *ct = &guc->ct; - - ct_process_host_channel(ct); -} - -/** - * intel_guc_ct_init - Init CT communication - * @ct: pointer to CT struct - * - * Allocate memory required for communication via - * the CT channel. - * - * Return: 0 on success, a negative errno code on failure. - */ -int intel_guc_ct_init(struct intel_guc_ct *ct) -{ - struct intel_guc *guc = ct_to_guc(ct); - struct intel_guc_ct_channel *ctch = &ct->host_channel; - int err; - - err = ctch_init(guc, ctch); - if (unlikely(err)) { - DRM_ERROR("CT: can't open channel %d; err=%d\n", - ctch->owner, err); - return err; - } - - GEM_BUG_ON(!ctch->vma); - return 0; -} - -/** - * intel_guc_ct_fini - Fini CT communication - * @ct: pointer to CT struct - * - * Deallocate memory required for communication via - * the CT channel. - */ -void intel_guc_ct_fini(struct intel_guc_ct *ct) -{ - struct intel_guc *guc = ct_to_guc(ct); - struct intel_guc_ct_channel *ctch = &ct->host_channel; - - ctch_fini(guc, ctch); -} - -/** - * intel_guc_ct_enable - Enable buffer based command transport. - * @ct: pointer to CT struct - * - * Return: 0 on success, a negative errno code on failure. - */ -int intel_guc_ct_enable(struct intel_guc_ct *ct) -{ - struct intel_guc *guc = ct_to_guc(ct); - struct intel_guc_ct_channel *ctch = &ct->host_channel; - - return ctch_enable(guc, ctch); -} - -/** - * intel_guc_ct_disable - Disable buffer based command transport. - * @ct: pointer to CT struct - */ -void intel_guc_ct_disable(struct intel_guc_ct *ct) -{ - struct intel_guc *guc = ct_to_guc(ct); - struct intel_guc_ct_channel *ctch = &ct->host_channel; - - ctch_disable(guc, ctch); -} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h index 77c80d6cc25d..6e3d789b9f01 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h @@ -35,44 +35,25 @@ struct intel_guc_ct_buffer { u32 *cmds; }; -/** Represents pair of command transport buffers. - * - * Buffers go in pairs to allow bi-directional communication. - * To simplify the code we place both of them in the same vma. - * Buffers from the same pair must share unique owner id. - * - * @vma: pointer to the vma with pair of CT buffers - * @ctbs: buffers for sending(0) and receiving(1) commands - * @owner: unique identifier - * @next_fence: fence to be used with next send command - */ -struct intel_guc_ct_channel { - struct i915_vma *vma; - struct intel_guc_ct_buffer ctbs[2]; - u32 owner; - u32 next_fence; - bool enabled; -}; -/** Holds all command transport channels. +/** Top-level structure for Command Transport related data * - * @host_channel: main channel used by the host + * Includes a pair of CT buffers for bi-directional communication and tracking + * for the H2G and G2H requests sent and received through the buffers. */ struct intel_guc_ct { - struct intel_guc_ct_channel host_channel; - /* other channels are tbd */ - - /** @lock: protects pending requests list */ - spinlock_t lock; + struct i915_vma *vma; + bool enabled; - /** @pending_requests: list of requests waiting for response */ - struct list_head pending_requests; + /* buffers for sending(0) and receiving(1) commands */ + struct intel_guc_ct_buffer ctbs[2]; - /** @incoming_requests: list of incoming requests */ - struct list_head incoming_requests; + u32 next_fence; /* fence to be used with next send command */ - /** @worker: worker for handling incoming requests */ - struct work_struct worker; + spinlock_t lock; /* protects pending requests list */ + struct list_head pending_requests; /* requests waiting for response */ + struct list_head incoming_requests; /* incoming requests */ + struct work_struct worker; /* handler for incoming requests */ }; void intel_guc_ct_init_early(struct intel_guc_ct *ct); -- cgit v1.2.3 From 7524c365c31c9435ff4891bfabf52dcfa62edb6a Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 16 Dec 2019 17:23:13 -0800 Subject: drm/i915/guc/ct: Group request-related variables in a sub-structure For better isolation of the request tracking from the rest of the CT-related data. v2: split to separate patch, move next_fence to substructure (Michal) Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20191217012316.13271-4-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 47 ++++++++++++++++--------------- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 13 +++++---- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 4e20f6c48a4f..f22cd9b2311b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -37,10 +37,10 @@ static void ct_incoming_request_worker_func(struct work_struct *w); */ void intel_guc_ct_init_early(struct intel_guc_ct *ct) { - spin_lock_init(&ct->lock); - INIT_LIST_HEAD(&ct->pending_requests); - INIT_LIST_HEAD(&ct->incoming_requests); - INIT_WORK(&ct->worker, ct_incoming_request_worker_func); + spin_lock_init(&ct->requests.lock); + INIT_LIST_HEAD(&ct->requests.pending); + INIT_LIST_HEAD(&ct->requests.incoming); + INIT_WORK(&ct->requests.worker, ct_incoming_request_worker_func); } static inline struct intel_guc *ct_to_guc(struct intel_guc_ct *ct) @@ -267,7 +267,7 @@ void intel_guc_ct_disable(struct intel_guc_ct *ct) static u32 ct_get_next_fence(struct intel_guc_ct *ct) { /* For now it's trivial */ - return ++ct->next_fence; + return ++ct->requests.next_fence; } /** @@ -465,9 +465,9 @@ static int ct_send(struct intel_guc_ct *ct, request.response_len = response_buf_size; request.response_buf = response_buf; - spin_lock_irqsave(&ct->lock, flags); - list_add_tail(&request.link, &ct->pending_requests); - spin_unlock_irqrestore(&ct->lock, flags); + spin_lock_irqsave(&ct->requests.lock, flags); + list_add_tail(&request.link, &ct->requests.pending); + spin_unlock_irqrestore(&ct->requests.lock, flags); err = ctb_write(ctb, action, len, fence, !!response_buf); if (unlikely(err)) @@ -500,9 +500,9 @@ static int ct_send(struct intel_guc_ct *ct, } unlink: - spin_lock_irqsave(&ct->lock, flags); + spin_lock_irqsave(&ct->requests.lock, flags); list_del(&request.link); - spin_unlock_irqrestore(&ct->lock, flags); + spin_unlock_irqrestore(&ct->requests.lock, flags); return err; } @@ -650,8 +650,8 @@ static int ct_handle_response(struct intel_guc_ct *ct, const u32 *msg) CT_DEBUG_DRIVER("CT: response fence %u status %#x\n", fence, status); - spin_lock(&ct->lock); - list_for_each_entry(req, &ct->pending_requests, link) { + spin_lock(&ct->requests.lock); + list_for_each_entry(req, &ct->requests.pending, link) { if (unlikely(fence != req->fence)) { CT_DEBUG_DRIVER("CT: request %u awaits response\n", req->fence); @@ -669,7 +669,7 @@ static int ct_handle_response(struct intel_guc_ct *ct, const u32 *msg) found = true; break; } - spin_unlock(&ct->lock); + spin_unlock(&ct->requests.lock); if (!found) DRM_ERROR("CT: unsolicited response %*ph\n", 4 * msglen, msg); @@ -707,13 +707,13 @@ static bool ct_process_incoming_requests(struct intel_guc_ct *ct) u32 *payload; bool done; - spin_lock_irqsave(&ct->lock, flags); - request = list_first_entry_or_null(&ct->incoming_requests, + spin_lock_irqsave(&ct->requests.lock, flags); + request = list_first_entry_or_null(&ct->requests.incoming, struct ct_incoming_request, link); if (request) list_del(&request->link); - done = !!list_empty(&ct->incoming_requests); - spin_unlock_irqrestore(&ct->lock, flags); + done = !!list_empty(&ct->requests.incoming); + spin_unlock_irqrestore(&ct->requests.lock, flags); if (!request) return true; @@ -731,12 +731,13 @@ static bool ct_process_incoming_requests(struct intel_guc_ct *ct) static void ct_incoming_request_worker_func(struct work_struct *w) { - struct intel_guc_ct *ct = container_of(w, struct intel_guc_ct, worker); + struct intel_guc_ct *ct = + container_of(w, struct intel_guc_ct, requests.worker); bool done; done = ct_process_incoming_requests(ct); if (!done) - queue_work(system_unbound_wq, &ct->worker); + queue_work(system_unbound_wq, &ct->requests.worker); } /** @@ -774,11 +775,11 @@ static int ct_handle_request(struct intel_guc_ct *ct, const u32 *msg) } memcpy(request->msg, msg, 4 * msglen); - spin_lock_irqsave(&ct->lock, flags); - list_add_tail(&request->link, &ct->incoming_requests); - spin_unlock_irqrestore(&ct->lock, flags); + spin_lock_irqsave(&ct->requests.lock, flags); + list_add_tail(&request->link, &ct->requests.incoming); + spin_unlock_irqrestore(&ct->requests.lock, flags); - queue_work(system_unbound_wq, &ct->worker); + queue_work(system_unbound_wq, &ct->requests.worker); return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h index 6e3d789b9f01..29a026dc3a13 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h @@ -48,12 +48,15 @@ struct intel_guc_ct { /* buffers for sending(0) and receiving(1) commands */ struct intel_guc_ct_buffer ctbs[2]; - u32 next_fence; /* fence to be used with next send command */ + struct { + u32 next_fence; /* fence to be used with next request to send */ - spinlock_t lock; /* protects pending requests list */ - struct list_head pending_requests; /* requests waiting for response */ - struct list_head incoming_requests; /* incoming requests */ - struct work_struct worker; /* handler for incoming requests */ + spinlock_t lock; /* protects pending requests list */ + struct list_head pending; /* requests waiting for response */ + + struct list_head incoming; /* incoming requests */ + struct work_struct worker; /* handler for incoming requests */ + } requests; }; void intel_guc_ct_init_early(struct intel_guc_ct *ct); -- cgit v1.2.3 From 8c69bd74a00baff85f4ef46b9f79263a42e0d82c Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 16 Dec 2019 17:23:14 -0800 Subject: drm/i915/guc: Remove function pointers for send/receive calls Since we started using CT buffers on all gens, the function pointers can only be set to either the _nop() or the _ct() functions. Since the _nop() case applies to when the CT are disabled, we can just handle that case in the _ct() functions and call them directly. v2: keep intel_guc_send() and make the CT send/receive functions work on intel_guc_ct. (Michal) Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20191217012316.13271-5-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 14 -------------- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 18 ++++-------------- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 16 +++++++++++----- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h | 9 +++++++-- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 1 - drivers/gpu/drm/i915/gt/uc/intel_uc.c | 20 +++++++------------- 6 files changed, 29 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 922a19635d20..daebfec0034c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -177,8 +177,6 @@ void intel_guc_init_early(struct intel_guc *guc) mutex_init(&guc->send_mutex); spin_lock_init(&guc->irq_lock); - guc->send = intel_guc_send_nop; - guc->handler = intel_guc_to_host_event_handler_nop; if (INTEL_GEN(i915) >= 11) { guc->notify = gen11_guc_raise_irq; guc->interrupts.reset = gen11_reset_guc_interrupts; @@ -403,18 +401,6 @@ void intel_guc_fini(struct intel_guc *guc) intel_uc_fw_cleanup_fetch(&guc->fw); } -int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len, - u32 *response_buf, u32 response_buf_size) -{ - WARN(1, "Unexpected send: action=%#x\n", *action); - return -ENODEV; -} - -void intel_guc_to_host_event_handler_nop(struct intel_guc *guc) -{ - WARN(1, "Unexpected event: no suitable handler\n"); -} - /* * This function implements the MMIO based host to GuC interface. */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index cd09c912e361..253b1ac7716e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -70,13 +70,6 @@ struct intel_guc { /* To serialize the intel_guc_send actions */ struct mutex send_mutex; - /* GuC's FW specific send function */ - int (*send)(struct intel_guc *guc, const u32 *data, u32 len, - u32 *response_buf, u32 response_buf_size); - - /* GuC's FW specific event handler function */ - void (*handler)(struct intel_guc *guc); - /* GuC's FW specific notify function */ void (*notify)(struct intel_guc *guc); }; @@ -84,14 +77,15 @@ struct intel_guc { static inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) { - return guc->send(guc, action, len, NULL, 0); + return intel_guc_ct_send(&guc->ct, action, len, NULL, 0); } static inline int intel_guc_send_and_receive(struct intel_guc *guc, const u32 *action, u32 len, u32 *response_buf, u32 response_buf_size) { - return guc->send(guc, action, len, response_buf, response_buf_size); + return intel_guc_ct_send(&guc->ct, action, len, + response_buf, response_buf_size); } static inline void intel_guc_notify(struct intel_guc *guc) @@ -101,7 +95,7 @@ static inline void intel_guc_notify(struct intel_guc *guc) static inline void intel_guc_to_host_event_handler(struct intel_guc *guc) { - guc->handler(guc); + intel_guc_ct_event_handler(&guc->ct); } /* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */ @@ -136,12 +130,8 @@ void intel_guc_init_send_regs(struct intel_guc *guc); void intel_guc_write_params(struct intel_guc *guc); int intel_guc_init(struct intel_guc *guc); void intel_guc_fini(struct intel_guc *guc); -int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len, - u32 *response_buf, u32 response_buf_size); int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len, u32 *response_buf, u32 response_buf_size); -void intel_guc_to_host_event_handler(struct intel_guc *guc); -void intel_guc_to_host_event_handler_nop(struct intel_guc *guc); int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, const u32 *payload, u32 len); int intel_guc_sample_forcewake(struct intel_guc *guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index f22cd9b2311b..c6f971a049f9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -510,13 +510,18 @@ unlink: /* * Command Transport (CT) buffer based GuC send function. */ -int intel_guc_send_ct(struct intel_guc *guc, const u32 *action, u32 len, +int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len, u32 *response_buf, u32 response_buf_size) { - struct intel_guc_ct *ct = &guc->ct; + struct intel_guc *guc = ct_to_guc(ct); u32 status = ~0; /* undefined */ int ret; + if (unlikely(!ct->enabled)) { + WARN(1, "Unexpected send: action=%#x\n", *action); + return -ENODEV; + } + mutex_lock(&guc->send_mutex); ret = ct_send(ct, action, len, response_buf, response_buf_size, &status); @@ -787,15 +792,16 @@ static int ct_handle_request(struct intel_guc_ct *ct, const u32 *msg) * When we're communicating with the GuC over CT, GuC uses events * to notify us about new messages being posted on the RECV buffer. */ -void intel_guc_to_host_event_handler_ct(struct intel_guc *guc) +void intel_guc_ct_event_handler(struct intel_guc_ct *ct) { - struct intel_guc_ct *ct = &guc->ct; struct intel_guc_ct_buffer *ctb = &ct->ctbs[CTB_RECV]; u32 msg[GUC_CT_MSG_LEN_MASK + 1]; /* one extra dw for the header */ int err = 0; - if (!ct->enabled) + if (unlikely(!ct->enabled)) { + WARN(1, "Unexpected GuC event received while CT disabled!\n"); return; + } do { err = ctb_read(ctb, msg); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h index 29a026dc3a13..3e7fe237cfa5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h @@ -65,8 +65,13 @@ void intel_guc_ct_fini(struct intel_guc_ct *ct); int intel_guc_ct_enable(struct intel_guc_ct *ct); void intel_guc_ct_disable(struct intel_guc_ct *ct); -int intel_guc_send_ct(struct intel_guc *guc, const u32 *action, u32 len, +static inline bool intel_guc_ct_enabled(struct intel_guc_ct *ct) +{ + return ct->enabled; +} + +int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len, u32 *response_buf, u32 response_buf_size); -void intel_guc_to_host_event_handler_ct(struct intel_guc *guc); +void intel_guc_ct_event_handler(struct intel_guc_ct *ct); #endif /* _INTEL_GUC_CT_H_ */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index af04ed6e48d9..44a7d2e736a7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -43,7 +43,6 @@ * Firmware writes a success/fail code back to the action register after * processes the request. The kernel driver polls waiting for this update and * then proceeds. - * See intel_guc_send() * * Work Items: * There are several types of work items that the host may place into a diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 6e17e449e0a8..782b8f95183f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -123,6 +123,11 @@ static void __uc_free_load_err_log(struct intel_uc *uc) i915_gem_object_put(log); } +static inline bool guc_communication_enabled(struct intel_guc *guc) +{ + return intel_guc_ct_enabled(&guc->ct); +} + /* * Events triggered while CT buffers are disabled are logged in the SCRATCH_15 * register using the same bits used in the CT message payload. Since our @@ -158,7 +163,7 @@ static void guc_handle_mmio_msg(struct intel_guc *guc) struct drm_i915_private *i915 = guc_to_gt(guc)->i915; /* we need communication to be enabled to reply to GuC */ - GEM_BUG_ON(guc->handler == intel_guc_to_host_event_handler_nop); + GEM_BUG_ON(!guc_communication_enabled(guc)); if (!guc->mmio_msg) return; @@ -185,11 +190,6 @@ static void guc_disable_interrupts(struct intel_guc *guc) guc->interrupts.disable(guc); } -static inline bool guc_communication_enabled(struct intel_guc *guc) -{ - return guc->send != intel_guc_send_nop; -} - static int guc_enable_communication(struct intel_guc *guc) { struct drm_i915_private *i915 = guc_to_gt(guc)->i915; @@ -205,9 +205,6 @@ static int guc_enable_communication(struct intel_guc *guc) if (ret) return ret; - guc->send = intel_guc_send_ct; - guc->handler = intel_guc_to_host_event_handler_ct; - /* check for mmio messages received before/during the CT enable */ guc_get_mmio_msg(guc); guc_handle_mmio_msg(guc); @@ -216,7 +213,7 @@ static int guc_enable_communication(struct intel_guc *guc) /* check for CT messages received before we enabled interrupts */ spin_lock_irq(&i915->irq_lock); - intel_guc_to_host_event_handler_ct(guc); + intel_guc_ct_event_handler(&guc->ct); spin_unlock_irq(&i915->irq_lock); DRM_INFO("GuC communication enabled\n"); @@ -235,9 +232,6 @@ static void guc_disable_communication(struct intel_guc *guc) guc_disable_interrupts(guc); - guc->send = intel_guc_send_nop; - guc->handler = intel_guc_to_host_event_handler_nop; - intel_guc_ct_disable(&guc->ct); /* -- cgit v1.2.3 From f20c6b278d1a0cedc691c3b0ebcf9154ad9d8a1a Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 16 Dec 2019 17:23:15 -0800 Subject: drm/i915/guc: Unify notify() functions The Gen11+ and the legacy function differ in the register and value written to interrupt the GuC. However, while on older gen the value matches a bit on the register, on Gen11+ the value is a SW defined payload that is sent to the FW. Since the FW behaves the same no matter what value we pass to it, we can just write the same thing on all gens and get rid of the function pointer by saving the register offset. Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20191217012316.13271-6-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 21 ++++++++++----------- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 12 ++++-------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index daebfec0034c..9d6301292e13 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -32,18 +32,17 @@ * just the HuC, but more are expected to land in the future). */ -static void gen8_guc_raise_irq(struct intel_guc *guc) +void intel_guc_notify(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); - intel_uncore_write(gt->uncore, GUC_SEND_INTERRUPT, GUC_SEND_TRIGGER); -} - -static void gen11_guc_raise_irq(struct intel_guc *guc) -{ - struct intel_gt *gt = guc_to_gt(guc); - - intel_uncore_write(gt->uncore, GEN11_GUC_HOST_INTERRUPT, 0); + /* + * On Gen11+, the value written to the register is passes as a payload + * to the FW. However, the FW currently treats all values the same way + * (H2G interrupt), so we can just write the value that the HW expects + * on older gens. + */ + intel_uncore_write(gt->uncore, guc->notify_reg, GUC_SEND_TRIGGER); } static inline i915_reg_t guc_send_reg(struct intel_guc *guc, u32 i) @@ -178,12 +177,12 @@ void intel_guc_init_early(struct intel_guc *guc) mutex_init(&guc->send_mutex); spin_lock_init(&guc->irq_lock); if (INTEL_GEN(i915) >= 11) { - guc->notify = gen11_guc_raise_irq; + guc->notify_reg = GEN11_GUC_HOST_INTERRUPT; guc->interrupts.reset = gen11_reset_guc_interrupts; guc->interrupts.enable = gen11_enable_guc_interrupts; guc->interrupts.disable = gen11_disable_guc_interrupts; } else { - guc->notify = gen8_guc_raise_irq; + guc->notify_reg = GUC_SEND_INTERRUPT; guc->interrupts.reset = gen9_reset_guc_interrupts; guc->interrupts.enable = gen9_enable_guc_interrupts; guc->interrupts.disable = gen9_disable_guc_interrupts; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 253b1ac7716e..910d49590068 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -64,14 +64,14 @@ struct intel_guc { enum forcewake_domains fw_domains; } send_regs; + /* register used to send interrupts to the GuC FW */ + i915_reg_t notify_reg; + /* Store msg (e.g. log flush) that we see while CTBs are disabled */ u32 mmio_msg; /* To serialize the intel_guc_send actions */ struct mutex send_mutex; - - /* GuC's FW specific notify function */ - void (*notify)(struct intel_guc *guc); }; static @@ -88,11 +88,6 @@ intel_guc_send_and_receive(struct intel_guc *guc, const u32 *action, u32 len, response_buf, response_buf_size); } -static inline void intel_guc_notify(struct intel_guc *guc) -{ - guc->notify(guc); -} - static inline void intel_guc_to_host_event_handler(struct intel_guc *guc) { intel_guc_ct_event_handler(&guc->ct); @@ -130,6 +125,7 @@ void intel_guc_init_send_regs(struct intel_guc *guc); void intel_guc_write_params(struct intel_guc *guc); int intel_guc_init(struct intel_guc *guc); void intel_guc_fini(struct intel_guc *guc); +void intel_guc_notify(struct intel_guc *guc); int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len, u32 *response_buf, u32 response_buf_size); int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, -- cgit v1.2.3 From 54d7195f8c64c83a13bd343e349b1bbf158c8aad Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Dec 2019 16:17:16 +0000 Subject: drm/i915: Unpin vma->obj on early error If we inherit an error along the fence chain, we skip the main work callback and go straight to the error. In the case of the vma bind worker, we only dropped the pinned pages from the worker. In the process, make sure we call the release earlier rather than wait until the final reference to the fence is dropped (as a reference is kept while being listened upon). Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191216161717.2688274-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_clflush.c | 11 ++++------- drivers/gpu/drm/i915/i915_sw_fence_work.c | 15 ++++++++++----- drivers/gpu/drm/i915/i915_vma.c | 17 +++++++++++++---- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index b9f504ba3b32..5448efa77710 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -26,27 +26,24 @@ static void __do_clflush(struct drm_i915_gem_object *obj) static int clflush_work(struct dma_fence_work *base) { struct clflush *clflush = container_of(base, typeof(*clflush), base); - struct drm_i915_gem_object *obj = fetch_and_zero(&clflush->obj); + struct drm_i915_gem_object *obj = clflush->obj; int err; err = i915_gem_object_pin_pages(obj); if (err) - goto put; + return err; __do_clflush(obj); i915_gem_object_unpin_pages(obj); -put: - i915_gem_object_put(obj); - return err; + return 0; } static void clflush_release(struct dma_fence_work *base) { struct clflush *clflush = container_of(base, typeof(*clflush), base); - if (clflush->obj) - i915_gem_object_put(clflush->obj); + i915_gem_object_put(clflush->obj); } static const struct dma_fence_work_ops clflush_ops = { diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.c b/drivers/gpu/drm/i915/i915_sw_fence_work.c index 8538ee7a521d..997b2998f1f2 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence_work.c +++ b/drivers/gpu/drm/i915/i915_sw_fence_work.c @@ -6,6 +6,13 @@ #include "i915_sw_fence_work.h" +static void fence_complete(struct dma_fence_work *f) +{ + if (f->ops->release) + f->ops->release(f); + dma_fence_signal(&f->dma); +} + static void fence_work(struct work_struct *work) { struct dma_fence_work *f = container_of(work, typeof(*f), work); @@ -14,7 +21,8 @@ static void fence_work(struct work_struct *work) err = f->ops->work(f); if (err) dma_fence_set_error(&f->dma, err); - dma_fence_signal(&f->dma); + + fence_complete(f); dma_fence_put(&f->dma); } @@ -32,7 +40,7 @@ fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) dma_fence_get(&f->dma); queue_work(system_unbound_wq, &f->work); } else { - dma_fence_signal(&f->dma); + fence_complete(f); } break; @@ -60,9 +68,6 @@ static void fence_release(struct dma_fence *fence) { struct dma_fence_work *f = container_of(fence, typeof(*f), dma); - if (f->ops->release) - f->ops->release(f); - i915_sw_fence_fini(&f->chain); BUILD_BUG_ON(offsetof(typeof(*f), dma)); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 6794c742fbbf..62670459ee8e 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -292,6 +292,7 @@ i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_vma_work { struct dma_fence_work base; struct i915_vma *vma; + struct drm_i915_gem_object *pinned; enum i915_cache_level cache_level; unsigned int flags; }; @@ -306,15 +307,21 @@ static int __vma_bind(struct dma_fence_work *work) if (err) atomic_or(I915_VMA_ERROR, &vma->flags); - if (vma->obj) - __i915_gem_object_unpin_pages(vma->obj); - return err; } +static void __vma_release(struct dma_fence_work *work) +{ + struct i915_vma_work *vw = container_of(work, typeof(*vw), base); + + if (vw->pinned) + __i915_gem_object_unpin_pages(vw->pinned); +} + static const struct dma_fence_work_ops bind_ops = { .name = "bind", .work = __vma_bind, + .release = __vma_release, }; struct i915_vma_work *i915_vma_work(void) @@ -395,8 +402,10 @@ int i915_vma_bind(struct i915_vma *vma, i915_active_set_exclusive(&vma->active, &work->base.dma); work->base.dma.error = 0; /* enable the queue_work() */ - if (vma->obj) + if (vma->obj) { __i915_gem_object_pin_pages(vma->obj); + work->pinned = vma->obj; + } } else { GEM_BUG_ON((bind_flags & ~vma_flags) & vma->vm->bind_async_flags); ret = vma->ops->bind_vma(vma, cache_level, bind_flags); -- cgit v1.2.3 From edb1ecad77d44e21a56e9b1bba747174379b2b54 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Dec 2019 00:07:56 +0000 Subject: drm/i915/pmu: Skip sampling engines if gt is asleep If the whole GT is asleep, we know that each engine must also be asleep and so we can quickly return without checking them all. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191218000756.3475668-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_pmu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 5f2adfbf85be..00325471be90 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -312,6 +312,9 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns) if ((i915->pmu.enable & ENGINE_SAMPLE_MASK) == 0) return; + if (!intel_gt_pm_is_awake(gt)) + return; + for_each_engine(engine, gt, id) { struct intel_engine_pmu *pmu = &engine->pmu; spinlock_t *mmio_lock; -- cgit v1.2.3 From da42104f589d979bbe402703fd836cec60befae1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Dec 2019 10:40:43 +0000 Subject: drm/i915: Hold reference to intel_frontbuffer as we track activity Since obj->frontbuffer is no longer protected by the struct_mutex, as we are processing the execbuf, it may be removed. Mark the intel_frontbuffer as rcu protected, and so acquire a reference to the struct as we track activity upon it. Closes: https://gitlab.freedesktop.org/drm/intel/issues/827 Fixes: 8e7cb1799b4f ("drm/i915: Extract intel_frontbuffer active tracking") Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: # v5.4+ Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191218104043.3539458-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_frontbuffer.c | 16 +++++------ drivers/gpu/drm/i915/display/intel_frontbuffer.h | 34 +++++++++++++++++++++--- drivers/gpu/drm/i915/display/intel_overlay.c | 17 +++++++++--- drivers/gpu/drm/i915/gem/i915_gem_clflush.c | 3 ++- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 4 +-- drivers/gpu/drm/i915/gem/i915_gem_object.c | 26 +++++++++++++++++- drivers/gpu/drm/i915/gem/i915_gem_object.h | 23 +++++++++++++++- drivers/gpu/drm/i915/gem/i915_gem_object_types.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 10 +++---- drivers/gpu/drm/i915/i915_vma.c | 10 +++++-- 11 files changed, 116 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8b69a7947cbe..bba73b0783ad 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15186,7 +15186,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, return ret; fb_obj_bump_render_priority(obj); - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB); + i915_gem_object_flush_frontbuffer(obj, ORIGIN_DIRTYFB); if (!new_plane_state->uapi.fence) { /* implicit fencing */ struct dma_fence *fence; diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 84b164f31895..6cb02c912acc 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -229,11 +229,11 @@ static void frontbuffer_release(struct kref *ref) vma->display_alignment = I915_GTT_MIN_ALIGNMENT; spin_unlock(&obj->vma.lock); - obj->frontbuffer = NULL; + RCU_INIT_POINTER(obj->frontbuffer, NULL); spin_unlock(&to_i915(obj->base.dev)->fb_tracking.lock); i915_gem_object_put(obj); - kfree(front); + kfree_rcu(front, rcu); } struct intel_frontbuffer * @@ -242,11 +242,7 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj) struct drm_i915_private *i915 = to_i915(obj->base.dev); struct intel_frontbuffer *front; - spin_lock(&i915->fb_tracking.lock); - front = obj->frontbuffer; - if (front) - kref_get(&front->ref); - spin_unlock(&i915->fb_tracking.lock); + front = __intel_frontbuffer_get(obj); if (front) return front; @@ -262,13 +258,13 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj) i915_active_may_sleep(frontbuffer_retire)); spin_lock(&i915->fb_tracking.lock); - if (obj->frontbuffer) { + if (rcu_access_pointer(obj->frontbuffer)) { kfree(front); - front = obj->frontbuffer; + front = rcu_dereference_protected(obj->frontbuffer, true); kref_get(&front->ref); } else { i915_gem_object_get(obj); - obj->frontbuffer = front; + rcu_assign_pointer(obj->frontbuffer, front); } spin_unlock(&i915->fb_tracking.lock); diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.h b/drivers/gpu/drm/i915/display/intel_frontbuffer.h index adc64d61a4a5..6d41f5394425 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.h +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.h @@ -27,10 +27,10 @@ #include #include +#include "gem/i915_gem_object_types.h" #include "i915_active.h" struct drm_i915_private; -struct drm_i915_gem_object; enum fb_op_origin { ORIGIN_GTT, @@ -45,6 +45,7 @@ struct intel_frontbuffer { atomic_t bits; struct i915_active write; struct drm_i915_gem_object *obj; + struct rcu_head rcu; }; void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915, @@ -54,6 +55,35 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *i915, void intel_frontbuffer_flip(struct drm_i915_private *i915, unsigned frontbuffer_bits); +void intel_frontbuffer_put(struct intel_frontbuffer *front); + +static inline struct intel_frontbuffer * +__intel_frontbuffer_get(const struct drm_i915_gem_object *obj) +{ + struct intel_frontbuffer *front; + + if (likely(!rcu_access_pointer(obj->frontbuffer))) + return NULL; + + rcu_read_lock(); + do { + front = rcu_dereference(obj->frontbuffer); + if (!front) + break; + + if (unlikely(!kref_get_unless_zero(&front->ref))) + continue; + + if (likely(front == rcu_access_pointer(obj->frontbuffer))) + break; + + intel_frontbuffer_put(front); + } while (1); + rcu_read_unlock(); + + return front; +} + struct intel_frontbuffer * intel_frontbuffer_get(struct drm_i915_gem_object *obj); @@ -119,6 +149,4 @@ void intel_frontbuffer_track(struct intel_frontbuffer *old, struct intel_frontbuffer *new, unsigned int frontbuffer_bits); -void intel_frontbuffer_put(struct intel_frontbuffer *front); - #endif /* __INTEL_FRONTBUFFER_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 2a44b3be2600..6097594468a9 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -279,12 +279,21 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay, struct i915_vma *vma) { enum pipe pipe = overlay->crtc->pipe; + struct intel_frontbuffer *from, *to; WARN_ON(overlay->old_vma); - intel_frontbuffer_track(overlay->vma ? overlay->vma->obj->frontbuffer : NULL, - vma ? vma->obj->frontbuffer : NULL, - INTEL_FRONTBUFFER_OVERLAY(pipe)); + if (overlay->vma) + from = intel_frontbuffer_get(overlay->vma->obj); + if (vma) + to = intel_frontbuffer_get(vma->obj); + + intel_frontbuffer_track(from, to, INTEL_FRONTBUFFER_OVERLAY(pipe)); + + if (to) + intel_frontbuffer_put(to); + if (from) + intel_frontbuffer_put(from); intel_frontbuffer_flip_prepare(overlay->i915, INTEL_FRONTBUFFER_OVERLAY(pipe)); @@ -764,7 +773,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, ret = PTR_ERR(vma); goto out_pin_section; } - intel_frontbuffer_flush(new_bo->frontbuffer, ORIGIN_DIRTYFB); + i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB); if (!overlay->active) { u32 oconfig; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index 5448efa77710..34be4c0ee7c5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -20,7 +20,8 @@ static void __do_clflush(struct drm_i915_gem_object *obj) { GEM_BUG_ON(!i915_gem_object_has_pages(obj)); drm_clflush_sg(obj->mm.pages); - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); + + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); } static int clflush_work(struct dma_fence_work *base) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 65f1851e2863..0cc40e77bbd2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -558,7 +558,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, i915_gem_object_unlock(obj); if (write_domain) - intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU); + i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU); out_unpin: i915_gem_object_unpin_pages(obj); @@ -678,7 +678,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj, } out: - intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU); + i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU); obj->mm.dirty = true; /* return with the pages pinned */ return 0; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 16d611db9ca6..ddc82a7a34ff 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -313,7 +313,7 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj, } spin_unlock(&obj->vma.lock); - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); break; case I915_GEM_DOMAIN_WC: @@ -333,6 +333,30 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj, obj->write_domain = 0; } +void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, + enum fb_op_origin origin) +{ + struct intel_frontbuffer *front; + + front = __intel_frontbuffer_get(obj); + if (front) { + intel_frontbuffer_flush(front, origin); + intel_frontbuffer_put(front); + } +} + +void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, + enum fb_op_origin origin) +{ + struct intel_frontbuffer *front; + + front = __intel_frontbuffer_get(obj); + if (front) { + intel_frontbuffer_invalidate(front, origin); + intel_frontbuffer_put(front); + } +} + void i915_gem_init__objects(struct drm_i915_private *i915) { INIT_WORK(&i915->mm.free_work, __i915_gem_free_work); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index a1eb7c0b23ac..858f8bf49a04 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -13,8 +13,8 @@ #include +#include "display/intel_frontbuffer.h" #include "i915_gem_object_types.h" - #include "i915_gem_gtt.h" void i915_gem_init__objects(struct drm_i915_private *i915); @@ -471,4 +471,25 @@ int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, unsigned int flags, const struct i915_sched_attr *attr); +void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, + enum fb_op_origin origin); +void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, + enum fb_op_origin origin); + +static inline void +i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, + enum fb_op_origin origin) +{ + if (unlikely(rcu_access_pointer(obj->frontbuffer))) + __i915_gem_object_flush_frontbuffer(obj, origin); +} + +static inline void +i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, + enum fb_op_origin origin) +{ + if (unlikely(rcu_access_pointer(obj->frontbuffer))) + __i915_gem_object_invalidate_frontbuffer(obj, origin); +} + #endif diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 2d404e6f63df..88e268633fdc 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -173,7 +173,7 @@ struct drm_i915_gem_object { */ u16 write_domain; - struct intel_frontbuffer *frontbuffer; + struct intel_frontbuffer __rcu *frontbuffer; /** Current tiling stride for the object, if it's tiled. */ unsigned int tiling_and_stride; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5eeef1ef7448..f19c678ebefc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -200,7 +200,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, * We manually control the domain here and pretend that it * remains coherent i.e. in the GTT domain, like shmem_pwrite. */ - intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU); + i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU); if (copy_from_user(vaddr, user_data, args->size)) return -EFAULT; @@ -208,7 +208,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj, drm_clflush_virt_range(vaddr, args->size); intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt); - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); return 0; } @@ -628,7 +628,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, goto out_unpin; } - intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU); + i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU); user_data = u64_to_user_ptr(args->data_ptr); offset = args->offset; @@ -672,7 +672,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, } intel_gt_flush_ggtt_writes(ggtt->vm.gt); - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); i915_gem_object_unlock_fence(obj, fence); out_unpin: @@ -761,7 +761,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj, offset = 0; } - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); i915_gem_object_unlock_fence(obj, fence); return ret; diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 62670459ee8e..c5330f36687d 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1148,8 +1148,14 @@ int i915_vma_move_to_active(struct i915_vma *vma, return err; if (flags & EXEC_OBJECT_WRITE) { - if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS)) - i915_active_add_request(&obj->frontbuffer->write, rq); + struct intel_frontbuffer *front; + + front = __intel_frontbuffer_get(obj); + if (unlikely(front)) { + if (intel_frontbuffer_invalidate(front, ORIGIN_CS)) + i915_active_add_request(&front->write, rq); + intel_frontbuffer_put(front); + } dma_resv_add_excl_fence(vma->resv, &rq->fence); obj->write_domain = I915_GEM_DOMAIN_RENDER; -- cgit v1.2.3 From 81ff52b705775433a955b2746d37b87bdc89a3d0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Dec 2019 09:35:04 +0000 Subject: drm/i915/gt: Ratelimit display power w/a For very light workloads that frequently park, acquiring the display power well (required to prevent the dmc from trashing the system) takes longer than the execution. A good example is the igt_coherency selftest, which is slowed down by an order of magnitude in the worst case with powerwell cycling. To prevent frequent cycling, while keeping our fast soft-rc6, use a timer to delay release of the display powerwell. Fixes: 311770173fac ("drm/i915/gt: Schedule request retirement when timeline idles") References: https://gitlab.freedesktop.org/drm/intel/issues/848 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191218093504.3477048-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index bb57e3443a50..f36ce36dabeb 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -88,8 +88,9 @@ static int __gt_park(struct intel_wakeref *wf) /* Everything switched off, flush any residual interrupt just in case */ intel_synchronize_irq(i915); + /* Defer dropping the display power well for 100ms, it's slow! */ GEM_BUG_ON(!wakeref); - intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref); + intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref); i915_globals_park(); -- cgit v1.2.3 From ab2dd990f4abfb3897d1180fa39a8b2fbaef2f0c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 7 Nov 2019 16:24:13 +0200 Subject: drm: Add __drm_atomic_helper_crtc_state_reset() & co. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Annoyingly __drm_atomic_helper_crtc_reset() does two totally separate things: a) reset the state to defaults values b) assign the crtc->state pointer I just want a) without the b) so let's split out part a) into __drm_atomic_helper_crtc_state_reset(). And of course we'll do the same thing for planes and connectors. v2: Fix conn__state vs. conn_state typo (Lucas) Make code and kerneldoc match for __drm_atomic_helper_plane_state_reset() Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191107142417.11107-1-ville.syrjala@linux.intel.com Reviewed-by: Lucas De Marchi Reviewed-by: Daniel Vetter Acked-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_state_helper.c | 78 +++++++++++++++++++++++++------ include/drm/drm_atomic_state_helper.h | 6 +++ 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index d0a937fb0c56..7cf3cf936547 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -57,6 +57,22 @@ * for these functions. */ +/** + * __drm_atomic_helper_crtc_state_reset - reset the CRTC state + * @crtc_state: atomic CRTC state, must not be NULL + * @crtc: CRTC object, must not be NULL + * + * Initializes the newly allocated @crtc_state with default + * values. This is useful for drivers that subclass the CRTC state. + */ +void +__drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *crtc_state, + struct drm_crtc *crtc) +{ + crtc_state->crtc = crtc; +} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset); + /** * __drm_atomic_helper_crtc_reset - reset state on CRTC * @crtc: drm CRTC @@ -74,7 +90,7 @@ __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state) { if (crtc_state) - crtc_state->crtc = crtc; + __drm_atomic_helper_crtc_state_reset(crtc_state, crtc); crtc->state = crtc_state; } @@ -212,23 +228,43 @@ void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); /** - * __drm_atomic_helper_plane_reset - resets planes state to default values + * __drm_atomic_helper_plane_state_reset - resets plane state to default values + * @plane_state: atomic plane state, must not be NULL * @plane: plane object, must not be NULL - * @state: atomic plane state, must not be NULL * - * Initializes plane state to default. This is useful for drivers that subclass - * the plane state. + * Initializes the newly allocated @plane_state with default + * values. This is useful for drivers that subclass the CRTC state. */ -void __drm_atomic_helper_plane_reset(struct drm_plane *plane, - struct drm_plane_state *state) +void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state, + struct drm_plane *plane) { - state->plane = plane; - state->rotation = DRM_MODE_ROTATE_0; + plane_state->plane = plane; + plane_state->rotation = DRM_MODE_ROTATE_0; - state->alpha = DRM_BLEND_ALPHA_OPAQUE; - state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; + plane_state->alpha = DRM_BLEND_ALPHA_OPAQUE; + plane_state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; +} +EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset); - plane->state = state; +/** + * __drm_atomic_helper_plane_reset - reset state on plane + * @plane: drm plane + * @plane_state: plane state to assign + * + * Initializes the newly allocated @plane_state and assigns it to + * the &drm_crtc->state pointer of @plane, usually required when + * initializing the drivers or when called from the &drm_plane_funcs.reset + * hook. + * + * This is useful for drivers that subclass the plane state. + */ +void __drm_atomic_helper_plane_reset(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + if (plane_state) + __drm_atomic_helper_plane_state_reset(plane_state, plane); + + plane->state = plane_state; } EXPORT_SYMBOL(__drm_atomic_helper_plane_reset); @@ -335,6 +371,22 @@ void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, } EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); +/** + * __drm_atomic_helper_connector_state_reset - reset the connector state + * @conn_state: atomic connector state, must not be NULL + * @connector: connectotr object, must not be NULL + * + * Initializes the newly allocated @conn_state with default + * values. This is useful for drivers that subclass the connector state. + */ +void +__drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state, + struct drm_connector *connector) +{ + conn_state->connector = connector; +} +EXPORT_SYMBOL(__drm_atomic_helper_connector_state_reset); + /** * __drm_atomic_helper_connector_reset - reset state on connector * @connector: drm connector @@ -352,7 +404,7 @@ __drm_atomic_helper_connector_reset(struct drm_connector *connector, struct drm_connector_state *conn_state) { if (conn_state) - conn_state->connector = connector; + __drm_atomic_helper_connector_state_reset(conn_state, connector); connector->state = conn_state; } diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index e4577cc11689..8171dea4cc22 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -37,6 +37,8 @@ struct drm_private_state; struct drm_modeset_acquire_ctx; struct drm_device; +void __drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *state, + struct drm_crtc *crtc); void __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc, struct drm_crtc_state *state); void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); @@ -48,6 +50,8 @@ void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state); void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); +void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *state, + struct drm_plane *plane); void __drm_atomic_helper_plane_reset(struct drm_plane *plane, struct drm_plane_state *state); void drm_atomic_helper_plane_reset(struct drm_plane *plane); @@ -59,6 +63,8 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state); void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); +void __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state, + struct drm_connector *connector); void __drm_atomic_helper_connector_reset(struct drm_connector *connector, struct drm_connector_state *conn_state); void drm_atomic_helper_connector_reset(struct drm_connector *connector); -- cgit v1.2.3 From f44bfa7fbfbb6ab1642d12565673a70c0e99c320 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 7 Nov 2019 16:24:14 +0200 Subject: drm/i915: s/intel_crtc/crtc/ in intel_crtc_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's get rid of the redundant intel_ prefix on our variables. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191107142417.11107-2-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index bba73b0783ad..1cd37cbdd353 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15787,14 +15787,14 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = { static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) { const struct drm_crtc_funcs *funcs; - struct intel_crtc *intel_crtc; + struct intel_crtc *crtc; struct intel_crtc_state *crtc_state = NULL; struct intel_plane *primary = NULL; struct intel_plane *cursor = NULL; int sprite, ret; - intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); - if (!intel_crtc) + crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); + if (!crtc) return -ENOMEM; crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); @@ -15802,15 +15802,15 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) ret = -ENOMEM; goto fail; } - __drm_atomic_helper_crtc_reset(&intel_crtc->base, &crtc_state->uapi); - intel_crtc->config = crtc_state; + __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->uapi); + crtc->config = crtc_state; primary = intel_primary_plane_create(dev_priv, pipe); if (IS_ERR(primary)) { ret = PTR_ERR(primary); goto fail; } - intel_crtc->plane_ids_mask |= BIT(primary->id); + crtc->plane_ids_mask |= BIT(primary->id); for_each_sprite(dev_priv, pipe, sprite) { struct intel_plane *plane; @@ -15820,7 +15820,7 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) ret = PTR_ERR(plane); goto fail; } - intel_crtc->plane_ids_mask |= BIT(plane->id); + crtc->plane_ids_mask |= BIT(plane->id); } cursor = intel_cursor_plane_create(dev_priv, pipe); @@ -15828,7 +15828,7 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) ret = PTR_ERR(cursor); goto fail; } - intel_crtc->plane_ids_mask |= BIT(cursor->id); + crtc->plane_ids_mask |= BIT(cursor->id); if (HAS_GMCH(dev_priv)) { if (IS_CHERRYVIEW(dev_priv) || @@ -15849,32 +15849,32 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) funcs = &ilk_crtc_funcs; } - ret = drm_crtc_init_with_planes(&dev_priv->drm, &intel_crtc->base, + ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base, &primary->base, &cursor->base, funcs, "pipe %c", pipe_name(pipe)); if (ret) goto fail; - intel_crtc->pipe = pipe; + crtc->pipe = pipe; /* initialize shared scalers */ - intel_crtc_init_scalers(intel_crtc, crtc_state); + intel_crtc_init_scalers(crtc, crtc_state); BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) || dev_priv->pipe_to_crtc_mapping[pipe] != NULL); - dev_priv->pipe_to_crtc_mapping[pipe] = intel_crtc; + dev_priv->pipe_to_crtc_mapping[pipe] = crtc; if (INTEL_GEN(dev_priv) < 9) { enum i9xx_plane_id i9xx_plane = primary->i9xx_plane; BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL); - dev_priv->plane_to_crtc_mapping[i9xx_plane] = intel_crtc; + dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc; } - intel_color_init(intel_crtc); + intel_color_init(crtc); - WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe); + WARN_ON(drm_crtc_index(&crtc->base) != crtc->pipe); return 0; @@ -15884,7 +15884,7 @@ fail: * crtcs/planes already initialized. */ kfree(crtc_state); - kfree(intel_crtc); + kfree(crtc); return ret; } -- cgit v1.2.3 From 6643453987c44d5d37709c3021d21d0e3bb4d5c4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 7 Nov 2019 16:24:15 +0200 Subject: drm/i915: Introduce intel_crtc_{alloc,free}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have alloc/free helpers for planes, add the same for crtcs. The main benefit is we get to move all the annoying state initialization out of the main crtc_init() flow. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191107142417.11107-3-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 74 ++++++++++++++-------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1cd37cbdd353..d8ccbb0b4653 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -164,8 +164,7 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); -static void intel_crtc_init_scalers(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state); +static void intel_crtc_init_scalers(struct intel_crtc_state *crtc_state); static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state); static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state); static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state); @@ -10630,7 +10629,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, u64 power_domain_mask; bool active; - intel_crtc_init_scalers(crtc, pipe_config); + intel_crtc_init_scalers(pipe_config); pipe_config->master_transcoder = INVALID_TRANSCODER; @@ -15695,25 +15694,12 @@ fail: return ERR_PTR(ret); } -static void intel_crtc_init_scalers(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) +static void intel_crtc_init_scalers(struct intel_crtc_state *crtc_state) { struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - int i; - - crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[crtc->pipe]; - if (!crtc->num_scalers) - return; - - for (i = 0; i < crtc->num_scalers; i++) { - struct intel_scaler *scaler = &scaler_state->scalers[i]; - - scaler->in_use = 0; - scaler->mode = 0; - } + memset(scaler_state, 0, sizeof(*scaler_state)); scaler_state->scaler_id = -1; } @@ -15784,27 +15770,49 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = { .disable_vblank = i8xx_disable_vblank, }; -static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) +static struct intel_crtc *intel_crtc_alloc(void) { - const struct drm_crtc_funcs *funcs; + struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; - struct intel_crtc_state *crtc_state = NULL; - struct intel_plane *primary = NULL; - struct intel_plane *cursor = NULL; - int sprite, ret; crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); if (!crtc) - return -ENOMEM; + return ERR_PTR(-ENOMEM); crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); if (!crtc_state) { - ret = -ENOMEM; - goto fail; + kfree(crtc); + return ERR_PTR(-ENOMEM); } + __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->uapi); + intel_crtc_init_scalers(crtc_state); + crtc->config = crtc_state; + return crtc; +} + +static void intel_crtc_free(struct intel_crtc *crtc) +{ + intel_crtc_destroy_state(&crtc->base, crtc->base.state); + kfree(crtc); +} + +static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) +{ + struct intel_plane *primary, *cursor; + const struct drm_crtc_funcs *funcs; + struct intel_crtc *crtc; + int sprite, ret; + + crtc = intel_crtc_alloc(); + if (IS_ERR(crtc)) + return PTR_ERR(crtc); + + crtc->pipe = pipe; + crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe]; + primary = intel_primary_plane_create(dev_priv, pipe); if (IS_ERR(primary)) { ret = PTR_ERR(primary); @@ -15855,11 +15863,6 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) if (ret) goto fail; - crtc->pipe = pipe; - - /* initialize shared scalers */ - intel_crtc_init_scalers(crtc, crtc_state); - BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) || dev_priv->pipe_to_crtc_mapping[pipe] != NULL); dev_priv->pipe_to_crtc_mapping[pipe] = crtc; @@ -15879,12 +15882,7 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) return 0; fail: - /* - * drm_mode_config_cleanup() will free up any - * crtcs/planes already initialized. - */ - kfree(crtc_state); - kfree(crtc); + intel_crtc_free(crtc); return ret; } -- cgit v1.2.3 From 979e94c1d64ae961016f5da2118dd46c87826d9e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 7 Nov 2019 16:24:16 +0200 Subject: drm/i915: Introduce intel_crtc_state_reset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a few places where we want to reset a crtc state to its default values. Let's add a helper for that. We'll need the new __drm_atomic_helper_crtc_state_reset() helper for this to allow us to just reset the state itself without clobbering the crtc->state pointer. And while at it let's zero out the whole thing, except a few choice member which we'll mark as "invalid". And thanks to this we can now nuke intel_crtc_init_scalers(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191107142417.11107-4-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 47 +++++++++++++--------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d8ccbb0b4653..ab47816df2a2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -164,7 +164,6 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); -static void intel_crtc_init_scalers(struct intel_crtc_state *crtc_state); static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state); static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state); static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state); @@ -10629,8 +10628,6 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, u64 power_domain_mask; bool active; - intel_crtc_init_scalers(pipe_config); - pipe_config->master_transcoder = INVALID_TRANSCODER; power_domain = POWER_DOMAIN_PIPE(crtc->pipe); @@ -11678,6 +11675,20 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, &pipe_config->fdi_m_n); } +static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, + struct intel_crtc *crtc) +{ + memset(crtc_state, 0, sizeof(*crtc_state)); + + __drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base); + + crtc_state->cpu_transcoder = INVALID_TRANSCODER; + crtc_state->master_transcoder = INVALID_TRANSCODER; + crtc_state->hsw_workaround_pipe = INVALID_PIPE; + crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID; + crtc_state->scaler_state.scaler_id = -1; +} + /* Returns the currently programmed mode of the given encoder. */ struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder) @@ -11703,7 +11714,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder) return NULL; } - crtc_state->uapi.crtc = &crtc->base; + intel_crtc_state_reset(crtc_state, crtc); if (!dev_priv->display.get_pipe_config(crtc, crtc_state)) { kfree(crtc_state); @@ -13555,18 +13566,14 @@ verify_crtc_state(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_encoder *encoder; - struct intel_crtc_state *pipe_config; - struct drm_atomic_state *state; + struct intel_crtc_state *pipe_config = old_crtc_state; + struct drm_atomic_state *state = old_crtc_state->uapi.state; bool active; - state = old_crtc_state->uapi.state; __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); intel_crtc_free_hw_state(old_crtc_state); - - pipe_config = old_crtc_state; - memset(pipe_config, 0, sizeof(*pipe_config)); - pipe_config->uapi.crtc = &crtc->base; - pipe_config->uapi.state = state; + intel_crtc_state_reset(old_crtc_state, crtc); + old_crtc_state->uapi.state = state; DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.base.id, crtc->base.name); @@ -15694,15 +15701,6 @@ fail: return ERR_PTR(ret); } -static void intel_crtc_init_scalers(struct intel_crtc_state *crtc_state) -{ - struct intel_crtc_scaler_state *scaler_state = - &crtc_state->scaler_state; - - memset(scaler_state, 0, sizeof(*scaler_state)); - scaler_state->scaler_id = -1; -} - #define INTEL_CRTC_FUNCS \ .gamma_set = drm_atomic_helper_legacy_gamma_set, \ .set_config = drm_atomic_helper_set_config, \ @@ -15785,9 +15783,9 @@ static struct intel_crtc *intel_crtc_alloc(void) return ERR_PTR(-ENOMEM); } - __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->uapi); - intel_crtc_init_scalers(crtc_state); + intel_crtc_state_reset(crtc_state, crtc); + crtc->base.state = &crtc_state->uapi; crtc->config = crtc_state; return crtc; @@ -17408,8 +17406,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi); intel_crtc_free_hw_state(crtc_state); - memset(crtc_state, 0, sizeof(*crtc_state)); - __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->uapi); + intel_crtc_state_reset(crtc_state, crtc); crtc_state->hw.active = crtc_state->hw.enable = dev_priv->display.get_pipe_config(crtc, crtc_state); -- cgit v1.2.3 From 74cb2751d42efc17abdeba8ed3f2c322e41cfad5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 7 Nov 2019 16:24:17 +0200 Subject: drm/i915: Introduce intel_plane_state_reset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the sake of symmetry with the crtc stuff let's add a helper to reset the plane state to sane default values. For the moment this only gets caller from the plane init. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191107142417.11107-5-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 42b3b3449d2e..9429b8e17270 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -41,6 +41,16 @@ #include "intel_pm.h" #include "intel_sprite.h" +static void intel_plane_state_reset(struct intel_plane_state *plane_state, + struct intel_plane *plane) +{ + memset(plane_state, 0, sizeof(*plane_state)); + + __drm_atomic_helper_plane_state_reset(&plane_state->uapi, &plane->base); + + plane_state->scaler_id = -1; +} + struct intel_plane *intel_plane_alloc(void) { struct intel_plane_state *plane_state; @@ -56,8 +66,9 @@ struct intel_plane *intel_plane_alloc(void) return ERR_PTR(-ENOMEM); } - __drm_atomic_helper_plane_reset(&plane->base, &plane_state->uapi); - plane_state->scaler_id = -1; + intel_plane_state_reset(plane_state, plane); + + plane->base.state = &plane_state->uapi; return plane; } -- cgit v1.2.3 From 6a6d79de4d194c7b8db35be74b9f29863f74f76b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2019 21:52:13 +0200 Subject: drm/i915: Call hsw_fdi_link_train() directly() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the pointless vfunc detour for hsw_fdi_link_train() and just call it directly. Also pass the encoder in so we can nuke the silly encoder loop within. Cc: José Roberto de Souza Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213195217.15168-1-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_crt.c | 2 +- drivers/gpu/drm/i915/display/intel_ddi.c | 12 ++++-------- drivers/gpu/drm/i915/display/intel_ddi.h | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 2 -- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 7a2d36905155..50624b8f064d 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -278,7 +278,7 @@ static void hsw_pre_enable_crt(struct intel_encoder *encoder, intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - dev_priv->display.fdi_link_train(crtc, crtc_state); + hsw_fdi_link_train(encoder, crtc_state); intel_ddi_enable_pipe_clock(crtc_state); } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 5b6f32517c75..94f8bc4cd335 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1107,18 +1107,14 @@ static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder, * DDI A (which is used for eDP) */ -void hsw_fdi_link_train(struct intel_crtc *crtc, +void hsw_fdi_link_train(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_encoder *encoder; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 temp, i, rx_ctl_val, ddi_pll_sel; - for_each_encoder_on_crtc(dev, &crtc->base, encoder) { - WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG); - intel_prepare_dp_ddi_buffers(encoder, crtc_state); - } + intel_prepare_dp_ddi_buffers(encoder, crtc_state); /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the * mode set "sequence for CRT port" document: diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index 19aeab1246ee..167c6579d972 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -22,7 +22,7 @@ struct intel_encoder; void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state); -void hsw_fdi_link_train(struct intel_crtc *crtc, +void hsw_fdi_link_train(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port); bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ab47816df2a2..2cef56ff0011 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -16672,8 +16672,6 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) } else if (IS_IVYBRIDGE(dev_priv)) { /* FIXME: detect B0+ stepping and use auto training */ dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; - } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - dev_priv->display.fdi_link_train = hsw_fdi_link_train; } if (INTEL_GEN(dev_priv) >= 9) -- cgit v1.2.3 From 17bef9baf33913ecb27f85f81b48afeca34946bb Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2019 21:52:14 +0200 Subject: drm/i915: Nuke .post_pll_disable() for DDI platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HSW+ platforms call encoder .post_disable() and .post_pll_disable() back to back. And since we don't even disable the PLL in between let's just move everything into .post_disable(). intel_dp_mst does forward the .post_disable() call to intel_ddi at the very end of its own .post_disable() hook, so this time MST I shouldn't even break MST by accident. Cc: José Roberto de Souza Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213195217.15168-2-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_ddi.c | 29 ++++++++++------------------ drivers/gpu/drm/i915/display/intel_display.c | 2 -- drivers/gpu/drm/i915/display/intel_dp_mst.c | 15 -------------- 3 files changed, 10 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 94f8bc4cd335..cac0be47e500 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3856,6 +3856,9 @@ static void intel_ddi_post_disable(struct intel_encoder *encoder, const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); + enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + bool is_tc_port = intel_phy_is_tc(dev_priv, phy); /* * When called from DP MST code: @@ -3879,6 +3882,13 @@ static void intel_ddi_post_disable(struct intel_encoder *encoder, if (INTEL_GEN(dev_priv) >= 11) icl_unmap_plls_to_ports(encoder); + + if (intel_crtc_has_dp_encoder(old_crtc_state) || is_tc_port) + intel_display_power_put_unchecked(dev_priv, + intel_ddi_main_link_aux_domain(dig_port)); + + if (is_tc_port) + intel_tc_port_put_link(dig_port); } void intel_ddi_fdi_post_disable(struct intel_encoder *encoder, @@ -4191,24 +4201,6 @@ intel_ddi_pre_pll_enable(struct intel_encoder *encoder, crtc_state->lane_lat_optim_mask); } -static void -intel_ddi_post_pll_disable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); - bool is_tc_port = intel_phy_is_tc(dev_priv, phy); - - if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port) - intel_display_power_put_unchecked(dev_priv, - intel_ddi_main_link_aux_domain(dig_port)); - - if (is_tc_port) - intel_tc_port_put_link(dig_port); -} - static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); @@ -4795,7 +4787,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->compute_config = intel_ddi_compute_config; encoder->enable = intel_enable_ddi; encoder->pre_pll_enable = intel_ddi_pre_pll_enable; - encoder->post_pll_disable = intel_ddi_post_pll_disable; encoder->pre_enable = intel_ddi_pre_enable; encoder->disable = intel_disable_ddi; encoder->post_disable = intel_ddi_post_disable; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2cef56ff0011..d922f5918fcd 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6765,8 +6765,6 @@ static void haswell_crtc_disable(struct intel_atomic_state *state, ironlake_pfit_disable(old_crtc_state); intel_encoders_post_disable(state, crtc); - - intel_encoders_post_pll_disable(state, crtc); } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 926e49f449a6..8bdbb15799ee 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -286,20 +286,6 @@ static void intel_mst_pre_pll_enable_dp(struct intel_encoder *encoder, pipe_config, NULL); } -static void intel_mst_post_pll_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_mst_encoder *intel_mst = enc_to_mst(&encoder->base); - struct intel_digital_port *intel_dig_port = intel_mst->primary; - struct intel_dp *intel_dp = &intel_dig_port->dp; - - if (intel_dp->active_mst_links == 0) - intel_dig_port->base.post_pll_disable(&intel_dig_port->base, - old_crtc_state, - old_conn_state); -} - static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) @@ -656,7 +642,6 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum intel_encoder->disable = intel_mst_disable_dp; intel_encoder->post_disable = intel_mst_post_disable_dp; intel_encoder->pre_pll_enable = intel_mst_pre_pll_enable_dp; - intel_encoder->post_pll_disable = intel_mst_post_pll_disable_dp; intel_encoder->pre_enable = intel_mst_pre_enable_dp; intel_encoder->enable = intel_mst_enable_dp; intel_encoder->get_hw_state = intel_dp_mst_enc_get_hw_state; -- cgit v1.2.3 From cfb627c448510e07194cd97ec05fce3f7f279069 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2019 21:52:15 +0200 Subject: drm/i915: Pass old crtc state to skylake_scaler_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make life easier in the future let's pass the old crtc state to skylake_scaler_disable() just like we already do for for its ancestor ironlake_pfit_disable(). Cc: José Roberto de Souza Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213195217.15168-3-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d922f5918fcd..12e39911b22a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5767,8 +5767,9 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, return 0; } -static void skylake_scaler_disable(struct intel_crtc *crtc) +static void skylake_scaler_disable(const struct intel_crtc_state *old_crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); int i; for (i = 0; i < crtc->num_scalers; i++) @@ -6760,7 +6761,7 @@ static void haswell_crtc_disable(struct intel_atomic_state *state, intel_dsc_disable(old_crtc_state); if (INTEL_GEN(dev_priv) >= 9) - skylake_scaler_disable(crtc); + skylake_scaler_disable(old_crtc_state); else ironlake_pfit_disable(old_crtc_state); -- cgit v1.2.3 From f5271ee50d28451d960072737e55d826c7976fc4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2019 21:52:16 +0200 Subject: drm/i915: Pass old crtc state to intel_crtc_vblank_off() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make life easier in the future let's pass the old crtc state to intel_crtc_vblank_off() just like we already do for its counterpart intel_crtc_vblank_on(). Cc: José Roberto de Souza Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213195217.15168-4-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 12e39911b22a..cd79b4a5acf6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1823,8 +1823,10 @@ static void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) drm_crtc_vblank_on(&crtc->base); } -static void intel_crtc_vblank_off(struct intel_crtc *crtc) +static void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + drm_crtc_vblank_off(&crtc->base); assert_vblank_disabled(&crtc->base); } @@ -6697,7 +6699,7 @@ static void ironlake_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); - intel_crtc_vblank_off(crtc); + intel_crtc_vblank_off(old_crtc_state); intel_disable_pipe(old_crtc_state); @@ -6746,7 +6748,7 @@ static void haswell_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); - intel_crtc_vblank_off(crtc); + intel_crtc_vblank_off(old_crtc_state); /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) @@ -7111,7 +7113,7 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); - intel_crtc_vblank_off(crtc); + intel_crtc_vblank_off(old_crtc_state); intel_disable_pipe(old_crtc_state); -- cgit v1.2.3 From 773b4b54351c0491d4edbfc9caf1ee0231e7c506 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2019 21:52:17 +0200 Subject: drm/i915: Move stuff from haswell_crtc_disable() into encoder .post_disable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move all of haswell_crtc_disable() into the encoder .post_disable() hooks. Now we're left with just calling the .disable() and .post_disable() hooks back to back. I chose to move the code into the .post_disable() hook instead of the .disable() hook as most of the sequence is currently implemented in the .post_disable() hook. We should collapse it all down to just one hook and then the encoders can drive the modeset sequence fully. But that may need some further refactoring as we currently call the ddi .post_disable() hook from mst code and we can't just replace that with a call to the ddi .disable() hook. Should also follow up with similar treatment for the enable sequence but let's start here where it's easier. Cc: José Roberto de Souza Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213195217.15168-5-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/icl_dsi.c | 12 ++++++ drivers/gpu/drm/i915/display/intel_crt.c | 8 ++++ drivers/gpu/drm/i915/display/intel_ddi.c | 35 +++++++++++++++++ drivers/gpu/drm/i915/display/intel_display.c | 57 ++++------------------------ drivers/gpu/drm/i915/display/intel_display.h | 4 ++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 11 ++++++ drivers/gpu/drm/i915/display/vlv_dsi.c | 10 ++++- 7 files changed, 86 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 03aa92d317a2..006b1a297e6f 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1251,6 +1251,17 @@ static void gen11_dsi_disable(struct intel_encoder *encoder, gen11_dsi_disable_io_power(encoder); } +static void gen11_dsi_post_disable(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + intel_crtc_vblank_off(old_crtc_state); + + intel_dsc_disable(old_crtc_state); + + skylake_scaler_disable(old_crtc_state); +} + static enum drm_mode_status gen11_dsi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { @@ -1697,6 +1708,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) encoder->pre_pll_enable = gen11_dsi_pre_pll_enable; encoder->pre_enable = gen11_dsi_pre_enable; encoder->disable = gen11_dsi_disable; + encoder->post_disable = gen11_dsi_post_disable; encoder->port = port; encoder->get_config = gen11_dsi_get_config; encoder->update_pipe = intel_panel_update_backlight; diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 50624b8f064d..b2b1336ecdb6 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -241,6 +241,14 @@ static void hsw_post_disable_crt(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + intel_crtc_vblank_off(old_crtc_state); + + intel_disable_pipe(old_crtc_state); + + intel_ddi_disable_transcoder_func(old_crtc_state); + + ironlake_pfit_disable(old_crtc_state); + intel_ddi_disable_pipe_clock(old_crtc_state); pch_post_disable_crt(encoder, old_crtc_state, old_conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index cac0be47e500..fa40ba7cbcad 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3851,6 +3851,25 @@ static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder, intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); } +static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + i915_reg_t reg; + u32 trans_ddi_func_ctl2_val; + + if (old_crtc_state->master_transcoder == INVALID_TRANSCODER) + return; + + DRM_DEBUG_KMS("Disabling Transcoder Port Sync on Slave Transcoder %s\n", + transcoder_name(old_crtc_state->cpu_transcoder)); + + reg = TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder); + trans_ddi_func_ctl2_val = ~(PORT_SYNC_MODE_ENABLE | + PORT_SYNC_MODE_MASTER_SELECT_MASK); + I915_WRITE(reg, trans_ddi_func_ctl2_val); +} + static void intel_ddi_post_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -3860,6 +3879,22 @@ static void intel_ddi_post_disable(struct intel_encoder *encoder, enum phy phy = intel_port_to_phy(dev_priv, encoder->port); bool is_tc_port = intel_phy_is_tc(dev_priv, phy); + intel_crtc_vblank_off(old_crtc_state); + + intel_disable_pipe(old_crtc_state); + + if (INTEL_GEN(dev_priv) >= 11) + icl_disable_transcoder_port_sync(old_crtc_state); + + intel_ddi_disable_transcoder_func(old_crtc_state); + + intel_dsc_disable(old_crtc_state); + + if (INTEL_GEN(dev_priv) >= 9) + skylake_scaler_disable(old_crtc_state); + else + ironlake_pfit_disable(old_crtc_state); + /* * When called from DP MST code: * - old_conn_state will be NULL diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index cd79b4a5acf6..38bc92256f64 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -165,7 +165,6 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state); -static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state); static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state); static void intel_modeset_setup_hw_state(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx); @@ -1823,7 +1822,7 @@ static void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state) drm_crtc_vblank_on(&crtc->base); } -static void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state) +void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -1889,7 +1888,7 @@ static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state) intel_wait_for_pipe_scanline_moving(crtc); } -static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state) +void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -4580,25 +4579,6 @@ static void icl_enable_trans_port_sync(const struct intel_crtc_state *crtc_state trans_ddi_func_ctl2_val); } -static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - i915_reg_t reg; - u32 trans_ddi_func_ctl2_val; - - if (old_crtc_state->master_transcoder == INVALID_TRANSCODER) - return; - - DRM_DEBUG_KMS("Disabling Transcoder Port Sync on Slave Transcoder %s\n", - transcoder_name(old_crtc_state->cpu_transcoder)); - - reg = TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder); - trans_ddi_func_ctl2_val = ~(PORT_SYNC_MODE_ENABLE | - PORT_SYNC_MODE_MASTER_SELECT_MASK); - I915_WRITE(reg, trans_ddi_func_ctl2_val); -} - static void intel_fdi_normal_train(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; @@ -5769,7 +5749,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, return 0; } -static void skylake_scaler_disable(const struct intel_crtc_state *old_crtc_state) +void skylake_scaler_disable(const struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); int i; @@ -6666,7 +6646,7 @@ static void haswell_crtc_enable(struct intel_atomic_state *state, } } -static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state) +void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -6741,32 +6721,11 @@ static void ironlake_crtc_disable(struct intel_atomic_state *state, static void haswell_crtc_disable(struct intel_atomic_state *state, struct intel_crtc *crtc) { - const struct intel_crtc_state *old_crtc_state = - intel_atomic_get_old_crtc_state(state, crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; - + /* + * FIXME collapse everything to one hook. + * Need care with mst->ddi interactions. + */ intel_encoders_disable(state, crtc); - - intel_crtc_vblank_off(old_crtc_state); - - /* XXX: Do the pipe assertions at the right place for BXT DSI. */ - if (!transcoder_is_dsi(cpu_transcoder)) - intel_disable_pipe(old_crtc_state); - - if (INTEL_GEN(dev_priv) >= 11) - icl_disable_transcoder_port_sync(old_crtc_state); - - if (!transcoder_is_dsi(cpu_transcoder)) - intel_ddi_disable_transcoder_func(old_crtc_state); - - intel_dsc_disable(old_crtc_state); - - if (INTEL_GEN(dev_priv) >= 9) - skylake_scaler_disable(old_crtc_state); - else - ironlake_pfit_disable(old_crtc_state); - intel_encoders_post_disable(state, crtc); } diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 327376810f66..ff496cfbd4ab 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -485,6 +485,7 @@ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port); bool is_trans_port_sync_mode(const struct intel_crtc_state *state); void intel_plane_destroy(struct drm_plane *plane); +void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state); void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc); @@ -518,6 +519,7 @@ enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc); +void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state); int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp); void vlv_wait_port_ready(struct drm_i915_private *dev_priv, @@ -576,6 +578,8 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center); int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); +void skylake_scaler_disable(const struct intel_crtc_state *old_crtc_state); +void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state); u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 8bdbb15799ee..7aa0975c33b7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -241,6 +241,17 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, intel_dp->active_mst_links--; last_mst_stream = intel_dp->active_mst_links == 0; + intel_crtc_vblank_off(old_crtc_state); + + intel_disable_pipe(old_crtc_state); + + intel_ddi_disable_transcoder_func(old_crtc_state); + + if (INTEL_GEN(dev_priv) >= 9) + skylake_scaler_disable(old_crtc_state); + else + ironlake_pfit_disable(old_crtc_state); + /* * From TGL spec: "If multi-stream slave transcoder: Configure * Transcoder Clock Select to direct no clock to the transcoder" diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 8398a265b6a3..21e820299107 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -882,8 +882,8 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) } static void intel_dsi_post_disable(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); @@ -892,6 +892,12 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder, DRM_DEBUG_KMS("\n"); + if (IS_GEN9_LP(dev_priv)) { + intel_crtc_vblank_off(old_crtc_state); + + skylake_scaler_disable(old_crtc_state); + } + if (is_vid_mode(intel_dsi)) { for_each_dsi_port(port, intel_dsi->ports) vlv_dsi_wait_for_fifo_empty(intel_dsi, port); -- cgit v1.2.3 From df6a42053513846475ae1fbd224dfbdbcd0c7010 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 17 Dec 2019 14:20:57 +0000 Subject: drm/i915/pmu: Ensure monotonic rc6 Avoid rc6 counter going backward in close to 0% RC6 scenarios like: 15.005477996 114,246,613 ns i915/rc6-residency/ 16.005876662 667,657 ns i915/rc6-residency/ 17.006131417 7,286 ns i915/rc6-residency/ 18.006615031 18,446,744,073,708,914,688 ns i915/rc6-residency/ 19.007158361 18,446,744,073,709,447,168 ns i915/rc6-residency/ 20.007806498 0 ns i915/rc6-residency/ 21.008227495 1,440,403 ns i915/rc6-residency/ There are two aspects to this fix. First is not assuming rc6 value zero means GT is asleep since that can also mean GPU is fully busy and we do not want to enter the estimation path in that case. Second is ensuring monotonicity on the estimation path itself. I suspect what is happening is with extremely rapid park/unpark cycles we get no updates on the real rc6 and therefore have to careful not to unconditionally trust use last known real rc6 when creating a new estimation. v2: * Simplify logic by not tracking the estimate but last reported value. Signed-off-by: Tvrtko Ursulin Fixes: 16ffe73c186b ("drm/i915/pmu: Use GT parked for estimating RC6 while asleep") Cc: Chris Wilson Reviewed-by: Chris Wilson # v1 Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191217142057.1000-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 73 +++++++++++------------------------------ drivers/gpu/drm/i915/i915_pmu.h | 2 +- 2 files changed, 21 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 00325471be90..f3ef6700a5f2 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -144,61 +144,40 @@ static inline s64 ktime_since(const ktime_t kt) return ktime_to_ns(ktime_sub(ktime_get(), kt)); } -static u64 __pmu_estimate_rc6(struct i915_pmu *pmu) -{ - u64 val; - - /* - * We think we are runtime suspended. - * - * Report the delta from when the device was suspended to now, - * on top of the last known real value, as the approximated RC6 - * counter value. - */ - val = ktime_since(pmu->sleep_last); - val += pmu->sample[__I915_SAMPLE_RC6].cur; - - pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val; - - return val; -} - -static u64 __pmu_update_rc6(struct i915_pmu *pmu, u64 val) -{ - /* - * If we are coming back from being runtime suspended we must - * be careful not to report a larger value than returned - * previously. - */ - if (val >= pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur) { - pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0; - pmu->sample[__I915_SAMPLE_RC6].cur = val; - } else { - val = pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur; - } - - return val; -} - static u64 get_rc6(struct intel_gt *gt) { struct drm_i915_private *i915 = gt->i915; struct i915_pmu *pmu = &i915->pmu; unsigned long flags; + bool awake = false; u64 val; - val = 0; if (intel_gt_pm_get_if_awake(gt)) { val = __get_rc6(gt); intel_gt_pm_put_async(gt); + awake = true; } spin_lock_irqsave(&pmu->lock, flags); - if (val) - val = __pmu_update_rc6(pmu, val); + if (awake) { + pmu->sample[__I915_SAMPLE_RC6].cur = val; + } else { + /* + * We think we are runtime suspended. + * + * Report the delta from when the device was suspended to now, + * on top of the last known real value, as the approximated RC6 + * counter value. + */ + val = ktime_since(pmu->sleep_last); + val += pmu->sample[__I915_SAMPLE_RC6].cur; + } + + if (val < pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur) + val = pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur; else - val = __pmu_estimate_rc6(pmu); + pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = val; spin_unlock_irqrestore(&pmu->lock, flags); @@ -210,20 +189,11 @@ static void park_rc6(struct drm_i915_private *i915) struct i915_pmu *pmu = &i915->pmu; if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY)) - __pmu_update_rc6(pmu, __get_rc6(&i915->gt)); + pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt); pmu->sleep_last = ktime_get(); } -static void unpark_rc6(struct drm_i915_private *i915) -{ - struct i915_pmu *pmu = &i915->pmu; - - /* Estimate how long we slept and accumulate that into rc6 counters */ - if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY)) - __pmu_estimate_rc6(pmu); -} - #else static u64 get_rc6(struct intel_gt *gt) @@ -232,7 +202,6 @@ static u64 get_rc6(struct intel_gt *gt) } static void park_rc6(struct drm_i915_private *i915) {} -static void unpark_rc6(struct drm_i915_private *i915) {} #endif @@ -281,8 +250,6 @@ void i915_pmu_gt_unparked(struct drm_i915_private *i915) */ __i915_pmu_maybe_start_timer(pmu); - unpark_rc6(i915); - spin_unlock_irq(&pmu->lock); } diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index bf52e3983631..6c1647c5daf2 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -18,7 +18,7 @@ enum { __I915_SAMPLE_FREQ_ACT = 0, __I915_SAMPLE_FREQ_REQ, __I915_SAMPLE_RC6, - __I915_SAMPLE_RC6_ESTIMATED, + __I915_SAMPLE_RC6_LAST_REPORTED, __I915_NUM_PMU_SAMPLERS }; -- cgit v1.2.3 From 54400257ae523fa7fff11fe4209e7f9dcafdefa0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 17 Dec 2019 09:56:41 +0000 Subject: drm/i915/gt: Remove direct invocation of breadcrumb signaling Only signal the breadcrumbs from inside the irq_work, simplifying our interface and calling conventions. The micro-optimisation here is that by always using the irq_work interface, we know we are always inside an irq-off critical section for the breadcrumb signaling and can ellide save/restore of the irq flags. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191217095642.3124521-7-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 27 +++++++++---------------- drivers/gpu/drm/i915/gt/intel_engine.h | 4 +--- drivers/gpu/drm/i915/gt/intel_gt_irq.c | 12 +++++------ drivers/gpu/drm/i915/gt/intel_lrc.c | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 4 ++-- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 2 +- drivers/gpu/drm/i915/gt/intel_rps.c | 2 +- drivers/gpu/drm/i915/gt/mock_engine.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 8 ++++---- drivers/gpu/drm/i915/i915_request.c | 2 +- 10 files changed, 27 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 8a9facf4f3b6..5fa4d621528e 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -130,16 +130,15 @@ __dma_fence_signal__notify(struct dma_fence *fence, } } -void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) +static void signal_irq_work(struct irq_work *work) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; + struct intel_breadcrumbs *b = container_of(work, typeof(*b), irq_work); const ktime_t timestamp = ktime_get(); struct intel_context *ce, *cn; struct list_head *pos, *next; - unsigned long flags; LIST_HEAD(signal); - spin_lock_irqsave(&b->irq_lock, flags); + spin_lock(&b->irq_lock); if (b->irq_armed && list_empty(&b->signalers)) __intel_breadcrumbs_disarm_irq(b); @@ -185,31 +184,23 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) } } - spin_unlock_irqrestore(&b->irq_lock, flags); + spin_unlock(&b->irq_lock); list_for_each_safe(pos, next, &signal) { struct i915_request *rq = list_entry(pos, typeof(*rq), signal_link); struct list_head cb_list; - spin_lock_irqsave(&rq->lock, flags); + spin_lock(&rq->lock); list_replace(&rq->fence.cb_list, &cb_list); __dma_fence_signal__timestamp(&rq->fence, timestamp); __dma_fence_signal__notify(&rq->fence, &cb_list); - spin_unlock_irqrestore(&rq->lock, flags); + spin_unlock(&rq->lock); i915_request_put(rq); } } -static void signal_irq_work(struct irq_work *work) -{ - struct intel_engine_cs *engine = - container_of(work, typeof(*engine), breadcrumbs.irq_work); - - intel_engine_breadcrumbs_irq(engine); -} - static bool __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) { struct intel_engine_cs *engine = @@ -290,9 +281,9 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) /* * We keep the seqno in retirement order, so we can break - * inside intel_engine_breadcrumbs_irq as soon as we've passed - * the last completed request (or seen a request that hasn't - * event started). We could iterate the timeline->requests list, + * inside intel_engine_signal_breadcrumbs as soon as we've + * passed the last completed request (or seen a request that + * hasn't event started). We could walk the timeline->requests, * but keeping a separate signalers_list has the advantage of * hopefully being much smaller than the full list and so * provides faster iteration and detection when there are no diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index 0926ecea9147..b21c20ee9e23 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -213,13 +213,11 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine); static inline void -intel_engine_queue_breadcrumbs(struct intel_engine_cs *engine) +intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) { irq_work_queue(&engine->breadcrumbs.irq_work); } -void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine); - void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index 332b12a574fb..f796bdf1ed30 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -28,7 +28,7 @@ cs_irq_handler(struct intel_engine_cs *engine, u32 iir) tasklet = true; if (iir & GT_RENDER_USER_INTERRUPT) { - intel_engine_queue_breadcrumbs(engine); + intel_engine_signal_breadcrumbs(engine); tasklet |= intel_engine_needs_breadcrumb_tasklet(engine); } @@ -245,9 +245,9 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) void gen5_gt_irq_handler(struct intel_gt *gt, u32 gt_iir) { if (gt_iir & GT_RENDER_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(gt->engine_class[RENDER_CLASS][0]); + intel_engine_signal_breadcrumbs(gt->engine_class[RENDER_CLASS][0]); if (gt_iir & ILK_BSD_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(gt->engine_class[VIDEO_DECODE_CLASS][0]); + intel_engine_signal_breadcrumbs(gt->engine_class[VIDEO_DECODE_CLASS][0]); } static void gen7_parity_error_irq_handler(struct intel_gt *gt, u32 iir) @@ -271,11 +271,11 @@ static void gen7_parity_error_irq_handler(struct intel_gt *gt, u32 iir) void gen6_gt_irq_handler(struct intel_gt *gt, u32 gt_iir) { if (gt_iir & GT_RENDER_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(gt->engine_class[RENDER_CLASS][0]); + intel_engine_signal_breadcrumbs(gt->engine_class[RENDER_CLASS][0]); if (gt_iir & GT_BSD_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(gt->engine_class[VIDEO_DECODE_CLASS][0]); + intel_engine_signal_breadcrumbs(gt->engine_class[VIDEO_DECODE_CLASS][0]); if (gt_iir & GT_BLT_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(gt->engine_class[COPY_ENGINE_CLASS][0]); + intel_engine_signal_breadcrumbs(gt->engine_class[COPY_ENGINE_CLASS][0]); if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | GT_BSD_CS_ERROR_INTERRUPT | diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 4ebfecd95032..4db54fd6a2fe 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1483,7 +1483,7 @@ static void virtual_xfer_breadcrumbs(struct virtual_engine *ve, if (!list_empty(&ve->context.signal_link)) { list_move_tail(&ve->context.signal_link, &engine->breadcrumbs.signalers); - intel_engine_queue_breadcrumbs(engine); + intel_engine_signal_breadcrumbs(engine); } spin_unlock(&old->breadcrumbs.irq_lock); } diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index f5b2e7c7e6c8..f3d1e921fba6 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -742,7 +742,7 @@ static void reset_finish_engine(struct intel_engine_cs *engine) engine->reset.finish(engine); intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL); - intel_engine_breadcrumbs_irq(engine); + intel_engine_signal_breadcrumbs(engine); } static void reset_finish(struct intel_gt *gt, intel_engine_mask_t awake) @@ -771,7 +771,7 @@ static void nop_submit_request(struct i915_request *request) i915_request_mark_complete(request); spin_unlock_irqrestore(&engine->active.lock, flags); - intel_engine_queue_breadcrumbs(engine); + intel_engine_signal_breadcrumbs(engine); } static void __intel_gt_set_wedged(struct intel_gt *gt) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index b14d69d60e00..b61658601c86 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -719,7 +719,7 @@ static int xcs_resume(struct intel_engine_cs *engine) } /* Papering over lost _interrupts_ immediately following the restart */ - intel_engine_queue_breadcrumbs(engine); + intel_engine_signal_breadcrumbs(engine); out: intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 5f5a000c801d..eabd5e1a2b95 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1566,7 +1566,7 @@ void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir) return; if (pm_iir & PM_VEBOX_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(gt->engine[VECS0]); + intel_engine_signal_breadcrumbs(gt->engine[VECS0]); if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 83f549d203a0..39df9d49a134 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -77,7 +77,7 @@ static void advance(struct i915_request *request) i915_request_mark_complete(request); GEM_BUG_ON(!i915_request_completed(request)); - intel_engine_queue_breadcrumbs(request->engine); + intel_engine_signal_breadcrumbs(request->engine); } static void hw_delay_complete(struct timer_list *t) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a5348f79114f..42b79f577500 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3619,7 +3619,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir); if (iir & I915_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); + intel_engine_signal_breadcrumbs(dev_priv->engine[RCS0]); if (iir & I915_MASTER_ERROR_INTERRUPT) i8xx_error_irq_handler(dev_priv, eir, eir_stuck); @@ -3724,7 +3724,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) I915_WRITE(GEN2_IIR, iir); if (iir & I915_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); + intel_engine_signal_breadcrumbs(dev_priv->engine[RCS0]); if (iir & I915_MASTER_ERROR_INTERRUPT) i9xx_error_irq_handler(dev_priv, eir, eir_stuck); @@ -3866,10 +3866,10 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) I915_WRITE(GEN2_IIR, iir); if (iir & I915_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); + intel_engine_signal_breadcrumbs(dev_priv->engine[RCS0]); if (iir & I915_BSD_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); + intel_engine_signal_breadcrumbs(dev_priv->engine[VCS0]); if (iir & I915_MASTER_ERROR_INTERRUPT) i9xx_error_irq_handler(dev_priv, eir, eir_stuck); diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 269470d3527a..2118284b796e 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -408,7 +408,7 @@ xfer: /* We may be recursing from the signal callback of another i915 fence */ if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags) && !i915_request_enable_breadcrumb(request)) - intel_engine_queue_breadcrumbs(engine); + intel_engine_signal_breadcrumbs(engine); __notify_execute_cb(request); -- cgit v1.2.3 From 01f624f01845a1685b6070bfa6be9a13ed03b712 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Dec 2019 09:40:57 +0000 Subject: drm/i915: Ratelimit i915_globals_park When doing our global park, we like to be a good citizen and shrink our slab caches (of which we have quite a few now), but each kmem_cache_shrink() incurs a stop_machine() and so ends up being quite expensive, causing machine-wide stalls. While ideally we would like to throw away unused pages in our slab caches whenever it appears that we are idling, doing so will require a much cheaper mechanism. In the meantime use a delayed worked to impose a rate-limit that means we have to have been idle for more than 2 seconds before we start shrinking. References: https://gitlab.freedesktop.org/drm/intel/issues/848 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191218094057.3510459-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_globals.c | 53 ++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_globals.c b/drivers/gpu/drm/i915/i915_globals.c index be127cd28931..3aa213684293 100644 --- a/drivers/gpu/drm/i915/i915_globals.c +++ b/drivers/gpu/drm/i915/i915_globals.c @@ -20,7 +20,10 @@ static LIST_HEAD(globals); static atomic_t active; static atomic_t epoch; static struct park_work { - struct rcu_work work; + struct delayed_work work; + struct rcu_head rcu; + unsigned long flags; +#define PENDING 0 int epoch; } park; @@ -37,11 +40,33 @@ static void i915_globals_shrink(void) global->shrink(); } +static void __i915_globals_grace(struct rcu_head *rcu) +{ + /* Ratelimit parking as shrinking is quite slow */ + schedule_delayed_work(&park.work, round_jiffies_up_relative(2 * HZ)); +} + +static void __i915_globals_queue_rcu(void) +{ + park.epoch = atomic_inc_return(&epoch); + if (!atomic_read(&active)) { + init_rcu_head(&park.rcu); + call_rcu(&park.rcu, __i915_globals_grace); + } +} + static void __i915_globals_park(struct work_struct *work) { + destroy_rcu_head(&park.rcu); + /* Confirm nothing woke up in the last grace period */ - if (park.epoch == atomic_read(&epoch)) - i915_globals_shrink(); + if (park.epoch != atomic_read(&epoch)) { + __i915_globals_queue_rcu(); + return; + } + + clear_bit(PENDING, &park.flags); + i915_globals_shrink(); } void __init i915_global_register(struct i915_global *global) @@ -85,7 +110,7 @@ int __init i915_globals_init(void) } } - INIT_RCU_WORK(&park.work, __i915_globals_park); + INIT_DELAYED_WORK(&park.work, __i915_globals_park); return 0; } @@ -103,8 +128,9 @@ void i915_globals_park(void) if (!atomic_dec_and_test(&active)) return; - park.epoch = atomic_inc_return(&epoch); - queue_rcu_work(system_wq, &park.work); + /* Queue cleanup after the next RCU grace period has freed slabs */ + if (!test_and_set_bit(PENDING, &park.flags)) + __i915_globals_queue_rcu(); } void i915_globals_unpark(void) @@ -113,12 +139,21 @@ void i915_globals_unpark(void) atomic_inc(&active); } +static void __exit __i915_globals_flush(void) +{ + atomic_inc(&active); /* skip shrinking */ + + rcu_barrier(); /* wait for the work to be queued */ + flush_delayed_work(&park.work); + + atomic_dec(&active); +} + void __exit i915_globals_exit(void) { - /* Flush any residual park_work */ - atomic_inc(&epoch); - flush_rcu_work(&park.work); + GEM_BUG_ON(atomic_read(&active)); + __i915_globals_flush(); __i915_globals_cleanup(); /* And ensure that our DESTROY_BY_RCU slabs are truly destroyed */ -- cgit v1.2.3 From 5956f44028f5a0b15f6930256af3d5dbdf1f1f57 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 17 Dec 2019 15:05:27 -0800 Subject: drm/i915/display: move clk off sanitize to its own function This allows us to isolate reading and writing to the ICL_DPCLKA_CFGCR0 during the sanitize phase. Signed-off-by: Lucas De Marchi Reviewed-by: Clinton Taylor Link: https://patchwork.freedesktop.org/patch/msgid/20191217230529.25092-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 57 ++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index fa40ba7cbcad..6e419b1f2737 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2999,11 +2999,40 @@ static void icl_unmap_plls_to_ports(struct intel_encoder *encoder) mutex_unlock(&dev_priv->dpll_lock); } +static void icl_sanitize_port_clk_off(struct drm_i915_private *dev_priv, + u32 port_mask, bool ddi_clk_needed) +{ + enum port port; + u32 val; + + val = I915_READ(ICL_DPCLKA_CFGCR0); + for_each_port_masked(port, port_mask) { + enum phy phy = intel_port_to_phy(dev_priv, port); + + bool ddi_clk_ungated = !(val & + icl_dpclka_cfgcr0_clk_off(dev_priv, + phy)); + + if (ddi_clk_needed == ddi_clk_ungated) + continue; + + /* + * Punt on the case now where clock is gated, but it would + * be needed by the port. Something else is really broken then. + */ + if (WARN_ON(ddi_clk_needed)) + continue; + + DRM_NOTE("PHY %c is disabled/in DSI mode with an ungated DDI clock, gate it\n", + phy_name(port)); + val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy); + I915_WRITE(ICL_DPCLKA_CFGCR0, val); + } +} + void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - u32 val; - enum port port; u32 port_mask; bool ddi_clk_needed; @@ -3052,29 +3081,7 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder) ddi_clk_needed = false; } - val = I915_READ(ICL_DPCLKA_CFGCR0); - for_each_port_masked(port, port_mask) { - enum phy phy = intel_port_to_phy(dev_priv, port); - - bool ddi_clk_ungated = !(val & - icl_dpclka_cfgcr0_clk_off(dev_priv, - phy)); - - if (ddi_clk_needed == ddi_clk_ungated) - continue; - - /* - * Punt on the case now where clock is gated, but it would - * be needed by the port. Something else is really broken then. - */ - if (WARN_ON(ddi_clk_needed)) - continue; - - DRM_NOTE("PHY %c is disabled/in DSI mode with an ungated DDI clock, gate it\n", - phy_name(port)); - val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy); - I915_WRITE(ICL_DPCLKA_CFGCR0, val); - } + icl_sanitize_port_clk_off(dev_priv, port_mask, ddi_clk_needed); } static void intel_ddi_clk_select(struct intel_encoder *encoder, -- cgit v1.2.3 From 41ba19fca303895434961084bcd0a8ad8504e970 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 17 Dec 2019 15:05:28 -0800 Subject: drm/i915/display: use clk_off name to avoid double negation Instead of "ungated" use the same name for the variable as the bitfield, making it clearer what's the intent of the checks. Signed-off-by: Lucas De Marchi Reviewed-by: Clinton Taylor Link: https://patchwork.freedesktop.org/patch/msgid/20191217230529.25092-2-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 6e419b1f2737..9d2b7244f7ca 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3008,12 +3008,10 @@ static void icl_sanitize_port_clk_off(struct drm_i915_private *dev_priv, val = I915_READ(ICL_DPCLKA_CFGCR0); for_each_port_masked(port, port_mask) { enum phy phy = intel_port_to_phy(dev_priv, port); + bool ddi_clk_off = val & icl_dpclka_cfgcr0_clk_off(dev_priv, + phy); - bool ddi_clk_ungated = !(val & - icl_dpclka_cfgcr0_clk_off(dev_priv, - phy)); - - if (ddi_clk_needed == ddi_clk_ungated) + if (ddi_clk_needed == !ddi_clk_off) continue; /* -- cgit v1.2.3 From d6f970f0dad6c053bf7a9be81e91cb95e4ff4af9 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 17 Dec 2019 15:05:29 -0800 Subject: drm/i915/display: fix phy name Pass the correct variable as argument. Signed-off-by: Lucas De Marchi Reviewed-by: Clinton Taylor Link: https://patchwork.freedesktop.org/patch/msgid/20191217230529.25092-3-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 9d2b7244f7ca..c9ba7d7f3787 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3022,7 +3022,7 @@ static void icl_sanitize_port_clk_off(struct drm_i915_private *dev_priv, continue; DRM_NOTE("PHY %c is disabled/in DSI mode with an ungated DDI clock, gate it\n", - phy_name(port)); + phy_name(phy)); val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy); I915_WRITE(ICL_DPCLKA_CFGCR0, val); } -- cgit v1.2.3 From c360824a9d84339bde15a9402e839b5c28564c05 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 28 Nov 2019 16:01:30 +0100 Subject: drm/i915: Provide ddc symlink in hdmi connector sysfs directory Use the ddc pointer provided by the generic connector. Signed-off-by: Andrzej Pietrasiewicz Acked-by: Sam Ravnborg Reviewed-by: Emil Velikov Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191128150130.26266-1-andrzej.p@collabora.com --- drivers/gpu/drm/i915/display/intel_hdmi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index a89a09b25260..685589064d10 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -3131,6 +3131,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, struct intel_encoder *intel_encoder = &intel_dig_port->base; struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct i2c_adapter *ddc; enum port port = intel_encoder->port; struct cec_connector_info conn_info; @@ -3146,8 +3147,13 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_encoder->base.name)) return; - drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA); + intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port); + ddc = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); + + drm_connector_init_with_ddc(dev, connector, + &intel_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + ddc); drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); connector->interlace_allowed = 1; @@ -3157,8 +3163,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) connector->ycbcr_420_allowed = true; - intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port); - intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); if (HAS_DDI(dev_priv)) -- cgit v1.2.3 From 0314da782d4812548aae0607b369f4f43d6bc6b4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 11 Dec 2019 18:23:46 +0200 Subject: drm/i915/dsc: fix DSC register selection for ICL DSI transcoders ICL eDP and DSI transcoders have a DSC engine separate from the pipe. Abstract the register selection and fix it for ICL. Add a warning for pipe A DSC on ICL; it does not exist. Cc: Manasi Navare Cc: Vandita Kulkarni Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/01bcddcdf397b1c8eb859ed18ebe023fb64383d9.1576081155.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 58 ++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index ed9048140937..e6f60be9ee84 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -353,6 +353,26 @@ bool intel_dsc_source_support(struct intel_encoder *encoder, return false; } +static bool is_pipe_dsc(const struct intel_crtc_state *crtc_state) +{ + const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + const struct drm_i915_private *i915 = to_i915(crtc->base.dev); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + + if (INTEL_GEN(i915) >= 12) + return true; + + if (cpu_transcoder == TRANSCODER_EDP || + cpu_transcoder == TRANSCODER_DSI_0 || + cpu_transcoder == TRANSCODER_DSI_1) + return false; + + /* There's no pipe A DSC engine on ICL */ + WARN_ON(crtc->pipe == PIPE_A); + + return true; +} + int intel_dsc_compute_params(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -471,7 +491,6 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; enum pipe pipe = crtc->pipe; - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 pps_val = 0; u32 rc_buf_thresh_dword[4]; u32 rc_range_params_dword[8]; @@ -492,7 +511,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, if (vdsc_cfg->vbr_enable) pps_val |= DSC_VBR_ENABLE; DRM_INFO("PPS0 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_0, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -511,7 +530,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, pps_val = 0; pps_val |= DSC_BPP(vdsc_cfg->bits_per_pixel); DRM_INFO("PPS1 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_1, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -531,7 +550,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, pps_val |= DSC_PIC_HEIGHT(vdsc_cfg->pic_height) | DSC_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances); DRM_INFO("PPS2 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_2, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -551,7 +570,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, pps_val |= DSC_SLICE_HEIGHT(vdsc_cfg->slice_height) | DSC_SLICE_WIDTH(vdsc_cfg->slice_width); DRM_INFO("PPS3 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_3, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -571,7 +590,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, pps_val |= DSC_INITIAL_XMIT_DELAY(vdsc_cfg->initial_xmit_delay) | DSC_INITIAL_DEC_DELAY(vdsc_cfg->initial_dec_delay); DRM_INFO("PPS4 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_4, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -591,7 +610,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, pps_val |= DSC_SCALE_INC_INT(vdsc_cfg->scale_increment_interval) | DSC_SCALE_DEC_INT(vdsc_cfg->scale_decrement_interval); DRM_INFO("PPS5 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_5, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -613,7 +632,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, DSC_FLATNESS_MIN_QP(vdsc_cfg->flatness_min_qp) | DSC_FLATNESS_MAX_QP(vdsc_cfg->flatness_max_qp); DRM_INFO("PPS6 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_6, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -633,7 +652,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, pps_val |= DSC_SLICE_BPG_OFFSET(vdsc_cfg->slice_bpg_offset) | DSC_NFL_BPG_OFFSET(vdsc_cfg->nfl_bpg_offset); DRM_INFO("PPS7 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_7, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -653,7 +672,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, pps_val |= DSC_FINAL_OFFSET(vdsc_cfg->final_offset) | DSC_INITIAL_OFFSET(vdsc_cfg->initial_offset); DRM_INFO("PPS8 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_8, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -673,7 +692,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, pps_val |= DSC_RC_MODEL_SIZE(DSC_RC_MODEL_SIZE_CONST) | DSC_RC_EDGE_FACTOR(DSC_RC_EDGE_FACTOR_CONST); DRM_INFO("PPS9 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_9, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -695,7 +714,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, DSC_RC_TARGET_OFF_HIGH(DSC_RC_TGT_OFFSET_HI_CONST) | DSC_RC_TARGET_OFF_LOW(DSC_RC_TGT_OFFSET_LO_CONST); DRM_INFO("PPS10 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_10, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -718,7 +737,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, DSC_SLICE_ROW_PER_FRAME(vdsc_cfg->pic_height / vdsc_cfg->slice_height); DRM_INFO("PPS16 = 0x%08x\n", pps_val); - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_PICTURE_PARAMETER_SET_16, pps_val); /* * If 2 VDSC instances are needed, configure PPS for second @@ -742,7 +761,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, DRM_INFO(" RC_BUF_THRESH%d = 0x%08x\n", i, rc_buf_thresh_dword[i / 4]); } - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_RC_BUF_THRESH_0, rc_buf_thresh_dword[0]); I915_WRITE(DSCA_RC_BUF_THRESH_0_UDW, rc_buf_thresh_dword[1]); I915_WRITE(DSCA_RC_BUF_THRESH_1, rc_buf_thresh_dword[2]); @@ -791,7 +810,7 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, DRM_INFO(" RC_RANGE_PARAM_%d = 0x%08x\n", i, rc_range_params_dword[i / 2]); } - if (cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { I915_WRITE(DSCA_RC_RANGE_PARAMETERS_0, rc_range_params_dword[0]); I915_WRITE(DSCA_RC_RANGE_PARAMETERS_0_UDW, @@ -870,7 +889,6 @@ void intel_dsc_get_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum pipe pipe = crtc->pipe; enum intel_display_power_domain power_domain; intel_wakeref_t wakeref; @@ -885,7 +903,7 @@ void intel_dsc_get_config(struct intel_encoder *encoder, if (!wakeref) return; - if (crtc_state->cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { dss_ctl1 = I915_READ(DSS_CTL1); dss_ctl2 = I915_READ(DSS_CTL2); } else { @@ -903,7 +921,7 @@ void intel_dsc_get_config(struct intel_encoder *encoder, /* FIXME: add more state readout as needed */ /* PPS1 */ - if (cpu_transcoder == TRANSCODER_EDP) + if (!is_pipe_dsc(crtc_state)) val = I915_READ(DSCA_PICTURE_PARAMETER_SET_1); else val = I915_READ(ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe)); @@ -975,7 +993,7 @@ void intel_dsc_enable(struct intel_encoder *encoder, else intel_dsc_dp_pps_write(encoder, crtc_state); - if (crtc_state->cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(crtc_state)) { dss_ctl1_reg = DSS_CTL1; dss_ctl2_reg = DSS_CTL2; } else { @@ -1002,7 +1020,7 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->dsc.compression_enable) return; - if (old_crtc_state->cpu_transcoder == TRANSCODER_EDP) { + if (!is_pipe_dsc(old_crtc_state)) { dss_ctl1_reg = DSS_CTL1; dss_ctl2_reg = DSS_CTL2; } else { -- cgit v1.2.3 From 4cb48c447e8753aec2c96630a539eb6207fd6814 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 11 Dec 2019 18:23:47 +0200 Subject: drm/i915/dsc: clarify DSC support for pipe A on ICL The check for cpu_transcoder != TRANSCODER_A is more magic than necessary, and potentially misleading. Before TGL, DSC is supported on pipe A if, and only if, it's used with eDP or DSI transcoders. No functional changes. Cc: Manasi Navare Cc: Vandita Kulkarni Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/f00e9d55ce20b256177222588780c660aa587cc3.1576081155.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index e6f60be9ee84..41718f721484 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -337,7 +337,10 @@ static const struct rc_parameters *get_rc_params(u16 compressed_bpp, bool intel_dsc_source_support(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + enum pipe pipe = crtc->pipe; if (!INTEL_INFO(i915)->display.has_dsc) return false; @@ -347,7 +350,10 @@ bool intel_dsc_source_support(struct intel_encoder *encoder, return true; if (INTEL_GEN(i915) >= 10 && - crtc_state->cpu_transcoder != TRANSCODER_A) + (pipe != PIPE_A || + (cpu_transcoder == TRANSCODER_EDP || + cpu_transcoder == TRANSCODER_DSI_0 || + cpu_transcoder == TRANSCODER_DSI_1))) return true; return false; -- cgit v1.2.3 From cabeacd4cc132873de212fcb0e8739b95e6f2a02 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 12 Dec 2019 15:47:28 +0200 Subject: drm/i915/dsc: fix DSC power domains for DSI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix several issues with DSC power domains that did not take DSI transcoders into account: - On TGL+ we need to use PW2 for DSC on pipe A, not transcoder A. There is no longer an eDP transcoder, but there are two DSI transcoders which may be connected to pipe A. - On TGL+ we need to use the pipe, not transcoder, power domains for DSC on pipes other than A. Again, there are DSI transcoders. - On ICL we need to use PW2 for DSC also for DSI transcoders, not just for the eDP transcoder. Using is_pipe_dsc() also adds the warning about ICL pipe A DSC, which does not exist. Cc: José Roberto de Souza Cc: Manasi Navare Cc: Vandita Kulkarni Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191212134728.18432-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 41718f721484..6bab08db5d75 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -469,25 +469,27 @@ int intel_dsc_compute_params(struct intel_encoder *encoder, enum intel_display_power_domain intel_dsc_power_domain(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; /* - * On ICL VDSC/joining for eDP transcoder uses a separate power well, - * PW2. This requires POWER_DOMAIN_TRANSCODER_VDSC_PW2 power domain. - * For any other transcoder, VDSC/joining uses the power well associated - * with the pipe/transcoder in use. Hence another reference on the - * transcoder power domain will suffice. + * VDSC/joining uses a separate power well, PW2, and requires + * POWER_DOMAIN_TRANSCODER_VDSC_PW2 power domain in two cases: * - * On TGL we have the same mapping, but for transcoder A (the special - * TRANSCODER_EDP is gone). + * - ICL eDP/DSI transcoder + * - TGL pipe A + * + * For any other pipe, VDSC/joining uses the power well associated with + * the pipe in use. Hence another reference on the pipe power domain + * will suffice. (Except no VDSC/joining on ICL pipe A.) */ - if (INTEL_GEN(i915) >= 12 && cpu_transcoder == TRANSCODER_A) - return POWER_DOMAIN_TRANSCODER_VDSC_PW2; - else if (cpu_transcoder == TRANSCODER_EDP) + if (INTEL_GEN(i915) >= 12 && pipe == PIPE_A) return POWER_DOMAIN_TRANSCODER_VDSC_PW2; + else if (is_pipe_dsc(crtc_state)) + return POWER_DOMAIN_PIPE(pipe); else - return POWER_DOMAIN_TRANSCODER(cpu_transcoder); + return POWER_DOMAIN_TRANSCODER_VDSC_PW2; } static void intel_dsc_pps_configure(struct intel_encoder *encoder, -- cgit v1.2.3 From dc93c9b69315167f5678b94aa911dc8e7c299fe5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 19 Dec 2019 12:43:52 +0000 Subject: drm/i915/gt: Schedule request retirement when signaler idles Very similar to commit 4f88f8747fa4 ("drm/i915/gt: Schedule request retirement when timeline idles"), but this time instead of coupling into the execlists CS event interrupt, we couple into the breadcrumb interrupt and queue a timeline's retirement when the last signaler is completed. This should allow us to more rapidly park ringbuffer submission, and so help reduce power consumption on older systems. v2: Fixup intel_engine_add_retire() to handle concurrent callers References: 4f88f8747fa4 ("drm/i915/gt: Schedule request retirement when timeline idles") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191219124353.8607-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 6 +++++- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 7 ++----- drivers/gpu/drm/i915/gt/intel_lrc.c | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 5fa4d621528e..4f491791b4ba 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -29,6 +29,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_gt_pm.h" +#include "intel_gt_requests.h" static void irq_enable(struct intel_engine_cs *engine) { @@ -179,8 +180,11 @@ static void signal_irq_work(struct irq_work *work) if (!list_is_first(pos, &ce->signals)) { /* Advance the list to the first incomplete request */ __list_del_many(&ce->signals, pos); - if (&ce->signals == pos) /* now empty */ + if (&ce->signals == pos) { /* now empty */ list_del_init(&ce->signal_link); + intel_engine_add_retire(ce->engine, + ce->timeline); + } } } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index 8cb5421e5f0e..0d1bca787288 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -62,19 +62,16 @@ static void engine_retire(struct work_struct *work) static bool add_retire(struct intel_engine_cs *engine, struct intel_timeline *tl) { +#define STUB ((struct intel_timeline *)1) struct intel_timeline *first; /* * We open-code a llist here to include the additional tag [BIT(0)] * so that we know when the timeline is already on a * retirement queue: either this engine or another. - * - * However, we rely on that a timeline can only be active on a single - * engine at any one time and that add_retire() is called before the - * engine releases the timeline and transferred to another to retire. */ - if (READ_ONCE(tl->retire)) /* already queued */ + if (cmpxchg(&tl->retire, NULL, STUB)) /* already queued */ return false; intel_timeline_get(tl); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 4db54fd6a2fe..56cf71d8bbda 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4511,8 +4511,8 @@ intel_execlists_create_virtual(struct i915_gem_context *ctx, intel_engine_init_active(&ve->base, ENGINE_VIRTUAL); intel_engine_init_breadcrumbs(&ve->base); - intel_engine_init_execlists(&ve->base); + intel_engine_init_retire(&ve->base); ve->base.cops = &virtual_context_ops; ve->base.request_alloc = execlists_request_alloc; -- cgit v1.2.3 From b81e4d9b594188a8babf06442e1d6f28de78c68f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 19 Dec 2019 12:43:53 +0000 Subject: drm/i915/gt: Track engine round-trip times Knowing the round trip time of an engine is useful for tracking the health of the system as well as providing a metric for the baseline responsiveness of the engine. We can use the latter metric for automatically tuning our waits in selftests and when idling so we don't confuse a slower system with a dead one. Upon idling the engine, we send one last pulse to switch the context away from precious user state to the volatile kernel context. We know the engine is idle at this point, and the pulse is non-preemptible, so this provides us with a good measurement of the round trip time. It also provides us with faster engine parking for ringbuffer submission, which is a welcome bonus (e.g. softer-rc6). Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Stuart Summers Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191219105043.4169050-1-chris@chris-wilson.co.uk Link: https://patchwork.freedesktop.org/patch/msgid/20191219124353.8607-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 3 +++ drivers/gpu/drm/i915/gt/intel_engine_pm.c | 22 +++++++++++++++++++++- drivers/gpu/drm/i915/gt/intel_engine_types.h | 11 +++++++++++ drivers/gpu/drm/i915/i915_request.h | 4 ++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 3d1d48bf90cf..6dd18f93d45c 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -334,6 +334,7 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id) /* Nothing to do here, execute in order of dependencies */ engine->schedule = NULL; + ewma__engine_latency_init(&engine->latency); seqlock_init(&engine->stats.lock); ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); @@ -1481,6 +1482,8 @@ void intel_engine_dump(struct intel_engine_cs *engine, drm_printf(m, "\tAwake? %d\n", atomic_read(&engine->wakeref.count)); drm_printf(m, "\tBarriers?: %s\n", yesno(!llist_empty(&engine->barrier_tasks))); + drm_printf(m, "\tLatency: %luus\n", + ewma__engine_latency_read(&engine->latency)); rcu_read_lock(); rq = READ_ONCE(engine->heartbeat.systole); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index bcbda8e52d41..8fb7b34fc5a6 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -73,6 +73,15 @@ static inline void __timeline_mark_unlock(struct intel_context *ce, #endif /* !IS_ENABLED(CONFIG_LOCKDEP) */ +static void duration(struct dma_fence *fence, struct dma_fence_cb *cb) +{ + struct i915_request *rq = to_request(fence); + + ewma__engine_latency_add(&rq->engine->latency, + ktime_us_delta(rq->fence.timestamp, + rq->duration.emitted)); +} + static void __queue_and_release_pm(struct i915_request *rq, struct intel_timeline *tl, @@ -163,7 +172,18 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) /* Install ourselves as a preemption barrier */ rq->sched.attr.priority = I915_PRIORITY_BARRIER; - __i915_request_commit(rq); + if (likely(!__i915_request_commit(rq))) { /* engine should be idle! */ + /* + * Use an interrupt for precise measurement of duration, + * otherwise we rely on someone else retiring all the requests + * which may delay the signaling (i.e. we will likely wait + * until the background request retirement running every + * second or two). + */ + BUILD_BUG_ON(sizeof(rq->duration) > sizeof(rq->submitq)); + dma_fence_add_callback(&rq->fence, &rq->duration.cb, duration); + rq->duration.emitted = ktime_get(); + } /* Expose ourselves to the world */ __queue_and_release_pm(rq, ce->timeline, engine); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 17f1f1441efc..7f227da09d66 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -7,6 +7,7 @@ #ifndef __INTEL_ENGINE_TYPES__ #define __INTEL_ENGINE_TYPES__ +#include #include #include #include @@ -119,6 +120,9 @@ enum intel_engine_id { #define INVALID_ENGINE ((enum intel_engine_id)-1) }; +/* A simple estimator for the round-trip latency of an engine */ +DECLARE_EWMA(_engine_latency, 6, 4) + struct st_preempt_hang { struct completion completion; unsigned int count; @@ -316,6 +320,13 @@ struct intel_engine_cs { struct intel_timeline *timeline; } legacy; + /* + * We track the average duration of the idle pulse on parking the + * engine to keep an estimate of the how the fast the engine is + * under ideal conditions. + */ + struct ewma__engine_latency latency; + /* Rather than have every client wait upon all user interrupts, * with the herd waking after every interrupt and each doing the * heavyweight seqno dance, we delegate the task (of being the diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index aa38290eea3d..c18c0bcd0193 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -150,6 +150,10 @@ struct i915_request { union { wait_queue_entry_t submitq; struct i915_sw_dma_fence_cb dmaq; + struct i915_request_duration_cb { + struct dma_fence_cb cb; + ktime_t emitted; + } duration; }; struct list_head execute_cb; struct i915_sw_fence semaphore; -- cgit v1.2.3 From 35cc7f32c298ba163a009598e6e7e15920a2e4e6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Dec 2019 21:05:44 +0000 Subject: drm/i915/gt: Use non-forcewake writes for RPS Use non-forcewaked writes to queue RPS register changes that will take effect when the write buffer is flushed, rather than wake the mmio device for immediate effect. This is so that we can avoid a slow forcewake dance upon unparking, and at our irregular updates. Signed-off-by: Chris Wilson Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191218210545.3975426-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rps.c | 66 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index eabd5e1a2b95..443d4ba3bbb7 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -37,6 +37,11 @@ static u32 rps_pm_sanitize_mask(struct intel_rps *rps, u32 mask) return mask & ~rps->pm_intrmsk_mbz; } +static inline void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val) +{ + intel_uncore_write_fw(uncore, reg, val); +} + static u32 rps_pm_mask(struct intel_rps *rps, u8 val) { u32 mask = 0; @@ -78,8 +83,7 @@ static void rps_enable_interrupts(struct intel_rps *rps) gen6_gt_pm_enable_irq(gt, rps->pm_events); spin_unlock_irq(>->irq_lock); - intel_uncore_write(gt->uncore, GEN6_PMINTRMSK, - rps_pm_mask(rps, rps->cur_freq)); + set(gt->uncore, GEN6_PMINTRMSK, rps_pm_mask(rps, rps->cur_freq)); } static void gen6_rps_reset_interrupts(struct intel_rps *rps) @@ -113,8 +117,7 @@ static void rps_disable_interrupts(struct intel_rps *rps) rps->pm_events = 0; - intel_uncore_write(gt->uncore, GEN6_PMINTRMSK, - rps_pm_sanitize_mask(rps, ~0u)); + set(gt->uncore, GEN6_PMINTRMSK, rps_pm_sanitize_mask(rps, ~0u)); spin_lock_irq(>->irq_lock); gen6_gt_pm_disable_irq(gt, GEN6_PM_RPS_EVENTS); @@ -573,25 +576,21 @@ static void rps_set_power(struct intel_rps *rps, int new_power) if (IS_VALLEYVIEW(i915)) goto skip_hw_write; - intel_uncore_write(uncore, GEN6_RP_UP_EI, - GT_INTERVAL_FROM_US(i915, ei_up)); - intel_uncore_write(uncore, GEN6_RP_UP_THRESHOLD, - GT_INTERVAL_FROM_US(i915, - ei_up * threshold_up / 100)); - - intel_uncore_write(uncore, GEN6_RP_DOWN_EI, - GT_INTERVAL_FROM_US(i915, ei_down)); - intel_uncore_write(uncore, GEN6_RP_DOWN_THRESHOLD, - GT_INTERVAL_FROM_US(i915, - ei_down * threshold_down / 100)); - - intel_uncore_write(uncore, GEN6_RP_CONTROL, - (INTEL_GEN(i915) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_AVG); + set(uncore, GEN6_RP_UP_EI, GT_INTERVAL_FROM_US(i915, ei_up)); + set(uncore, GEN6_RP_UP_THRESHOLD, + GT_INTERVAL_FROM_US(i915, ei_up * threshold_up / 100)); + + set(uncore, GEN6_RP_DOWN_EI, GT_INTERVAL_FROM_US(i915, ei_down)); + set(uncore, GEN6_RP_DOWN_THRESHOLD, + GT_INTERVAL_FROM_US(i915, ei_down * threshold_down / 100)); + + set(uncore, GEN6_RP_CONTROL, + (INTEL_GEN(i915) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG); skip_hw_write: rps->power.mode = new_power; @@ -666,7 +665,7 @@ static int gen6_rps_set(struct intel_rps *rps, u8 val) swreq = (GEN6_FREQUENCY(val) | GEN6_OFFSET(0) | GEN6_AGGRESSIVE_TURBO); - intel_uncore_write(uncore, GEN6_RPNSWREQ, swreq); + set(uncore, GEN6_RPNSWREQ, swreq); return 0; } @@ -790,7 +789,7 @@ void intel_rps_boost(struct i915_request *rq) int intel_rps_set(struct intel_rps *rps, u8 val) { - int err = 0; + int err; lockdep_assert_held(&rps->lock); GEM_BUG_ON(val > rps->max_freq); @@ -798,6 +797,8 @@ int intel_rps_set(struct intel_rps *rps, u8 val) if (rps->active) { err = rps_set(rps, val); + if (err) + return err; /* * Make sure we continue to get interrupts @@ -806,18 +807,15 @@ int intel_rps_set(struct intel_rps *rps, u8 val) if (INTEL_GEN(rps_to_i915(rps)) >= 6) { struct intel_uncore *uncore = rps_to_uncore(rps); - intel_uncore_write(uncore, GEN6_RP_INTERRUPT_LIMITS, - rps_limits(rps, val)); + set(uncore, + GEN6_RP_INTERRUPT_LIMITS, rps_limits(rps, val)); - intel_uncore_write(uncore, GEN6_PMINTRMSK, - rps_pm_mask(rps, val)); + set(uncore, GEN6_PMINTRMSK, rps_pm_mask(rps, val)); } } - if (err == 0) - rps->cur_freq = val; - - return err; + rps->cur_freq = val; + return 0; } static void gen6_rps_init(struct intel_rps *rps) @@ -1201,7 +1199,7 @@ void intel_rps_enable(struct intel_rps *rps) static void gen6_rps_disable(struct intel_rps *rps) { - intel_uncore_write(rps_to_uncore(rps), GEN6_RP_CONTROL, 0); + set(rps_to_uncore(rps), GEN6_RP_CONTROL, 0); } void intel_rps_disable(struct intel_rps *rps) -- cgit v1.2.3 From 281176327d0217d3ee0f7acc93f7542cc1b1ce9d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 18 Dec 2019 21:05:45 +0000 Subject: drm/i915/gt: Suppress threshold updates on RPS parking When we park RPS, we set the GPU to run at minimum 'idle' frequency. However, as the GPU is idle, we also disable the worker and RPS interrupts - changing the RPS thresholds has no effect, it just incurs extra changes to restore them when we unpark. So on parking, leave the thresholds set to the current power level and so we expect them to be valid for our restart. References: https://gitlab.freedesktop.org/drm/intel/issues/848 Signed-off-by: Chris Wilson Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191218210545.3975426-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_rps.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 443d4ba3bbb7..f232036c3c7a 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -682,7 +682,7 @@ static int vlv_rps_set(struct intel_rps *rps, u8 val) return err; } -static int rps_set(struct intel_rps *rps, u8 val) +static int rps_set(struct intel_rps *rps, u8 val, bool update) { struct drm_i915_private *i915 = rps_to_i915(rps); int err; @@ -700,7 +700,8 @@ static int rps_set(struct intel_rps *rps, u8 val) if (err) return err; - gen6_rps_set_thresholds(rps, val); + if (update) + gen6_rps_set_thresholds(rps, val); rps->last_freq = val; return 0; @@ -760,7 +761,7 @@ void intel_rps_park(struct intel_rps *rps) * power than the render powerwell. */ intel_uncore_forcewake_get(rps_to_uncore(rps), FORCEWAKE_MEDIA); - rps_set(rps, rps->idle_freq); + rps_set(rps, rps->idle_freq, false); intel_uncore_forcewake_put(rps_to_uncore(rps), FORCEWAKE_MEDIA); } @@ -796,7 +797,7 @@ int intel_rps_set(struct intel_rps *rps, u8 val) GEM_BUG_ON(val < rps->min_freq); if (rps->active) { - err = rps_set(rps, val); + err = rps_set(rps, val, true); if (err) return err; @@ -876,7 +877,7 @@ static bool rps_reset(struct intel_rps *rps) rps->power.mode = -1; rps->last_freq = -1; - if (rps_set(rps, rps->min_freq)) { + if (rps_set(rps, rps->min_freq, true)) { DRM_ERROR("Failed to reset RPS to initial values\n"); return false; } -- cgit v1.2.3 From e1f0fbda75e6447077205b472d1dd71bef417a4c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 19 Dec 2019 19:09:16 +0000 Subject: drm/i915: fix uninitialized pointer reads on pointers to and from Currently pointers to and from are not initialized and may contain garbage values. This will cause uninitialized pointer reads in the call to intel_frontbuffer_track and later checks to see if to and from are null. Fix this by ensuring to and from are initialized to NULL. Addresses-Coverity: ("Uninitialised pointer read)" Fixes: da42104f589d ("drm/i915: Hold reference to intel_frontbuffer as we track activity") Signed-off-by: Colin Ian King Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191219190916.24693-1-colin.king@canonical.com --- drivers/gpu/drm/i915/display/intel_overlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 6097594468a9..e869a3d86522 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -279,7 +279,7 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay, struct i915_vma *vma) { enum pipe pipe = overlay->crtc->pipe; - struct intel_frontbuffer *from, *to; + struct intel_frontbuffer *from = NULL, *to = NULL; WARN_ON(overlay->old_vma); -- cgit v1.2.3 From 317b2cac79a66c7156dbe7983b825dc417acf9a8 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2019 15:34:48 +0200 Subject: drm/i915/fbc: Reject PLANE_OFFSET.y%4!=0 on icl+ too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit icl and tgl are still affected by the modulo 4 PLANE_OFFSET.y underrun issue. Reject such configurations on all gen9+ platforms. Can be reproduced easily with the following sequence of hardware poking: while { write FBC_CTL.enable=1 wait for vblank write PLANE_OFFSET .x=0 .y=32 write PLANE_SURF wait for vblank # if PLANE_OFFSET.y is multiple of 4 the underrun won't happen write PLANE_OFFSET .x=0 .y=31 write PLANE_SURF wait for vblank # extra vblank wait is required here presumably # to get FBC into the proper state wait for vblank write FBC_CTL.enable=0 # underrun happens some time after FBC disable wait for vblank } Both 8888 and 565 pixel formats and all tilinga formats seem affected. Reproduced on KBL/GLK/ICL/TGL. BDW confirmed not affected. Closes: https://gitlab.freedesktop.org/drm/intel/issues/792 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213133453.22152-1-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/intel_fbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 6f1d5c032681..a1048ece541e 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -776,7 +776,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * having a Y offset that isn't divisible by 4 causes FIFO underrun * and screen flicker. */ - if (IS_GEN_RANGE(dev_priv, 9, 10) && + if (INTEL_GEN(dev_priv) >= 9 && (fbc->state_cache.plane.adjusted_y & 3)) { fbc->no_fbc_reason = "plane Y offset is misaligned"; return false; -- cgit v1.2.3 From 36fef958e2da969595871da07dd913a2e5be2816 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2019 15:34:49 +0200 Subject: drm/i915/fbc: Remove second redundant intel_fbc_pre_update() call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I fumbled the conflict resolution a bit when applying the fbc vblank wait w/a. Because of that we now call intel_fbc_pre_update() twice. Remove the second redundant call. Reported-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213133453.22152-2-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/display/intel_display.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 38bc92256f64..983f5b084ff9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6043,9 +6043,6 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state)) intel_wait_for_vblank(dev_priv, pipe); - if (new_primary_state) - intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state); - /* Display WA 827 */ if (!needs_nv12_wa(old_crtc_state) && needs_nv12_wa(new_crtc_state)) -- cgit v1.2.3 From f7f1538c3f7c03eca66a85a6e847108e18ef88bf Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 13 Dec 2019 15:34:53 +0200 Subject: drm/i915: Rename pipe update tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the other display related tracepoints use intel_ instead if i915_ as the prefix. Do the same for the pipe update tracepoints so I don't always have to spend time looking for them. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213133453.22152-6-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/display/intel_sprite.c | 6 +++--- drivers/gpu/drm/i915/i915_trace.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 8394502b092d..a5b7cab6dff3 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -120,7 +120,7 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) crtc->debug.min_vbl = min; crtc->debug.max_vbl = max; - trace_i915_pipe_update_start(crtc); + trace_intel_pipe_update_start(crtc); for (;;) { /* @@ -173,7 +173,7 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) crtc->debug.start_vbl_time = ktime_get(); crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc); - trace_i915_pipe_update_vblank_evaded(crtc); + trace_intel_pipe_update_vblank_evaded(crtc); return; irq_disable: @@ -197,7 +197,7 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) ktime_t end_vbl_time = ktime_get(); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); + trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end); /* We're still in the vblank-evade critical section, this can't race. * Would be slightly nice to just grab the vblank count and arm the diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 7ef7a1e1664c..233a97a2c276 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -341,7 +341,7 @@ TRACE_EVENT(intel_disable_plane, /* pipe updates */ -TRACE_EVENT(i915_pipe_update_start, +TRACE_EVENT(intel_pipe_update_start, TP_PROTO(struct intel_crtc *crtc), TP_ARGS(crtc), @@ -366,7 +366,7 @@ TRACE_EVENT(i915_pipe_update_start, __entry->scanline, __entry->min, __entry->max) ); -TRACE_EVENT(i915_pipe_update_vblank_evaded, +TRACE_EVENT(intel_pipe_update_vblank_evaded, TP_PROTO(struct intel_crtc *crtc), TP_ARGS(crtc), @@ -391,7 +391,7 @@ TRACE_EVENT(i915_pipe_update_vblank_evaded, __entry->scanline, __entry->min, __entry->max) ); -TRACE_EVENT(i915_pipe_update_end, +TRACE_EVENT(intel_pipe_update_end, TP_PROTO(struct intel_crtc *crtc, u32 frame, int scanline_end), TP_ARGS(crtc, frame, scanline_end), -- cgit v1.2.3 From 7d1ff0d9faf66f630c104a6ca6b8a3c6091ba3a3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 19 Dec 2019 22:13:44 +0000 Subject: drm/i915/gt: Add breadcrumb retire to physical engine Avoid adding the retire workers to the virtual engine so that we don't end up in the unenviable situation of trying to free the virtual engine while its worker remains active. Fixes: dc93c9b69315 ("drm/i915/gt: Schedule request retirement when signaler idles") Closes: https://gitlab.freedesktop.org/drm/intel/issues/867 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Joonas Lahtinen Acked-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191219221344.161523-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 11 +++++++++-- drivers/gpu/drm/i915/gt/intel_lrc.c | 1 - 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 4f491791b4ba..2979f0fd9270 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -131,6 +131,14 @@ __dma_fence_signal__notify(struct dma_fence *fence, } } +static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl) +{ + struct intel_engine_cs *engine = + container_of(b, struct intel_engine_cs, breadcrumbs); + + intel_engine_add_retire(engine, tl); +} + static void signal_irq_work(struct irq_work *work) { struct intel_breadcrumbs *b = container_of(work, typeof(*b), irq_work); @@ -182,8 +190,7 @@ static void signal_irq_work(struct irq_work *work) __list_del_many(&ce->signals, pos); if (&ce->signals == pos) { /* now empty */ list_del_init(&ce->signal_link); - intel_engine_add_retire(ce->engine, - ce->timeline); + add_retire(b, ce->timeline); } } } diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 56cf71d8bbda..31815d5e3b74 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4512,7 +4512,6 @@ intel_execlists_create_virtual(struct i915_gem_context *ctx, intel_engine_init_active(&ve->base, ENGINE_VIRTUAL); intel_engine_init_breadcrumbs(&ve->base); intel_engine_init_execlists(&ve->base); - intel_engine_init_retire(&ve->base); ve->base.cops = &virtual_context_ops; ve->base.request_alloc = execlists_request_alloc; -- cgit v1.2.3 From d5e1935381a156be1e79b4229172bee7ff550ded Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 19 Dec 2019 23:29:32 +0000 Subject: drm/i915/gt: Teach veng to defer the context allocation Since we added the context_alloc callback to intel_context_ops, we can safely install a custom hook for the deferred virtual context allocation. This means that all new contexts behave the same upon creation, simplifying later code. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191219232932.189197-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 31815d5e3b74..b7da6d7e7e2a 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4240,6 +4240,13 @@ static void virtual_engine_initial_hint(struct virtual_engine *ve) ve->siblings[0]); } +static int virtual_context_alloc(struct intel_context *ce) +{ + struct virtual_engine *ve = container_of(ce, typeof(*ve), context); + + return __execlists_context_alloc(ce, ve->siblings[0]); +} + static int virtual_context_pin(struct intel_context *ce) { struct virtual_engine *ve = container_of(ce, typeof(*ve), context); @@ -4277,6 +4284,8 @@ static void virtual_context_exit(struct intel_context *ce) } static const struct intel_context_ops virtual_context_ops = { + .alloc = virtual_context_alloc, + .pin = virtual_context_pin, .unpin = execlists_context_unpin, @@ -4593,12 +4602,6 @@ intel_execlists_create_virtual(struct i915_gem_context *ctx, ve->base.flags |= I915_ENGINE_IS_VIRTUAL; - err = __execlists_context_alloc(&ve->context, siblings[0]); - if (err) - goto err_put; - - __set_bit(CONTEXT_ALLOC_BIT, &ve->context.flags); - return &ve->context; err_put: -- cgit v1.2.3 From 9f3ccd40acf4a348aab4eda140cdb4d2f1f773b4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 20 Dec 2019 10:12:29 +0000 Subject: drm/i915: Drop GEM context as a direct link from i915_request Keep the intel_context as being the primary state for i915_request, with the GEM context a backpointer from the low level state for the rarer cases we need client information. Our goal is to remove such references to clients from the backend, and leave the HW submission agnostic to client interfaces and self-contained. Signed-off-by: Chris Wilson Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191220101230.256839-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 15 +++----- drivers/gpu/drm/i915/gem/i915_gem_context.h | 38 ------------------ drivers/gpu/drm/i915/gem/i915_gem_context_types.h | 7 +--- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 8 ++-- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 4 +- drivers/gpu/drm/i915/gt/intel_context.c | 2 +- drivers/gpu/drm/i915/gt/intel_context.h | 42 ++++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_context_types.h | 7 +++- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 6 +-- drivers/gpu/drm/i915/gt/intel_lrc.c | 47 +++++++++++------------ drivers/gpu/drm/i915/gt/intel_reset.c | 37 ++++++++++-------- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 8 ++-- drivers/gpu/drm/i915/gt/selftest_lrc.c | 20 +++++----- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 +-- drivers/gpu/drm/i915/gvt/scheduler.c | 27 ++++++------- drivers/gpu/drm/i915/i915_gem.c | 11 +++--- drivers/gpu/drm/i915/i915_gpu_error.c | 11 ++++-- drivers/gpu/drm/i915/i915_perf.c | 4 +- drivers/gpu/drm/i915/i915_request.c | 21 ++++++---- drivers/gpu/drm/i915/i915_request.h | 3 +- drivers/gpu/drm/i915/i915_scheduler.c | 2 +- 21 files changed, 165 insertions(+), 161 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 6618c0c6506c..42585a20a9ae 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -69,6 +69,7 @@ #include +#include "gt/intel_context.h" #include "gt/intel_engine_heartbeat.h" #include "gt/intel_engine_pm.h" #include "gt/intel_engine_user.h" @@ -423,15 +424,6 @@ static void kill_context(struct i915_gem_context *ctx) struct i915_gem_engines_iter it; struct intel_context *ce; - /* - * If we are already banned, it was due to a guilty request causing - * a reset and the entire context being evicted from the GPU. - */ - if (i915_gem_context_is_banned(ctx)) - return; - - i915_gem_context_set_banned(ctx); - /* * Map the user's engine back to the actual engines; one virtual * engine will be mapped to multiple engines, and using ctx->engine[] @@ -442,6 +434,9 @@ static void kill_context(struct i915_gem_context *ctx) for_each_gem_engine(ce, __context_engines_static(ctx), it) { struct intel_engine_cs *engine; + if (intel_context_set_banned(ce)) + continue; + /* * Check the current active state of this context; if we * are currently executing on the GPU we need to evict @@ -1093,7 +1088,7 @@ static void set_ppgtt_barrier(void *data) static int emit_ppgtt_update(struct i915_request *rq, void *data) { - struct i915_address_space *vm = rq->hw_context->vm; + struct i915_address_space *vm = rq->context->vm; struct intel_engine_cs *engine = rq->engine; u32 base = engine->mmio_base; u32 *cs; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.h b/drivers/gpu/drm/i915/gem/i915_gem_context.h index 18e50a769a6e..69932899803e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.h @@ -91,26 +91,6 @@ static inline void i915_gem_context_clear_persistence(struct i915_gem_context *c clear_bit(UCONTEXT_PERSISTENCE, &ctx->user_flags); } -static inline bool i915_gem_context_is_banned(const struct i915_gem_context *ctx) -{ - return test_bit(CONTEXT_BANNED, &ctx->flags); -} - -static inline void i915_gem_context_set_banned(struct i915_gem_context *ctx) -{ - set_bit(CONTEXT_BANNED, &ctx->flags); -} - -static inline bool i915_gem_context_force_single_submission(const struct i915_gem_context *ctx) -{ - return test_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ctx->flags); -} - -static inline void i915_gem_context_set_force_single_submission(struct i915_gem_context *ctx) -{ - __set_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ctx->flags); -} - static inline bool i915_gem_context_user_engines(const struct i915_gem_context *ctx) { @@ -129,24 +109,6 @@ i915_gem_context_clear_user_engines(struct i915_gem_context *ctx) clear_bit(CONTEXT_USER_ENGINES, &ctx->flags); } -static inline bool -i915_gem_context_nopreempt(const struct i915_gem_context *ctx) -{ - return test_bit(CONTEXT_NOPREEMPT, &ctx->flags); -} - -static inline void -i915_gem_context_set_nopreempt(struct i915_gem_context *ctx) -{ - set_bit(CONTEXT_NOPREEMPT, &ctx->flags); -} - -static inline void -i915_gem_context_clear_nopreempt(struct i915_gem_context *ctx) -{ - clear_bit(CONTEXT_NOPREEMPT, &ctx->flags); -} - static inline bool i915_gem_context_is_kernel(struct i915_gem_context *ctx) { return !ctx->file_priv; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index 69df5459c350..017ca803ab47 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -134,11 +134,8 @@ struct i915_gem_context { * @flags: small set of booleans */ unsigned long flags; -#define CONTEXT_BANNED 0 -#define CONTEXT_CLOSED 1 -#define CONTEXT_FORCE_SINGLE_SUBMISSION 2 -#define CONTEXT_USER_ENGINES 3 -#define CONTEXT_NOPREEMPT 4 +#define CONTEXT_CLOSED 0 +#define CONTEXT_USER_ENGINES 1 struct mutex mutex; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 7d07131aa3f7..cbd2bcade3c8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -730,9 +730,6 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) unsigned int i, batch; int err; - if (unlikely(i915_gem_context_is_banned(eb->gem_context))) - return -EIO; - INIT_LIST_HEAD(&eb->relocs); INIT_LIST_HEAD(&eb->unbound); @@ -2175,7 +2172,7 @@ static int eb_submit(struct i915_execbuffer *eb) return err; } - if (i915_gem_context_nopreempt(eb->gem_context)) + if (intel_context_nopreempt(eb->context)) eb->request->flags |= I915_REQUEST_NOPREEMPT; return 0; @@ -2261,6 +2258,9 @@ static int __eb_pin_engine(struct i915_execbuffer *eb, struct intel_context *ce) if (err) return err; + if (unlikely(intel_context_is_banned(ce))) + return -EIO; + /* * Pinning the contexts may generate requests in order to acquire * GGTT space, so do this first before we reserve a seqno for diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 2979f0fd9270..0ba524a414c6 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -281,7 +281,7 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) { struct intel_breadcrumbs *b = &rq->engine->breadcrumbs; - struct intel_context *ce = rq->hw_context; + struct intel_context *ce = rq->context; struct list_head *pos; spin_lock(&b->irq_lock); @@ -338,7 +338,7 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq) */ spin_lock(&b->irq_lock); if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) { - struct intel_context *ce = rq->hw_context; + struct intel_context *ce = rq->context; list_del(&rq->signal_link); if (list_empty(&ce->signals)) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index b1e346d2d35f..ae0dc40031df 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -302,7 +302,7 @@ int intel_context_prepare_remote_request(struct intel_context *ce, int err; /* Only suitable for use in remotely modifying this context */ - GEM_BUG_ON(rq->hw_context == ce); + GEM_BUG_ON(rq->context == ce); if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */ /* Queue this switch after current activity by this context. */ diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index b39eb1fcfbca..65389cb8a565 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -7,7 +7,9 @@ #ifndef __INTEL_CONTEXT_H__ #define __INTEL_CONTEXT_H__ +#include #include +#include #include "i915_active.h" #include "intel_context_types.h" @@ -160,4 +162,44 @@ static inline struct intel_ring *__intel_context_ring_size(u64 sz) return u64_to_ptr(struct intel_ring, sz); } +static inline bool intel_context_is_banned(const struct intel_context *ce) +{ + return test_bit(CONTEXT_BANNED, &ce->flags); +} + +static inline bool intel_context_set_banned(struct intel_context *ce) +{ + return test_and_set_bit(CONTEXT_BANNED, &ce->flags); +} + +static inline bool +intel_context_force_single_submission(const struct intel_context *ce) +{ + return test_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ce->flags); +} + +static inline void +intel_context_set_single_submission(struct intel_context *ce) +{ + __set_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ce->flags); +} + +static inline bool +intel_context_nopreempt(const struct intel_context *ce) +{ + return test_bit(CONTEXT_NOPREEMPT, &ce->flags); +} + +static inline void +intel_context_set_nopreempt(struct intel_context *ce) +{ + set_bit(CONTEXT_NOPREEMPT, &ce->flags); +} + +static inline void +intel_context_clear_nopreempt(struct intel_context *ce) +{ + clear_bit(CONTEXT_NOPREEMPT, &ce->flags); +} + #endif /* __INTEL_CONTEXT_H__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index d1204cc899a3..597448f6e98b 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -54,8 +54,11 @@ struct intel_context { struct intel_timeline *timeline; unsigned long flags; -#define CONTEXT_ALLOC_BIT 0 -#define CONTEXT_VALID_BIT 1 +#define CONTEXT_ALLOC_BIT 0 +#define CONTEXT_VALID_BIT 1 +#define CONTEXT_BANNED 2 +#define CONTEXT_FORCE_SINGLE_SUBMISSION 3 +#define CONTEXT_NOPREEMPT 4 u32 *lrc_reg_state; u64 lrc_desc; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 6dd18f93d45c..e091b3366eae 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1523,9 +1523,9 @@ void intel_engine_dump(struct intel_engine_cs *engine, print_request_ring(m, rq); - if (rq->hw_context->lrc_reg_state) { + if (rq->context->lrc_reg_state) { drm_printf(m, "Logical Ring Context:\n"); - hexdump(m, rq->hw_context->lrc_reg_state, PAGE_SIZE); + hexdump(m, rq->context->lrc_reg_state, PAGE_SIZE); } } spin_unlock_irqrestore(&engine->active.lock, flags); @@ -1586,7 +1586,7 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine) for (port = execlists->pending; (rq = *port); port++) { /* Exclude any contexts already counted in active */ - if (!intel_context_inflight_count(rq->hw_context)) + if (!intel_context_inflight_count(rq->context)) engine->stats.active++; } diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index b7da6d7e7e2a..ec93c47c4bdd 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -880,7 +880,7 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine) list_move(&rq->sched.link, pl); active = rq; } else { - struct intel_engine_cs *owner = rq->hw_context->engine; + struct intel_engine_cs *owner = rq->context->engine; /* * Decouple the virtual breadcrumb before moving it @@ -1051,7 +1051,7 @@ static void restore_default_state(struct intel_context *ce, static void reset_active(struct i915_request *rq, struct intel_engine_cs *engine) { - struct intel_context * const ce = rq->hw_context; + struct intel_context * const ce = rq->context; u32 head; /* @@ -1092,11 +1092,11 @@ static inline struct intel_engine_cs * __execlists_schedule_in(struct i915_request *rq) { struct intel_engine_cs * const engine = rq->engine; - struct intel_context * const ce = rq->hw_context; + struct intel_context * const ce = rq->context; intel_context_get(ce); - if (unlikely(i915_gem_context_is_banned(ce->gem_context))) + if (unlikely(intel_context_is_banned(ce))) reset_active(rq, engine); if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) @@ -1124,7 +1124,7 @@ __execlists_schedule_in(struct i915_request *rq) static inline struct i915_request * execlists_schedule_in(struct i915_request *rq, int idx) { - struct intel_context * const ce = rq->hw_context; + struct intel_context * const ce = rq->context; struct intel_engine_cs *old; GEM_BUG_ON(!intel_engine_pm_is_awake(rq->engine)); @@ -1155,7 +1155,7 @@ static inline void __execlists_schedule_out(struct i915_request *rq, struct intel_engine_cs * const engine) { - struct intel_context * const ce = rq->hw_context; + struct intel_context * const ce = rq->context; /* * NB process_csb() is not under the engine->active.lock and hence @@ -1193,7 +1193,7 @@ __execlists_schedule_out(struct i915_request *rq, static inline void execlists_schedule_out(struct i915_request *rq) { - struct intel_context * const ce = rq->hw_context; + struct intel_context * const ce = rq->context; struct intel_engine_cs *cur, *old; trace_i915_request_out(rq); @@ -1210,7 +1210,7 @@ execlists_schedule_out(struct i915_request *rq) static u64 execlists_update_context(struct i915_request *rq) { - struct intel_context *ce = rq->hw_context; + struct intel_context *ce = rq->context; u64 desc = ce->lrc_desc; u32 tail; @@ -1311,13 +1311,13 @@ assert_pending_valid(const struct intel_engine_execlists *execlists, GEM_BUG_ON(!kref_read(&rq->fence.refcount)); GEM_BUG_ON(!i915_request_is_active(rq)); - if (ce == rq->hw_context) { + if (ce == rq->context) { GEM_TRACE_ERR("Dup context:%llx in pending[%zd]\n", ce->timeline->fence_context, port - execlists->pending); return false; } - ce = rq->hw_context; + ce = rq->context; /* Hold tightly onto the lock to prevent concurrent retires! */ if (!spin_trylock_irqsave(&rq->lock, flags)) @@ -1326,8 +1326,7 @@ assert_pending_valid(const struct intel_engine_execlists *execlists, if (i915_request_completed(rq)) goto unlock; - if (i915_active_is_idle(&ce->active) && - !i915_gem_context_is_kernel(ce->gem_context)) { + if (i915_active_is_idle(&ce->active) && ce->gem_context) { GEM_TRACE_ERR("Inactive context:%llx in pending[%zd]\n", ce->timeline->fence_context, port - execlists->pending); @@ -1399,7 +1398,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) static bool ctx_single_port_submission(const struct intel_context *ce) { return (IS_ENABLED(CONFIG_DRM_I915_GVT) && - i915_gem_context_force_single_submission(ce->gem_context)); + intel_context_force_single_submission(ce)); } static bool can_merge_ctx(const struct intel_context *prev, @@ -1435,7 +1434,7 @@ static bool can_merge_rq(const struct i915_request *prev, (I915_REQUEST_NOPREEMPT | I915_REQUEST_SENTINEL))) return false; - if (!can_merge_ctx(prev->hw_context, next->hw_context)) + if (!can_merge_ctx(prev->context, next->context)) return false; return true; @@ -1622,7 +1621,7 @@ static unsigned long active_preempt_timeout(struct intel_engine_cs *engine) return 0; /* Force a fast reset for terminated contexts (ignoring sysfs!) */ - if (unlikely(i915_gem_context_is_banned(rq->gem_context))) + if (unlikely(intel_context_is_banned(rq->context))) return 1; return READ_ONCE(engine->props.preempt_timeout_ms); @@ -1730,7 +1729,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * tendency to ignore us rewinding the TAIL to the * end of an earlier request. */ - last->hw_context->lrc_desc |= CTX_DESC_FORCE_RESTORE; + last->context->lrc_desc |= CTX_DESC_FORCE_RESTORE; last = NULL; } else if (need_timeslice(engine, last) && timer_expired(&engine->execlists.timer)) { @@ -1802,7 +1801,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) GEM_BUG_ON(rq != ve->request); GEM_BUG_ON(rq->engine != &ve->base); - GEM_BUG_ON(rq->hw_context != &ve->context); + GEM_BUG_ON(rq->context != &ve->context); if (rq_prio(rq) >= queue_prio(execlists)) { if (!virtual_matches(ve, rq, engine)) { @@ -1921,7 +1920,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * same LRCA, i.e. we must submit 2 different * contexts if we submit 2 ELSP. */ - if (last->hw_context == rq->hw_context) + if (last->context == rq->context) goto done; if (i915_request_has_sentinel(last)) @@ -1934,8 +1933,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * the same context (even though a different * request) to the second port. */ - if (ctx_single_port_submission(last->hw_context) || - ctx_single_port_submission(rq->hw_context)) + if (ctx_single_port_submission(last->context) || + ctx_single_port_submission(rq->context)) goto done; merge = false; @@ -1949,8 +1948,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine) } GEM_BUG_ON(last && - !can_merge_ctx(last->hw_context, - rq->hw_context)); + !can_merge_ctx(last->context, + rq->context)); submit = true; last = rq; @@ -2564,7 +2563,7 @@ static int execlists_request_alloc(struct i915_request *request) { int ret; - GEM_BUG_ON(!intel_context_is_pinned(request->hw_context)); + GEM_BUG_ON(!intel_context_is_pinned(request->context)); /* * Flush enough space to reduce the likelihood of waiting after @@ -3071,7 +3070,7 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled) /* We still have requests in-flight; the engine should be active */ GEM_BUG_ON(!intel_engine_pm_is_awake(engine)); - ce = rq->hw_context; + ce = rq->context; GEM_BUG_ON(!i915_vma_is_pinned(ce->state)); if (i915_request_completed(rq)) { diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index f3d1e921fba6..3d293be64fc2 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -41,27 +41,30 @@ static void rmw_clear_fw(struct intel_uncore *uncore, i915_reg_t reg, u32 clr) static void engine_skip_context(struct i915_request *rq) { struct intel_engine_cs *engine = rq->engine; - struct i915_gem_context *hung_ctx = rq->gem_context; + struct intel_context *hung_ctx = rq->context; if (!i915_request_is_active(rq)) return; lockdep_assert_held(&engine->active.lock); list_for_each_entry_continue(rq, &engine->active.requests, sched.link) - if (rq->gem_context == hung_ctx) + if (rq->context == hung_ctx) i915_request_skip(rq, -EIO); } -static void client_mark_guilty(struct drm_i915_file_private *file_priv, - const struct i915_gem_context *ctx) +static void client_mark_guilty(struct i915_request *rq, bool banned) { - unsigned int score; + struct i915_gem_context *ctx = rq->context->gem_context; + struct drm_i915_file_private *file_priv = ctx->file_priv; unsigned long prev_hang; + unsigned int score; - if (i915_gem_context_is_banned(ctx)) + if (IS_ERR_OR_NULL(file_priv)) + return; + + score = 0; + if (banned) score = I915_CLIENT_SCORE_CONTEXT_BAN; - else - score = 0; prev_hang = xchg(&file_priv->hang_timestamp, jiffies); if (time_before(jiffies, prev_hang + I915_CLIENT_FAST_HANG_JIFFIES)) @@ -76,14 +79,15 @@ static void client_mark_guilty(struct drm_i915_file_private *file_priv, } } -static bool context_mark_guilty(struct i915_gem_context *ctx) +static bool mark_guilty(struct i915_request *rq) { + struct i915_gem_context *ctx = rq->context->gem_context; unsigned long prev_hang; bool banned; int i; if (i915_gem_context_is_closed(ctx)) { - i915_gem_context_set_banned(ctx); + intel_context_set_banned(rq->context); return true; } @@ -110,18 +114,17 @@ static bool context_mark_guilty(struct i915_gem_context *ctx) if (banned) { DRM_DEBUG_DRIVER("context %s: guilty %d, banned\n", ctx->name, atomic_read(&ctx->guilty_count)); - i915_gem_context_set_banned(ctx); + intel_context_set_banned(rq->context); } - if (!IS_ERR_OR_NULL(ctx->file_priv)) - client_mark_guilty(ctx->file_priv, ctx); + client_mark_guilty(rq, banned); return banned; } -static void context_mark_innocent(struct i915_gem_context *ctx) +static void mark_innocent(struct i915_request *rq) { - atomic_inc(&ctx->active_count); + atomic_inc(&rq->context->gem_context->active_count); } void __i915_request_reset(struct i915_request *rq, bool guilty) @@ -137,11 +140,11 @@ void __i915_request_reset(struct i915_request *rq, bool guilty) rcu_read_lock(); /* protect the GEM context */ if (guilty) { i915_request_skip(rq, -EIO); - if (context_mark_guilty(rq->gem_context)) + if (mark_guilty(rq)) engine_skip_context(rq); } else { dma_fence_set_error(&rq->fence, -EAGAIN); - context_mark_innocent(rq->gem_context); + mark_innocent(rq); } rcu_read_unlock(); } diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index b61658601c86..a5d30d1468f7 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1480,7 +1480,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags) *cs++ = MI_NOOP; *cs++ = MI_SET_CONTEXT; - *cs++ = i915_ggtt_offset(rq->hw_context->state) | flags; + *cs++ = i915_ggtt_offset(rq->context->state) | flags; /* * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP * WaMiSetContext_Hang:snb,ivb,vlv @@ -1550,7 +1550,7 @@ static int remap_l3_slice(struct i915_request *rq, int slice) static int remap_l3(struct i915_request *rq) { - struct i915_gem_context *ctx = rq->gem_context; + struct i915_gem_context *ctx = rq->context->gem_context; int i, err; if (!ctx->remap_slice) @@ -1597,7 +1597,7 @@ static int switch_mm(struct i915_request *rq, struct i915_address_space *vm) static int switch_context(struct i915_request *rq) { - struct intel_context *ce = rq->hw_context; + struct intel_context *ce = rq->context; int ret; GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); @@ -1631,7 +1631,7 @@ static int ring_request_alloc(struct i915_request *request) { int ret; - GEM_BUG_ON(!intel_context_is_pinned(request->hw_context)); + GEM_BUG_ON(!intel_context_is_pinned(request->context)); GEM_BUG_ON(i915_request_timeline(request)->has_initial_breadcrumb); /* diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index ac8b9116d307..619e34813ade 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -1195,13 +1195,13 @@ static int __cancel_active0(struct live_preempt_cancel *arg) __func__, arg->engine->name)) return -EIO; - clear_bit(CONTEXT_BANNED, &arg->a.ctx->flags); rq = spinner_create_request(&arg->a.spin, arg->a.ctx, arg->engine, MI_ARB_CHECK); if (IS_ERR(rq)) return PTR_ERR(rq); + clear_bit(CONTEXT_BANNED, &rq->context->flags); i915_request_get(rq); i915_request_add(rq); if (!igt_wait_for_spinner(&arg->a.spin, rq)) { @@ -1209,7 +1209,7 @@ static int __cancel_active0(struct live_preempt_cancel *arg) goto out; } - i915_gem_context_set_banned(arg->a.ctx); + intel_context_set_banned(rq->context); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -1244,13 +1244,13 @@ static int __cancel_active1(struct live_preempt_cancel *arg) __func__, arg->engine->name)) return -EIO; - clear_bit(CONTEXT_BANNED, &arg->a.ctx->flags); rq[0] = spinner_create_request(&arg->a.spin, arg->a.ctx, arg->engine, MI_NOOP); /* no preemption */ if (IS_ERR(rq[0])) return PTR_ERR(rq[0]); + clear_bit(CONTEXT_BANNED, &rq[0]->context->flags); i915_request_get(rq[0]); i915_request_add(rq[0]); if (!igt_wait_for_spinner(&arg->a.spin, rq[0])) { @@ -1258,7 +1258,6 @@ static int __cancel_active1(struct live_preempt_cancel *arg) goto out; } - clear_bit(CONTEXT_BANNED, &arg->b.ctx->flags); rq[1] = spinner_create_request(&arg->b.spin, arg->b.ctx, arg->engine, MI_ARB_CHECK); @@ -1267,13 +1266,14 @@ static int __cancel_active1(struct live_preempt_cancel *arg) goto out; } + clear_bit(CONTEXT_BANNED, &rq[1]->context->flags); i915_request_get(rq[1]); err = i915_request_await_dma_fence(rq[1], &rq[0]->fence); i915_request_add(rq[1]); if (err) goto out; - i915_gem_context_set_banned(arg->b.ctx); + intel_context_set_banned(rq[1]->context); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -1316,13 +1316,13 @@ static int __cancel_queued(struct live_preempt_cancel *arg) __func__, arg->engine->name)) return -EIO; - clear_bit(CONTEXT_BANNED, &arg->a.ctx->flags); rq[0] = spinner_create_request(&arg->a.spin, arg->a.ctx, arg->engine, MI_ARB_CHECK); if (IS_ERR(rq[0])) return PTR_ERR(rq[0]); + clear_bit(CONTEXT_BANNED, &rq[0]->context->flags); i915_request_get(rq[0]); i915_request_add(rq[0]); if (!igt_wait_for_spinner(&arg->a.spin, rq[0])) { @@ -1330,13 +1330,13 @@ static int __cancel_queued(struct live_preempt_cancel *arg) goto out; } - clear_bit(CONTEXT_BANNED, &arg->b.ctx->flags); rq[1] = igt_request_alloc(arg->b.ctx, arg->engine); if (IS_ERR(rq[1])) { err = PTR_ERR(rq[1]); goto out; } + clear_bit(CONTEXT_BANNED, &rq[1]->context->flags); i915_request_get(rq[1]); err = i915_request_await_dma_fence(rq[1], &rq[0]->fence); i915_request_add(rq[1]); @@ -1357,7 +1357,7 @@ static int __cancel_queued(struct live_preempt_cancel *arg) if (err) goto out; - i915_gem_context_set_banned(arg->a.ctx); + intel_context_set_banned(rq[2]->context); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -1404,13 +1404,13 @@ static int __cancel_hostile(struct live_preempt_cancel *arg) return 0; GEM_TRACE("%s(%s)\n", __func__, arg->engine->name); - clear_bit(CONTEXT_BANNED, &arg->a.ctx->flags); rq = spinner_create_request(&arg->a.spin, arg->a.ctx, arg->engine, MI_NOOP); /* preemption disabled */ if (IS_ERR(rq)) return PTR_ERR(rq); + clear_bit(CONTEXT_BANNED, &rq->context->flags); i915_request_get(rq); i915_request_add(rq); if (!igt_wait_for_spinner(&arg->a.spin, rq)) { @@ -1418,7 +1418,7 @@ static int __cancel_hostile(struct live_preempt_cancel *arg) goto out; } - i915_gem_context_set_banned(arg->a.ctx); + intel_context_set_banned(rq->context); err = intel_engine_pulse(arg->engine); /* force reset */ if (err) goto out; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 44a7d2e736a7..007636221a71 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -217,7 +217,7 @@ static void guc_wq_item_append(struct intel_guc *guc, static void guc_add_request(struct intel_guc *guc, struct i915_request *rq) { struct intel_engine_cs *engine = rq->engine; - u32 ctx_desc = lower_32_bits(rq->hw_context->lrc_desc); + u32 ctx_desc = lower_32_bits(rq->context->lrc_desc); u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); guc_wq_item_append(guc, engine->guc_id, ctx_desc, @@ -315,7 +315,7 @@ static void __guc_dequeue(struct intel_engine_cs *engine) int i; priolist_for_each_request_consume(rq, rn, p, i) { - if (last && rq->hw_context != last->hw_context) { + if (last && rq->context != last->context) { if (port == last_port) goto done; @@ -420,7 +420,7 @@ static void guc_reset(struct intel_engine_cs *engine, bool stalled) stalled = false; __i915_request_reset(rq, stalled); - intel_lr_context_reset(engine, rq->hw_context, rq->head, stalled); + intel_lr_context_reset(engine, rq->context, rq->head, stalled); out_unlock: spin_unlock_irqrestore(&engine->active.lock, flags); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 5b2a7d072ec9..228c66534e21 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -59,7 +59,7 @@ static void set_context_pdp_root_pointer( static void update_shadow_pdps(struct intel_vgpu_workload *workload) { struct drm_i915_gem_object *ctx_obj = - workload->req->hw_context->state->obj; + workload->req->context->state->obj; struct execlist_ring_context *shadow_ring_context; struct page *page; @@ -130,7 +130,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) struct intel_gvt *gvt = vgpu->gvt; int ring_id = workload->ring_id; struct drm_i915_gem_object *ctx_obj = - workload->req->hw_context->state->obj; + workload->req->context->state->obj; struct execlist_ring_context *shadow_ring_context; struct page *page; void *dst; @@ -205,9 +205,9 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) return 0; } -static inline bool is_gvt_request(struct i915_request *req) +static inline bool is_gvt_request(struct i915_request *rq) { - return i915_gem_context_force_single_submission(req->gem_context); + return intel_context_force_single_submission(rq->context); } static void save_ring_hw_state(struct intel_vgpu *vgpu, int ring_id) @@ -307,7 +307,7 @@ static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload) u32 *cs; int err; - if (IS_GEN(req->i915, 9) && is_inhibit_context(req->hw_context)) + if (IS_GEN(req->i915, 9) && is_inhibit_context(req->context)) intel_vgpu_restore_inhibit_context(vgpu, req); /* @@ -363,11 +363,10 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) } static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, - struct i915_gem_context *ctx) + struct intel_context *ce) { struct intel_vgpu_mm *mm = workload->shadow_mm; - struct i915_ppgtt *ppgtt = - i915_vm_to_ppgtt(i915_gem_context_get_vm_rcu(ctx)); + struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(ce->vm); int i = 0; if (mm->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) { @@ -380,8 +379,6 @@ static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, px_dma(pd) = mm->ppgtt_mm.shadow_pdps[i]; } } - - i915_vm_put(&ppgtt->vm); } static int @@ -529,7 +526,7 @@ static void update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) container_of(wa_ctx, struct intel_vgpu_workload, wa_ctx); struct i915_request *rq = workload->req; struct execlist_ring_context *shadow_ring_context = - (struct execlist_ring_context *)rq->hw_context->lrc_reg_state; + (struct execlist_ring_context *)rq->context->lrc_reg_state; shadow_ring_context->bb_per_ctx_ptr.val = (shadow_ring_context->bb_per_ctx_ptr.val & @@ -628,7 +625,7 @@ static int prepare_workload(struct intel_vgpu_workload *workload) update_shadow_pdps(workload); - set_context_ppgtt_from_shadow(workload, s->shadow[ring]->gem_context); + set_context_ppgtt_from_shadow(workload, s->shadow[ring]); ret = intel_vgpu_sync_oos_pages(workload->vgpu); if (ret) { @@ -787,7 +784,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload) struct i915_request *rq = workload->req; struct intel_vgpu *vgpu = workload->vgpu; struct intel_gvt *gvt = vgpu->gvt; - struct drm_i915_gem_object *ctx_obj = rq->hw_context->state->obj; + struct drm_i915_gem_object *ctx_obj = rq->context->state->obj; struct execlist_ring_context *shadow_ring_context; struct page *page; void *src; @@ -1232,8 +1229,6 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) if (IS_ERR(ctx)) return PTR_ERR(ctx); - i915_gem_context_set_force_single_submission(ctx); - ppgtt = i915_vm_to_ppgtt(i915_gem_context_get_vm_rcu(ctx)); i915_context_ppgtt_root_save(s, ppgtt); @@ -1249,6 +1244,8 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) goto out_shadow_ctx; } + intel_context_set_single_submission(ce); + if (!USES_GUC_SUBMISSION(i915)) { /* Max ring buffer size */ const unsigned int ring_size = 512 * SZ_4K; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f19c678ebefc..6e7010089e23 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1168,19 +1168,18 @@ err_rq: if (!rq) continue; - GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT, - &rq->hw_context->flags)); - state = rq->hw_context->state; + GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT, &rq->context->flags)); + state = rq->context->state; if (!state) continue; /* Serialise with retirement on another CPU */ - err = __intel_context_flush_retire(rq->hw_context); + err = __intel_context_flush_retire(rq->context); if (err) goto out; /* We want to be able to unbind the state from the GGTT */ - GEM_BUG_ON(intel_context_is_pinned(rq->hw_context)); + GEM_BUG_ON(intel_context_is_pinned(rq->context)); /* * As we will hold a reference to the logical state, it will @@ -1230,7 +1229,7 @@ out: if (!rq) continue; - ce = rq->hw_context; + ce = rq->context; i915_request_put(rq); intel_context_put(ce); } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 8374d50c0770..7e2cb063110c 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1221,7 +1221,7 @@ static void error_record_engine_registers(struct i915_gpu_state *error, static void record_request(const struct i915_request *request, struct drm_i915_error_request *erq) { - const struct i915_gem_context *ctx = request->gem_context; + const struct i915_gem_context *ctx = request->context->gem_context; erq->flags = request->fence.flags; erq->context = request->fence.context; @@ -1231,7 +1231,7 @@ static void record_request(const struct i915_request *request, erq->start = i915_ggtt_offset(request->ring->vma); erq->head = request->head; erq->tail = request->tail; - erq->pid = ctx->pid ? pid_nr(ctx->pid) : 0; + erq->pid = ctx && ctx->pid ? pid_nr(ctx->pid) : 0; } static void engine_record_requests(struct intel_engine_cs *engine, @@ -1298,7 +1298,10 @@ static void error_record_engine_execlists(const struct intel_engine_cs *engine, static bool record_context(struct drm_i915_error_context *e, const struct i915_request *rq) { - const struct i915_gem_context *ctx = rq->gem_context; + const struct i915_gem_context *ctx = rq->context->gem_context; + + if (!ctx) + return false; if (ctx->pid) { struct task_struct *task; @@ -1452,7 +1455,7 @@ gem_record_rings(struct i915_gpu_state *error, struct compress *compress) capture = request_record_user_bo(request, ee, capture); capture = capture_vma(capture, - request->hw_context->state, + request->context->state, &ee->ctx); capture = capture_vma(capture, diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 3c163a9d69a9..9d4733927a2c 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -3112,7 +3112,7 @@ static void i915_perf_enable_locked(struct i915_perf_stream *stream) stream->ops->enable(stream); if (stream->hold_preemption) - i915_gem_context_set_nopreempt(stream->ctx); + intel_context_set_nopreempt(stream->pinned_ctx); } /** @@ -3138,7 +3138,7 @@ static void i915_perf_disable_locked(struct i915_perf_stream *stream) stream->enabled = false; if (stream->hold_preemption) - i915_gem_context_clear_nopreempt(stream->ctx); + intel_context_clear_nopreempt(stream->pinned_ctx); if (stream->ops->disable) stream->ops->disable(stream); diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 2118284b796e..218d20d4e414 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -62,6 +62,8 @@ static const char *i915_fence_get_driver_name(struct dma_fence *fence) static const char *i915_fence_get_timeline_name(struct dma_fence *fence) { + const struct i915_gem_context *ctx; + /* * The timeline struct (as part of the ppgtt underneath a context) * may be freed when the request is no longer in use by the GPU. @@ -74,7 +76,11 @@ static const char *i915_fence_get_timeline_name(struct dma_fence *fence) if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) return "signaled"; - return to_request(fence)->gem_context->name ?: "[" DRIVER_NAME "]"; + ctx = to_request(fence)->context->gem_context; + if (!ctx) + return "[" DRIVER_NAME "]"; + + return ctx->name; } static bool i915_fence_signaled(struct dma_fence *fence) @@ -269,8 +275,8 @@ bool i915_request_retire(struct i915_request *rq) remove_from_client(rq); list_del(&rq->link); - intel_context_exit(rq->hw_context); - intel_context_unpin(rq->hw_context); + intel_context_exit(rq->context); + intel_context_unpin(rq->context); free_capture_list(rq); i915_sched_node_fini(&rq->sched); @@ -369,7 +375,7 @@ bool __i915_request_submit(struct i915_request *request) if (i915_request_completed(request)) goto xfer; - if (i915_gem_context_is_banned(request->gem_context)) + if (intel_context_is_banned(request->context)) i915_request_skip(request, -EIO); /* @@ -648,8 +654,7 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp) goto err_free; rq->i915 = ce->engine->i915; - rq->hw_context = ce; - rq->gem_context = ce->gem_context; + rq->context = ce; rq->engine = ce->engine; rq->ring = ce->ring; rq->execution_mask = ce->engine->mask; @@ -917,7 +922,7 @@ i915_request_await_request(struct i915_request *to, struct i915_request *from) &from->submit, I915_FENCE_GFP); } else if (intel_engine_has_semaphores(to->engine) && - to->gem_context->sched.priority >= I915_PRIORITY_NORMAL) { + to->context->gem_context->sched.priority >= I915_PRIORITY_NORMAL) { ret = emit_semaphore_wait(to, from, I915_FENCE_GFP); } else { ret = i915_sw_fence_await_dma_fence(&to->submit, @@ -1298,7 +1303,7 @@ void __i915_request_queue(struct i915_request *rq, void i915_request_add(struct i915_request *rq) { - struct i915_sched_attr attr = rq->gem_context->sched; + struct i915_sched_attr attr = rq->context->gem_context->sched; struct intel_timeline * const tl = i915_request_timeline(rq); struct i915_request *prev; diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index c18c0bcd0193..0e4fe3205ce7 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -115,9 +115,8 @@ struct i915_request { * i915_request_free() will then decrement the refcount on the * context. */ - struct i915_gem_context *gem_context; struct intel_engine_cs *engine; - struct intel_context *hw_context; + struct intel_context *context; struct intel_ring *ring; struct intel_timeline __rcu *timeline; struct list_head signal_link; diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index 2bc2aa46a1b9..bf87c70bfdd9 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.c +++ b/drivers/gpu/drm/i915/i915_scheduler.c @@ -213,7 +213,7 @@ static void kick_submission(struct intel_engine_cs *engine, * If we are already the currently executing context, don't * bother evaluating if we should preempt ourselves. */ - if (inflight->hw_context == rq->hw_context) + if (inflight->context == rq->context) goto unlock; engine->execlists.queue_priority_hint = prio; -- cgit v1.2.3 From 0f100b70487ab8b1323eed1f99cfc10eb18a688e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 20 Dec 2019 10:12:30 +0000 Subject: drm/i915: Push the use-semaphore marker onto the intel_context Instead of rummaging through the intel_context to peek at the GEM context in the middle of request submission to decide whether to use semaphores, store that information on the intel_context itself. Signed-off-by: Chris Wilson Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191220101230.256839-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 56 +++++++++++++++++++-------- drivers/gpu/drm/i915/gt/intel_context.c | 3 ++ drivers/gpu/drm/i915/gt/intel_context.h | 15 +++++++ drivers/gpu/drm/i915/gt/intel_context_types.h | 7 ++-- drivers/gpu/drm/i915/i915_request.c | 8 ++-- 5 files changed, 64 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 42585a20a9ae..e488bd8a6b5e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1852,6 +1852,44 @@ set_persistence(struct i915_gem_context *ctx, return __context_set_persistence(ctx, args->value); } +static void __apply_priority(struct intel_context *ce, void *arg) +{ + struct i915_gem_context *ctx = arg; + + if (!intel_engine_has_semaphores(ce->engine)) + return; + + if (ctx->sched.priority >= I915_PRIORITY_NORMAL) + intel_context_set_use_semaphores(ce); + else + intel_context_clear_use_semaphores(ce); +} + +static int set_priority(struct i915_gem_context *ctx, + const struct drm_i915_gem_context_param *args) +{ + s64 priority = args->value; + + if (args->size) + return -EINVAL; + + if (!(ctx->i915->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY)) + return -ENODEV; + + if (priority > I915_CONTEXT_MAX_USER_PRIORITY || + priority < I915_CONTEXT_MIN_USER_PRIORITY) + return -EINVAL; + + if (priority > I915_CONTEXT_DEFAULT_PRIORITY && + !capable(CAP_SYS_NICE)) + return -EPERM; + + ctx->sched.priority = I915_USER_PRIORITY(priority); + context_apply_all(ctx, __apply_priority, ctx); + + return 0; +} + static int ctx_setparam(struct drm_i915_file_private *fpriv, struct i915_gem_context *ctx, struct drm_i915_gem_context_param *args) @@ -1898,23 +1936,7 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv, break; case I915_CONTEXT_PARAM_PRIORITY: - { - s64 priority = args->value; - - if (args->size) - ret = -EINVAL; - else if (!(ctx->i915->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY)) - ret = -ENODEV; - else if (priority > I915_CONTEXT_MAX_USER_PRIORITY || - priority < I915_CONTEXT_MIN_USER_PRIORITY) - ret = -EINVAL; - else if (priority > I915_CONTEXT_DEFAULT_PRIORITY && - !capable(CAP_SYS_NICE)) - ret = -EPERM; - else - ctx->sched.priority = - I915_USER_PRIORITY(priority); - } + ret = set_priority(ctx, args); break; case I915_CONTEXT_PARAM_SSEU: diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index ae0dc40031df..e73e976e5ecd 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -233,6 +233,9 @@ intel_context_init(struct intel_context *ce, rcu_read_unlock(); if (ctx->timeline) ce->timeline = intel_timeline_get(ctx->timeline); + if (ctx->sched.priority >= I915_PRIORITY_NORMAL && + intel_engine_has_semaphores(engine)) + __set_bit(CONTEXT_USE_SEMAPHORES, &ce->flags); ce->engine = engine; ce->ops = engine->cops; diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index 65389cb8a565..e7ac7027969f 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -162,6 +162,21 @@ static inline struct intel_ring *__intel_context_ring_size(u64 sz) return u64_to_ptr(struct intel_ring, sz); } +static inline bool intel_context_use_semaphores(const struct intel_context *ce) +{ + return test_bit(CONTEXT_USE_SEMAPHORES, &ce->flags); +} + +static inline void intel_context_set_use_semaphores(struct intel_context *ce) +{ + set_bit(CONTEXT_USE_SEMAPHORES, &ce->flags); +} + +static inline void intel_context_clear_use_semaphores(struct intel_context *ce) +{ + clear_bit(CONTEXT_USE_SEMAPHORES, &ce->flags); +} + static inline bool intel_context_is_banned(const struct intel_context *ce) { return test_bit(CONTEXT_BANNED, &ce->flags); diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 597448f6e98b..af0d55b111f5 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -56,9 +56,10 @@ struct intel_context { unsigned long flags; #define CONTEXT_ALLOC_BIT 0 #define CONTEXT_VALID_BIT 1 -#define CONTEXT_BANNED 2 -#define CONTEXT_FORCE_SINGLE_SUBMISSION 3 -#define CONTEXT_NOPREEMPT 4 +#define CONTEXT_USE_SEMAPHORES 2 +#define CONTEXT_BANNED 3 +#define CONTEXT_FORCE_SINGLE_SUBMISSION 4 +#define CONTEXT_NOPREEMPT 5 u32 *lrc_reg_state; u64 lrc_desc; diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 218d20d4e414..ed70d8dcea74 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -917,18 +917,16 @@ i915_request_await_request(struct i915_request *to, struct i915_request *from) return ret; } - if (to->engine == from->engine) { + if (to->engine == from->engine) ret = i915_sw_fence_await_sw_fence_gfp(&to->submit, &from->submit, I915_FENCE_GFP); - } else if (intel_engine_has_semaphores(to->engine) && - to->context->gem_context->sched.priority >= I915_PRIORITY_NORMAL) { + else if (intel_context_use_semaphores(to->context)) ret = emit_semaphore_wait(to, from, I915_FENCE_GFP); - } else { + else ret = i915_sw_fence_await_dma_fence(&to->submit, &from->fence, 0, I915_FENCE_GFP); - } if (ret < 0) return ret; -- cgit v1.2.3 From a5e93b42f462fc87f884f12f5176b10dca5a3bf1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 13 Dec 2019 15:13:31 +0000 Subject: drm/i915/execlists: Select arb on/off around batches based on preemption Decide whether or not we need to disable arbitration within user batches based on our intel_engine_has_preemption() flag. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20191213151331.1788371-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_lrc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index ec93c47c4bdd..f060baf04bc0 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -3256,9 +3256,9 @@ static void execlists_reset_finish(struct intel_engine_cs *engine) atomic_read(&execlists->tasklet.count)); } -static int gen8_emit_bb_start(struct i915_request *rq, - u64 offset, u32 len, - const unsigned int flags) +static int gen8_emit_bb_start_noarb(struct i915_request *rq, + u64 offset, u32 len, + const unsigned int flags) { u32 *cs; @@ -3292,7 +3292,7 @@ static int gen8_emit_bb_start(struct i915_request *rq, return 0; } -static int gen9_emit_bb_start(struct i915_request *rq, +static int gen8_emit_bb_start(struct i915_request *rq, u64 offset, u32 len, const unsigned int flags) { @@ -3767,6 +3767,11 @@ void intel_execlists_set_default_submission(struct intel_engine_cs *engine) if (INTEL_GEN(engine->i915) >= 12) engine->flags |= I915_ENGINE_HAS_RELATIVE_MMIO; + + if (intel_engine_has_preemption(engine)) + engine->emit_bb_start = gen8_emit_bb_start; + else + engine->emit_bb_start = gen8_emit_bb_start_noarb; } static void execlists_shutdown(struct intel_engine_cs *engine) @@ -3820,10 +3825,6 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) * until a more refined solution exists. */ } - if (IS_GEN(engine->i915, 8)) - engine->emit_bb_start = gen8_emit_bb_start; - else - engine->emit_bb_start = gen9_emit_bb_start; } static inline void -- cgit v1.2.3 From 216383e920e85f3c1d9772030a69c4dab7455f47 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 19 Dec 2019 13:14:30 +0200 Subject: drm/i915: Introduce intel_crtc_state_alloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have several places where we want to allocate a pristine crtc state. Some of those currently call intel_crtc_state_reset() to properly initialize all the non-zero defaults in the state, but some places do not. Let's add intel_crtc_state_alloc() to do both the alloc and the reset, and call that everywhere we need a fresh crtc state. v2: s/kzalloc/kmalloc/ since we memset() anyway (José) Cc: José Roberto de Souza Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191219111430.17527-1-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 30 ++++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 983f5b084ff9..06e799db0211 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -168,6 +168,7 @@ static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state); static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state); static void intel_modeset_setup_hw_state(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx); +static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc); struct intel_limit { struct { @@ -8051,11 +8052,10 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe, struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); struct intel_crtc_state *pipe_config; - pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); + pipe_config = intel_crtc_state_alloc(crtc); if (!pipe_config) return -ENOMEM; - pipe_config->uapi.crtc = &crtc->base; pipe_config->cpu_transcoder = (enum transcoder)pipe; pipe_config->pixel_multiplier = 1; pipe_config->dpll = *dpll; @@ -11646,6 +11646,18 @@ static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state, crtc_state->scaler_state.scaler_id = -1; } +static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state; + + crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL); + + if (crtc_state) + intel_crtc_state_reset(crtc_state, crtc); + + return crtc_state; +} + /* Returns the currently programmed mode of the given encoder. */ struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder) @@ -11665,14 +11677,12 @@ intel_encoder_current_mode(struct intel_encoder *encoder) if (!mode) return NULL; - crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); + crtc_state = intel_crtc_state_alloc(crtc); if (!crtc_state) { kfree(mode); return NULL; } - intel_crtc_state_reset(crtc_state, crtc); - if (!dev_priv->display.get_pipe_config(crtc, crtc_state)) { kfree(crtc_state); kfree(mode); @@ -12609,11 +12619,11 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state static int intel_crtc_prepare_cleared_state(struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = - to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_crtc_state *saved_state; - saved_state = kzalloc(sizeof(*saved_state), GFP_KERNEL); + saved_state = intel_crtc_state_alloc(crtc); if (!saved_state) return -ENOMEM; @@ -15734,14 +15744,12 @@ static struct intel_crtc *intel_crtc_alloc(void) if (!crtc) return ERR_PTR(-ENOMEM); - crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); + crtc_state = intel_crtc_state_alloc(crtc); if (!crtc_state) { kfree(crtc); return ERR_PTR(-ENOMEM); } - intel_crtc_state_reset(crtc_state, crtc); - crtc->base.state = &crtc_state->uapi; crtc->config = crtc_state; -- cgit v1.2.3 From ed7dd73cd8ca143ddd80654c67e5d2e66e3df42f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 21 Dec 2019 00:11:36 +0000 Subject: drm/i915/selftests: Setup engine->retire for mock_engine Enable and cleanup the engine->retire for the mock engine. Fixes: dc93c9b69315 ("drm/i915/gt: Schedule request retirement when signaler idles") Signed-off-by: Chris Wilson Acked-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20191221001136.720154-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/mock_engine.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 39df9d49a134..9efb63a03129 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -290,6 +290,7 @@ int mock_engine_init(struct intel_engine_cs *engine) intel_engine_init_breadcrumbs(engine); intel_engine_init_execlists(engine); intel_engine_init__pm(engine); + intel_engine_init_retire(engine); intel_engine_pool_init(&engine->pool); ce = create_kernel_context(engine); @@ -332,6 +333,7 @@ void mock_engine_free(struct intel_engine_cs *engine) intel_context_unpin(engine->kernel_context); intel_context_put(engine->kernel_context); + intel_engine_fini_retire(engine); intel_engine_fini_breadcrumbs(engine); kfree(engine); -- cgit v1.2.3 From e6ba76480299a0d77c51d846f7467b1673aad25b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 21 Dec 2019 16:03:24 +0000 Subject: drm/i915: Remove i915->kernel_context Allocate only an internal intel_context for the kernel_context, forgoing a global GEM context for internal use as we only require a separate address space (for our own protection). Now having weaned GT from requiring ce->gem_context, we can stop referencing it entirely. This also means we no longer have to create random and unnecessary GEM contexts for internal use. GEM contexts are now entirely for tracking GEM clients, and intel_context the execution environment on the GPU. Signed-off-by: Chris Wilson Cc: Andi Shyti Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191221160324.1073045-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 97 +++++----- drivers/gpu/drm/i915/gem/i915_gem_context.h | 10 +- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 6 +- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 5 +- drivers/gpu/drm/i915/gem/selftests/mock_context.c | 11 +- drivers/gpu/drm/i915/gt/intel_context.c | 32 +--- drivers/gpu/drm/i915/gt/intel_context.h | 9 +- drivers/gpu/drm/i915/gt/intel_context_types.h | 13 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 23 +-- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 3 + drivers/gpu/drm/i915/gt/intel_gt.c | 25 ++- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 18 +- drivers/gpu/drm/i915/gt/intel_gt_types.h | 7 + drivers/gpu/drm/i915/gt/intel_lrc.c | 21 +-- drivers/gpu/drm/i915/gt/intel_lrc.h | 6 +- drivers/gpu/drm/i915/gt/intel_reset.c | 14 +- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 2 +- drivers/gpu/drm/i915/gt/selftest_context.c | 57 +----- .../gpu/drm/i915/gt/selftest_engine_heartbeat.c | 3 +- drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 178 +++++++++--------- drivers/gpu/drm/i915/gt/selftest_lrc.c | 201 +++++++++------------ drivers/gpu/drm/i915/gt/selftest_mocs.c | 6 +- drivers/gpu/drm/i915/gt/selftest_rc6.c | 3 +- drivers/gpu/drm/i915/gt/selftest_workarounds.c | 72 +++----- drivers/gpu/drm/i915/gvt/scheduler.c | 16 +- drivers/gpu/drm/i915/i915_active.c | 2 + drivers/gpu/drm/i915/i915_drv.h | 3 - drivers/gpu/drm/i915/i915_gem.c | 19 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 8 +- drivers/gpu/drm/i915/i915_perf.c | 3 - drivers/gpu/drm/i915/i915_request.c | 5 +- drivers/gpu/drm/i915/i915_vma.c | 3 + drivers/gpu/drm/i915/selftests/i915_request.c | 6 +- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 8 +- 34 files changed, 388 insertions(+), 507 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index e488bd8a6b5e..6167e68bbb25 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -209,6 +209,35 @@ context_get_vm_rcu(struct i915_gem_context *ctx) } while (1); } +static void intel_context_set_gem(struct intel_context *ce, + struct i915_gem_context *ctx) +{ + GEM_BUG_ON(ce->gem_context); + ce->gem_context = ctx; + + if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) + ce->ring = __intel_context_ring_size(SZ_16K); + + if (rcu_access_pointer(ctx->vm)) { + struct i915_address_space *vm; + + rcu_read_lock(); + vm = context_get_vm_rcu(ctx); /* hmm */ + rcu_read_unlock(); + + i915_vm_put(ce->vm); + ce->vm = vm; + } + + GEM_BUG_ON(ce->timeline); + if (ctx->timeline) + ce->timeline = intel_timeline_get(ctx->timeline); + + if (ctx->sched.priority >= I915_PRIORITY_NORMAL && + intel_engine_has_semaphores(ce->engine)) + __set_bit(CONTEXT_USE_SEMAPHORES, &ce->flags); +} + static void __free_engines(struct i915_gem_engines *e, unsigned int count) { while (count--) { @@ -251,12 +280,14 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx) GEM_BUG_ON(engine->legacy_idx >= I915_NUM_ENGINES); GEM_BUG_ON(e->engines[engine->legacy_idx]); - ce = intel_context_create(ctx, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) { __free_engines(e, e->num_engines + 1); return ERR_CAST(ce); } + intel_context_set_gem(ce, ctx); + e->engines[engine->legacy_idx] = ce; e->num_engines = max(e->num_engines, engine->legacy_idx); } @@ -706,37 +737,6 @@ i915_gem_create_context(struct drm_i915_private *i915, unsigned int flags) return ctx; } -static void -destroy_kernel_context(struct i915_gem_context **ctxp) -{ - struct i915_gem_context *ctx; - - /* Keep the context ref so that we can free it immediately ourselves */ - ctx = i915_gem_context_get(fetch_and_zero(ctxp)); - GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); - - context_close(ctx); - i915_gem_context_free(ctx); -} - -struct i915_gem_context * -i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio) -{ - struct i915_gem_context *ctx; - - ctx = i915_gem_create_context(i915, 0); - if (IS_ERR(ctx)) - return ctx; - - i915_gem_context_clear_bannable(ctx); - i915_gem_context_set_persistence(ctx); - ctx->sched.priority = I915_USER_PRIORITY(prio); - - GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); - - return ctx; -} - static void init_contexts(struct i915_gem_contexts *gc) { spin_lock_init(&gc->lock); @@ -746,32 +746,16 @@ static void init_contexts(struct i915_gem_contexts *gc) init_llist_head(&gc->free_list); } -int i915_gem_init_contexts(struct drm_i915_private *i915) +void i915_gem_init__contexts(struct drm_i915_private *i915) { - struct i915_gem_context *ctx; - - /* Reassure ourselves we are only called once */ - GEM_BUG_ON(i915->kernel_context); - init_contexts(&i915->gem.contexts); - - /* lowest priority; idle task */ - ctx = i915_gem_context_create_kernel(i915, I915_PRIORITY_MIN); - if (IS_ERR(ctx)) { - DRM_ERROR("Failed to create default global context\n"); - return PTR_ERR(ctx); - } - i915->kernel_context = ctx; - DRM_DEBUG_DRIVER("%s context support initialized\n", DRIVER_CAPS(i915)->has_logical_contexts ? "logical" : "fake"); - return 0; } void i915_gem_driver_release__contexts(struct drm_i915_private *i915) { - destroy_kernel_context(&i915->kernel_context); flush_work(&i915->gem.contexts.free_work); } @@ -840,7 +824,6 @@ int i915_gem_context_open(struct drm_i915_private *i915, if (err < 0) goto err_ctx; - GEM_BUG_ON(i915_gem_context_is_kernel(ctx)); GEM_BUG_ON(err > 0); return 0; @@ -1531,12 +1514,14 @@ set_engines__load_balance(struct i915_user_extension __user *base, void *data) } } - ce = intel_execlists_create_virtual(set->ctx, siblings, n); + ce = intel_execlists_create_virtual(siblings, n); if (IS_ERR(ce)) { err = PTR_ERR(ce); goto out_siblings; } + intel_context_set_gem(ce, set->ctx); + if (cmpxchg(&set->engines->engines[idx], NULL, ce)) { intel_context_put(ce); err = -EEXIST; @@ -1706,12 +1691,14 @@ set_engines(struct i915_gem_context *ctx, return -ENOENT; } - ce = intel_context_create(ctx, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) { __free_engines(set.engines, n); return PTR_ERR(ce); } + intel_context_set_gem(ce, ctx); + set.engines->engines[n] = ce; } set.engines->num_engines = num_engines; @@ -2016,13 +2003,15 @@ static int clone_engines(struct i915_gem_context *dst, */ if (intel_engine_is_virtual(engine)) clone->engines[n] = - intel_execlists_clone_virtual(dst, engine); + intel_execlists_clone_virtual(engine); else - clone->engines[n] = intel_context_create(dst, engine); + clone->engines[n] = intel_context_create(engine); if (IS_ERR_OR_NULL(clone->engines[n])) { __free_engines(clone, n); goto err_unlock; } + + intel_context_set_gem(clone->engines[n], dst); } clone->num_engines = n; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.h b/drivers/gpu/drm/i915/gem/i915_gem_context.h index 69932899803e..14f3cc1b7583 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.h @@ -109,13 +109,8 @@ i915_gem_context_clear_user_engines(struct i915_gem_context *ctx) clear_bit(CONTEXT_USER_ENGINES, &ctx->flags); } -static inline bool i915_gem_context_is_kernel(struct i915_gem_context *ctx) -{ - return !ctx->file_priv; -} - /* i915_gem_context.c */ -int __must_check i915_gem_init_contexts(struct drm_i915_private *i915); +void i915_gem_init__contexts(struct drm_i915_private *i915); void i915_gem_driver_release__contexts(struct drm_i915_private *i915); int i915_gem_context_open(struct drm_i915_private *i915, @@ -140,9 +135,6 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data, struct drm_file *file); -struct i915_gem_context * -i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio); - static inline struct i915_gem_context * i915_gem_context_get(struct i915_gem_context *ctx) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index f7f66c62cf0e..e5558af111e2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -779,15 +779,11 @@ i915_gem_userptr_ioctl(struct drm_device *dev, return -EFAULT; if (args->flags & I915_USERPTR_READ_ONLY) { - struct i915_address_space *vm; - /* * On almost all of the older hw, we cannot tell the GPU that * a page is readonly. */ - vm = rcu_dereference_protected(dev_priv->kernel_context->vm, - true); /* static vm */ - if (!vm || !vm->has_read_only) + if (!dev_priv->gt.vm->has_read_only) return -ENODEV; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 780e58fe5c64..7fc46861a54d 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -337,7 +337,7 @@ static int live_parallel_switch(void *arg) if (!data[m].ce[0]) continue; - ce = intel_context_create(ctx, data[m].ce[0]->engine); + ce = intel_context_create(data[m].ce[0]->engine); if (IS_ERR(ce)) goto out; @@ -1264,8 +1264,7 @@ __igt_ctx_sseu(struct drm_i915_private *i915, hweight32(engine->sseu.slice_mask), hweight32(pg_sseu.slice_mask)); - ce = intel_context_create(engine->kernel_context->gem_context, - engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) { ret = PTR_ERR(ce); goto out_put; diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.c b/drivers/gpu/drm/i915/gem/selftests/mock_context.c index 53e89efb09c0..7d7e13dc2fdf 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.c @@ -96,7 +96,16 @@ err_ctx: struct i915_gem_context * kernel_context(struct drm_i915_private *i915) { - return i915_gem_context_create_kernel(i915, I915_PRIORITY_NORMAL); + struct i915_gem_context *ctx; + + ctx = i915_gem_create_context(i915, 0); + if (IS_ERR(ctx)) + return ctx; + + i915_gem_context_clear_bannable(ctx); + i915_gem_context_set_persistence(ctx); + + return ctx; } void kernel_context_close(struct i915_gem_context *ctx) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index e73e976e5ecd..fbaa9df6f436 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -31,8 +31,7 @@ void intel_context_free(struct intel_context *ce) } struct intel_context * -intel_context_create(struct i915_gem_context *ctx, - struct intel_engine_cs *engine) +intel_context_create(struct intel_engine_cs *engine) { struct intel_context *ce; @@ -40,7 +39,7 @@ intel_context_create(struct i915_gem_context *ctx, if (!ce) return ERR_PTR(-ENOMEM); - intel_context_init(ce, ctx, engine); + intel_context_init(ce, engine); return ce; } @@ -71,8 +70,6 @@ int __intel_context_do_pin(struct intel_context *ce) CE_TRACE(ce, "pin ring:{head:%04x, tail:%04x}\n", ce->ring->head, ce->ring->tail); - i915_gem_context_get(ce->gem_context); /* for ctx->ppgtt */ - smp_mb__before_atomic(); /* flush pin before it is visible */ } @@ -101,7 +98,6 @@ void intel_context_unpin(struct intel_context *ce) ce->ops->unpin(ce); - i915_gem_context_put(ce->gem_context); intel_context_active_release(ce); } @@ -193,7 +189,7 @@ int intel_context_active_acquire(struct intel_context *ce) return err; /* Preallocate tracking nodes */ - if (!i915_gem_context_is_kernel(ce->gem_context)) { + if (!intel_context_is_barrier(ce)) { err = i915_active_acquire_preallocate_barrier(&ce->active, ce->engine); if (err) { @@ -214,33 +210,19 @@ void intel_context_active_release(struct intel_context *ce) void intel_context_init(struct intel_context *ce, - struct i915_gem_context *ctx, struct intel_engine_cs *engine) { - struct i915_address_space *vm; - GEM_BUG_ON(!engine->cops); + GEM_BUG_ON(!engine->gt->vm); kref_init(&ce->ref); - ce->gem_context = ctx; - rcu_read_lock(); - vm = rcu_dereference(ctx->vm); - if (vm) - ce->vm = i915_vm_get(vm); - else - ce->vm = i915_vm_get(&engine->gt->ggtt->vm); - rcu_read_unlock(); - if (ctx->timeline) - ce->timeline = intel_timeline_get(ctx->timeline); - if (ctx->sched.priority >= I915_PRIORITY_NORMAL && - intel_engine_has_semaphores(engine)) - __set_bit(CONTEXT_USE_SEMAPHORES, &ce->flags); - ce->engine = engine; ce->ops = engine->cops; ce->sseu = engine->sseu; - ce->ring = __intel_context_ring_size(SZ_16K); + ce->ring = __intel_context_ring_size(SZ_4K); + + ce->vm = i915_vm_get(engine->gt->vm); INIT_LIST_HEAD(&ce->signal_link); INIT_LIST_HEAD(&ce->signals); diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index e7ac7027969f..1d4a1b1357cf 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -25,13 +25,11 @@ } while (0) void intel_context_init(struct intel_context *ce, - struct i915_gem_context *ctx, struct intel_engine_cs *engine); void intel_context_fini(struct intel_context *ce); struct intel_context * -intel_context_create(struct i915_gem_context *ctx, - struct intel_engine_cs *engine); +intel_context_create(struct intel_engine_cs *engine); void intel_context_free(struct intel_context *ce); @@ -162,6 +160,11 @@ static inline struct intel_ring *__intel_context_ring_size(u64 sz) return u64_to_ptr(struct intel_ring, sz); } +static inline bool intel_context_is_barrier(const struct intel_context *ce) +{ + return test_bit(CONTEXT_BARRIER_BIT, &ce->flags); +} + static inline bool intel_context_use_semaphores(const struct intel_context *ce) { return test_bit(CONTEXT_USE_SEMAPHORES, &ce->flags); diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index af0d55b111f5..7dd03ad9826c 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -54,12 +54,13 @@ struct intel_context { struct intel_timeline *timeline; unsigned long flags; -#define CONTEXT_ALLOC_BIT 0 -#define CONTEXT_VALID_BIT 1 -#define CONTEXT_USE_SEMAPHORES 2 -#define CONTEXT_BANNED 3 -#define CONTEXT_FORCE_SINGLE_SUBMISSION 4 -#define CONTEXT_NOPREEMPT 5 +#define CONTEXT_BARRIER_BIT 0 +#define CONTEXT_ALLOC_BIT 1 +#define CONTEXT_VALID_BIT 2 +#define CONTEXT_USE_SEMAPHORES 3 +#define CONTEXT_BANNED 4 +#define CONTEXT_FORCE_SINGLE_SUBMISSION 5 +#define CONTEXT_NOPREEMPT 6 u32 *lrc_reg_state; u64 lrc_desc; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index e091b3366eae..0c4c07072473 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -759,13 +759,13 @@ create_kernel_context(struct intel_engine_cs *engine) struct intel_context *ce; int err; - ce = intel_context_create(engine->i915->kernel_context, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) return ce; - ce->ring = __intel_context_ring_size(SZ_4K); + __set_bit(CONTEXT_BARRIER_BIT, &ce->flags); - err = intel_context_pin(ce); + err = intel_context_pin(ce); /* perma-pin so it is always available */ if (err) { intel_context_put(ce); return ERR_PTR(err); @@ -800,6 +800,12 @@ int intel_engine_init_common(struct intel_engine_cs *engine) engine->set_default_submission(engine); + ret = measure_breadcrumb_dw(engine); + if (ret < 0) + return ret; + + engine->emit_fini_breadcrumb_dw = ret; + /* * We may need to do things with the shrinker which * require us to immediately switch back to the default @@ -814,18 +820,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) engine->kernel_context = ce; - ret = measure_breadcrumb_dw(engine); - if (ret < 0) - goto err_unpin; - - engine->emit_fini_breadcrumb_dw = ret; - return 0; - -err_unpin: - intel_context_unpin(ce); - intel_context_put(ce); - return ret; } /** diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 8fb7b34fc5a6..010620b78202 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -6,6 +6,7 @@ #include "i915_drv.h" +#include "intel_context.h" #include "intel_engine.h" #include "intel_engine_heartbeat.h" #include "intel_engine_pm.h" @@ -122,6 +123,8 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) unsigned long flags; bool result = true; + GEM_BUG_ON(!intel_context_is_barrier(ce)); + /* Already inside the kernel context, safe to power down. */ if (engine->wakeref_serial == engine->serial) return true; diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index c4fd8d65b8a3..af4f8c810009 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -74,7 +74,6 @@ int intel_gt_init_hw(struct intel_gt *gt) struct intel_uncore *uncore = gt->uncore; int ret; - BUG_ON(!i915->kernel_context); ret = intel_gt_terminally_wedged(gt); if (ret) return ret; @@ -365,6 +364,14 @@ static void intel_gt_fini_scratch(struct intel_gt *gt) i915_vma_unpin_and_release(>->scratch, 0); } +static struct i915_address_space *kernel_vm(struct intel_gt *gt) +{ + if (INTEL_PPGTT(gt->i915) > INTEL_PPGTT_ALIASING) + return &i915_ppgtt_create(gt->i915)->vm; + else + return i915_vm_get(>->ggtt->vm); +} + int intel_gt_init(struct intel_gt *gt) { int err; @@ -375,7 +382,17 @@ int intel_gt_init(struct intel_gt *gt) intel_gt_pm_init(gt); + gt->vm = kernel_vm(gt); + if (!gt->vm) { + err = -ENOMEM; + goto err_scratch; + } + return 0; + +err_scratch: + intel_gt_fini_scratch(gt); + return err; } void intel_gt_driver_remove(struct intel_gt *gt) @@ -390,6 +407,12 @@ void intel_gt_driver_unregister(struct intel_gt *gt) void intel_gt_driver_release(struct intel_gt *gt) { + struct i915_address_space *vm; + + vm = fetch_and_zero(>->vm); + if (vm) /* FIXME being called twice on error paths :( */ + i915_vm_put(vm); + intel_gt_pm_fini(gt); intel_gt_fini_scratch(gt); } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index 0d1bca787288..063f863ee21c 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -8,6 +8,7 @@ #include "i915_drv.h" /* for_each_engine() */ #include "i915_request.h" +#include "intel_engine_heartbeat.h" #include "intel_gt.h" #include "intel_gt_pm.h" #include "intel_gt_requests.h" @@ -27,8 +28,10 @@ static void flush_submission(struct intel_gt *gt) struct intel_engine_cs *engine; enum intel_engine_id id; - for_each_engine(engine, gt, id) + for_each_engine(engine, gt, id) { intel_engine_flush_submission(engine); + flush_work(&engine->retire_work); + } } static void engine_retire(struct work_struct *work) @@ -117,10 +120,9 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) spin_lock(&timelines->lock); list_for_each_entry_safe(tl, tn, &timelines->active_list, link) { - if (!mutex_trylock(&tl->mutex)) { - active_count++; /* report busy to caller, try again? */ + active_count++; /* report busy to caller, try again? */ + if (!mutex_trylock(&tl->mutex)) continue; - } intel_timeline_get(tl); GEM_BUG_ON(!atomic_read(&tl->active_count)); @@ -145,10 +147,10 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) /* Resume iteration after dropping lock */ list_safe_reset_next(tl, tn, link); - if (atomic_dec_and_test(&tl->active_count)) + if (atomic_dec_and_test(&tl->active_count)) { list_del(&tl->link); - else - active_count += !!rcu_access_pointer(tl->last_request.fence); + active_count--; + } mutex_unlock(&tl->mutex); @@ -163,6 +165,8 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) list_for_each_entry_safe(tl, tn, &free, link) __intel_timeline_free(&tl->kref); + flush_submission(gt); + return active_count ? timeout : 0; } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h index d4e14dbd172e..96890dd12b5f 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_types.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h @@ -90,6 +90,13 @@ struct intel_gt { struct intel_engine_cs *engine[I915_NUM_ENGINES]; struct intel_engine_cs *engine_class[MAX_ENGINE_CLASS + 1] [MAX_ENGINE_INSTANCE + 1]; + + /* + * Default address space (either GGTT or ppGTT depending on arch). + * + * Reserved for exclusive use by the kernel. + */ + struct i915_address_space *vm; }; enum intel_gt_scratch_field { diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index f060baf04bc0..fe2d1523bda3 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -133,12 +133,11 @@ */ #include -#include "gem/i915_gem_context.h" - #include "i915_drv.h" #include "i915_perf.h" #include "i915_trace.h" #include "i915_vgpu.h" +#include "intel_context.h" #include "intel_engine_pm.h" #include "intel_gt.h" #include "intel_gt_pm.h" @@ -1326,7 +1325,8 @@ assert_pending_valid(const struct intel_engine_execlists *execlists, if (i915_request_completed(rq)) goto unlock; - if (i915_active_is_idle(&ce->active) && ce->gem_context) { + if (i915_active_is_idle(&ce->active) && + !intel_context_is_barrier(ce)) { GEM_TRACE_ERR("Inactive context:%llx in pending[%zd]\n", ce->timeline->fence_context, port - execlists->pending); @@ -4475,8 +4475,7 @@ virtual_bond_execute(struct i915_request *rq, struct dma_fence *signal) } struct intel_context * -intel_execlists_create_virtual(struct i915_gem_context *ctx, - struct intel_engine_cs **siblings, +intel_execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count) { struct virtual_engine *ve; @@ -4487,13 +4486,13 @@ intel_execlists_create_virtual(struct i915_gem_context *ctx, return ERR_PTR(-EINVAL); if (count == 1) - return intel_context_create(ctx, siblings[0]); + return intel_context_create(siblings[0]); ve = kzalloc(struct_size(ve, siblings, count), GFP_KERNEL); if (!ve) return ERR_PTR(-ENOMEM); - ve->base.i915 = ctx->i915; + ve->base.i915 = siblings[0]->i915; ve->base.gt = siblings[0]->gt; ve->base.uncore = siblings[0]->uncore; ve->base.id = -1; @@ -4535,7 +4534,7 @@ intel_execlists_create_virtual(struct i915_gem_context *ctx, virtual_submission_tasklet, (unsigned long)ve); - intel_context_init(&ve->context, ctx, &ve->base); + intel_context_init(&ve->context, &ve->base); for (n = 0; n < count; n++) { struct intel_engine_cs *sibling = siblings[n]; @@ -4610,14 +4609,12 @@ err_put: } struct intel_context * -intel_execlists_clone_virtual(struct i915_gem_context *ctx, - struct intel_engine_cs *src) +intel_execlists_clone_virtual(struct intel_engine_cs *src) { struct virtual_engine *se = to_virtual_engine(src); struct intel_context *dst; - dst = intel_execlists_create_virtual(ctx, - se->siblings, + dst = intel_execlists_create_virtual(se->siblings, se->num_siblings); if (IS_ERR(dst)) return dst; diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.h b/drivers/gpu/drm/i915/gt/intel_lrc.h index 04511d8ebdc1..081521f17c74 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.h +++ b/drivers/gpu/drm/i915/gt/intel_lrc.h @@ -111,13 +111,11 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine, unsigned int max); struct intel_context * -intel_execlists_create_virtual(struct i915_gem_context *ctx, - struct intel_engine_cs **siblings, +intel_execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count); struct intel_context * -intel_execlists_clone_virtual(struct i915_gem_context *ctx, - struct intel_engine_cs *src); +intel_execlists_clone_virtual(struct intel_engine_cs *src); int intel_virtual_engine_attach_bond(struct intel_engine_cs *engine, const struct intel_engine_cs *master, diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 3d293be64fc2..95c24176ab64 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -52,9 +52,8 @@ static void engine_skip_context(struct i915_request *rq) i915_request_skip(rq, -EIO); } -static void client_mark_guilty(struct i915_request *rq, bool banned) +static void client_mark_guilty(struct i915_gem_context *ctx, bool banned) { - struct i915_gem_context *ctx = rq->context->gem_context; struct drm_i915_file_private *file_priv = ctx->file_priv; unsigned long prev_hang; unsigned int score; @@ -81,11 +80,15 @@ static void client_mark_guilty(struct i915_request *rq, bool banned) static bool mark_guilty(struct i915_request *rq) { - struct i915_gem_context *ctx = rq->context->gem_context; + struct i915_gem_context *ctx; unsigned long prev_hang; bool banned; int i; + ctx = rq->context->gem_context; + if (!ctx) + return false; + if (i915_gem_context_is_closed(ctx)) { intel_context_set_banned(rq->context); return true; @@ -117,14 +120,15 @@ static bool mark_guilty(struct i915_request *rq) intel_context_set_banned(rq->context); } - client_mark_guilty(rq, banned); + client_mark_guilty(ctx, banned); return banned; } static void mark_innocent(struct i915_request *rq) { - atomic_inc(&rq->context->gem_context->active_count); + if (rq->context->gem_context) + atomic_inc(&rq->context->gem_context->active_count); } void __i915_request_reset(struct i915_request *rq, bool guilty) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index a5d30d1468f7..3dc0d0a97a61 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1553,7 +1553,7 @@ static int remap_l3(struct i915_request *rq) struct i915_gem_context *ctx = rq->context->gem_context; int i, err; - if (!ctx->remap_slice) + if (!ctx || !ctx->remap_slice) return 0; for (i = 0; i < MAX_L3_SLICES; i++) { diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index af354ccdbf40..e874dfaa5316 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -70,15 +70,14 @@ static int context_sync(struct intel_context *ce) return err; } -static int __live_context_size(struct intel_engine_cs *engine, - struct i915_gem_context *fixme) +static int __live_context_size(struct intel_engine_cs *engine) { struct intel_context *ce; struct i915_request *rq; void *vaddr; int err; - ce = intel_context_create(fixme, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) return PTR_ERR(ce); @@ -146,7 +145,6 @@ static int live_context_size(void *arg) { struct intel_gt *gt = arg; struct intel_engine_cs *engine; - struct i915_gem_context *fixme; enum intel_engine_id id; int err = 0; @@ -155,10 +153,6 @@ static int live_context_size(void *arg) * HW tries to write past the end of one. */ - fixme = kernel_context(gt->i915); - if (IS_ERR(fixme)) - return PTR_ERR(fixme); - for_each_engine(engine, gt, id) { struct { struct drm_i915_gem_object *state; @@ -183,7 +177,7 @@ static int live_context_size(void *arg) /* Overlaps with the execlists redzone */ engine->context_size += I915_GTT_PAGE_SIZE; - err = __live_context_size(engine, fixme); + err = __live_context_size(engine); engine->context_size -= I915_GTT_PAGE_SIZE; @@ -196,12 +190,10 @@ static int live_context_size(void *arg) break; } - kernel_context_close(fixme); return err; } -static int __live_active_context(struct intel_engine_cs *engine, - struct i915_gem_context *fixme) +static int __live_active_context(struct intel_engine_cs *engine) { unsigned long saved_heartbeat; struct intel_context *ce; @@ -227,7 +219,7 @@ static int __live_active_context(struct intel_engine_cs *engine, return -EINVAL; } - ce = intel_context_create(fixme, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) return PTR_ERR(ce); @@ -310,23 +302,11 @@ static int live_active_context(void *arg) { struct intel_gt *gt = arg; struct intel_engine_cs *engine; - struct i915_gem_context *fixme; enum intel_engine_id id; - struct file *file; int err = 0; - file = mock_file(gt->i915); - if (IS_ERR(file)) - return PTR_ERR(file); - - fixme = live_context(gt->i915, file); - if (IS_ERR(fixme)) { - err = PTR_ERR(fixme); - goto out_file; - } - for_each_engine(engine, gt, id) { - err = __live_active_context(engine, fixme); + err = __live_active_context(engine); if (err) break; @@ -335,8 +315,6 @@ static int live_active_context(void *arg) break; } -out_file: - fput(file); return err; } @@ -368,8 +346,7 @@ unpin: return err; } -static int __live_remote_context(struct intel_engine_cs *engine, - struct i915_gem_context *fixme) +static int __live_remote_context(struct intel_engine_cs *engine) { struct intel_context *local, *remote; unsigned long saved_heartbeat; @@ -390,11 +367,11 @@ static int __live_remote_context(struct intel_engine_cs *engine, return -EINVAL; } - remote = intel_context_create(fixme, engine); + remote = intel_context_create(engine); if (IS_ERR(remote)) return PTR_ERR(remote); - local = intel_context_create(fixme, engine); + local = intel_context_create(engine); if (IS_ERR(local)) { err = PTR_ERR(local); goto err_remote; @@ -434,23 +411,11 @@ static int live_remote_context(void *arg) { struct intel_gt *gt = arg; struct intel_engine_cs *engine; - struct i915_gem_context *fixme; enum intel_engine_id id; - struct file *file; int err = 0; - file = mock_file(gt->i915); - if (IS_ERR(file)) - return PTR_ERR(file); - - fixme = live_context(gt->i915, file); - if (IS_ERR(fixme)) { - err = PTR_ERR(fixme); - goto out_file; - } - for_each_engine(engine, gt, id) { - err = __live_remote_context(engine, fixme); + err = __live_remote_context(engine); if (err) break; @@ -459,8 +424,6 @@ static int live_remote_context(void *arg) break; } -out_file: - fput(file); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c index 5227e79204a5..43d4d589749f 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c @@ -200,8 +200,7 @@ static int __live_heartbeat_fast(struct intel_engine_cs *engine) int err; int i; - ce = intel_context_create(engine->kernel_context->gem_context, - engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) return PTR_ERR(ce); diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c index d155c9374453..5dbda2a74272 100644 --- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c @@ -25,7 +25,9 @@ #include #include "gem/i915_gem_context.h" -#include "gt/intel_gt.h" + +#include "intel_gt.h" +#include "intel_engine_heartbeat.h" #include "intel_engine_pm.h" #include "i915_selftest.h" @@ -308,6 +310,24 @@ static bool wait_until_running(struct hang *h, struct i915_request *rq) 1000)); } +static void engine_heartbeat_disable(struct intel_engine_cs *engine, + unsigned long *saved) +{ + *saved = engine->props.heartbeat_interval_ms; + engine->props.heartbeat_interval_ms = 0; + + intel_engine_pm_get(engine); + intel_engine_park_heartbeat(engine); +} + +static void engine_heartbeat_enable(struct intel_engine_cs *engine, + unsigned long saved) +{ + intel_engine_pm_put(engine); + + engine->props.heartbeat_interval_ms = saved; +} + static int igt_hang_sanitycheck(void *arg) { struct intel_gt *gt = arg; @@ -377,36 +397,30 @@ static int igt_reset_nop(void *arg) struct intel_gt *gt = arg; struct i915_gpu_error *global = >->i915->gpu_error; struct intel_engine_cs *engine; - struct i915_gem_context *ctx; unsigned int reset_count, count; enum intel_engine_id id; IGT_TIMEOUT(end_time); - struct file *file; int err = 0; /* Check that we can reset during non-user portions of requests */ - file = mock_file(gt->i915); - if (IS_ERR(file)) - return PTR_ERR(file); - - ctx = live_context(gt->i915, file); - if (IS_ERR(ctx)) { - err = PTR_ERR(ctx); - goto out; - } - - i915_gem_context_clear_bannable(ctx); reset_count = i915_reset_count(global); count = 0; do { for_each_engine(engine, gt, id) { + struct intel_context *ce; int i; + ce = intel_context_create(engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + break; + } + for (i = 0; i < 16; i++) { struct i915_request *rq; - rq = igt_request_alloc(ctx, engine); + rq = intel_context_create_request(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); break; @@ -414,6 +428,8 @@ static int igt_reset_nop(void *arg) i915_request_add(rq); } + + intel_context_put(ce); } igt_global_reset_lock(gt); @@ -437,10 +453,7 @@ static int igt_reset_nop(void *arg) } while (time_before(jiffies, end_time)); pr_info("%s: %d resets\n", __func__, count); - err = igt_flush_test(gt->i915); -out: - fput(file); - if (intel_gt_is_wedged(gt)) + if (igt_flush_test(gt->i915)) err = -EIO; return err; } @@ -450,36 +463,29 @@ static int igt_reset_nop_engine(void *arg) struct intel_gt *gt = arg; struct i915_gpu_error *global = >->i915->gpu_error; struct intel_engine_cs *engine; - struct i915_gem_context *ctx; enum intel_engine_id id; - struct file *file; - int err = 0; /* Check that we can engine-reset during non-user portions */ if (!intel_has_reset_engine(gt)) return 0; - file = mock_file(gt->i915); - if (IS_ERR(file)) - return PTR_ERR(file); - - ctx = live_context(gt->i915, file); - if (IS_ERR(ctx)) { - err = PTR_ERR(ctx); - goto out; - } - - i915_gem_context_clear_bannable(ctx); for_each_engine(engine, gt, id) { - unsigned int reset_count, reset_engine_count; - unsigned int count; + unsigned int reset_count, reset_engine_count, count; + struct intel_context *ce; + unsigned long heartbeat; IGT_TIMEOUT(end_time); + int err; + + ce = intel_context_create(engine); + if (IS_ERR(ce)) + return PTR_ERR(ce); reset_count = i915_reset_count(global); reset_engine_count = i915_reset_engine_count(global, engine); count = 0; + engine_heartbeat_disable(engine, &heartbeat); set_bit(I915_RESET_ENGINE + id, >->reset.flags); do { int i; @@ -494,7 +500,7 @@ static int igt_reset_nop_engine(void *arg) for (i = 0; i < 16; i++) { struct i915_request *rq; - rq = igt_request_alloc(ctx, engine); + rq = intel_context_create_request(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); break; @@ -523,22 +529,18 @@ static int igt_reset_nop_engine(void *arg) } } while (time_before(jiffies, end_time)); clear_bit(I915_RESET_ENGINE + id, >->reset.flags); - pr_info("%s(%s): %d resets\n", __func__, engine->name, count); + engine_heartbeat_enable(engine, heartbeat); - if (err) - break; + pr_info("%s(%s): %d resets\n", __func__, engine->name, count); - err = igt_flush_test(gt->i915); + intel_context_put(ce); + if (igt_flush_test(gt->i915)) + err = -EIO; if (err) - break; + return err; } - err = igt_flush_test(gt->i915); -out: - fput(file); - if (intel_gt_is_wedged(gt)) - err = -EIO; - return err; + return 0; } static int __igt_reset_engine(struct intel_gt *gt, bool active) @@ -562,6 +564,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active) for_each_engine(engine, gt, id) { unsigned int reset_count, reset_engine_count; + unsigned long heartbeat; IGT_TIMEOUT(end_time); if (active && !intel_engine_can_store_dword(engine)) @@ -577,7 +580,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active) reset_count = i915_reset_count(global); reset_engine_count = i915_reset_engine_count(global, engine); - intel_engine_pm_get(engine); + engine_heartbeat_disable(engine, &heartbeat); set_bit(I915_RESET_ENGINE + id, >->reset.flags); do { if (active) { @@ -629,7 +632,7 @@ static int __igt_reset_engine(struct intel_gt *gt, bool active) } } while (time_before(jiffies, end_time)); clear_bit(I915_RESET_ENGINE + id, >->reset.flags); - intel_engine_pm_put(engine); + engine_heartbeat_enable(engine, heartbeat); if (err) break; @@ -699,43 +702,43 @@ static int active_engine(void *data) struct active_engine *arg = data; struct intel_engine_cs *engine = arg->engine; struct i915_request *rq[8] = {}; - struct i915_gem_context *ctx[ARRAY_SIZE(rq)]; - unsigned long count = 0; - struct file *file; + struct intel_context *ce[ARRAY_SIZE(rq)]; + unsigned long count; int err = 0; - file = mock_file(engine->i915); - if (IS_ERR(file)) - return PTR_ERR(file); - - for (count = 0; count < ARRAY_SIZE(ctx); count++) { - ctx[count] = live_context(engine->i915, file); - if (IS_ERR(ctx[count])) { - err = PTR_ERR(ctx[count]); + for (count = 0; count < ARRAY_SIZE(ce); count++) { + ce[count] = intel_context_create(engine); + if (IS_ERR(ce[count])) { + err = PTR_ERR(ce[count]); while (--count) - i915_gem_context_put(ctx[count]); - goto err_file; + intel_context_put(ce[count]); + return err; } } + count = 0; while (!kthread_should_stop()) { unsigned int idx = count++ & (ARRAY_SIZE(rq) - 1); struct i915_request *old = rq[idx]; struct i915_request *new; - new = igt_request_alloc(ctx[idx], engine); + new = intel_context_create_request(ce[idx]); if (IS_ERR(new)) { err = PTR_ERR(new); break; } - if (arg->flags & TEST_PRIORITY) - ctx[idx]->sched.priority = - i915_prandom_u32_max_state(512, &prng); - rq[idx] = i915_request_get(new); i915_request_add(new); + if (engine->schedule && arg->flags & TEST_PRIORITY) { + struct i915_sched_attr attr = { + .priority = + i915_prandom_u32_max_state(512, &prng), + }; + engine->schedule(rq[idx], &attr); + } + err = active_request_put(old); if (err) break; @@ -749,10 +752,10 @@ static int active_engine(void *data) /* Keep the first error */ if (!err) err = err__; + + intel_context_put(ce[count]); } -err_file: - fput(file); return err; } @@ -786,6 +789,7 @@ static int __igt_reset_engines(struct intel_gt *gt, struct active_engine threads[I915_NUM_ENGINES] = {}; unsigned long device = i915_reset_count(global); unsigned long count = 0, reported; + unsigned long heartbeat; IGT_TIMEOUT(end_time); if (flags & TEST_ACTIVE && @@ -828,7 +832,7 @@ static int __igt_reset_engines(struct intel_gt *gt, yield(); /* start all threads before we begin */ - intel_engine_pm_get(engine); + engine_heartbeat_disable(engine, &heartbeat); set_bit(I915_RESET_ENGINE + id, >->reset.flags); do { struct i915_request *rq = NULL; @@ -902,7 +906,8 @@ static int __igt_reset_engines(struct intel_gt *gt, } } while (time_before(jiffies, end_time)); clear_bit(I915_RESET_ENGINE + id, >->reset.flags); - intel_engine_pm_put(engine); + engine_heartbeat_enable(engine, heartbeat); + pr_info("i915_reset_engine(%s:%s): %lu resets\n", engine->name, test_name, count); @@ -1300,32 +1305,21 @@ static int igt_reset_evict_ggtt(void *arg) static int igt_reset_evict_ppgtt(void *arg) { struct intel_gt *gt = arg; - struct i915_gem_context *ctx; - struct i915_address_space *vm; - struct file *file; + struct i915_ppgtt *ppgtt; int err; - file = mock_file(gt->i915); - if (IS_ERR(file)) - return PTR_ERR(file); + /* aliasing == global gtt locking, covered above */ + if (INTEL_PPGTT(gt->i915) < INTEL_PPGTT_FULL) + return 0; - ctx = live_context(gt->i915, file); - if (IS_ERR(ctx)) { - err = PTR_ERR(ctx); - goto out; - } + ppgtt = i915_ppgtt_create(gt->i915); + if (IS_ERR(ppgtt)) + return PTR_ERR(ppgtt); - err = 0; - vm = i915_gem_context_get_vm_rcu(ctx); - if (!i915_is_ggtt(vm)) { - /* aliasing == global gtt locking, covered above */ - err = __igt_reset_evict_vma(gt, vm, - evict_vma, EXEC_OBJECT_WRITE); - } - i915_vm_put(vm); + err = __igt_reset_evict_vma(gt, &ppgtt->vm, + evict_vma, EXEC_OBJECT_WRITE); + i915_vm_put(&ppgtt->vm); -out: - fput(file); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index 619e34813ade..9ec9833c9c7b 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -50,14 +50,31 @@ static struct i915_vma *create_scratch(struct intel_gt *gt) return vma; } +static void engine_heartbeat_disable(struct intel_engine_cs *engine, + unsigned long *saved) +{ + *saved = engine->props.heartbeat_interval_ms; + engine->props.heartbeat_interval_ms = 0; + + intel_engine_pm_get(engine); + intel_engine_park_heartbeat(engine); +} + +static void engine_heartbeat_enable(struct intel_engine_cs *engine, + unsigned long saved) +{ + intel_engine_pm_put(engine); + + engine->props.heartbeat_interval_ms = saved; +} + static int live_sanitycheck(void *arg) { struct intel_gt *gt = arg; - struct i915_gem_engines_iter it; - struct i915_gem_context *ctx; - struct intel_context *ce; + struct intel_engine_cs *engine; + enum intel_engine_id id; struct igt_spinner spin; - int err = -ENOMEM; + int err = 0; if (!HAS_LOGICAL_RING_CONTEXTS(gt->i915)) return 0; @@ -65,17 +82,20 @@ static int live_sanitycheck(void *arg) if (igt_spinner_init(&spin, gt)) return -ENOMEM; - ctx = kernel_context(gt->i915); - if (!ctx) - goto err_spin; - - for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) { + for_each_engine(engine, gt, id) { + struct intel_context *ce; struct i915_request *rq; + ce = intel_context_create(engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + break; + } + rq = igt_spinner_create_request(&spin, ce, MI_NOOP); if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto err_ctx; + goto out_ctx; } i915_request_add(rq); @@ -84,21 +104,21 @@ static int live_sanitycheck(void *arg) GEM_TRACE_DUMP(); intel_gt_set_wedged(gt); err = -EIO; - goto err_ctx; + goto out_ctx; } igt_spinner_end(&spin); if (igt_flush_test(gt->i915)) { err = -EIO; - goto err_ctx; + goto out_ctx; } + +out_ctx: + intel_context_put(ce); + if (err) + break; } - err = 0; -err_ctx: - i915_gem_context_unlock_engines(ctx); - kernel_context_close(ctx); -err_spin: igt_spinner_fini(&spin); return err; } @@ -106,7 +126,6 @@ err_spin: static int live_unlite_restore(struct intel_gt *gt, int prio) { struct intel_engine_cs *engine; - struct i915_gem_context *ctx; enum intel_engine_id id; struct igt_spinner spin; int err = -ENOMEM; @@ -119,15 +138,12 @@ static int live_unlite_restore(struct intel_gt *gt, int prio) if (igt_spinner_init(&spin, gt)) return err; - ctx = kernel_context(gt->i915); - if (!ctx) - goto err_spin; - err = 0; for_each_engine(engine, gt, id) { struct intel_context *ce[2] = {}; struct i915_request *rq[2]; struct igt_live_test t; + unsigned long saved; int n; if (prio && !intel_engine_has_preemption(engine)) @@ -140,11 +156,12 @@ static int live_unlite_restore(struct intel_gt *gt, int prio) err = -EIO; break; } + engine_heartbeat_disable(engine, &saved); for (n = 0; n < ARRAY_SIZE(ce); n++) { struct intel_context *tmp; - tmp = intel_context_create(ctx, engine); + tmp = intel_context_create(engine); if (IS_ERR(tmp)) { err = PTR_ERR(tmp); goto err_ce; @@ -247,14 +264,13 @@ err_ce: intel_context_put(ce[n]); } + engine_heartbeat_enable(engine, saved); if (igt_live_test_end(&t)) err = -EIO; if (err) break; } - kernel_context_close(ctx); -err_spin: igt_spinner_fini(&spin); return err; } @@ -309,17 +325,17 @@ emit_semaphore_chain(struct i915_request *rq, struct i915_vma *vma, int idx) static struct i915_request * semaphore_queue(struct intel_engine_cs *engine, struct i915_vma *vma, int idx) { - struct i915_gem_context *ctx; + struct intel_context *ce; struct i915_request *rq; int err; - ctx = kernel_context(engine->i915); - if (!ctx) - return ERR_PTR(-ENOMEM); + ce = intel_context_create(engine); + if (IS_ERR(ce)) + return ERR_CAST(ce); - rq = igt_request_alloc(ctx, engine); + rq = intel_context_create_request(ce); if (IS_ERR(rq)) - goto out_ctx; + goto out_ce; err = 0; if (rq->engine->emit_init_breadcrumb) @@ -332,8 +348,8 @@ semaphore_queue(struct intel_engine_cs *engine, struct i915_vma *vma, int idx) if (err) rq = ERR_PTR(err); -out_ctx: - kernel_context_close(ctx); +out_ce: + intel_context_put(ce); return rq; } @@ -468,12 +484,16 @@ static int live_timeslice_preempt(void *arg) enum intel_engine_id id; for_each_engine(engine, gt, id) { + unsigned long saved; + if (!intel_engine_has_preemption(engine)) continue; memset(vaddr, 0, PAGE_SIZE); + engine_heartbeat_disable(engine, &saved); err = slice_semaphore_queue(engine, vma, count); + engine_heartbeat_enable(engine, saved); if (err) goto err_pin; @@ -566,17 +586,19 @@ static int live_timeslice_queue(void *arg) .priority = I915_USER_PRIORITY(I915_PRIORITY_MAX), }; struct i915_request *rq, *nop; + unsigned long saved; if (!intel_engine_has_preemption(engine)) continue; + engine_heartbeat_disable(engine, &saved); memset(vaddr, 0, PAGE_SIZE); /* ELSP[0]: semaphore wait */ rq = semaphore_queue(engine, vma, 0); if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto err_pin; + goto err_heartbeat; } engine->schedule(rq, &attr); wait_for_submit(engine, rq); @@ -585,8 +607,7 @@ static int live_timeslice_queue(void *arg) nop = nop_request(engine); if (IS_ERR(nop)) { err = PTR_ERR(nop); - i915_request_put(rq); - goto err_pin; + goto err_rq; } wait_for_submit(engine, nop); i915_request_put(nop); @@ -596,10 +617,8 @@ static int live_timeslice_queue(void *arg) /* Queue: semaphore signal, matching priority as semaphore */ err = release_queue(engine, vma, 1, effective_prio(rq)); - if (err) { - i915_request_put(rq); - goto err_pin; - } + if (err) + goto err_rq; intel_engine_flush_submission(engine); if (!READ_ONCE(engine->execlists.timer.expires) && @@ -630,12 +649,14 @@ static int live_timeslice_queue(void *arg) memset(vaddr, 0xff, PAGE_SIZE); err = -EIO; } +err_rq: i915_request_put(rq); +err_heartbeat: + engine_heartbeat_enable(engine, saved); if (err) break; } -err_pin: i915_vma_unpin(vma); err_map: i915_gem_object_unpin_map(obj); @@ -1956,7 +1977,7 @@ static int create_gang(struct intel_engine_cs *engine, u32 *cs; int err; - ce = intel_context_create(engine->kernel_context->gem_context, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) return PTR_ERR(ce); @@ -2618,27 +2639,17 @@ static int nop_virtual_engine(struct intel_gt *gt, { IGT_TIMEOUT(end_time); struct i915_request *request[16] = {}; - struct i915_gem_context *ctx[16]; struct intel_context *ve[16]; unsigned long n, prime, nc; struct igt_live_test t; ktime_t times[2] = {}; int err; - GEM_BUG_ON(!nctx || nctx > ARRAY_SIZE(ctx)); + GEM_BUG_ON(!nctx || nctx > ARRAY_SIZE(ve)); for (n = 0; n < nctx; n++) { - ctx[n] = kernel_context(gt->i915); - if (!ctx[n]) { - err = -ENOMEM; - nctx = n; - goto out; - } - - ve[n] = intel_execlists_create_virtual(ctx[n], - siblings, nsibling); + ve[n] = intel_execlists_create_virtual(siblings, nsibling); if (IS_ERR(ve[n])) { - kernel_context_close(ctx[n]); err = PTR_ERR(ve[n]); nctx = n; goto out; @@ -2647,7 +2658,6 @@ static int nop_virtual_engine(struct intel_gt *gt, err = intel_context_pin(ve[n]); if (err) { intel_context_put(ve[n]); - kernel_context_close(ctx[n]); nctx = n; goto out; } @@ -2742,7 +2752,6 @@ out: i915_request_put(request[nc]); intel_context_unpin(ve[nc]); intel_context_put(ve[nc]); - kernel_context_close(ctx[nc]); } return err; } @@ -2801,7 +2810,6 @@ static int mask_virtual_engine(struct intel_gt *gt, unsigned int nsibling) { struct i915_request *request[MAX_ENGINE_INSTANCE + 1]; - struct i915_gem_context *ctx; struct intel_context *ve; struct igt_live_test t; unsigned int n; @@ -2812,11 +2820,7 @@ static int mask_virtual_engine(struct intel_gt *gt, * restrict it to our desired engine within the virtual engine. */ - ctx = kernel_context(gt->i915); - if (!ctx) - return -ENOMEM; - - ve = intel_execlists_create_virtual(ctx, siblings, nsibling); + ve = intel_execlists_create_virtual(siblings, nsibling); if (IS_ERR(ve)) { err = PTR_ERR(ve); goto out_close; @@ -2884,7 +2888,6 @@ out_unpin: out_put: intel_context_put(ve); out_close: - kernel_context_close(ctx); return err; } @@ -2924,7 +2927,6 @@ static int preserved_virtual_engine(struct intel_gt *gt, unsigned int nsibling) { struct i915_request *last = NULL; - struct i915_gem_context *ctx; struct intel_context *ve; struct i915_vma *scratch; struct igt_live_test t; @@ -2932,17 +2934,11 @@ static int preserved_virtual_engine(struct intel_gt *gt, int err = 0; u32 *cs; - ctx = kernel_context(gt->i915); - if (!ctx) - return -ENOMEM; - scratch = create_scratch(siblings[0]->gt); - if (IS_ERR(scratch)) { - err = PTR_ERR(scratch); - goto out_close; - } + if (IS_ERR(scratch)) + return PTR_ERR(scratch); - ve = intel_execlists_create_virtual(ctx, siblings, nsibling); + ve = intel_execlists_create_virtual(siblings, nsibling); if (IS_ERR(ve)) { err = PTR_ERR(ve); goto out_scratch; @@ -3025,8 +3021,6 @@ out_put: intel_context_put(ve); out_scratch: i915_vma_unpin_and_release(&scratch, 0); -out_close: - kernel_context_close(ctx); return err; } @@ -3078,7 +3072,6 @@ static int bond_virtual_engine(struct intel_gt *gt, #define BOND_SCHEDULE BIT(0) { struct intel_engine_cs *master; - struct i915_gem_context *ctx; struct i915_request *rq[16]; enum intel_engine_id id; struct igt_spinner spin; @@ -3129,12 +3122,6 @@ static int bond_virtual_engine(struct intel_gt *gt, if (igt_spinner_init(&spin, gt)) return -ENOMEM; - ctx = kernel_context(gt->i915); - if (!ctx) { - err = -ENOMEM; - goto err_spin; - } - err = 0; rq[0] = ERR_PTR(-ENOMEM); for_each_engine(master, gt, id) { @@ -3145,7 +3132,9 @@ static int bond_virtual_engine(struct intel_gt *gt, memset_p((void *)rq, ERR_PTR(-EINVAL), ARRAY_SIZE(rq)); - rq[0] = spinner_create_request(&spin, ctx, master, MI_NOOP); + rq[0] = igt_spinner_create_request(&spin, + master->kernel_context, + MI_NOOP); if (IS_ERR(rq[0])) { err = PTR_ERR(rq[0]); goto out; @@ -3172,9 +3161,7 @@ static int bond_virtual_engine(struct intel_gt *gt, for (n = 0; n < nsibling; n++) { struct intel_context *ve; - ve = intel_execlists_create_virtual(ctx, - siblings, - nsibling); + ve = intel_execlists_create_virtual(siblings, nsibling); if (IS_ERR(ve)) { err = PTR_ERR(ve); onstack_fence_fini(&fence); @@ -3254,8 +3241,6 @@ out: if (igt_flush_test(gt->i915)) err = -EIO; - kernel_context_close(ctx); -err_spin: igt_spinner_fini(&spin); return err; } @@ -3567,8 +3552,7 @@ static int live_lrc_fixed(void *arg) return err; } -static int __live_lrc_state(struct i915_gem_context *fixme, - struct intel_engine_cs *engine, +static int __live_lrc_state(struct intel_engine_cs *engine, struct i915_vma *scratch) { struct intel_context *ce; @@ -3583,7 +3567,7 @@ static int __live_lrc_state(struct i915_gem_context *fixme, int err; int n; - ce = intel_context_create(fixme, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) return PTR_ERR(ce); @@ -3657,7 +3641,6 @@ static int live_lrc_state(void *arg) { struct intel_gt *gt = arg; struct intel_engine_cs *engine; - struct i915_gem_context *fixme; struct i915_vma *scratch; enum intel_engine_id id; int err = 0; @@ -3667,18 +3650,12 @@ static int live_lrc_state(void *arg) * intel_context. */ - fixme = kernel_context(gt->i915); - if (!fixme) - return -ENOMEM; - scratch = create_scratch(gt); - if (IS_ERR(scratch)) { - err = PTR_ERR(scratch); - goto out_close; - } + if (IS_ERR(scratch)) + return PTR_ERR(scratch); for_each_engine(engine, gt, id) { - err = __live_lrc_state(fixme, engine, scratch); + err = __live_lrc_state(engine, scratch); if (err) break; } @@ -3687,8 +3664,6 @@ static int live_lrc_state(void *arg) err = -EIO; i915_vma_unpin_and_release(&scratch, 0); -out_close: - kernel_context_close(fixme); return err; } @@ -3721,8 +3696,7 @@ static int gpr_make_dirty(struct intel_engine_cs *engine) return 0; } -static int __live_gpr_clear(struct i915_gem_context *fixme, - struct intel_engine_cs *engine, +static int __live_gpr_clear(struct intel_engine_cs *engine, struct i915_vma *scratch) { struct intel_context *ce; @@ -3738,7 +3712,7 @@ static int __live_gpr_clear(struct i915_gem_context *fixme, if (err) return err; - ce = intel_context_create(fixme, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) return PTR_ERR(ce); @@ -3800,7 +3774,6 @@ static int live_gpr_clear(void *arg) { struct intel_gt *gt = arg; struct intel_engine_cs *engine; - struct i915_gem_context *fixme; struct i915_vma *scratch; enum intel_engine_id id; int err = 0; @@ -3810,18 +3783,12 @@ static int live_gpr_clear(void *arg) * to avoid leaking any information from previous contexts. */ - fixme = kernel_context(gt->i915); - if (!fixme) - return -ENOMEM; - scratch = create_scratch(gt); - if (IS_ERR(scratch)) { - err = PTR_ERR(scratch); - goto out_close; - } + if (IS_ERR(scratch)) + return PTR_ERR(scratch); for_each_engine(engine, gt, id) { - err = __live_gpr_clear(fixme, engine, scratch); + err = __live_gpr_clear(engine, scratch); if (err) break; } @@ -3830,8 +3797,6 @@ static int live_gpr_clear(void *arg) err = -EIO; i915_vma_unpin_and_release(&scratch, 0); -out_close: - kernel_context_close(fixme); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c index de010f527757..de1f83100fb6 100644 --- a/drivers/gpu/drm/i915/gt/selftest_mocs.c +++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c @@ -289,8 +289,7 @@ static int live_mocs_clean(void *arg) for_each_engine(engine, gt, id) { struct intel_context *ce; - ce = intel_context_create(engine->kernel_context->gem_context, - engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) { err = PTR_ERR(ce); break; @@ -384,8 +383,7 @@ static int live_mocs_reset(void *arg) for_each_engine(engine, gt, id) { struct intel_context *ce; - ce = intel_context_create(engine->kernel_context->gem_context, - engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) { err = PTR_ERR(ce); break; diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.c b/drivers/gpu/drm/i915/gt/selftest_rc6.c index f8b7691be4d1..8cc55a0e9e06 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rc6.c +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.c @@ -160,8 +160,7 @@ int live_rc6_ctx_wa(void *arg) const u32 *res; /* Use a sacrifical context */ - ce = intel_context_create(engine->kernel_context->gem_context, - engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) { err = PTR_ERR(ce); goto out; diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c index d5d1e1a32187..ac1921854cbf 100644 --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c @@ -264,22 +264,15 @@ static int switch_to_scratch_context(struct intel_engine_cs *engine, struct igt_spinner *spin) { - struct i915_gem_context *ctx; struct intel_context *ce; struct i915_request *rq; int err = 0; - ctx = kernel_context(engine->i915); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - GEM_BUG_ON(i915_gem_context_is_bannable(ctx)); - - ce = i915_gem_context_get_engine(ctx, engine->legacy_idx); - GEM_BUG_ON(IS_ERR(ce)); + ce = intel_context_create(engine); + if (IS_ERR(ce)) + return PTR_ERR(ce); rq = igt_spinner_create_request(spin, ce, MI_NOOP); - intel_context_put(ce); if (IS_ERR(rq)) { @@ -293,7 +286,6 @@ err: if (err && spin) igt_spinner_end(spin); - kernel_context_close(ctx); return err; } @@ -367,20 +359,17 @@ out_ctx: return err; } -static struct i915_vma *create_batch(struct i915_gem_context *ctx) +static struct i915_vma *create_batch(struct i915_address_space *vm) { struct drm_i915_gem_object *obj; - struct i915_address_space *vm; struct i915_vma *vma; int err; - obj = i915_gem_object_create_internal(ctx->i915, 16 * PAGE_SIZE); + obj = i915_gem_object_create_internal(vm->i915, 16 * PAGE_SIZE); if (IS_ERR(obj)) return ERR_CAST(obj); - vm = i915_gem_context_get_vm_rcu(ctx); vma = i915_vma_instance(obj, vm, NULL); - i915_vm_put(vm); if (IS_ERR(vma)) { err = PTR_ERR(vma); goto err_obj; @@ -452,8 +441,7 @@ static int whitelist_writable_count(struct intel_engine_cs *engine) return count; } -static int check_dirty_whitelist(struct i915_gem_context *ctx, - struct intel_engine_cs *engine) +static int check_dirty_whitelist(struct intel_context *ce) { const u32 values[] = { 0x00000000, @@ -481,19 +469,17 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx, 0xffff00ff, 0xffffffff, }; - struct i915_address_space *vm; + struct intel_engine_cs *engine = ce->engine; struct i915_vma *scratch; struct i915_vma *batch; int err = 0, i, v; u32 *cs, *results; - vm = i915_gem_context_get_vm_rcu(ctx); - scratch = create_scratch(vm, 2 * ARRAY_SIZE(values) + 1); - i915_vm_put(vm); + scratch = create_scratch(ce->vm, 2 * ARRAY_SIZE(values) + 1); if (IS_ERR(scratch)) return PTR_ERR(scratch); - batch = create_batch(ctx); + batch = create_batch(ce->vm); if (IS_ERR(batch)) { err = PTR_ERR(batch); goto out_scratch; @@ -518,7 +504,7 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx, srm = MI_STORE_REGISTER_MEM; lrm = MI_LOAD_REGISTER_MEM; - if (INTEL_GEN(ctx->i915) >= 8) + if (INTEL_GEN(engine->i915) >= 8) lrm++, srm++; pr_debug("%s: Writing garbage to %x\n", @@ -577,7 +563,7 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx, i915_gem_object_unpin_map(batch->obj); intel_gt_chipset_flush(engine->gt); - rq = igt_request_alloc(ctx, engine); + rq = intel_context_create_request(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out_batch; @@ -696,7 +682,7 @@ out_unpin: break; } - if (igt_flush_test(ctx->i915)) + if (igt_flush_test(engine->i915)) err = -EIO; out_batch: i915_vma_unpin_and_release(&batch, 0); @@ -709,38 +695,31 @@ static int live_dirty_whitelist(void *arg) { struct intel_gt *gt = arg; struct intel_engine_cs *engine; - struct i915_gem_context *ctx; enum intel_engine_id id; - struct file *file; - int err = 0; /* Can the user write to the whitelisted registers? */ if (INTEL_GEN(gt->i915) < 7) /* minimum requirement for LRI, SRM, LRM */ return 0; - file = mock_file(gt->i915); - if (IS_ERR(file)) - return PTR_ERR(file); - - ctx = live_context(gt->i915, file); - if (IS_ERR(ctx)) { - err = PTR_ERR(ctx); - goto out_file; - } - for_each_engine(engine, gt, id) { + struct intel_context *ce; + int err; + if (engine->whitelist.count == 0) continue; - err = check_dirty_whitelist(ctx, engine); + ce = intel_context_create(engine); + if (IS_ERR(ce)) + return PTR_ERR(ce); + + err = check_dirty_whitelist(ce); + intel_context_put(ce); if (err) - goto out_file; + return err; } -out_file: - fput(file); - return err; + return 0; } static int live_reset_whitelist(void *arg) @@ -830,12 +809,15 @@ err_req: static int scrub_whitelisted_registers(struct i915_gem_context *ctx, struct intel_engine_cs *engine) { + struct i915_address_space *vm; struct i915_request *rq; struct i915_vma *batch; int i, err = 0; u32 *cs; - batch = create_batch(ctx); + vm = i915_gem_context_get_vm_rcu(ctx); + batch = create_batch(vm); + i915_vm_put(vm); if (IS_ERR(batch)) return PTR_ERR(batch); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 228c66534e21..b3299f88e24e 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -35,12 +35,12 @@ #include -#include "gem/i915_gem_context.h" #include "gem/i915_gem_pm.h" #include "gt/intel_context.h" #include "gt/intel_ring.h" #include "i915_drv.h" +#include "i915_gem_gtt.h" #include "gvt.h" #define RING_CTX_OFF(x) \ @@ -1220,16 +1220,14 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) struct drm_i915_private *i915 = vgpu->gvt->dev_priv; struct intel_vgpu_submission *s = &vgpu->submission; struct intel_engine_cs *engine; - struct i915_gem_context *ctx; struct i915_ppgtt *ppgtt; enum intel_engine_id i; int ret; - ctx = i915_gem_context_create_kernel(i915, I915_PRIORITY_MAX); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); + ppgtt = i915_ppgtt_create(i915); + if (IS_ERR(ppgtt)) + return PTR_ERR(ppgtt); - ppgtt = i915_vm_to_ppgtt(i915_gem_context_get_vm_rcu(ctx)); i915_context_ppgtt_root_save(s, ppgtt); for_each_engine(engine, i915, i) { @@ -1238,12 +1236,14 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) INIT_LIST_HEAD(&s->workload_q_head[i]); s->shadow[i] = ERR_PTR(-EINVAL); - ce = intel_context_create(ctx, engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) { ret = PTR_ERR(ce); goto out_shadow_ctx; } + i915_vm_put(ce->vm); + ce->vm = i915_vm_get(&ppgtt->vm); intel_context_set_single_submission(ce); if (!USES_GUC_SUBMISSION(i915)) { /* Max ring buffer size */ @@ -1278,7 +1278,6 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) bitmap_zero(s->tlb_handle_pending, I915_NUM_ENGINES); i915_vm_put(&ppgtt->vm); - i915_gem_context_put(ctx); return 0; out_shadow_ctx: @@ -1291,7 +1290,6 @@ out_shadow_ctx: intel_context_put(s->shadow[i]); } i915_vm_put(&ppgtt->vm); - i915_gem_context_put(ctx); return ret; } diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 3d0edde84705..cfe09964622b 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -6,6 +6,7 @@ #include +#include "gt/intel_context.h" #include "gt/intel_engine_pm.h" #include "gt/intel_ring.h" @@ -724,6 +725,7 @@ void i915_request_add_active_barriers(struct i915_request *rq) struct llist_node *node, *next; unsigned long flags; + GEM_BUG_ON(!intel_context_is_barrier(rq->context)); GEM_BUG_ON(intel_engine_is_virtual(engine)); GEM_BUG_ON(i915_request_timeline(rq) != engine->kernel_context->timeline); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0781b6326b8c..95db8017f138 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -955,9 +955,6 @@ struct drm_i915_private { struct pci_dev *bridge_dev; - /* Context used internally to idle the GPU and setup initial state */ - struct i915_gem_context *kernel_context; - struct intel_engine_cs *engine[I915_NUM_ENGINES]; struct rb_root uabi_engines; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6e7010089e23..8f4a3832ee85 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1123,8 +1123,7 @@ static int __intel_engines_record_defaults(struct intel_gt *gt) GEM_BUG_ON(!engine->kernel_context); engine->serial++; /* force the kernel context switch */ - ce = intel_context_create(engine->kernel_context->gem_context, - engine); + ce = intel_context_create(engine); if (IS_ERR(ce)) { err = PTR_ERR(ce); goto out; @@ -1174,6 +1173,7 @@ err_rq: continue; /* Serialise with retirement on another CPU */ + GEM_BUG_ON(!i915_request_completed(rq)); err = __intel_context_flush_retire(rq->context); if (err) goto out; @@ -1284,6 +1284,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv) } intel_gt_init(&dev_priv->gt); + i915_gem_init__contexts(dev_priv); ret = intel_engines_setup(&dev_priv->gt); if (ret) { @@ -1291,16 +1292,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv) goto err_unlock; } - ret = i915_gem_init_contexts(dev_priv); - if (ret) { - GEM_BUG_ON(ret == -EIO); - goto err_scratch; - } - ret = intel_engines_init(&dev_priv->gt); if (ret) { GEM_BUG_ON(ret == -EIO); - goto err_context; + goto err_scratch; } intel_uc_init(&dev_priv->gt.uc); @@ -1364,9 +1359,6 @@ err_uc_init: intel_uc_fini(&dev_priv->gt.uc); intel_engines_cleanup(&dev_priv->gt); } -err_context: - if (ret != -EIO) - i915_gem_driver_release__contexts(dev_priv); err_scratch: intel_gt_driver_release(&dev_priv->gt); err_unlock: @@ -1431,7 +1423,6 @@ void i915_gem_driver_remove(struct drm_i915_private *dev_priv) void i915_gem_driver_release(struct drm_i915_private *dev_priv) { intel_engines_cleanup(&dev_priv->gt); - i915_gem_driver_release__contexts(dev_priv); intel_gt_driver_release(&dev_priv->gt); intel_wa_list_free(&dev_priv->gt_wa_list); @@ -1439,6 +1430,8 @@ void i915_gem_driver_release(struct drm_i915_private *dev_priv) intel_uc_cleanup_firmwares(&dev_priv->gt.uc); i915_gem_cleanup_userptr(dev_priv); + i915_gem_driver_release__contexts(dev_priv); + i915_gem_drain_freed_objects(dev_priv); WARN_ON(!list_empty(&dev_priv->gem.contexts.list)); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index d9a2f58a620a..2ad2fc5efdbf 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1375,12 +1375,8 @@ static int gen8_init_scratch(struct i915_address_space *vm) * If everybody agrees to not to write into the scratch page, * we can reuse it for all vm, keeping contexts and processes separate. */ - if (vm->has_read_only && - vm->i915->kernel_context && - vm->i915->kernel_context->vm) { - struct i915_address_space *clone = - rcu_dereference_protected(vm->i915->kernel_context->vm, - true); /* static */ + if (vm->has_read_only && vm->gt->vm && !i915_is_ggtt(vm->gt->vm)) { + struct i915_address_space *clone = vm->gt->vm; GEM_BUG_ON(!clone->has_read_only); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 9d4733927a2c..84350c7bc711 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2323,9 +2323,6 @@ static int oa_configure_all_contexts(struct i915_perf_stream *stream, */ spin_lock(&i915->gem.contexts.lock); list_for_each_entry_safe(ctx, cn, &i915->gem.contexts.list, link) { - if (ctx == i915->kernel_context) - continue; - if (!kref_get_unless_zero(&ctx->ref)) continue; diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index ed70d8dcea74..14a5a99284fa 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1301,8 +1301,8 @@ void __i915_request_queue(struct i915_request *rq, void i915_request_add(struct i915_request *rq) { - struct i915_sched_attr attr = rq->context->gem_context->sched; struct intel_timeline * const tl = i915_request_timeline(rq); + struct i915_sched_attr attr = {}; struct i915_request *prev; lockdep_assert_held(&tl->mutex); @@ -1312,6 +1312,9 @@ void i915_request_add(struct i915_request *rq) prev = __i915_request_commit(rq); + if (rq->context->gem_context) + attr = rq->context->gem_context->sched; + /* * Boost actual workloads past semaphores! * diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index c5330f36687d..f3ac837ba3b3 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1245,6 +1245,9 @@ int i915_vma_unbind(struct i915_vma *vma) struct i915_address_space *vm = vma->vm; int err; + if (!drm_mm_node_allocated(&vma->node)) + return 0; + err = mutex_lock_interruptible(&vm->mutex); if (err) return err; diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 71a4ca38fbac..f89d9c42f1fa 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -749,10 +749,8 @@ out_batch: static struct i915_vma *recursive_batch(struct drm_i915_private *i915) { - struct i915_gem_context *ctx = i915->kernel_context; struct drm_i915_gem_object *obj; const int gen = INTEL_GEN(i915); - struct i915_address_space *vm; struct i915_vma *vma; u32 *cmd; int err; @@ -761,9 +759,7 @@ static struct i915_vma *recursive_batch(struct drm_i915_private *i915) if (IS_ERR(obj)) return ERR_CAST(obj); - vm = i915_gem_context_get_vm_rcu(ctx); - vma = i915_vma_instance(obj, vm, NULL); - i915_vm_put(vm); + vma = i915_vma_instance(obj, i915->gt.vm, NULL); if (IS_ERR(vma)) { err = PTR_ERR(vma); goto err; diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index d14ba8498f57..a5e46a4739f9 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -63,7 +63,6 @@ static void mock_device_release(struct drm_device *dev) for_each_engine(engine, &i915->gt, id) mock_engine_free(engine); - i915_gem_driver_release__contexts(i915); drain_workqueue(i915->wq); i915_gem_drain_freed_objects(i915); @@ -180,6 +179,7 @@ struct drm_i915_private *mock_gem_device(void) mock_init_contexts(i915); mock_init_ggtt(i915, &i915->ggtt); + i915->gt.vm = i915_vm_get(&i915->ggtt.vm); mkwrite_device_info(i915)->engine_mask = BIT(0); @@ -187,10 +187,6 @@ struct drm_i915_private *mock_gem_device(void) if (!i915->engine[RCS0]) goto err_unlock; - i915->kernel_context = mock_context(i915, NULL); - if (!i915->kernel_context) - goto err_engine; - if (mock_engine_init(i915->engine[RCS0])) goto err_context; @@ -199,8 +195,6 @@ struct drm_i915_private *mock_gem_device(void) return i915; err_context: - i915_gem_driver_release__contexts(i915); -err_engine: mock_engine_free(i915->engine[RCS0]); err_unlock: destroy_workqueue(i915->wq); -- cgit v1.2.3 From 4856254d48d3d4435f4919dc505c9749e33eec7d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 21 Dec 2019 18:02:04 +0000 Subject: drm/i915/gt: Repeat wait_for_idle for retirement workers Since we may retire timelines from secondary workers, intel_gt_retire_requests() is not always a reliable indicator that all pending retirements are complete. If we do detect secondary workers are in progress, recommend intel_gt_wait_for_idle() to repeat the retirement check. Signed-off-by: Chris Wilson Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191221180204.1201217-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine.h | 2 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 6 +++++- drivers/gpu/drm/i915/gt/intel_gt_requests.c | 23 ++++++++++++++--------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index b21c20ee9e23..d4fd56f1e65e 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -282,7 +282,7 @@ static inline void __intel_engine_reset(struct intel_engine_cs *engine, bool intel_engines_are_idle(struct intel_gt *gt); bool intel_engine_is_idle(struct intel_engine_cs *engine); -void intel_engine_flush_submission(struct intel_engine_cs *engine); +bool intel_engine_flush_submission(struct intel_engine_cs *engine); void intel_engines_reset_default_submission(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 0c4c07072473..5309c61ad527 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1079,9 +1079,10 @@ static bool ring_is_idle(struct intel_engine_cs *engine) return idle; } -void intel_engine_flush_submission(struct intel_engine_cs *engine) +bool intel_engine_flush_submission(struct intel_engine_cs *engine) { struct tasklet_struct *t = &engine->execlists.tasklet; + bool active = tasklet_is_locked(t); if (__tasklet_is_scheduled(t)) { local_bh_disable(); @@ -1092,10 +1093,13 @@ void intel_engine_flush_submission(struct intel_engine_cs *engine) tasklet_unlock(t); } local_bh_enable(); + active = true; } /* Otherwise flush the tasklet if it was running on another cpu */ tasklet_unlock_wait(t); + + return active; } /** diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index 063f863ee21c..b4f04614230e 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -23,15 +23,18 @@ static void retire_requests(struct intel_timeline *tl) break; } -static void flush_submission(struct intel_gt *gt) +static bool flush_submission(struct intel_gt *gt) { struct intel_engine_cs *engine; enum intel_engine_id id; + bool active = false; for_each_engine(engine, gt, id) { - intel_engine_flush_submission(engine); - flush_work(&engine->retire_work); + active |= intel_engine_flush_submission(engine); + active |= flush_work(&engine->retire_work); } + + return active; } static void engine_retire(struct work_struct *work) @@ -120,9 +123,10 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) spin_lock(&timelines->lock); list_for_each_entry_safe(tl, tn, &timelines->active_list, link) { - active_count++; /* report busy to caller, try again? */ - if (!mutex_trylock(&tl->mutex)) + if (!mutex_trylock(&tl->mutex)) { + active_count++; /* report busy to caller, try again? */ continue; + } intel_timeline_get(tl); GEM_BUG_ON(!atomic_read(&tl->active_count)); @@ -147,10 +151,10 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) /* Resume iteration after dropping lock */ list_safe_reset_next(tl, tn, link); - if (atomic_dec_and_test(&tl->active_count)) { + if (atomic_dec_and_test(&tl->active_count)) list_del(&tl->link); - active_count--; - } + else + active_count += i915_active_fence_isset(&tl->last_request); mutex_unlock(&tl->mutex); @@ -165,7 +169,8 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout) list_for_each_entry_safe(tl, tn, &free, link) __intel_timeline_free(&tl->kref); - flush_submission(gt); + if (flush_submission(gt)) + active_count++; return active_count ? timeout : 0; } -- cgit v1.2.3 From 78be2c303acae8e3581328fab4b22ce8f1cc4cf9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 21 Dec 2019 20:01:09 +0000 Subject: drm/i915: Move i915_gem_init_contexts() earlier As the GEM global context setup is now independent of the GT state (although GT does currently still depend upon the global i915->kernel_context), we can move its init earlier, leaving the gt init ready to be extracted. Signed-off-by: Chris Wilson Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191221200109.1202310-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8f4a3832ee85..1d23d8bfcc6b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1284,18 +1284,17 @@ int i915_gem_init(struct drm_i915_private *dev_priv) } intel_gt_init(&dev_priv->gt); - i915_gem_init__contexts(dev_priv); ret = intel_engines_setup(&dev_priv->gt); if (ret) { GEM_BUG_ON(ret == -EIO); - goto err_unlock; + goto err_gt_early; } ret = intel_engines_init(&dev_priv->gt); if (ret) { GEM_BUG_ON(ret == -EIO); - goto err_scratch; + goto err_engines; } intel_uc_init(&dev_priv->gt.uc); @@ -1322,19 +1321,19 @@ int i915_gem_init(struct drm_i915_private *dev_priv) ret = intel_engines_verify_workarounds(&dev_priv->gt); if (ret) - goto err_gt; + goto err_gt_late; ret = __intel_engines_record_defaults(&dev_priv->gt); if (ret) - goto err_gt; + goto err_gt_late; ret = i915_inject_probe_error(dev_priv, -ENODEV); if (ret) - goto err_gt; + goto err_gt_late; ret = i915_inject_probe_error(dev_priv, -EIO); if (ret) - goto err_gt; + goto err_gt_late; intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); @@ -1346,7 +1345,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv) * HW as irrevisibly wedged, but keep enough state around that the * driver doesn't explode during runtime. */ -err_gt: +err_gt_late: intel_gt_set_wedged_on_init(&dev_priv->gt); i915_gem_suspend(dev_priv); i915_gem_suspend_late(dev_priv); @@ -1355,11 +1354,12 @@ err_gt: err_init_hw: intel_uc_fini_hw(&dev_priv->gt.uc); err_uc_init: - if (ret != -EIO) { + if (ret != -EIO) intel_uc_fini(&dev_priv->gt.uc); +err_engines: + if (ret != -EIO) intel_engines_cleanup(&dev_priv->gt); - } -err_scratch: +err_gt_early: intel_gt_driver_release(&dev_priv->gt); err_unlock: intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); @@ -1452,6 +1452,7 @@ static void i915_gem_init__mm(struct drm_i915_private *i915) void i915_gem_init_early(struct drm_i915_private *dev_priv) { i915_gem_init__mm(dev_priv); + i915_gem_init__contexts(dev_priv); spin_lock_init(&dev_priv->fb_tracking.lock); } -- cgit v1.2.3 From e26b6d4341476f6944f57bb78fffcdf332c5948b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 22 Dec 2019 12:07:52 +0000 Subject: drm/i915/gt: Pull GT initialisation under intel_gt_init() Begin pulling the GT setup underneath a single GT umbrella; let intel_gt take ownership of its engines! As hinted, the complication is the lifetime of the probed engine versus the active lifetime of the GT backends. We need to detect the engine layout early and keep it until the end so that we can sanitize state on takeover and release. Signed-off-by: Chris Wilson Cc: Andi Shyti Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191222120752.1368352-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/display/intel_overlay.c | 6 +- drivers/gpu/drm/i915/gt/intel_engine.h | 8 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 42 ++-- drivers/gpu/drm/i915/gt/intel_engine_types.h | 15 +- drivers/gpu/drm/i915/gt/intel_gt.c | 257 +++++++++++++++++++++- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 5 + drivers/gpu/drm/i915/gt/intel_lrc.c | 17 +- drivers/gpu/drm/i915/gt/intel_reset.c | 9 +- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 14 +- drivers/gpu/drm/i915/gt/intel_timeline_types.h | 2 +- drivers/gpu/drm/i915/gt/mock_engine.c | 48 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 2 + drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 9 +- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 18 +- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 5 +- drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/i915/i915_gem.c | 253 +-------------------- drivers/gpu/drm/i915/selftests/i915_gem.c | 1 + drivers/gpu/drm/i915/selftests/mock_gem_device.c | 10 +- 19 files changed, 357 insertions(+), 365 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index e869a3d86522..e40c3a0e2cd7 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -1333,12 +1333,14 @@ err_put_bo: void intel_overlay_setup(struct drm_i915_private *dev_priv) { struct intel_overlay *overlay; + struct intel_engine_cs *engine; int ret; if (!HAS_OVERLAY(dev_priv)) return; - if (!HAS_ENGINE(dev_priv, RCS0)) + engine = dev_priv->engine[RCS0]; + if (!engine || !engine->kernel_context) return; overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); @@ -1346,7 +1348,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv) return; overlay->i915 = dev_priv; - overlay->context = dev_priv->engine[RCS0]->kernel_context; + overlay->context = engine->kernel_context; GEM_BUG_ON(!overlay->context); overlay->color_key = 0x0101fe; diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index d4fd56f1e65e..428ec76b49d0 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -186,7 +186,9 @@ void intel_engine_cleanup(struct intel_engine_cs *engine); int intel_engines_init_mmio(struct intel_gt *gt); int intel_engines_setup(struct intel_gt *gt); int intel_engines_init(struct intel_gt *gt); -void intel_engines_cleanup(struct intel_gt *gt); + +void intel_engines_release(struct intel_gt *gt); +void intel_engines_free(struct intel_gt *gt); int intel_engine_init_common(struct intel_engine_cs *engine); void intel_engine_cleanup_common(struct intel_engine_cs *engine); @@ -275,8 +277,8 @@ gen8_emit_ggtt_write(u32 *cs, u32 value, u32 gtt_offset, u32 flags) static inline void __intel_engine_reset(struct intel_engine_cs *engine, bool stalled) { - if (engine->reset.reset) - engine->reset.reset(engine, stalled); + if (engine->reset.rewind) + engine->reset.rewind(engine, stalled); engine->serial++; /* contexts lost */ } diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 5309c61ad527..909614f581ac 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -319,12 +319,6 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id) engine->props.timeslice_duration_ms = CONFIG_DRM_I915_TIMESLICE_DURATION; - /* - * To be overridden by the backend on setup. However to facilitate - * cleanup on error during setup, we always provide the destroy vfunc. - */ - engine->destroy = (typeof(engine->destroy))kfree; - engine->context_size = intel_engine_context_size(gt, engine->class); if (WARN_ON(engine->context_size > BIT(20))) engine->context_size = 0; @@ -390,21 +384,39 @@ static void intel_setup_engine_capabilities(struct intel_gt *gt) } /** - * intel_engines_cleanup() - free the resources allocated for Command Streamers + * intel_engines_release() - free the resources allocated for Command Streamers * @gt: pointer to struct intel_gt */ -void intel_engines_cleanup(struct intel_gt *gt) +void intel_engines_release(struct intel_gt *gt) { struct intel_engine_cs *engine; enum intel_engine_id id; + /* Decouple the backend; but keep the layout for late GPU resets */ for_each_engine(engine, gt, id) { - engine->destroy(engine); - gt->engine[id] = NULL; + if (!engine->release) + continue; + + engine->release(engine); + engine->release = NULL; + + memset(&engine->reset, 0, sizeof(engine->reset)); + gt->i915->engine[id] = NULL; } } +void intel_engines_free(struct intel_gt *gt) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + + for_each_engine(engine, gt, id) { + kfree(engine); + gt->engine[id] = NULL; + } +} + /** * intel_engines_init_mmio() - allocate and prepare the Engine Command Streamers * @gt: pointer to struct intel_gt @@ -455,7 +467,7 @@ int intel_engines_init_mmio(struct intel_gt *gt) return 0; cleanup: - intel_engines_cleanup(gt); + intel_engines_free(gt); return err; } @@ -488,7 +500,7 @@ int intel_engines_init(struct intel_gt *gt) return 0; cleanup: - intel_engines_cleanup(gt); + intel_engines_release(gt); return err; } @@ -663,16 +675,13 @@ int intel_engines_setup(struct intel_gt *gt) if (err) goto cleanup; - /* We expect the backend to take control over its state */ - GEM_BUG_ON(engine->destroy == (typeof(engine->destroy))kfree); - GEM_BUG_ON(!engine->cops); } return 0; cleanup: - intel_engines_cleanup(gt); + intel_engines_release(gt); return err; } @@ -833,6 +842,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) void intel_engine_cleanup_common(struct intel_engine_cs *engine) { GEM_BUG_ON(!list_empty(&engine->active.requests)); + tasklet_kill(&engine->execlists.tasklet); /* flush the callback */ cleanup_status_page(engine); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 7f227da09d66..00287515e7af 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -400,7 +400,10 @@ struct intel_engine_cs { struct { void (*prepare)(struct intel_engine_cs *engine); - void (*reset)(struct intel_engine_cs *engine, bool stalled); + + void (*rewind)(struct intel_engine_cs *engine, bool stalled); + void (*cancel)(struct intel_engine_cs *engine); + void (*finish)(struct intel_engine_cs *engine); } reset; @@ -450,15 +453,7 @@ struct intel_engine_cs { void (*schedule)(struct i915_request *request, const struct i915_sched_attr *attr); - /* - * 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); - - void (*destroy)(struct intel_engine_cs *engine); + void (*release)(struct intel_engine_cs *engine); struct intel_engine_execlists execlists; diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index af4f8c810009..f29c44bf992f 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -4,11 +4,13 @@ */ #include "i915_drv.h" +#include "intel_context.h" #include "intel_gt.h" #include "intel_gt_pm.h" #include "intel_gt_requests.h" #include "intel_mocs.h" #include "intel_rc6.h" +#include "intel_renderstate.h" #include "intel_rps.h" #include "intel_uncore.h" #include "intel_pm.h" @@ -372,32 +374,276 @@ static struct i915_address_space *kernel_vm(struct intel_gt *gt) return i915_vm_get(>->ggtt->vm); } +static int __intel_context_flush_retire(struct intel_context *ce) +{ + struct intel_timeline *tl; + + tl = intel_context_timeline_lock(ce); + if (IS_ERR(tl)) + return PTR_ERR(tl); + + intel_context_timeline_unlock(tl); + return 0; +} + +static int __engines_record_defaults(struct intel_gt *gt) +{ + struct i915_request *requests[I915_NUM_ENGINES] = {}; + struct intel_engine_cs *engine; + enum intel_engine_id id; + int err = 0; + + /* + * As we reset the gpu during very early sanitisation, the current + * register state on the GPU should reflect its defaults values. + * We load a context onto the hw (with restore-inhibit), then switch + * over to a second context to save that default register state. We + * can then prime every new context with that state so they all start + * from the same default HW values. + */ + + for_each_engine(engine, gt, id) { + struct intel_renderstate so; + struct intel_context *ce; + struct i915_request *rq; + + err = intel_renderstate_init(&so, engine); + if (err) + goto out; + + /* We must be able to switch to something! */ + GEM_BUG_ON(!engine->kernel_context); + engine->serial++; /* force the kernel context switch */ + + ce = intel_context_create(engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + goto out; + } + + rq = intel_context_create_request(ce); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + intel_context_put(ce); + goto out; + } + + err = intel_engine_emit_ctx_wa(rq); + if (err) + goto err_rq; + + err = intel_renderstate_emit(&so, rq); + if (err) + goto err_rq; + +err_rq: + requests[id] = i915_request_get(rq); + i915_request_add(rq); + intel_renderstate_fini(&so); + if (err) + goto out; + } + + /* Flush the default context image to memory, and enable powersaving. */ + if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) { + err = -EIO; + goto out; + } + + for (id = 0; id < ARRAY_SIZE(requests); id++) { + struct i915_request *rq; + struct i915_vma *state; + void *vaddr; + + rq = requests[id]; + if (!rq) + continue; + + GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT, &rq->context->flags)); + state = rq->context->state; + if (!state) + continue; + + /* Serialise with retirement on another CPU */ + GEM_BUG_ON(!i915_request_completed(rq)); + err = __intel_context_flush_retire(rq->context); + if (err) + goto out; + + /* We want to be able to unbind the state from the GGTT */ + GEM_BUG_ON(intel_context_is_pinned(rq->context)); + + /* + * As we will hold a reference to the logical state, it will + * not be torn down with the context, and importantly the + * object will hold onto its vma (making it possible for a + * stray GTT write to corrupt our defaults). Unmap the vma + * from the GTT to prevent such accidents and reclaim the + * space. + */ + err = i915_vma_unbind(state); + if (err) + goto out; + + i915_gem_object_lock(state->obj); + err = i915_gem_object_set_to_cpu_domain(state->obj, false); + i915_gem_object_unlock(state->obj); + if (err) + goto out; + + i915_gem_object_set_cache_coherency(state->obj, I915_CACHE_LLC); + + /* Check we can acquire the image of the context state */ + vaddr = i915_gem_object_pin_map(state->obj, I915_MAP_FORCE_WB); + if (IS_ERR(vaddr)) { + err = PTR_ERR(vaddr); + goto out; + } + + rq->engine->default_state = i915_gem_object_get(state->obj); + i915_gem_object_unpin_map(state->obj); + } + +out: + /* + * If we have to abandon now, we expect the engines to be idle + * and ready to be torn-down. The quickest way we can accomplish + * this is by declaring ourselves wedged. + */ + if (err) + intel_gt_set_wedged(gt); + + for (id = 0; id < ARRAY_SIZE(requests); id++) { + struct intel_context *ce; + struct i915_request *rq; + + rq = requests[id]; + if (!rq) + continue; + + ce = rq->context; + i915_request_put(rq); + intel_context_put(ce); + } + return err; +} + +static int __engines_verify_workarounds(struct intel_gt *gt) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + int err = 0; + + if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) + return 0; + + for_each_engine(engine, gt, id) { + if (intel_engine_verify_workarounds(engine, "load")) + err = -EIO; + } + + return err; +} + +static void __intel_gt_disable(struct intel_gt *gt) +{ + intel_gt_set_wedged_on_init(gt); + + intel_gt_suspend_prepare(gt); + intel_gt_suspend_late(gt); + + GEM_BUG_ON(intel_gt_pm_is_awake(gt)); +} + int intel_gt_init(struct intel_gt *gt) { int err; - err = intel_gt_init_scratch(gt, IS_GEN(gt->i915, 2) ? SZ_256K : SZ_4K); + err = i915_inject_probe_error(gt->i915, -ENODEV); if (err) return err; + /* + * This is just a security blanket to placate dragons. + * On some systems, we very sporadically observe that the first TLBs + * used by the CS may be stale, despite us poking the TLB reset. If + * we hold the forcewake during initialisation these problems + * just magically go away. + */ + intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); + + err = intel_gt_init_scratch(gt, IS_GEN(gt->i915, 2) ? SZ_256K : SZ_4K); + if (err) + goto out_fw; + intel_gt_pm_init(gt); gt->vm = kernel_vm(gt); if (!gt->vm) { err = -ENOMEM; - goto err_scratch; + goto err_pm; } - return 0; + err = intel_engines_setup(gt); + if (err) + goto err_vm; + + err = intel_engines_init(gt); + if (err) + goto err_engines; + + intel_uc_init(>->uc); + + err = intel_gt_init_hw(gt); + if (err) + goto err_uc_init; -err_scratch: + /* Only when the HW is re-initialised, can we replay the requests */ + err = intel_gt_resume(gt); + if (err) + goto err_gt_init_hw; + + err = __engines_record_defaults(gt); + if (err) + goto err_gt; + + err = __engines_verify_workarounds(gt); + if (err) + goto err_gt; + + err = i915_inject_probe_error(gt->i915, -EIO); + if (err) + goto err_gt; + + goto out_fw; +err_gt: + __intel_gt_disable(gt); +err_gt_init_hw: + intel_uc_fini_hw(>->uc); +err_uc_init: + intel_uc_fini(>->uc); +err_engines: + intel_engines_release(gt); +err_vm: + i915_vm_put(fetch_and_zero(>->vm)); +err_pm: + intel_gt_pm_fini(gt); intel_gt_fini_scratch(gt); +out_fw: + if (err) + intel_gt_set_wedged_on_init(gt); + intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); return err; } void intel_gt_driver_remove(struct intel_gt *gt) { - GEM_BUG_ON(gt->awake); + __intel_gt_disable(gt); + + intel_uc_fini_hw(>->uc); + intel_uc_fini(>->uc); + + intel_engines_release(gt); } void intel_gt_driver_unregister(struct intel_gt *gt) @@ -423,4 +669,5 @@ void intel_gt_driver_late_release(struct intel_gt *gt) intel_gt_fini_requests(gt); intel_gt_fini_reset(gt); intel_gt_fini_timelines(gt); + intel_engines_free(gt); } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index f36ce36dabeb..6231fe91a3b1 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -281,6 +281,11 @@ void intel_gt_suspend_late(struct intel_gt *gt) /* We expect to be idle already; but also want to be independent */ wait_for_suspend(gt); + if (is_mock_gt(gt)) + return; + + GEM_BUG_ON(gt->awake); + /* * On disabling the device, we want to turn off HW access to memory * that we no longer own. diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index fe2d1523bda3..36e24d987c88 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -3140,7 +3140,7 @@ unwind: __unwind_incomplete_requests(engine); } -static void execlists_reset(struct intel_engine_cs *engine, bool stalled) +static void execlists_reset_rewind(struct intel_engine_cs *engine, bool stalled) { unsigned long flags; @@ -3158,7 +3158,7 @@ static void nop_submission_tasklet(unsigned long data) /* The driver is wedged; don't process any more events. */ } -static void execlists_cancel_requests(struct intel_engine_cs *engine) +static void execlists_reset_cancel(struct intel_engine_cs *engine) { struct intel_engine_execlists * const execlists = &engine->execlists; struct i915_request *rq, *rn; @@ -3747,12 +3747,12 @@ static void execlists_park(struct intel_engine_cs *engine) void intel_execlists_set_default_submission(struct intel_engine_cs *engine) { engine->submit_request = execlists_submit_request; - engine->cancel_requests = execlists_cancel_requests; engine->schedule = i915_schedule; engine->execlists.tasklet.func = execlists_submission_tasklet; engine->reset.prepare = execlists_reset_prepare; - engine->reset.reset = execlists_reset; + engine->reset.rewind = execlists_reset_rewind; + engine->reset.cancel = execlists_reset_cancel; engine->reset.finish = execlists_reset_finish; engine->park = execlists_park; @@ -3782,13 +3782,12 @@ static void execlists_shutdown(struct intel_engine_cs *engine) tasklet_kill(&engine->execlists.tasklet); } -static void execlists_destroy(struct intel_engine_cs *engine) +static void execlists_release(struct intel_engine_cs *engine) { execlists_shutdown(engine); intel_engine_cleanup_common(engine); lrc_destroy_wa_ctx(engine); - kfree(engine); } static void @@ -3796,13 +3795,9 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) { /* Default vfuncs which can be overriden by each engine. */ - engine->destroy = execlists_destroy; + engine->release = execlists_release; engine->resume = execlists_resume; - engine->reset.prepare = execlists_reset_prepare; - engine->reset.reset = execlists_reset; - engine->reset.finish = execlists_reset_finish; - engine->cops = &execlists_context_ops; engine->request_alloc = execlists_request_alloc; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 95c24176ab64..ab8213b90517 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -666,7 +666,8 @@ static void reset_prepare_engine(struct intel_engine_cs *engine) * GPU state upon resume, i.e. fail to restart after a reset. */ intel_uncore_forcewake_get(engine->uncore, FORCEWAKE_ALL); - engine->reset.prepare(engine); + if (engine->reset.prepare) + engine->reset.prepare(engine); } static void revoke_mmaps(struct intel_gt *gt) @@ -746,7 +747,8 @@ static int gt_reset(struct intel_gt *gt, intel_engine_mask_t stalled_mask) static void reset_finish_engine(struct intel_engine_cs *engine) { - engine->reset.finish(engine); + if (engine->reset.finish) + engine->reset.finish(engine); intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL); intel_engine_signal_breadcrumbs(engine); @@ -823,7 +825,8 @@ static void __intel_gt_set_wedged(struct intel_gt *gt) /* Mark all executing requests as skipped */ for_each_engine(engine, gt, id) - engine->cancel_requests(engine); + if (engine->reset.cancel) + engine->reset.cancel(engine); reset_finish(gt, awake); diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 3dc0d0a97a61..13bd649c261e 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -768,7 +768,7 @@ static void reset_prepare(struct intel_engine_cs *engine) intel_uncore_read_fw(uncore, RING_HEAD(base))); } -static void reset_ring(struct intel_engine_cs *engine, bool stalled) +static void reset_rewind(struct intel_engine_cs *engine, bool stalled) { struct i915_request *pos, *rq; unsigned long flags; @@ -900,7 +900,7 @@ static int rcs_resume(struct intel_engine_cs *engine) return xcs_resume(engine); } -static void cancel_requests(struct intel_engine_cs *engine) +static void reset_cancel(struct intel_engine_cs *engine) { struct i915_request *request; unsigned long flags; @@ -1787,7 +1787,6 @@ static int gen6_ring_flush(struct i915_request *rq, u32 mode) static void i9xx_set_default_submission(struct intel_engine_cs *engine) { engine->submit_request = i9xx_submit_request; - engine->cancel_requests = cancel_requests; engine->park = NULL; engine->unpark = NULL; @@ -1799,7 +1798,7 @@ static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine) engine->submit_request = gen6_bsd_submit_request; } -static void ring_destroy(struct intel_engine_cs *engine) +static void ring_release(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; @@ -1813,8 +1812,6 @@ static void ring_destroy(struct intel_engine_cs *engine) intel_timeline_unpin(engine->legacy.timeline); intel_timeline_put(engine->legacy.timeline); - - kfree(engine); } static void setup_irq(struct intel_engine_cs *engine) @@ -1845,11 +1842,12 @@ static void setup_common(struct intel_engine_cs *engine) setup_irq(engine); - engine->destroy = ring_destroy; + engine->release = ring_release; engine->resume = xcs_resume; engine->reset.prepare = reset_prepare; - engine->reset.reset = reset_ring; + engine->reset.rewind = reset_rewind; + engine->reset.cancel = reset_cancel; engine->reset.finish = reset_finish; engine->cops = &ring_context_ops; diff --git a/drivers/gpu/drm/i915/gt/intel_timeline_types.h b/drivers/gpu/drm/i915/gt/intel_timeline_types.h index 24d040f14e89..02181c5020db 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline_types.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline_types.h @@ -15,9 +15,9 @@ #include "i915_active_types.h" -struct drm_i915_private; struct i915_vma; struct i915_syncmap; +struct intel_gt; struct intel_timeline_hwsp; struct intel_timeline { diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 9efb63a03129..4e1eafa94be9 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -207,16 +207,12 @@ static void mock_reset_prepare(struct intel_engine_cs *engine) { } -static void mock_reset(struct intel_engine_cs *engine, bool stalled) +static void mock_reset_rewind(struct intel_engine_cs *engine, bool stalled) { GEM_BUG_ON(stalled); } -static void mock_reset_finish(struct intel_engine_cs *engine) -{ -} - -static void mock_cancel_requests(struct intel_engine_cs *engine) +static void mock_reset_cancel(struct intel_engine_cs *engine) { struct i915_request *request; unsigned long flags; @@ -234,6 +230,24 @@ static void mock_cancel_requests(struct intel_engine_cs *engine) spin_unlock_irqrestore(&engine->active.lock, flags); } +static void mock_reset_finish(struct intel_engine_cs *engine) +{ +} + +static void mock_engine_release(struct intel_engine_cs *engine) +{ + struct mock_engine *mock = + container_of(engine, typeof(*mock), base); + + GEM_BUG_ON(timer_pending(&mock->hw_delay)); + + intel_context_unpin(engine->kernel_context); + intel_context_put(engine->kernel_context); + + intel_engine_fini_retire(engine); + intel_engine_fini_breadcrumbs(engine); +} + struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, const char *name, int id) @@ -265,9 +279,11 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, engine->base.submit_request = mock_submit_request; engine->base.reset.prepare = mock_reset_prepare; - engine->base.reset.reset = mock_reset; + engine->base.reset.rewind = mock_reset_rewind; + engine->base.reset.cancel = mock_reset_cancel; engine->base.reset.finish = mock_reset_finish; - engine->base.cancel_requests = mock_cancel_requests; + + engine->base.release = mock_engine_release; i915->gt.engine[id] = &engine->base; i915->gt.engine_class[0][id] = &engine->base; @@ -322,19 +338,3 @@ void mock_engine_flush(struct intel_engine_cs *engine) void mock_engine_reset(struct intel_engine_cs *engine) { } - -void mock_engine_free(struct intel_engine_cs *engine) -{ - struct mock_engine *mock = - container_of(engine, typeof(*mock), base); - - GEM_BUG_ON(timer_pending(&mock->hw_delay)); - - intel_context_unpin(engine->kernel_context); - intel_context_put(engine->kernel_context); - - intel_engine_fini_retire(engine); - intel_engine_fini_breadcrumbs(engine); - - kfree(engine); -} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 9d6301292e13..5d00a3b2d914 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -398,6 +398,8 @@ void intel_guc_fini(struct intel_guc *guc) intel_guc_log_destroy(&guc->log); intel_uc_fw_fini(&guc->fw); intel_uc_fw_cleanup_fetch(&guc->fw); + + intel_uc_fw_change_status(&guc->fw, INTEL_UC_FIRMWARE_DISABLED); } /* diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 007636221a71..9e42324fdecd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -401,7 +401,7 @@ cancel_port_requests(struct intel_engine_execlists * const execlists) memset(execlists->inflight, 0, sizeof(execlists->inflight)); } -static void guc_reset(struct intel_engine_cs *engine, bool stalled) +static void guc_reset_rewind(struct intel_engine_cs *engine, bool stalled) { struct intel_engine_execlists * const execlists = &engine->execlists; struct i915_request *rq; @@ -426,7 +426,7 @@ out_unlock: spin_unlock_irqrestore(&engine->active.lock, flags); } -static void guc_cancel_requests(struct intel_engine_cs *engine) +static void guc_reset_cancel(struct intel_engine_cs *engine) { struct intel_engine_execlists * const execlists = &engine->execlists; struct i915_request *rq, *rn; @@ -599,11 +599,10 @@ static void guc_set_default_submission(struct intel_engine_cs *engine) engine->park = engine->unpark = NULL; engine->reset.prepare = guc_reset_prepare; - engine->reset.reset = guc_reset; + engine->reset.rewind = guc_reset_rewind; + engine->reset.cancel = guc_reset_cancel; engine->reset.finish = guc_reset_finish; - engine->cancel_requests = guc_cancel_requests; - engine->flags &= ~I915_ENGINE_SUPPORTS_STATS; engine->flags |= I915_ENGINE_NEEDS_BREADCRUMB_TASKLET; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 782b8f95183f..3ffc6267f96e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -262,12 +262,7 @@ void intel_uc_fetch_firmwares(struct intel_uc *uc) void intel_uc_cleanup_firmwares(struct intel_uc *uc) { - if (!intel_uc_uses_guc(uc)) - return; - - if (intel_uc_uses_huc(uc)) - intel_uc_fw_cleanup_fetch(&uc->huc.fw); - + intel_uc_fw_cleanup_fetch(&uc->huc.fw); intel_uc_fw_cleanup_fetch(&uc->guc.fw); } @@ -295,15 +290,8 @@ void intel_uc_init(struct intel_uc *uc) void intel_uc_fini(struct intel_uc *uc) { - struct intel_guc *guc = &uc->guc; - - if (!intel_uc_uses_guc(uc)) - return; - - if (intel_uc_uses_huc(uc)) - intel_huc_fini(&uc->huc); - - intel_guc_fini(guc); + intel_huc_fini(&uc->huc); + intel_guc_fini(&uc->guc); __uc_free_load_err_log(uc); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index b6aedee46f9e..8ee0a0c7f447 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -544,10 +544,7 @@ int intel_uc_fw_init(struct intel_uc_fw *uc_fw) void intel_uc_fw_fini(struct intel_uc_fw *uc_fw) { - if (!intel_uc_fw_is_available(uc_fw)) - return; - - i915_gem_object_unpin_pages(uc_fw->obj); + intel_uc_fw_cleanup_fetch(uc_fw); } /** diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1234bd64db2f..01bbeb1c1841 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -619,7 +619,6 @@ err_bridge: */ static void i915_driver_mmio_release(struct drm_i915_private *dev_priv) { - intel_engines_cleanup(&dev_priv->gt); intel_teardown_mchbar(dev_priv); intel_uncore_fini_mmio(&dev_priv->uncore); pci_dev_put(dev_priv->bridge_dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1d23d8bfcc6b..983755bec76b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -45,20 +45,12 @@ #include "gem/i915_gem_context.h" #include "gem/i915_gem_ioctls.h" #include "gem/i915_gem_mman.h" -#include "gem/i915_gem_pm.h" -#include "gt/intel_context.h" #include "gt/intel_engine_user.h" #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" -#include "gt/intel_gt_requests.h" -#include "gt/intel_mocs.h" -#include "gt/intel_reset.h" -#include "gt/intel_renderstate.h" -#include "gt/intel_rps.h" #include "gt/intel_workarounds.h" #include "i915_drv.h" -#include "i915_scatterlist.h" #include "i915_trace.h" #include "i915_vgpu.h" @@ -1082,177 +1074,6 @@ out: return err; } -static int __intel_context_flush_retire(struct intel_context *ce) -{ - struct intel_timeline *tl; - - tl = intel_context_timeline_lock(ce); - if (IS_ERR(tl)) - return PTR_ERR(tl); - - intel_context_timeline_unlock(tl); - return 0; -} - -static int __intel_engines_record_defaults(struct intel_gt *gt) -{ - struct i915_request *requests[I915_NUM_ENGINES] = {}; - struct intel_engine_cs *engine; - enum intel_engine_id id; - int err = 0; - - /* - * As we reset the gpu during very early sanitisation, the current - * register state on the GPU should reflect its defaults values. - * We load a context onto the hw (with restore-inhibit), then switch - * over to a second context to save that default register state. We - * can then prime every new context with that state so they all start - * from the same default HW values. - */ - - for_each_engine(engine, gt, id) { - struct intel_renderstate so; - struct intel_context *ce; - struct i915_request *rq; - - err = intel_renderstate_init(&so, engine); - if (err) - goto out; - - /* We must be able to switch to something! */ - GEM_BUG_ON(!engine->kernel_context); - engine->serial++; /* force the kernel context switch */ - - ce = intel_context_create(engine); - if (IS_ERR(ce)) { - err = PTR_ERR(ce); - goto out; - } - - rq = intel_context_create_request(ce); - if (IS_ERR(rq)) { - err = PTR_ERR(rq); - intel_context_put(ce); - goto out; - } - - err = intel_engine_emit_ctx_wa(rq); - if (err) - goto err_rq; - - err = intel_renderstate_emit(&so, rq); - if (err) - goto err_rq; - -err_rq: - requests[id] = i915_request_get(rq); - i915_request_add(rq); - intel_renderstate_fini(&so); - if (err) - goto out; - } - - /* Flush the default context image to memory, and enable powersaving. */ - if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) { - err = -EIO; - goto out; - } - - for (id = 0; id < ARRAY_SIZE(requests); id++) { - struct i915_request *rq; - struct i915_vma *state; - void *vaddr; - - rq = requests[id]; - if (!rq) - continue; - - GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT, &rq->context->flags)); - state = rq->context->state; - if (!state) - continue; - - /* Serialise with retirement on another CPU */ - GEM_BUG_ON(!i915_request_completed(rq)); - err = __intel_context_flush_retire(rq->context); - if (err) - goto out; - - /* We want to be able to unbind the state from the GGTT */ - GEM_BUG_ON(intel_context_is_pinned(rq->context)); - - /* - * As we will hold a reference to the logical state, it will - * not be torn down with the context, and importantly the - * object will hold onto its vma (making it possible for a - * stray GTT write to corrupt our defaults). Unmap the vma - * from the GTT to prevent such accidents and reclaim the - * space. - */ - err = i915_vma_unbind(state); - if (err) - goto out; - - i915_gem_object_lock(state->obj); - err = i915_gem_object_set_to_cpu_domain(state->obj, false); - i915_gem_object_unlock(state->obj); - if (err) - goto out; - - i915_gem_object_set_cache_coherency(state->obj, I915_CACHE_LLC); - - /* Check we can acquire the image of the context state */ - vaddr = i915_gem_object_pin_map(state->obj, I915_MAP_FORCE_WB); - if (IS_ERR(vaddr)) { - err = PTR_ERR(vaddr); - goto out; - } - - rq->engine->default_state = i915_gem_object_get(state->obj); - i915_gem_object_unpin_map(state->obj); - } - -out: - /* - * If we have to abandon now, we expect the engines to be idle - * and ready to be torn-down. The quickest way we can accomplish - * this is by declaring ourselves wedged. - */ - if (err) - intel_gt_set_wedged(gt); - - for (id = 0; id < ARRAY_SIZE(requests); id++) { - struct intel_context *ce; - struct i915_request *rq; - - rq = requests[id]; - if (!rq) - continue; - - ce = rq->context; - i915_request_put(rq); - intel_context_put(ce); - } - return err; -} - -static int intel_engines_verify_workarounds(struct intel_gt *gt) -{ - struct intel_engine_cs *engine; - enum intel_engine_id id; - int err = 0; - - if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) - return 0; - - for_each_engine(engine, gt, id) { - if (intel_engine_verify_workarounds(engine, "load")) - err = -EIO; - } - - return err; -} - int i915_gem_init(struct drm_i915_private *dev_priv) { int ret; @@ -1269,45 +1090,12 @@ int i915_gem_init(struct drm_i915_private *dev_priv) intel_uc_fetch_firmwares(&dev_priv->gt.uc); intel_wopcm_init(&dev_priv->wopcm); - /* This is just a security blanket to placate dragons. - * On some systems, we very sporadically observe that the first TLBs - * used by the CS may be stale, despite us poking the TLB reset. If - * we hold the forcewake during initialisation these problems - * just magically go away. - */ - intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL); - ret = i915_init_ggtt(dev_priv); if (ret) { GEM_BUG_ON(ret == -EIO); goto err_unlock; } - intel_gt_init(&dev_priv->gt); - - ret = intel_engines_setup(&dev_priv->gt); - if (ret) { - GEM_BUG_ON(ret == -EIO); - goto err_gt_early; - } - - ret = intel_engines_init(&dev_priv->gt); - if (ret) { - GEM_BUG_ON(ret == -EIO); - goto err_engines; - } - - intel_uc_init(&dev_priv->gt.uc); - - ret = intel_gt_init_hw(&dev_priv->gt); - if (ret) - goto err_uc_init; - - /* Only when the HW is re-initialised, can we replay the requests */ - ret = intel_gt_resume(&dev_priv->gt); - if (ret) - goto err_init_hw; - /* * Despite its name intel_init_clock_gating applies both display * clock gating workarounds; GT mmio workarounds and the occasional @@ -1319,23 +1107,9 @@ int i915_gem_init(struct drm_i915_private *dev_priv) */ intel_init_clock_gating(dev_priv); - ret = intel_engines_verify_workarounds(&dev_priv->gt); - if (ret) - goto err_gt_late; - - ret = __intel_engines_record_defaults(&dev_priv->gt); - if (ret) - goto err_gt_late; - - ret = i915_inject_probe_error(dev_priv, -ENODEV); - if (ret) - goto err_gt_late; - - ret = i915_inject_probe_error(dev_priv, -EIO); + ret = intel_gt_init(&dev_priv->gt); if (ret) - goto err_gt_late; - - intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); + goto err_unlock; return 0; @@ -1345,24 +1119,8 @@ int i915_gem_init(struct drm_i915_private *dev_priv) * HW as irrevisibly wedged, but keep enough state around that the * driver doesn't explode during runtime. */ -err_gt_late: - intel_gt_set_wedged_on_init(&dev_priv->gt); - i915_gem_suspend(dev_priv); - i915_gem_suspend_late(dev_priv); - - i915_gem_drain_workqueue(dev_priv); -err_init_hw: - intel_uc_fini_hw(&dev_priv->gt.uc); -err_uc_init: - if (ret != -EIO) - intel_uc_fini(&dev_priv->gt.uc); -err_engines: - if (ret != -EIO) - intel_engines_cleanup(&dev_priv->gt); -err_gt_early: - intel_gt_driver_release(&dev_priv->gt); err_unlock: - intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); + i915_gem_drain_workqueue(dev_priv); if (ret != -EIO) { intel_uc_cleanup_firmwares(&dev_priv->gt.uc); @@ -1410,19 +1168,16 @@ void i915_gem_driver_remove(struct drm_i915_private *dev_priv) i915_gem_suspend_late(dev_priv); intel_gt_driver_remove(&dev_priv->gt); + dev_priv->uabi_engines = RB_ROOT; /* Flush any outstanding unpin_work. */ i915_gem_drain_workqueue(dev_priv); - intel_uc_fini_hw(&dev_priv->gt.uc); - intel_uc_fini(&dev_priv->gt.uc); - i915_gem_drain_freed_objects(dev_priv); } void i915_gem_driver_release(struct drm_i915_private *dev_priv) { - intel_engines_cleanup(&dev_priv->gt); intel_gt_driver_release(&dev_priv->gt); intel_wa_list_free(&dev_priv->gt_wa_list); diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index 657e23a8dd11..b37fc53973cc 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -9,6 +9,7 @@ #include "gem/selftests/igt_gem_utils.h" #include "gem/selftests/mock_context.h" #include "gt/intel_gt.h" +#include "gt/intel_gt_pm.h" #include "i915_selftest.h" diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index a5e46a4739f9..ac641f5360e1 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -54,17 +54,11 @@ void mock_device_flush(struct drm_i915_private *i915) static void mock_device_release(struct drm_device *dev) { struct drm_i915_private *i915 = to_i915(dev); - struct intel_engine_cs *engine; - enum intel_engine_id id; mock_device_flush(i915); + intel_gt_driver_remove(&i915->gt); i915_gem_drain_workqueue(i915); - - for_each_engine(engine, &i915->gt, id) - mock_engine_free(engine); - - drain_workqueue(i915->wq); i915_gem_drain_freed_objects(i915); mock_fini_ggtt(&i915->ggtt); @@ -195,7 +189,7 @@ struct drm_i915_private *mock_gem_device(void) return i915; err_context: - mock_engine_free(i915->engine[RCS0]); + intel_gt_driver_remove(&i915->gt); err_unlock: destroy_workqueue(i915->wq); err_drv: -- cgit v1.2.3 From cfe6b30fc37cc8a6ac9241e450c91ad7a7d6874c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 22 Dec 2019 14:40:44 +0000 Subject: drm/i915/gt: Pull intel_gt_init_hw() into intel_gt_resume() Since intel_gt_resume() is always immediately proceeded by init_hw, pull the call into intel_gt_resume, where we have the rpm and fw already held. Signed-off-by: Chris Wilson Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191222144046.1674865-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_pm.c | 20 +------------------- drivers/gpu/drm/i915/gt/intel_gt.c | 8 +------- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 12 +++++++++++- 3 files changed, 13 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c index 3671a4e7e1cb..c8264eb036bf 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c @@ -101,28 +101,10 @@ void i915_gem_resume(struct drm_i915_private *i915) { GEM_TRACE("%s\n", dev_name(i915->drm.dev)); - intel_uncore_forcewake_get(&i915->uncore, FORCEWAKE_ALL); - - if (intel_gt_init_hw(&i915->gt)) - goto err_wedged; - /* * As we didn't flush the kernel context before suspend, we cannot * guarantee that the context image is complete. So let's just reset * it and start again. */ - if (intel_gt_resume(&i915->gt)) - goto err_wedged; - -out_unlock: - intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL); - return; - -err_wedged: - if (!intel_gt_is_wedged(&i915->gt)) { - dev_err(i915->drm.dev, - "Failed to re-initialize GPU, declaring it wedged!\n"); - intel_gt_set_wedged(&i915->gt); - } - goto out_unlock; + intel_gt_resume(&i915->gt); } diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index f29c44bf992f..4a2d0eb05663 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -594,14 +594,9 @@ int intel_gt_init(struct intel_gt *gt) intel_uc_init(>->uc); - err = intel_gt_init_hw(gt); - if (err) - goto err_uc_init; - - /* Only when the HW is re-initialised, can we replay the requests */ err = intel_gt_resume(gt); if (err) - goto err_gt_init_hw; + goto err_uc_init; err = __engines_record_defaults(gt); if (err) @@ -618,7 +613,6 @@ int intel_gt_init(struct intel_gt *gt) goto out_fw; err_gt: __intel_gt_disable(gt); -err_gt_init_hw: intel_uc_fini_hw(>->uc); err_uc_init: intel_uc_fini(>->uc); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 6231fe91a3b1..45b68a17da4d 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -187,7 +187,7 @@ int intel_gt_resume(struct intel_gt *gt) { struct intel_engine_cs *engine; enum intel_engine_id id; - int err = 0; + int err; GT_TRACE(gt, "\n"); @@ -202,6 +202,15 @@ int intel_gt_resume(struct intel_gt *gt) intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); intel_rc6_sanitize(>->rc6); + /* Only when the HW is re-initialised, can we replay the requests */ + err = intel_gt_init_hw(gt); + if (err) { + dev_err(gt->i915->drm.dev, + "Failed to initialize GPU, declaring it wedged!\n"); + intel_gt_set_wedged(gt); + goto err_fw; + } + intel_rps_enable(>->rps); intel_llc_enable(>->llc); @@ -234,6 +243,7 @@ int intel_gt_resume(struct intel_gt *gt) user_forcewake(gt, false); +err_fw: intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); intel_gt_pm_put(gt); -- cgit v1.2.3 From 7d70a1233d11ce9286e1a04c4f1bcd263e3e405e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 22 Dec 2019 14:40:45 +0000 Subject: drm/i915/gt: Merge engine init/setup loops Now that we don't need to create GEM contexts in the middle of engine construction, we can pull the engine init/setup loops together. Signed-off-by: Chris Wilson Cc: Andi Shyti Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191222144046.1674865-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gt/intel_engine.h | 2 - drivers/gpu/drm/i915/gt/intel_engine_cs.c | 108 ++++++++---------------- drivers/gpu/drm/i915/gt/intel_gt.c | 5 -- drivers/gpu/drm/i915/gt/intel_lrc.c | 20 ++--- drivers/gpu/drm/i915/gt/intel_lrc.h | 1 - drivers/gpu/drm/i915/gt/intel_ring_submission.c | 19 +---- 6 files changed, 42 insertions(+), 113 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index 428ec76b49d0..79ecac5ac0ab 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -184,7 +184,6 @@ void intel_engine_stop(struct intel_engine_cs *engine); void intel_engine_cleanup(struct intel_engine_cs *engine); int intel_engines_init_mmio(struct intel_gt *gt); -int intel_engines_setup(struct intel_gt *gt); int intel_engines_init(struct intel_gt *gt); void intel_engines_release(struct intel_gt *gt); @@ -194,7 +193,6 @@ int intel_engine_init_common(struct intel_engine_cs *engine); void intel_engine_cleanup_common(struct intel_engine_cs *engine); int intel_ring_submission_setup(struct intel_engine_cs *engine); -int intel_ring_submission_init(struct intel_engine_cs *engine); int intel_engine_stop_cs(struct intel_engine_cs *engine); void intel_engine_cancel_stop_cs(struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 909614f581ac..ddf9543b1261 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -471,39 +471,6 @@ cleanup: return err; } -/** - * intel_engines_init() - init the Engine Command Streamers - * @gt: pointer to struct intel_gt - * - * Return: non-zero if the initialization failed. - */ -int intel_engines_init(struct intel_gt *gt) -{ - int (*init)(struct intel_engine_cs *engine); - struct intel_engine_cs *engine; - enum intel_engine_id id; - int err; - - if (HAS_EXECLISTS(gt->i915)) - init = intel_execlists_submission_init; - else - init = intel_ring_submission_init; - - for_each_engine(engine, gt, id) { - err = init(engine); - if (err) - goto cleanup; - - intel_engine_add_user(engine); - } - - return 0; - -cleanup: - intel_engines_release(gt); - return err; -} - void intel_engine_init_execlists(struct intel_engine_cs *engine) { struct intel_engine_execlists * const execlists = &engine->execlists; @@ -615,7 +582,7 @@ err: return ret; } -static int intel_engine_setup_common(struct intel_engine_cs *engine) +static int engine_setup_common(struct intel_engine_cs *engine) { int err; @@ -645,46 +612,6 @@ static int intel_engine_setup_common(struct intel_engine_cs *engine) return 0; } -/** - * intel_engines_setup- setup engine state not requiring hw access - * @gt: pointer to struct intel_gt - * - * Initializes engine structure members shared between legacy and execlists - * submission modes which do not require hardware access. - * - * Typically done early in the submission mode specific engine setup stage. - */ -int intel_engines_setup(struct intel_gt *gt) -{ - int (*setup)(struct intel_engine_cs *engine); - struct intel_engine_cs *engine; - enum intel_engine_id id; - int err; - - if (HAS_EXECLISTS(gt->i915)) - setup = intel_execlists_submission_setup; - else - setup = intel_ring_submission_setup; - - for_each_engine(engine, gt, id) { - err = intel_engine_setup_common(engine); - if (err) - goto cleanup; - - err = setup(engine); - if (err) - goto cleanup; - - GEM_BUG_ON(!engine->cops); - } - - return 0; - -cleanup: - intel_engines_release(gt); - return err; -} - struct measure_breadcrumb { struct i915_request rq; struct intel_timeline timeline; @@ -802,7 +729,7 @@ create_kernel_context(struct intel_engine_cs *engine) * * Returns zero on success or an error code on failure. */ -int intel_engine_init_common(struct intel_engine_cs *engine) +static int engine_init_common(struct intel_engine_cs *engine) { struct intel_context *ce; int ret; @@ -832,6 +759,37 @@ int intel_engine_init_common(struct intel_engine_cs *engine) return 0; } +int intel_engines_init(struct intel_gt *gt) +{ + int (*setup)(struct intel_engine_cs *engine); + struct intel_engine_cs *engine; + enum intel_engine_id id; + int err; + + if (HAS_EXECLISTS(gt->i915)) + setup = intel_execlists_submission_setup; + else + setup = intel_ring_submission_setup; + + for_each_engine(engine, gt, id) { + err = engine_setup_common(engine); + if (err) + return err; + + err = setup(engine); + if (err) + return err; + + err = engine_init_common(engine); + if (err) + return err; + + intel_engine_add_user(engine); + } + + return 0; +} + /** * intel_engines_cleanup_common - cleans up the engine state created by * the common initiailizers. diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 4a2d0eb05663..172102a6c5fb 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -584,10 +584,6 @@ int intel_gt_init(struct intel_gt *gt) goto err_pm; } - err = intel_engines_setup(gt); - if (err) - goto err_vm; - err = intel_engines_init(gt); if (err) goto err_engines; @@ -618,7 +614,6 @@ err_uc_init: intel_uc_fini(>->uc); err_engines: intel_engines_release(gt); -err_vm: i915_vm_put(fetch_and_zero(>->vm)); err_pm: intel_gt_pm_fini(gt); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 36e24d987c88..4fb70a7716e3 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -3863,6 +3863,11 @@ static void rcs_submission_override(struct intel_engine_cs *engine) int intel_execlists_submission_setup(struct intel_engine_cs *engine) { + struct intel_engine_execlists * const execlists = &engine->execlists; + struct drm_i915_private *i915 = engine->i915; + struct intel_uncore *uncore = engine->uncore; + u32 base = engine->mmio_base; + tasklet_init(&engine->execlists.tasklet, execlists_submission_tasklet, (unsigned long)engine); timer_setup(&engine->execlists.timer, execlists_timeslice, 0); @@ -3874,21 +3879,6 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine) if (engine->class == RENDER_CLASS) rcs_submission_override(engine); - return 0; -} - -int intel_execlists_submission_init(struct intel_engine_cs *engine) -{ - struct intel_engine_execlists * const execlists = &engine->execlists; - struct drm_i915_private *i915 = engine->i915; - struct intel_uncore *uncore = engine->uncore; - u32 base = engine->mmio_base; - int ret; - - ret = intel_engine_init_common(engine); - if (ret) - return ret; - if (intel_init_workaround_bb(engine)) /* * We continue even if we fail to initialize WA batch diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.h b/drivers/gpu/drm/i915/gt/intel_lrc.h index 081521f17c74..dfbc214e14f5 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.h +++ b/drivers/gpu/drm/i915/gt/intel_lrc.h @@ -83,7 +83,6 @@ enum { void intel_logical_ring_cleanup(struct intel_engine_cs *engine); int intel_execlists_submission_setup(struct intel_engine_cs *engine); -int intel_execlists_submission_init(struct intel_engine_cs *engine); /* Logical Ring Contexts */ /* At the start of the context image is its per-process HWS page */ diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 13bd649c261e..118170eb51b4 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1958,6 +1958,10 @@ static void setup_vecs(struct intel_engine_cs *engine) int intel_ring_submission_setup(struct intel_engine_cs *engine) { + struct intel_timeline *timeline; + struct intel_ring *ring; + int err; + setup_common(engine); switch (engine->class) { @@ -1978,15 +1982,6 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine) return -ENODEV; } - return 0; -} - -int intel_ring_submission_init(struct intel_engine_cs *engine) -{ - struct intel_timeline *timeline; - struct intel_ring *ring; - int err; - timeline = intel_timeline_create(engine->gt, engine->status_page.vma); if (IS_ERR(timeline)) { err = PTR_ERR(timeline); @@ -2012,16 +2007,10 @@ int intel_ring_submission_init(struct intel_engine_cs *engine) engine->legacy.ring = ring; engine->legacy.timeline = timeline; - err = intel_engine_init_common(engine); - if (err) - goto err_ring_unpin; - GEM_BUG_ON(timeline->hwsp_ggtt != engine->status_page.vma); return 0; -err_ring_unpin: - intel_ring_unpin(ring); err_ring: intel_ring_put(ring); err_timeline_unpin: -- cgit v1.2.3 From 9dd4b065446aebf61b84ba05fb4d78c39e33113b Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Sun, 22 Dec 2019 14:40:46 +0000 Subject: drm/i915/gt: Move pm debug files into a gt aware debugfs The GT system is becoming more and more a stand-alone system in i915 and it's fair to assign it its own debugfs directory. rc6, rps and llc debugfs files are gt related, move them into the gt debugfs directory. Signed-off-by: Andi Shyti Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20191222144046.1674865-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Makefile | 3 + drivers/gpu/drm/i915/gt/debugfs_engines.c | 36 ++ drivers/gpu/drm/i915/gt/debugfs_engines.h | 14 + drivers/gpu/drm/i915/gt/debugfs_gt.c | 42 +++ drivers/gpu/drm/i915/gt/debugfs_gt.h | 39 ++ drivers/gpu/drm/i915/gt/debugfs_gt_pm.c | 601 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gt/debugfs_gt_pm.h | 14 + drivers/gpu/drm/i915/gt/intel_gt.c | 3 + 8 files changed, 752 insertions(+) create mode 100644 drivers/gpu/drm/i915/gt/debugfs_engines.c create mode 100644 drivers/gpu/drm/i915/gt/debugfs_engines.h create mode 100644 drivers/gpu/drm/i915/gt/debugfs_gt.c create mode 100644 drivers/gpu/drm/i915/gt/debugfs_gt.h create mode 100644 drivers/gpu/drm/i915/gt/debugfs_gt_pm.c create mode 100644 drivers/gpu/drm/i915/gt/debugfs_gt_pm.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index e0fd10c0cfb8..b0c53661f62b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -75,6 +75,9 @@ i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o # "Graphics Technology" (aka we talk to the gpu) obj-y += gt/ gt-y += \ + gt/debugfs_engines.o \ + gt/debugfs_gt.o \ + gt/debugfs_gt_pm.o \ gt/intel_breadcrumbs.o \ gt/intel_context.o \ gt/intel_engine_cs.o \ diff --git a/drivers/gpu/drm/i915/gt/debugfs_engines.c b/drivers/gpu/drm/i915/gt/debugfs_engines.c new file mode 100644 index 000000000000..6a5e9ab20b94 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/debugfs_engines.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT + +/* + * Copyright © 2019 Intel Corporation + */ + +#include + +#include "debugfs_engines.h" +#include "debugfs_gt.h" +#include "i915_drv.h" /* for_each_engine! */ +#include "intel_engine.h" + +static int engines_show(struct seq_file *m, void *data) +{ + struct intel_gt *gt = m->private; + struct intel_engine_cs *engine; + enum intel_engine_id id; + struct drm_printer p; + + p = drm_seq_file_printer(m); + for_each_engine(engine, gt, id) + intel_engine_dump(engine, &p, "%s\n", engine->name); + + return 0; +} +DEFINE_GT_DEBUGFS_ATTRIBUTE(engines); + +void debugfs_engines_register(struct intel_gt *gt, struct dentry *root) +{ + static const struct debugfs_gt_file files[] = { + { "engines", &engines_fops }, + }; + + debugfs_gt_register_files(gt, root, files, ARRAY_SIZE(files)); +} diff --git a/drivers/gpu/drm/i915/gt/debugfs_engines.h b/drivers/gpu/drm/i915/gt/debugfs_engines.h new file mode 100644 index 000000000000..f69257eaa1cc --- /dev/null +++ b/drivers/gpu/drm/i915/gt/debugfs_engines.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef DEBUGFS_ENGINES_H +#define DEBUGFS_ENGINES_H + +struct intel_gt; +struct dentry; + +void debugfs_engines_register(struct intel_gt *gt, struct dentry *root); + +#endif /* DEBUGFS_ENGINES_H */ diff --git a/drivers/gpu/drm/i915/gt/debugfs_gt.c b/drivers/gpu/drm/i915/gt/debugfs_gt.c new file mode 100644 index 000000000000..75255aaacaed --- /dev/null +++ b/drivers/gpu/drm/i915/gt/debugfs_gt.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT + +/* + * Copyright © 2019 Intel Corporation + */ + +#include + +#include "debugfs_engines.h" +#include "debugfs_gt.h" +#include "debugfs_gt_pm.h" +#include "i915_drv.h" + +void debugfs_gt_register(struct intel_gt *gt) +{ + struct dentry *root; + + if (!gt->i915->drm.primary->debugfs_root) + return; + + root = debugfs_create_dir("gt", gt->i915->drm.primary->debugfs_root); + if (IS_ERR(root)) + return; + + debugfs_engines_register(gt, root); + debugfs_gt_pm_register(gt, root); +} + +void debugfs_gt_register_files(struct intel_gt *gt, + struct dentry *root, + const struct debugfs_gt_file *files, + unsigned long count) +{ + while (count--) { + if (!files->eval || files->eval(gt)) + debugfs_create_file(files->name, + 0444, root, gt, + files->fops); + + files++; + } +} diff --git a/drivers/gpu/drm/i915/gt/debugfs_gt.h b/drivers/gpu/drm/i915/gt/debugfs_gt.h new file mode 100644 index 000000000000..4ea0f06cda8f --- /dev/null +++ b/drivers/gpu/drm/i915/gt/debugfs_gt.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef DEBUGFS_GT_H +#define DEBUGFS_GT_H + +#include + +struct intel_gt; + +#define DEFINE_GT_DEBUGFS_ATTRIBUTE(__name) \ + static int __name ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private); \ +} \ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = __name ## _open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + +void debugfs_gt_register(struct intel_gt *gt); + +struct debugfs_gt_file { + const char *name; + const struct file_operations *fops; + bool (*eval)(const struct intel_gt *gt); +}; + +void debugfs_gt_register_files(struct intel_gt *gt, + struct dentry *root, + const struct debugfs_gt_file *files, + unsigned long count); + +#endif /* DEBUGFS_GT_H */ diff --git a/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c b/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c new file mode 100644 index 000000000000..059c9e5c002e --- /dev/null +++ b/drivers/gpu/drm/i915/gt/debugfs_gt_pm.c @@ -0,0 +1,601 @@ +// SPDX-License-Identifier: MIT + +/* + * Copyright © 2019 Intel Corporation + */ + +#include + +#include "debugfs_gt.h" +#include "debugfs_gt_pm.h" +#include "i915_drv.h" +#include "intel_gt.h" +#include "intel_llc.h" +#include "intel_rc6.h" +#include "intel_rps.h" +#include "intel_runtime_pm.h" +#include "intel_sideband.h" +#include "intel_uncore.h" + +static int fw_domains_show(struct seq_file *m, void *data) +{ + struct intel_gt *gt = m->private; + struct intel_uncore *uncore = gt->uncore; + struct intel_uncore_forcewake_domain *fw_domain; + unsigned int tmp; + + seq_printf(m, "user.bypass_count = %u\n", + uncore->user_forcewake_count); + + for_each_fw_domain(fw_domain, uncore, tmp) + seq_printf(m, "%s.wake_count = %u\n", + intel_uncore_forcewake_domain_to_str(fw_domain->id), + READ_ONCE(fw_domain->wake_count)); + + return 0; +} +DEFINE_GT_DEBUGFS_ATTRIBUTE(fw_domains); + +static void print_rc6_res(struct seq_file *m, + const char *title, + const i915_reg_t reg) +{ + struct intel_gt *gt = m->private; + intel_wakeref_t wakeref; + + with_intel_runtime_pm(gt->uncore->rpm, wakeref) + seq_printf(m, "%s %u (%llu us)\n", title, + intel_uncore_read(gt->uncore, reg), + intel_rc6_residency_us(>->rc6, reg)); +} + +static int vlv_drpc(struct seq_file *m) +{ + struct intel_gt *gt = m->private; + struct intel_uncore *uncore = gt->uncore; + u32 rcctl1, pw_status; + + pw_status = intel_uncore_read(uncore, VLV_GTLC_PW_STATUS); + rcctl1 = intel_uncore_read(uncore, GEN6_RC_CONTROL); + + seq_printf(m, "RC6 Enabled: %s\n", + yesno(rcctl1 & (GEN7_RC_CTL_TO_MODE | + GEN6_RC_CTL_EI_MODE(1)))); + seq_printf(m, "Render Power Well: %s\n", + (pw_status & VLV_GTLC_PW_RENDER_STATUS_MASK) ? "Up" : "Down"); + seq_printf(m, "Media Power Well: %s\n", + (pw_status & VLV_GTLC_PW_MEDIA_STATUS_MASK) ? "Up" : "Down"); + + print_rc6_res(m, "Render RC6 residency since boot:", VLV_GT_RENDER_RC6); + print_rc6_res(m, "Media RC6 residency since boot:", VLV_GT_MEDIA_RC6); + + return fw_domains_show(m, NULL); +} + +static int gen6_drpc(struct seq_file *m) +{ + struct intel_gt *gt = m->private; + struct drm_i915_private *i915 = gt->i915; + struct intel_uncore *uncore = gt->uncore; + u32 gt_core_status, rcctl1, rc6vids = 0; + u32 gen9_powergate_enable = 0, gen9_powergate_status = 0; + + gt_core_status = intel_uncore_read_fw(uncore, GEN6_GT_CORE_STATUS); + + rcctl1 = intel_uncore_read(uncore, GEN6_RC_CONTROL); + if (INTEL_GEN(i915) >= 9) { + gen9_powergate_enable = + intel_uncore_read(uncore, GEN9_PG_ENABLE); + gen9_powergate_status = + intel_uncore_read(uncore, GEN9_PWRGT_DOMAIN_STATUS); + } + + if (INTEL_GEN(i915) <= 7) + sandybridge_pcode_read(i915, GEN6_PCODE_READ_RC6VIDS, + &rc6vids, NULL); + + seq_printf(m, "RC1e Enabled: %s\n", + yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); + seq_printf(m, "RC6 Enabled: %s\n", + yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE)); + if (INTEL_GEN(i915) >= 9) { + seq_printf(m, "Render Well Gating Enabled: %s\n", + yesno(gen9_powergate_enable & GEN9_RENDER_PG_ENABLE)); + seq_printf(m, "Media Well Gating Enabled: %s\n", + yesno(gen9_powergate_enable & GEN9_MEDIA_PG_ENABLE)); + } + seq_printf(m, "Deep RC6 Enabled: %s\n", + yesno(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE)); + seq_printf(m, "Deepest RC6 Enabled: %s\n", + yesno(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE)); + seq_puts(m, "Current RC state: "); + switch (gt_core_status & GEN6_RCn_MASK) { + case GEN6_RC0: + if (gt_core_status & GEN6_CORE_CPD_STATE_MASK) + seq_puts(m, "Core Power Down\n"); + else + seq_puts(m, "on\n"); + break; + case GEN6_RC3: + seq_puts(m, "RC3\n"); + break; + case GEN6_RC6: + seq_puts(m, "RC6\n"); + break; + case GEN6_RC7: + seq_puts(m, "RC7\n"); + break; + default: + seq_puts(m, "Unknown\n"); + break; + } + + seq_printf(m, "Core Power Down: %s\n", + yesno(gt_core_status & GEN6_CORE_CPD_STATE_MASK)); + if (INTEL_GEN(i915) >= 9) { + seq_printf(m, "Render Power Well: %s\n", + (gen9_powergate_status & + GEN9_PWRGT_RENDER_STATUS_MASK) ? "Up" : "Down"); + seq_printf(m, "Media Power Well: %s\n", + (gen9_powergate_status & + GEN9_PWRGT_MEDIA_STATUS_MASK) ? "Up" : "Down"); + } + + /* Not exactly sure what this is */ + print_rc6_res(m, "RC6 \"Locked to RPn\" residency since boot:", + GEN6_GT_GFX_RC6_LOCKED); + print_rc6_res(m, "RC6 residency since boot:", GEN6_GT_GFX_RC6); + print_rc6_res(m, "RC6+ residency since boot:", GEN6_GT_GFX_RC6p); + print_rc6_res(m, "RC6++ residency since boot:", GEN6_GT_GFX_RC6pp); + + if (INTEL_GEN(i915) <= 7) { + seq_printf(m, "RC6 voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 0) & 0xff))); + seq_printf(m, "RC6+ voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 8) & 0xff))); + seq_printf(m, "RC6++ voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 16) & 0xff))); + } + + return fw_domains_show(m, NULL); +} + +static int ilk_drpc(struct seq_file *m) +{ + struct intel_gt *gt = m->private; + struct intel_uncore *uncore = gt->uncore; + u32 rgvmodectl, rstdbyctl; + u16 crstandvid; + + rgvmodectl = intel_uncore_read(uncore, MEMMODECTL); + rstdbyctl = intel_uncore_read(uncore, RSTDBYCTL); + crstandvid = intel_uncore_read16(uncore, CRSTANDVID); + + seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN)); + seq_printf(m, "Boost freq: %d\n", + (rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >> + MEMMODE_BOOST_FREQ_SHIFT); + seq_printf(m, "HW control enabled: %s\n", + yesno(rgvmodectl & MEMMODE_HWIDLE_EN)); + seq_printf(m, "SW control enabled: %s\n", + yesno(rgvmodectl & MEMMODE_SWMODE_EN)); + seq_printf(m, "Gated voltage change: %s\n", + yesno(rgvmodectl & MEMMODE_RCLK_GATE)); + seq_printf(m, "Starting frequency: P%d\n", + (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT); + seq_printf(m, "Max P-state: P%d\n", + (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT); + seq_printf(m, "Min P-state: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK)); + seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f)); + seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f)); + seq_printf(m, "Render standby enabled: %s\n", + yesno(!(rstdbyctl & RCX_SW_EXIT))); + seq_puts(m, "Current RS state: "); + switch (rstdbyctl & RSX_STATUS_MASK) { + case RSX_STATUS_ON: + seq_puts(m, "on\n"); + break; + case RSX_STATUS_RC1: + seq_puts(m, "RC1\n"); + break; + case RSX_STATUS_RC1E: + seq_puts(m, "RC1E\n"); + break; + case RSX_STATUS_RS1: + seq_puts(m, "RS1\n"); + break; + case RSX_STATUS_RS2: + seq_puts(m, "RS2 (RC6)\n"); + break; + case RSX_STATUS_RS3: + seq_puts(m, "RC3 (RC6+)\n"); + break; + default: + seq_puts(m, "unknown\n"); + break; + } + + return 0; +} + +static int drpc_show(struct seq_file *m, void *unused) +{ + struct intel_gt *gt = m->private; + struct drm_i915_private *i915 = gt->i915; + intel_wakeref_t wakeref; + int err = -ENODEV; + + with_intel_runtime_pm(gt->uncore->rpm, wakeref) { + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + err = vlv_drpc(m); + else if (INTEL_GEN(i915) >= 6) + err = gen6_drpc(m); + else + err = ilk_drpc(m); + } + + return err; +} +DEFINE_GT_DEBUGFS_ATTRIBUTE(drpc); + +static int frequency_show(struct seq_file *m, void *unused) +{ + struct intel_gt *gt = m->private; + struct drm_i915_private *i915 = gt->i915; + struct intel_uncore *uncore = gt->uncore; + struct intel_rps *rps = >->rps; + intel_wakeref_t wakeref; + + wakeref = intel_runtime_pm_get(uncore->rpm); + + if (IS_GEN(i915, 5)) { + u16 rgvswctl = intel_uncore_read16(uncore, MEMSWCTL); + u16 rgvstat = intel_uncore_read16(uncore, MEMSTAT_ILK); + + seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf); + seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f); + seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >> + MEMSTAT_VID_SHIFT); + seq_printf(m, "Current P-state: %d\n", + (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); + } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + u32 rpmodectl, freq_sts; + + rpmodectl = intel_uncore_read(uncore, GEN6_RP_CONTROL); + seq_printf(m, "Video Turbo Mode: %s\n", + yesno(rpmodectl & GEN6_RP_MEDIA_TURBO)); + seq_printf(m, "HW control enabled: %s\n", + yesno(rpmodectl & GEN6_RP_ENABLE)); + seq_printf(m, "SW control enabled: %s\n", + yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == + GEN6_RP_MEDIA_SW_MODE)); + + vlv_punit_get(i915); + freq_sts = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + vlv_punit_put(i915); + + seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); + seq_printf(m, "DDR freq: %d MHz\n", i915->mem_freq); + + seq_printf(m, "actual GPU freq: %d MHz\n", + intel_gpu_freq(rps, (freq_sts >> 8) & 0xff)); + + seq_printf(m, "current GPU freq: %d MHz\n", + intel_gpu_freq(rps, rps->cur_freq)); + + seq_printf(m, "max GPU freq: %d MHz\n", + intel_gpu_freq(rps, rps->max_freq)); + + seq_printf(m, "min GPU freq: %d MHz\n", + intel_gpu_freq(rps, rps->min_freq)); + + seq_printf(m, "idle GPU freq: %d MHz\n", + intel_gpu_freq(rps, rps->idle_freq)); + + seq_printf(m, "efficient (RPe) frequency: %d MHz\n", + intel_gpu_freq(rps, rps->efficient_freq)); + } else if (INTEL_GEN(i915) >= 6) { + u32 rp_state_limits; + u32 gt_perf_status; + u32 rp_state_cap; + u32 rpmodectl, rpinclimit, rpdeclimit; + u32 rpstat, cagf, reqf; + u32 rpupei, rpcurup, rpprevup; + u32 rpdownei, rpcurdown, rpprevdown; + u32 pm_ier, pm_imr, pm_isr, pm_iir, pm_mask; + int max_freq; + + rp_state_limits = intel_uncore_read(uncore, GEN6_RP_STATE_LIMITS); + if (IS_GEN9_LP(i915)) { + rp_state_cap = intel_uncore_read(uncore, BXT_RP_STATE_CAP); + gt_perf_status = intel_uncore_read(uncore, BXT_GT_PERF_STATUS); + } else { + rp_state_cap = intel_uncore_read(uncore, GEN6_RP_STATE_CAP); + gt_perf_status = intel_uncore_read(uncore, GEN6_GT_PERF_STATUS); + } + + /* RPSTAT1 is in the GT power well */ + intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); + + reqf = intel_uncore_read(uncore, GEN6_RPNSWREQ); + if (INTEL_GEN(i915) >= 9) { + reqf >>= 23; + } else { + reqf &= ~GEN6_TURBO_DISABLE; + if (IS_HASWELL(i915) || IS_BROADWELL(i915)) + reqf >>= 24; + else + reqf >>= 25; + } + reqf = intel_gpu_freq(rps, reqf); + + rpmodectl = intel_uncore_read(uncore, GEN6_RP_CONTROL); + rpinclimit = intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD); + rpdeclimit = intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD); + + rpstat = intel_uncore_read(uncore, GEN6_RPSTAT1); + rpupei = intel_uncore_read(uncore, GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK; + rpcurup = intel_uncore_read(uncore, GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK; + rpprevup = intel_uncore_read(uncore, GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK; + rpdownei = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK; + rpcurdown = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK; + rpprevdown = intel_uncore_read(uncore, GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK; + cagf = intel_rps_read_actual_frequency(rps); + + intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL); + + if (INTEL_GEN(i915) >= 11) { + pm_ier = intel_uncore_read(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE); + pm_imr = intel_uncore_read(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK); + /* + * The equivalent to the PM ISR & IIR cannot be read + * without affecting the current state of the system + */ + pm_isr = 0; + pm_iir = 0; + } else if (INTEL_GEN(i915) >= 8) { + pm_ier = intel_uncore_read(uncore, GEN8_GT_IER(2)); + pm_imr = intel_uncore_read(uncore, GEN8_GT_IMR(2)); + pm_isr = intel_uncore_read(uncore, GEN8_GT_ISR(2)); + pm_iir = intel_uncore_read(uncore, GEN8_GT_IIR(2)); + } else { + pm_ier = intel_uncore_read(uncore, GEN6_PMIER); + pm_imr = intel_uncore_read(uncore, GEN6_PMIMR); + pm_isr = intel_uncore_read(uncore, GEN6_PMISR); + pm_iir = intel_uncore_read(uncore, GEN6_PMIIR); + } + pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK); + + seq_printf(m, "Video Turbo Mode: %s\n", + yesno(rpmodectl & GEN6_RP_MEDIA_TURBO)); + seq_printf(m, "HW control enabled: %s\n", + yesno(rpmodectl & GEN6_RP_ENABLE)); + seq_printf(m, "SW control enabled: %s\n", + yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == + GEN6_RP_MEDIA_SW_MODE)); + + seq_printf(m, "PM IER=0x%08x IMR=0x%08x, MASK=0x%08x\n", + pm_ier, pm_imr, pm_mask); + if (INTEL_GEN(i915) <= 10) + seq_printf(m, "PM ISR=0x%08x IIR=0x%08x\n", + pm_isr, pm_iir); + seq_printf(m, "pm_intrmsk_mbz: 0x%08x\n", + rps->pm_intrmsk_mbz); + seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); + seq_printf(m, "Render p-state ratio: %d\n", + (gt_perf_status & (INTEL_GEN(i915) >= 9 ? 0x1ff00 : 0xff00)) >> 8); + seq_printf(m, "Render p-state VID: %d\n", + gt_perf_status & 0xff); + seq_printf(m, "Render p-state limit: %d\n", + rp_state_limits & 0xff); + seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat); + seq_printf(m, "RPMODECTL: 0x%08x\n", rpmodectl); + seq_printf(m, "RPINCLIMIT: 0x%08x\n", rpinclimit); + seq_printf(m, "RPDECLIMIT: 0x%08x\n", rpdeclimit); + seq_printf(m, "RPNSWREQ: %dMHz\n", reqf); + seq_printf(m, "CAGF: %dMHz\n", cagf); + seq_printf(m, "RP CUR UP EI: %d (%dus)\n", + rpupei, GT_PM_INTERVAL_TO_US(i915, rpupei)); + seq_printf(m, "RP CUR UP: %d (%dus)\n", + rpcurup, GT_PM_INTERVAL_TO_US(i915, rpcurup)); + seq_printf(m, "RP PREV UP: %d (%dus)\n", + rpprevup, GT_PM_INTERVAL_TO_US(i915, rpprevup)); + seq_printf(m, "Up threshold: %d%%\n", + rps->power.up_threshold); + + seq_printf(m, "RP CUR DOWN EI: %d (%dus)\n", + rpdownei, GT_PM_INTERVAL_TO_US(i915, rpdownei)); + seq_printf(m, "RP CUR DOWN: %d (%dus)\n", + rpcurdown, GT_PM_INTERVAL_TO_US(i915, rpcurdown)); + seq_printf(m, "RP PREV DOWN: %d (%dus)\n", + rpprevdown, GT_PM_INTERVAL_TO_US(i915, rpprevdown)); + seq_printf(m, "Down threshold: %d%%\n", + rps->power.down_threshold); + + max_freq = (IS_GEN9_LP(i915) ? rp_state_cap >> 0 : + rp_state_cap >> 16) & 0xff; + max_freq *= (IS_GEN9_BC(i915) || + INTEL_GEN(i915) >= 10 ? GEN9_FREQ_SCALER : 1); + seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", + intel_gpu_freq(rps, max_freq)); + + max_freq = (rp_state_cap & 0xff00) >> 8; + max_freq *= (IS_GEN9_BC(i915) || + INTEL_GEN(i915) >= 10 ? GEN9_FREQ_SCALER : 1); + seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", + intel_gpu_freq(rps, max_freq)); + + max_freq = (IS_GEN9_LP(i915) ? rp_state_cap >> 16 : + rp_state_cap >> 0) & 0xff; + max_freq *= (IS_GEN9_BC(i915) || + INTEL_GEN(i915) >= 10 ? GEN9_FREQ_SCALER : 1); + seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", + intel_gpu_freq(rps, max_freq)); + seq_printf(m, "Max overclocked frequency: %dMHz\n", + intel_gpu_freq(rps, rps->max_freq)); + + seq_printf(m, "Current freq: %d MHz\n", + intel_gpu_freq(rps, rps->cur_freq)); + seq_printf(m, "Actual freq: %d MHz\n", cagf); + seq_printf(m, "Idle freq: %d MHz\n", + intel_gpu_freq(rps, rps->idle_freq)); + seq_printf(m, "Min freq: %d MHz\n", + intel_gpu_freq(rps, rps->min_freq)); + seq_printf(m, "Boost freq: %d MHz\n", + intel_gpu_freq(rps, rps->boost_freq)); + seq_printf(m, "Max freq: %d MHz\n", + intel_gpu_freq(rps, rps->max_freq)); + seq_printf(m, + "efficient (RPe) frequency: %d MHz\n", + intel_gpu_freq(rps, rps->efficient_freq)); + } else { + seq_puts(m, "no P-state info available\n"); + } + + seq_printf(m, "Current CD clock frequency: %d kHz\n", i915->cdclk.hw.cdclk); + seq_printf(m, "Max CD clock frequency: %d kHz\n", i915->max_cdclk_freq); + seq_printf(m, "Max pixel clock frequency: %d kHz\n", i915->max_dotclk_freq); + + intel_runtime_pm_put(uncore->rpm, wakeref); + + return 0; +} +DEFINE_GT_DEBUGFS_ATTRIBUTE(frequency); + +static int llc_show(struct seq_file *m, void *data) +{ + struct intel_gt *gt = m->private; + struct drm_i915_private *i915 = gt->i915; + const bool edram = INTEL_GEN(i915) > 8; + struct intel_rps *rps = >->rps; + unsigned int max_gpu_freq, min_gpu_freq; + intel_wakeref_t wakeref; + int gpu_freq, ia_freq; + + seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(i915))); + seq_printf(m, "%s: %uMB\n", edram ? "eDRAM" : "eLLC", + i915->edram_size_mb); + + min_gpu_freq = rps->min_freq; + max_gpu_freq = rps->max_freq; + if (IS_GEN9_BC(i915) || INTEL_GEN(i915) >= 10) { + /* Convert GT frequency to 50 HZ units */ + min_gpu_freq /= GEN9_FREQ_SCALER; + max_gpu_freq /= GEN9_FREQ_SCALER; + } + + seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n"); + + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + for (gpu_freq = min_gpu_freq; gpu_freq <= max_gpu_freq; gpu_freq++) { + ia_freq = gpu_freq; + sandybridge_pcode_read(i915, + GEN6_PCODE_READ_MIN_FREQ_TABLE, + &ia_freq, NULL); + seq_printf(m, "%d\t\t%d\t\t\t\t%d\n", + intel_gpu_freq(rps, + (gpu_freq * + (IS_GEN9_BC(i915) || + INTEL_GEN(i915) >= 10 ? + GEN9_FREQ_SCALER : 1))), + ((ia_freq >> 0) & 0xff) * 100, + ((ia_freq >> 8) & 0xff) * 100); + } + intel_runtime_pm_put(gt->uncore->rpm, wakeref); + + return 0; +} + +static bool llc_eval(const struct intel_gt *gt) +{ + return HAS_LLC(gt->i915); +} + +DEFINE_GT_DEBUGFS_ATTRIBUTE(llc); + +static const char *rps_power_to_str(unsigned int power) +{ + static const char * const strings[] = { + [LOW_POWER] = "low power", + [BETWEEN] = "mixed", + [HIGH_POWER] = "high power", + }; + + if (power >= ARRAY_SIZE(strings) || !strings[power]) + return "unknown"; + + return strings[power]; +} + +static int rps_boost_show(struct seq_file *m, void *data) +{ + struct intel_gt *gt = m->private; + struct drm_i915_private *i915 = gt->i915; + struct intel_rps *rps = >->rps; + + seq_printf(m, "RPS enabled? %d\n", rps->enabled); + seq_printf(m, "GPU busy? %s\n", yesno(gt->awake)); + seq_printf(m, "Boosts outstanding? %d\n", + atomic_read(&rps->num_waiters)); + seq_printf(m, "Interactive? %d\n", READ_ONCE(rps->power.interactive)); + seq_printf(m, "Frequency requested %d, actual %d\n", + intel_gpu_freq(rps, rps->cur_freq), + intel_rps_read_actual_frequency(rps)); + seq_printf(m, " min hard:%d, soft:%d; max soft:%d, hard:%d\n", + intel_gpu_freq(rps, rps->min_freq), + intel_gpu_freq(rps, rps->min_freq_softlimit), + intel_gpu_freq(rps, rps->max_freq_softlimit), + intel_gpu_freq(rps, rps->max_freq)); + seq_printf(m, " idle:%d, efficient:%d, boost:%d\n", + intel_gpu_freq(rps, rps->idle_freq), + intel_gpu_freq(rps, rps->efficient_freq), + intel_gpu_freq(rps, rps->boost_freq)); + + seq_printf(m, "Wait boosts: %d\n", atomic_read(&rps->boosts)); + + if (INTEL_GEN(i915) >= 6 && rps->enabled && gt->awake) { + struct intel_uncore *uncore = gt->uncore; + u32 rpup, rpupei; + u32 rpdown, rpdownei; + + intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); + rpup = intel_uncore_read_fw(uncore, GEN6_RP_CUR_UP) & GEN6_RP_EI_MASK; + rpupei = intel_uncore_read_fw(uncore, GEN6_RP_CUR_UP_EI) & GEN6_RP_EI_MASK; + rpdown = intel_uncore_read_fw(uncore, GEN6_RP_CUR_DOWN) & GEN6_RP_EI_MASK; + rpdownei = intel_uncore_read_fw(uncore, GEN6_RP_CUR_DOWN_EI) & GEN6_RP_EI_MASK; + intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL); + + seq_printf(m, "\nRPS Autotuning (current \"%s\" window):\n", + rps_power_to_str(rps->power.mode)); + seq_printf(m, " Avg. up: %d%% [above threshold? %d%%]\n", + rpup && rpupei ? 100 * rpup / rpupei : 0, + rps->power.up_threshold); + seq_printf(m, " Avg. down: %d%% [below threshold? %d%%]\n", + rpdown && rpdownei ? 100 * rpdown / rpdownei : 0, + rps->power.down_threshold); + } else { + seq_puts(m, "\nRPS Autotuning inactive\n"); + } + + return 0; +} + +static bool rps_eval(const struct intel_gt *gt) +{ + return HAS_RPS(gt->i915); +} + +DEFINE_GT_DEBUGFS_ATTRIBUTE(rps_boost); + +void debugfs_gt_pm_register(struct intel_gt *gt, struct dentry *root) +{ + static const struct debugfs_gt_file files[] = { + { "drpc", &drpc_fops, NULL }, + { "frequency", &frequency_fops, NULL }, + { "forcewake", &fw_domains_fops, NULL }, + { "llc", &llc_fops, llc_eval }, + { "rps_boost", &rps_boost_fops, rps_eval }, + }; + + debugfs_gt_register_files(gt, root, files, ARRAY_SIZE(files)); +} diff --git a/drivers/gpu/drm/i915/gt/debugfs_gt_pm.h b/drivers/gpu/drm/i915/gt/debugfs_gt_pm.h new file mode 100644 index 000000000000..4cf5f5c9da7d --- /dev/null +++ b/drivers/gpu/drm/i915/gt/debugfs_gt_pm.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef DEBUGFS_GT_PM_H +#define DEBUGFS_GT_PM_H + +struct intel_gt; +struct dentry; + +void debugfs_gt_pm_register(struct intel_gt *gt, struct dentry *root); + +#endif /* DEBUGFS_GT_PM_H */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 172102a6c5fb..ec84b5e62fef 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -3,6 +3,7 @@ * Copyright © 2019 Intel Corporation */ +#include "debugfs_gt.h" #include "i915_drv.h" #include "intel_context.h" #include "intel_gt.h" @@ -325,6 +326,8 @@ void intel_gt_chipset_flush(struct intel_gt *gt) void intel_gt_driver_register(struct intel_gt *gt) { intel_rps_driver_register(>->rps); + + debugfs_gt_register(gt); } static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size) -- cgit v1.2.3 From f7fd23735f926f0161d03c5d1013626ff92c70a0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 19 Dec 2019 15:38:45 +0200 Subject: drm/i915: fix comment for POWER_DOMAIN_TRANSCODER_VDSC_PW2 The power domain covers VDSC for DSI transcoder on ICL, and it's pedantically about pipe, not transcoder, on TGL. Reported-by: Vandita Kulkarni Cc: Vandita Kulkarni Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191219133845.9333-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index 1da04f3e0fb3..2608a65af7fa 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -28,7 +28,7 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_D, POWER_DOMAIN_TRANSCODER_EDP, - /* VDSC/joining for TRANSCODER_EDP (ICL) or TRANSCODER_A (TGL) */ + /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */ POWER_DOMAIN_TRANSCODER_VDSC_PW2, POWER_DOMAIN_TRANSCODER_DSI_A, POWER_DOMAIN_TRANSCODER_DSI_C, -- cgit v1.2.3 From a6458951750fb43b8fdd3a06aaedff12f9df5e1a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 19 Dec 2019 17:56:50 +0200 Subject: drm/i915/selftests: make mock_context.h self-contained Fix the forward declaration. Cc: Chris Wilson Cc: Masahiro Yamada Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191219155652.2666-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/gem/selftests/mock_context.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.h b/drivers/gpu/drm/i915/gem/selftests/mock_context.h index c858db2362f1..fb83d2f09212 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.h +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.h @@ -7,7 +7,7 @@ #ifndef __MOCK_CONTEXT_H #define __MOCK_CONTEXT_H -struct drm_file; +struct file; struct drm_i915_private; void mock_init_contexts(struct drm_i915_private *i915); -- cgit v1.2.3 From 3531c4023cb5ba6adb38f6904201dc2bca8bb686 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 19 Dec 2019 17:56:51 +0200 Subject: drm/i915/selftests: make mock_drm.h self-contained Needs i915_drv.h because i915 gets dereferenced. Cc: Chris Wilson Cc: Masahiro Yamada Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191219155652.2666-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/selftests/mock_drm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/selftests/mock_drm.h b/drivers/gpu/drm/i915/selftests/mock_drm.h index d7f49e149f0c..9916b6f95526 100644 --- a/drivers/gpu/drm/i915/selftests/mock_drm.h +++ b/drivers/gpu/drm/i915/selftests/mock_drm.h @@ -27,7 +27,8 @@ #include -struct drm_i915_private; +#include "i915_drv.h" + struct drm_file; struct file; -- cgit v1.2.3 From 021a411684c808aa4e5c9fa7103c704d5f381a8b Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Sat, 21 Dec 2019 14:05:34 +0200 Subject: drm/i915: Use intel_tile_height() instead of re-implementing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_tile_dims() computes tile height using size and width, when there is already a function to do just that - intel_tile_height() Cc: Ville Syrjälä Cc: Matt Roper Cc: Mika Kahola Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 06e799db0211..99c8761e230b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1998,7 +1998,7 @@ static void intel_tile_dims(const struct drm_framebuffer *fb, int color_plane, unsigned int cpp = fb->format->cpp[color_plane]; *tile_width = tile_width_bytes / cpp; - *tile_height = intel_tile_size(to_i915(fb->dev)) / tile_width_bytes; + *tile_height = intel_tile_height(fb, color_plane); } unsigned int -- cgit v1.2.3 From 86f236bbbd880edb6e7224d121134378a8ef770e Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Sat, 21 Dec 2019 14:05:35 +0200 Subject: drm/i915: Move CCS stride alignment W/A inside intel_fb_stride_alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Easier to read if all the alignment changes are in one place and contained within a function. Cc: Ville Syrjälä Cc: Matt Roper Cc: Mika Kahola Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 31 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 99c8761e230b..5492946c0d2e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2590,7 +2590,22 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) else return 64; } else { - return intel_tile_width_bytes(fb, color_plane); + u32 tile_width = intel_tile_width_bytes(fb, color_plane); + + /* + * Display WA #0531: skl,bxt,kbl,glk + * + * Render decompression and plane width > 3840 + * combined with horizontal panning requires the + * plane stride to be a multiple of 4. We'll just + * require the entire fb to accommodate that to avoid + * potential runtime errors at plane configuration time. + */ + if (IS_GEN(dev_priv, 9) && is_ccs_modifier(fb->modifier) && + color_plane == 0 && fb->width > 3840) + tile_width *= 4; + + return tile_width; } } @@ -16346,20 +16361,6 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, } stride_alignment = intel_fb_stride_alignment(fb, i); - - /* - * Display WA #0531: skl,bxt,kbl,glk - * - * Render decompression and plane width > 3840 - * combined with horizontal panning requires the - * plane stride to be a multiple of 4. We'll just - * require the entire fb to accommodate that to avoid - * potential runtime errors at plane configuration time. - */ - if (IS_GEN(dev_priv, 9) && i == 0 && fb->width > 3840 && - is_ccs_modifier(fb->modifier)) - stride_alignment *= 4; - if (fb->pitches[i] & (stride_alignment - 1)) { DRM_DEBUG_KMS("plane %d pitch (%d) must be at least %u byte aligned\n", i, fb->pitches[i], stride_alignment); -- cgit v1.2.3 From 13f2cb9a280054c9c95c694a8837fd0828b03853 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Sat, 21 Dec 2019 14:05:36 +0200 Subject: drm/i915: Extract framebufer CCS offset checks into a function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_fill_fb_info() has grown quite large and wrapping the offset checks into a separate function makes the loop a bit easier to follow. v2: Skip the check for non-CCS planes. (Mika) Cc: Ville Syrjälä Cc: Matt Roper Cc: Mika Kahola Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-4-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 73 ++++++++++++++++------------ 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5492946c0d2e..e7903587e439 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2677,6 +2677,46 @@ static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state) return stride > max_stride; } +static int +intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int ccs_plane, int x, int y) +{ + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + int hsub = fb->format->hsub; + int vsub = fb->format->vsub; + int tile_width, tile_height; + int ccs_x, ccs_y; + int main_x, main_y; + + if (!is_ccs_modifier(fb->modifier) || ccs_plane != 1) + return 0; + + intel_tile_dims(fb, 1, &tile_width, &tile_height); + + tile_width *= hsub; + tile_height *= vsub; + + ccs_x = (x * hsub) % tile_width; + ccs_y = (y * vsub) % tile_height; + main_x = intel_fb->normal[0].x % tile_width; + main_y = intel_fb->normal[0].y % tile_height; + + /* + * CCS doesn't have its own x/y offset register, so the intra CCS tile + * x/y offsets must match between CCS and the main surface. + */ + if (main_x != ccs_x || main_y != ccs_y) { + DRM_DEBUG_KMS("Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n", + main_x, main_y, + ccs_x, ccs_y, + intel_fb->normal[0].x, + intel_fb->normal[0].y, + x, y); + return -EINVAL; + } + + return 0; +} + static int intel_fill_fb_info(struct drm_i915_private *dev_priv, struct drm_framebuffer *fb) @@ -2707,36 +2747,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, return ret; } - if (is_ccs_modifier(fb->modifier) && i == 1) { - int hsub = fb->format->hsub; - int vsub = fb->format->vsub; - int tile_width, tile_height; - int main_x, main_y; - int ccs_x, ccs_y; - - intel_tile_dims(fb, i, &tile_width, &tile_height); - tile_width *= hsub; - tile_height *= vsub; - - ccs_x = (x * hsub) % tile_width; - ccs_y = (y * vsub) % tile_height; - main_x = intel_fb->normal[0].x % tile_width; - main_y = intel_fb->normal[0].y % tile_height; - - /* - * CCS doesn't have its own x/y offset register, so the intra CCS tile - * x/y offsets must match between CCS and the main surface. - */ - if (main_x != ccs_x || main_y != ccs_y) { - DRM_DEBUG_KMS("Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n", - main_x, main_y, - ccs_x, ccs_y, - intel_fb->normal[0].x, - intel_fb->normal[0].y, - x, y); - return -EINVAL; - } - } + ret = intel_fb_check_ccs_xy(fb, i, x, y); + if (ret) + return ret; /* * The fence (if used) is aligned to the start of the object -- cgit v1.2.3 From e7af9094579474912ac7ea2d2f2434c4df2fd5e6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Sat, 21 Dec 2019 14:05:37 +0200 Subject: drm/i915: Add helpers to select correct ccs/aux planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using helpers instead of open coding this to select a CCS plane for a main plane makes the code cleaner and less error-prone when the location of CCS plane can be different based on the format (packed vs. YUV semiplanar). The same applies to selecting an AUX plane which can be a UV plane (for an uncompressed YUV semiplanar format), or a CCS plane. Cc: Dhinakaran Pandiyan Cc: Ville Syrjälä Cc: Mika Kahola Cc: Matt Roper Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-5-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 71 ++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e7903587e439..873fdbbeaa30 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1934,6 +1934,40 @@ static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv) return IS_GEN(dev_priv, 2) ? 2048 : 4096; } +static bool is_ccs_plane(const struct drm_framebuffer *fb, int plane) +{ + if (!is_ccs_modifier(fb->modifier)) + return false; + + return plane >= fb->format->num_planes / 2; +} + +static bool is_aux_plane(const struct drm_framebuffer *fb, int plane) +{ + if (is_ccs_modifier(fb->modifier)) + return is_ccs_plane(fb, plane); + + return plane == 1; +} + +static int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane) +{ + WARN_ON(!is_ccs_modifier(fb->modifier) || + (main_plane && main_plane >= fb->format->num_planes / 2)); + + return fb->format->num_planes / 2 + main_plane; +} + +/* Return either the main plane's CCS or - if not a CCS FB - UV plane */ +static int +intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane) +{ + if (is_ccs_modifier(fb->modifier)) + return main_to_ccs_plane(fb, main_plane); + + return 1; +} + static unsigned int intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) { @@ -1949,7 +1983,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) else return 512; case I915_FORMAT_MOD_Y_TILED_CCS: - if (color_plane == 1) + if (is_ccs_plane(fb, color_plane)) return 128; /* fall through */ case I915_FORMAT_MOD_Y_TILED: @@ -1958,7 +1992,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) else return 512; case I915_FORMAT_MOD_Yf_TILED_CCS: - if (color_plane == 1) + if (is_ccs_plane(fb, color_plane)) return 128; /* fall through */ case I915_FORMAT_MOD_Yf_TILED: @@ -2075,7 +2109,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, struct drm_i915_private *dev_priv = to_i915(fb->dev); /* AUX_DIST needs only 4K alignment */ - if (color_plane == 1) + if (is_aux_plane(fb, color_plane)) return 4096; switch (fb->modifier) { @@ -3461,10 +3495,11 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state const struct drm_framebuffer *fb = plane_state->hw.fb; int hsub = fb->format->hsub; int vsub = fb->format->vsub; - int aux_x = plane_state->color_plane[1].x; - int aux_y = plane_state->color_plane[1].y; - u32 aux_offset = plane_state->color_plane[1].offset; - u32 alignment = intel_surf_alignment(fb, 1); + int ccs_plane = main_to_ccs_plane(fb, 0); + int aux_x = plane_state->color_plane[ccs_plane].x; + int aux_y = plane_state->color_plane[ccs_plane].y; + u32 aux_offset = plane_state->color_plane[ccs_plane].offset; + u32 alignment = intel_surf_alignment(fb, ccs_plane); while (aux_offset >= main_offset && aux_y <= main_y) { int x, y; @@ -3477,8 +3512,12 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state x = aux_x / hsub; y = aux_y / vsub; - aux_offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 1, - aux_offset, aux_offset - alignment); + aux_offset = intel_plane_adjust_aligned_offset(&x, &y, + plane_state, + ccs_plane, + aux_offset, + aux_offset - + alignment); aux_x = x * hsub + aux_x % hsub; aux_y = y * vsub + aux_y % vsub; } @@ -3486,9 +3525,9 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state if (aux_x != main_x || aux_y != main_y) return false; - plane_state->color_plane[1].offset = aux_offset; - plane_state->color_plane[1].x = aux_x; - plane_state->color_plane[1].y = aux_y; + plane_state->color_plane[ccs_plane].offset = aux_offset; + plane_state->color_plane[ccs_plane].x = aux_x; + plane_state->color_plane[ccs_plane].y = aux_y; return true; } @@ -3504,7 +3543,10 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) int h = drm_rect_height(&plane_state->uapi.src) >> 16; int max_width; int max_height; - u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset; + u32 alignment; + u32 offset; + int aux_plane = intel_main_to_aux_plane(fb, 0); + u32 aux_offset = plane_state->color_plane[aux_plane].offset; if (INTEL_GEN(dev_priv) >= 11) max_width = icl_max_plane_width(fb, 0, rotation); @@ -3570,7 +3612,8 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) offset, offset - alignment); } - if (x != plane_state->color_plane[1].x || y != plane_state->color_plane[1].y) { + if (x != plane_state->color_plane[aux_plane].x || + y != plane_state->color_plane[aux_plane].y) { DRM_DEBUG_KMS("Unable to find suitable display surface offset due to CCS\n"); return -EINVAL; } -- cgit v1.2.3 From 55656505dc55481d862b7ff81aba69a002e39159 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Sat, 21 Dec 2019 14:05:38 +0200 Subject: drm/framebuffer: Format modifier for Intel Gen-12 render compression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gen-12 has a new compression format, add a new modifier to indicate that. Cc: Ville Syrjälä Cc: Matt Roper Cc: Nanley G Chery Cc: Jason Ekstrand Cc: Mika Kahola Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Lucas De Marchi Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-6-imre.deak@intel.com --- include/uapi/drm/drm_fourcc.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 8caaaf7ff91b..5ba481f49931 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -410,6 +410,17 @@ extern "C" { #define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4) #define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5) +/* + * Intel color control surfaces (CCS) for Gen-12 render compression. + * + * The main surface is Y-tiled and at plane index 0, the CCS is linear and + * at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in + * main surface. In other words, 4 bits in CCS map to a main surface cache + * line pair. The main surface pitch is required to be a multiple of four + * Y-tile widths. + */ +#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS fourcc_mod_code(INTEL, 6) + /* * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks * -- cgit v1.2.3 From b3e57bccd68a166f1a0e40e482b5645af15525b4 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Sat, 21 Dec 2019 14:05:39 +0200 Subject: drm/i915/tgl: Gen-12 render decompression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gen-12 display decompression operates on Y-tiled compressed main surface. The CCS is linear and has 4 bits of metadata for each main surface cache line pair, a size ratio of 1:256. Gen-12 display decompression is incompatible with buffers compressed by earlier GPUs, so make use of a new modifier to identify gen-12 compression. Another notable change is that render decompression is supported on all planes except cursor and on all pipes. Start by adding render decompression support for [A,X]BGR888 pixel formats. v2: Fix checkpatch warnings (Lucas) v3: Rebase, disable color clear, styling changes and modify intel_tile_width_bytes and intel_tile_height to handle linear CCS v4: - Use format block descriptors and the i915 specific func to get the subsampling for each color plane. - Use helpers to convert between CCS and main planes. v5: - Fix subsampling returned by intel_fb_plane_get_subsampling() for the CCS plane of the first plane. v6: - Rebased on v2 of patch 4. v7: - Fix plane dimensions during FB check. Cc: Ville Syrjälä Cc: Matt Roper Cc: Nanley G Chery Cc: Jason Ekstrand Cc: Radhakrishna Sripada Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Lucas De Marchi Signed-off-by: Imre Deak Reviewed-by: Radhakrishna Sripada (v6) Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-7-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 197 ++++++++++++++++++++++----- drivers/gpu/drm/i915/display/intel_sprite.c | 23 ++-- drivers/gpu/drm/i915/i915_reg.h | 1 + 3 files changed, 178 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 873fdbbeaa30..ae2858931c9d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1942,6 +1942,16 @@ static bool is_ccs_plane(const struct drm_framebuffer *fb, int plane) return plane >= fb->format->num_planes / 2; } +static bool is_gen12_ccs_modifier(u64 modifier) +{ + return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS; +} + +static bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane) +{ + return is_gen12_ccs_modifier(fb->modifier) && is_ccs_plane(fb, plane); +} + static bool is_aux_plane(const struct drm_framebuffer *fb, int plane) { if (is_ccs_modifier(fb->modifier)) @@ -1958,6 +1968,14 @@ static int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane) return fb->format->num_planes / 2 + main_plane; } +static int ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane) +{ + WARN_ON(!is_ccs_modifier(fb->modifier) || + ccs_plane < fb->format->num_planes / 2); + + return ccs_plane - fb->format->num_planes / 2; +} + /* Return either the main plane's CCS or - if not a CCS FB - UV plane */ static int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane) @@ -1986,6 +2004,10 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) if (is_ccs_plane(fb, color_plane)) return 128; /* fall through */ + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: + if (is_ccs_plane(fb, color_plane)) + return 64; + /* fall through */ case I915_FORMAT_MOD_Y_TILED: if (IS_GEN(dev_priv, 2) || HAS_128_BYTE_Y_TILING(dev_priv)) return 128; @@ -2019,6 +2041,9 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) static unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane) { + if (is_gen12_ccs_plane(fb, color_plane)) + return 1; + return intel_tile_size(to_i915(fb->dev)) / intel_tile_width_bytes(fb, color_plane); } @@ -2119,6 +2144,8 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, if (INTEL_GEN(dev_priv) >= 9) return 256 * 1024; return 0; + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: + return 16 * 1024; case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Yf_TILED_CCS: case I915_FORMAT_MOD_Y_TILED: @@ -2311,9 +2338,10 @@ static u32 intel_adjust_tile_offset(int *x, int *y, return new_offset; } -static bool is_surface_linear(u64 modifier, int color_plane) +static bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane) { - return modifier == DRM_FORMAT_MOD_LINEAR; + return fb->modifier == DRM_FORMAT_MOD_LINEAR || + is_gen12_ccs_plane(fb, color_plane); } static u32 intel_adjust_aligned_offset(int *x, int *y, @@ -2328,7 +2356,7 @@ static u32 intel_adjust_aligned_offset(int *x, int *y, WARN_ON(new_offset > old_offset); - if (!is_surface_linear(fb->modifier, color_plane)) { + if (!is_surface_linear(fb, color_plane)) { unsigned int tile_size, tile_width, tile_height; unsigned int pitch_tiles; @@ -2398,7 +2426,7 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv, if (alignment) alignment--; - if (!is_surface_linear(fb->modifier, color_plane)) { + if (!is_surface_linear(fb, color_plane)) { unsigned int tile_size, tile_width, tile_height; unsigned int tile_rows, tiles, pitch_tiles; @@ -2500,6 +2528,7 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) return I915_TILING_X; case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Y_TILED_CCS: + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: return I915_TILING_Y; default: return I915_TILING_NONE; @@ -2520,7 +2549,7 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) * us a ratio of one byte in the CCS for each 8x16 pixels in the * main surface. */ -static const struct drm_format_info ccs_formats[] = { +static const struct drm_format_info skl_ccs_formats[] = { { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, }, { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, @@ -2531,6 +2560,28 @@ static const struct drm_format_info ccs_formats[] = { .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, }, }; +/* + * Gen-12 compression uses 4 bits of CCS data for each cache line pair in the + * main surface. And each 64B CCS cache line represents an area of 4x1 Y-tiles + * in the main surface. With 4 byte pixels and each Y-tile having dimensions of + * 32x32 pixels, the ratio turns out to 1B in the CCS for every 2x32 pixels in + * the main surface. + */ +static const struct drm_format_info gen12_ccs_formats[] = { + { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, }, + { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, .has_alpha = true }, + { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2, + .char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 }, + .hsub = 1, .vsub = 1, .has_alpha = true }, +}; + static const struct drm_format_info * lookup_format_info(const struct drm_format_info formats[], int num_formats, u32 format) @@ -2551,8 +2602,12 @@ intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd) switch (cmd->modifier[0]) { case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Yf_TILED_CCS: - return lookup_format_info(ccs_formats, - ARRAY_SIZE(ccs_formats), + return lookup_format_info(skl_ccs_formats, + ARRAY_SIZE(skl_ccs_formats), + cmd->pixel_format); + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: + return lookup_format_info(gen12_ccs_formats, + ARRAY_SIZE(gen12_ccs_formats), cmd->pixel_format); default: return NULL; @@ -2561,7 +2616,8 @@ intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd) bool is_ccs_modifier(u64 modifier) { - return modifier == I915_FORMAT_MOD_Y_TILED_CCS || + return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || + modifier == I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS; } @@ -2609,8 +2665,9 @@ static u32 intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) { struct drm_i915_private *dev_priv = to_i915(fb->dev); + u32 tile_width; - if (fb->modifier == DRM_FORMAT_MOD_LINEAR) { + if (is_surface_linear(fb, color_plane)) { u32 max_stride = intel_plane_fb_max_stride(dev_priv, fb->format->format, fb->modifier); @@ -2619,13 +2676,15 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) * To make remapping with linear generally feasible * we need the stride to be page aligned. */ - if (fb->pitches[color_plane] > max_stride) + if (fb->pitches[color_plane] > max_stride && + !is_ccs_modifier(fb->modifier)) return intel_tile_size(dev_priv); else return 64; - } else { - u32 tile_width = intel_tile_width_bytes(fb, color_plane); + } + tile_width = intel_tile_width_bytes(fb, color_plane); + if (is_ccs_modifier(fb->modifier) && color_plane == 0) { /* * Display WA #0531: skl,bxt,kbl,glk * @@ -2635,12 +2694,16 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) * require the entire fb to accommodate that to avoid * potential runtime errors at plane configuration time. */ - if (IS_GEN(dev_priv, 9) && is_ccs_modifier(fb->modifier) && - color_plane == 0 && fb->width > 3840) + if (IS_GEN(dev_priv, 9) && fb->width > 3840) + tile_width *= 4; + /* + * The main surface pitch must be padded to a multiple of four + * tile widths. + */ + else if (INTEL_GEN(dev_priv) >= 12) tile_width *= 4; - - return tile_width; } + return tile_width; } bool intel_plane_can_remap(const struct intel_plane_state *plane_state) @@ -2711,28 +2774,73 @@ static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state) return stride > max_stride; } +static void +intel_fb_plane_get_subsampling(int *hsub, int *vsub, + const struct drm_framebuffer *fb, + int color_plane) +{ + int main_plane; + + if (color_plane == 0) { + *hsub = 1; + *vsub = 1; + + return; + } + + /* + * TODO: Deduct the subsampling from the char block for all CCS + * formats and planes. + */ + if (!is_gen12_ccs_plane(fb, color_plane)) { + *hsub = fb->format->hsub; + *vsub = fb->format->vsub; + + return; + } + + main_plane = ccs_to_main_plane(fb, color_plane); + *hsub = drm_format_info_block_width(fb->format, color_plane) / + drm_format_info_block_width(fb->format, main_plane); + + /* + * The min stride check in the core framebuffer_check() function + * assumes that format->hsub applies to every plane except for the + * first plane. That's incorrect for the CCS AUX plane of the first + * plane, but for the above check to pass we must define the block + * width with that subsampling applied to it. Adjust the width here + * accordingly, so we can calculate the actual subsampling factor. + */ + if (main_plane == 0) + *hsub *= fb->format->hsub; + + *vsub = 32; +} static int intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int ccs_plane, int x, int y) { struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - int hsub = fb->format->hsub; - int vsub = fb->format->vsub; + int main_plane; + int hsub, vsub; int tile_width, tile_height; int ccs_x, ccs_y; int main_x, main_y; - if (!is_ccs_modifier(fb->modifier) || ccs_plane != 1) + if (!is_ccs_plane(fb, ccs_plane)) return 0; - intel_tile_dims(fb, 1, &tile_width, &tile_height); + intel_tile_dims(fb, ccs_plane, &tile_width, &tile_height); + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); tile_width *= hsub; tile_height *= vsub; ccs_x = (x * hsub) % tile_width; ccs_y = (y * vsub) % tile_height; - main_x = intel_fb->normal[0].x % tile_width; - main_y = intel_fb->normal[0].y % tile_height; + + main_plane = ccs_to_main_plane(fb, ccs_plane); + main_x = intel_fb->normal[main_plane].x % tile_width; + main_y = intel_fb->normal[main_plane].y % tile_height; /* * CCS doesn't have its own x/y offset register, so the intra CCS tile @@ -2742,8 +2850,8 @@ intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int ccs_plane, int x, int y) DRM_DEBUG_KMS("Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n", main_x, main_y, ccs_x, ccs_y, - intel_fb->normal[0].x, - intel_fb->normal[0].y, + intel_fb->normal[main_plane].x, + intel_fb->normal[main_plane].y, x, y); return -EINVAL; } @@ -2751,6 +2859,16 @@ intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int ccs_plane, int x, int y) return 0; } +static void +intel_fb_plane_dims(int *w, int *h, struct drm_framebuffer *fb, int color_plane) +{ + int hsub, vsub; + + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, color_plane); + *w = fb->width / hsub; + *h = fb->height / vsub; +} + static int intel_fill_fb_info(struct drm_i915_private *dev_priv, struct drm_framebuffer *fb) @@ -2771,8 +2889,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, int ret; cpp = fb->format->cpp[i]; - width = drm_framebuffer_plane_width(fb->width, fb, i); - height = drm_framebuffer_plane_height(fb->height, fb, i); + intel_fb_plane_dims(&width, &height, fb, i); ret = intel_fb_offset_to_xy(&x, &y, fb, i); if (ret) { @@ -2814,7 +2931,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, tile_size); offset /= tile_size; - if (!is_surface_linear(fb->modifier, i)) { + if (!is_surface_linear(fb, i)) { unsigned int tile_width, tile_height; unsigned int pitch_tiles; struct drm_rect r; @@ -3493,14 +3610,15 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state int main_x, int main_y, u32 main_offset) { const struct drm_framebuffer *fb = plane_state->hw.fb; - int hsub = fb->format->hsub; - int vsub = fb->format->vsub; int ccs_plane = main_to_ccs_plane(fb, 0); int aux_x = plane_state->color_plane[ccs_plane].x; int aux_y = plane_state->color_plane[ccs_plane].y; u32 aux_offset = plane_state->color_plane[ccs_plane].offset; u32 alignment = intel_surf_alignment(fb, ccs_plane); + int hsub; + int vsub; + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); while (aux_offset >= main_offset && aux_y <= main_y) { int x, y; @@ -3667,12 +3785,15 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) const struct drm_framebuffer *fb = plane_state->hw.fb; int src_x = plane_state->uapi.src.x1 >> 16; int src_y = plane_state->uapi.src.y1 >> 16; - int hsub = fb->format->hsub; - int vsub = fb->format->vsub; - int x = src_x / hsub; - int y = src_y / vsub; + int hsub; + int vsub; + int x; + int y; u32 offset; + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, 1); + x = src_x / hsub; + y = src_y / vsub; intel_add_fb_offsets(&x, &y, plane_state, 1); offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1); @@ -4168,7 +4289,7 @@ static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb, * The stride is either expressed as a multiple of 64 bytes chunks for * linear buffers or in number of tiles for tiled buffers. */ - if (fb->modifier == DRM_FORMAT_MOD_LINEAR) + if (is_surface_linear(fb, color_plane)) return 64; else if (drm_rotation_90_or_270(rotation)) return intel_tile_height(fb, color_plane); @@ -4296,6 +4417,10 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier) return PLANE_CTL_TILED_Y; case I915_FORMAT_MOD_Y_TILED_CCS: return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: + return PLANE_CTL_TILED_Y | + PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | + PLANE_CTL_CLEAR_COLOR_DISABLE; case I915_FORMAT_MOD_Yf_TILED: return PLANE_CTL_TILED_YF; case I915_FORMAT_MOD_Yf_TILED_CCS: @@ -10027,7 +10152,9 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, case PLANE_CTL_TILED_Y: plane_config->tiling = I915_TILING_Y; if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) - fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS; + fb->modifier = INTEL_GEN(dev_priv) >= 12 ? + I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS : + I915_FORMAT_MOD_Y_TILED_CCS; else fb->modifier = I915_FORMAT_MOD_Y_TILED; break; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index a5b7cab6dff3..0a298667b7c6 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -583,6 +583,7 @@ skl_program_plane(struct intel_plane *plane, const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 surf_addr = plane_state->color_plane[color_plane].offset; u32 stride = skl_plane_stride(plane_state, color_plane); + u32 aux_dist = plane_state->color_plane[1].offset - surf_addr; u32 aux_stride = skl_plane_stride(plane_state, 1); int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; @@ -624,8 +625,10 @@ skl_program_plane(struct intel_plane *plane, I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride); I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x); I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); - I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), - (plane_state->color_plane[1].offset - surf_addr) | aux_stride); + + if (INTEL_GEN(dev_priv) < 12) + aux_dist |= aux_stride; + I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), aux_dist); if (icl_is_hdr_plane(dev_priv, plane_id)) I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), plane_state->cus_ctl); @@ -2102,7 +2105,8 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, (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)) { + fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS || + fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS)) { DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n"); return -EINVAL; } @@ -2573,7 +2577,8 @@ static const u64 skl_plane_format_modifiers_ccs[] = { DRM_FORMAT_MOD_INVALID }; -static const u64 gen12_plane_format_modifiers_noccs[] = { +static const u64 gen12_plane_format_modifiers_ccs[] = { + I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED, DRM_FORMAT_MOD_LINEAR, @@ -2744,6 +2749,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: break; default: return false; @@ -2754,6 +2760,9 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ABGR8888: + if (is_ccs_modifier(modifier)) + return true; + /* fall through */ case DRM_FORMAT_RGB565: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: @@ -2963,13 +2972,11 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, formats = skl_get_plane_formats(dev_priv, pipe, plane_id, &num_formats); + plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id); if (INTEL_GEN(dev_priv) >= 12) { - /* TODO: Implement support for gen-12 CCS modifiers */ - plane->has_ccs = false; - modifiers = gen12_plane_format_modifiers_noccs; + modifiers = gen12_plane_format_modifiers_ccs; plane_funcs = &gen12_plane_funcs; } else { - plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id); if (plane->has_ccs) modifiers = skl_plane_format_modifiers_ccs; else diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index cbb4689af432..bbfedeb00b7f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6800,6 +6800,7 @@ enum { #define PLANE_CTL_YUV422_VYUY (3 << 16) #define PLANE_CTL_RENDER_DECOMPRESSION_ENABLE (1 << 15) #define PLANE_CTL_TRICKLE_FEED_DISABLE (1 << 14) +#define PLANE_CTL_CLEAR_COLOR_DISABLE (1 << 13) /* TGL+ */ #define PLANE_CTL_PLANE_GAMMA_DISABLE (1 << 13) /* Pre-GLK */ #define PLANE_CTL_TILED_MASK (0x7 << 10) #define PLANE_CTL_TILED_LINEAR (0 << 10) -- cgit v1.2.3 From 71df86f0fbf5046a68a2adaaba98feee2f6e22d1 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Sat, 21 Dec 2019 14:05:40 +0200 Subject: drm/i915/tgl: Make sure FBs have a correct CCS plane stride MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CCS plane stride must be fixed on TGL, as it's not configurable for the display. Instead the HW has a hardwired logic to determine it from the main plane stride. Make sure userspace passes in the correct stride. Cc: Dhinakaran Pandiyan Cc: Ville Syrjälä Cc: Mika Kahola Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-8-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ae2858931c9d..7e55829736bb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2621,6 +2621,12 @@ bool is_ccs_modifier(u64 modifier) modifier == I915_FORMAT_MOD_Yf_TILED_CCS; } +static int gen12_ccs_aux_stride(struct drm_framebuffer *fb, int ccs_plane) +{ + return DIV_ROUND_UP(fb->pitches[ccs_to_main_plane(fb, ccs_plane)], + 512) * 64; +} + u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, u32 pixel_format, u64 modifier) { @@ -16550,6 +16556,17 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, goto err; } + if (is_gen12_ccs_plane(fb, i)) { + int ccs_aux_stride = gen12_ccs_aux_stride(fb, i); + + if (fb->pitches[i] != ccs_aux_stride) { + DRM_DEBUG_KMS("ccs aux plane %d pitch (%d) must be %d\n", + i, + fb->pitches[i], ccs_aux_stride); + goto err; + } + } + fb->obj[i] = &obj->base; } -- cgit v1.2.3 From 931cd348bb8dc9374b9561846be149bfae7571b6 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Sat, 21 Dec 2019 14:05:41 +0200 Subject: drm/i915: Skip rotated offset adjustment for unsupported modifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During framebuffer creation, we pre-compute offsets for 90/270 plane rotation. However, only Y and Yf modifiers support 90/270 rotation. So, skip the calculations for other modifiers. To keep the gem buffer size check still working for tiled planes, factor out the logic needed for rotation setup and skip only this part for tiled planes other than Y/Yf. v2: Add a bounds check WARN for the rotation info array. v3: Keep the gem buffer size check working for tiled planes. Cc: Matt Roper Cc: Ville Syrjälä Cc: Mika Kahola Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-9-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 118 +++++++++++++++++---------- 1 file changed, 77 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7e55829736bb..f118742f7951 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2875,12 +2875,72 @@ intel_fb_plane_dims(int *w, int *h, struct drm_framebuffer *fb, int color_plane) *h = fb->height / vsub; } +/* + * Setup the rotated view for an FB plane and return the size the GTT mapping + * requires for this view. + */ +static u32 +setup_fb_rotation(int plane, const struct intel_remapped_plane_info *plane_info, + u32 gtt_offset_rotated, int x, int y, + unsigned int width, unsigned int height, + unsigned int tile_size, + unsigned int tile_width, unsigned int tile_height, + struct drm_framebuffer *fb) +{ + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct intel_rotation_info *rot_info = &intel_fb->rot_info; + unsigned int pitch_tiles; + struct drm_rect r; + + /* Y or Yf modifiers required for 90/270 rotation */ + if (fb->modifier != I915_FORMAT_MOD_Y_TILED && + fb->modifier != I915_FORMAT_MOD_Yf_TILED) + return 0; + + if (WARN_ON(plane >= ARRAY_SIZE(rot_info->plane))) + return 0; + + rot_info->plane[plane] = *plane_info; + + intel_fb->rotated[plane].pitch = plane_info->height * tile_height; + + /* rotate the x/y offsets to match the GTT view */ + drm_rect_init(&r, x, y, width, height); + drm_rect_rotate(&r, + plane_info->width * tile_width, + plane_info->height * tile_height, + DRM_MODE_ROTATE_270); + x = r.x1; + y = r.y1; + + /* rotate the tile dimensions to match the GTT view */ + pitch_tiles = intel_fb->rotated[plane].pitch / tile_height; + swap(tile_width, tile_height); + + /* + * We only keep the x/y offsets, so push all of the + * gtt offset into the x/y offsets. + */ + intel_adjust_tile_offset(&x, &y, + tile_width, tile_height, + tile_size, pitch_tiles, + gtt_offset_rotated * tile_size, 0); + + /* + * First pixel of the framebuffer from + * the start of the rotated gtt mapping. + */ + intel_fb->rotated[plane].x = x; + intel_fb->rotated[plane].y = y; + + return plane_info->width * plane_info->height; +} + static int intel_fill_fb_info(struct drm_i915_private *dev_priv, struct drm_framebuffer *fb) { struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct intel_rotation_info *rot_info = &intel_fb->rot_info; struct drm_i915_gem_object *obj = intel_fb_obj(fb); u32 gtt_offset_rotated = 0; unsigned int max_size = 0; @@ -2938,22 +2998,20 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, offset /= tile_size; if (!is_surface_linear(fb, i)) { + struct intel_remapped_plane_info plane_info; unsigned int tile_width, tile_height; - unsigned int pitch_tiles; - struct drm_rect r; intel_tile_dims(fb, i, &tile_width, &tile_height); - rot_info->plane[i].offset = offset; - rot_info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp); - rot_info->plane[i].width = DIV_ROUND_UP(x + width, tile_width); - rot_info->plane[i].height = DIV_ROUND_UP(y + height, tile_height); - - intel_fb->rotated[i].pitch = - rot_info->plane[i].height * tile_height; + plane_info.offset = offset; + plane_info.stride = DIV_ROUND_UP(fb->pitches[i], + tile_width * cpp); + plane_info.width = DIV_ROUND_UP(x + width, tile_width); + plane_info.height = DIV_ROUND_UP(y + height, + tile_height); /* how many tiles does this plane need */ - size = rot_info->plane[i].stride * rot_info->plane[i].height; + size = plane_info.stride * plane_info.height; /* * If the plane isn't horizontally tile aligned, * we need one more tile. @@ -2961,36 +3019,13 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, if (x != 0) size++; - /* rotate the x/y offsets to match the GTT view */ - drm_rect_init(&r, x, y, width, height); - drm_rect_rotate(&r, - rot_info->plane[i].width * tile_width, - rot_info->plane[i].height * tile_height, - DRM_MODE_ROTATE_270); - x = r.x1; - y = r.y1; - - /* rotate the tile dimensions to match the GTT view */ - pitch_tiles = intel_fb->rotated[i].pitch / tile_height; - swap(tile_width, tile_height); - - /* - * We only keep the x/y offsets, so push all of the - * gtt offset into the x/y offsets. - */ - intel_adjust_tile_offset(&x, &y, - tile_width, tile_height, - tile_size, pitch_tiles, - gtt_offset_rotated * tile_size, 0); - - gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height; - - /* - * First pixel of the framebuffer from - * the start of the rotated gtt mapping. - */ - intel_fb->rotated[i].x = x; - intel_fb->rotated[i].y = y; + gtt_offset_rotated += + setup_fb_rotation(i, &plane_info, + gtt_offset_rotated, + x, y, width, height, + tile_size, + tile_width, tile_height, + fb); } else { size = DIV_ROUND_UP((y + height) * fb->pitches[i] + x * cpp, tile_size); @@ -3074,6 +3109,7 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state) DRM_MODE_ROTATE_0, tile_size); offset /= tile_size; + WARN_ON(i >= ARRAY_SIZE(info->plane)); info->plane[i].offset = offset; info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp); -- cgit v1.2.3 From 320625aac3c427118c8675404e01914ff51924cd Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Sat, 21 Dec 2019 14:05:42 +0200 Subject: drm/i915: Make sure Y slave planes get all the required state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Y planes program the offset and stride of the AUX plane, so make sure we copy the required info for this into their plane state. Cc: Maarten Lankhorst Cc: Ville Syrjälä Cc: Dhinakaran Pandiyan Cc: Mika Kahola Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-10-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index f118742f7951..e1a01e686a03 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -12234,7 +12234,8 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) /* Copy parameters to slave plane */ linked_state->ctl = plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE; linked_state->color_ctl = plane_state->color_ctl; - linked_state->color_plane[0] = plane_state->color_plane[0]; + memcpy(linked_state->color_plane, plane_state->color_plane, + sizeof(linked_state->color_plane)); intel_plane_copy_uapi_to_hw_state(linked_state, plane_state); linked_state->uapi.src = plane_state->uapi.src; -- cgit v1.2.3 From 4941f35b48f7f329bdf2ccad17d6fdb2190f8d34 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Sat, 21 Dec 2019 14:05:43 +0200 Subject: drm/i915: Make sure CCS YUV semiplanar format checks work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For CCS formats, the current DRM core check for YUV semiplanar formats doesn't work; use an i915 specific function for that. v2: Fix checkpatch warnings. Cc: Dhinakaran Pandiyan Cc: Ville Syrjälä Cc: Mika Kahola Signed-off-by: Imre Deak Reviewed-by: Mika Kahola Link: https://patchwork.freedesktop.org/patch/msgid/20191221120543.22816-11-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 25 +++++++++++++++++------ drivers/gpu/drm/i915/display/intel_display.h | 4 ++++ drivers/gpu/drm/i915/display/intel_sprite.c | 9 ++++---- drivers/gpu/drm/i915/intel_pm.c | 7 ++++--- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 9429b8e17270..3e97af682b1b 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -250,7 +250,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ new_crtc_state->active_planes |= BIT(plane->id); if (new_plane_state->uapi.visible && - drm_format_info_is_yuv_semiplanar(fb->format)) + intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) new_crtc_state->nv12_planes |= BIT(plane->id); if (new_plane_state->uapi.visible && diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e1a01e686a03..6fcf3d8bddc3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1986,6 +1986,14 @@ intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane) return 1; } +bool +intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, + uint64_t modifier) +{ + return info->is_yuv && + info->num_planes == (is_ccs_modifier(modifier) ? 4 : 2); +} + static unsigned int intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) { @@ -3862,7 +3870,8 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) * Handle the AUX surface first since * the main surface setup depends on it. */ - if (drm_format_info_is_yuv_semiplanar(fb->format)) { + if (intel_format_info_is_yuv_semiplanar(fb->format, + fb->modifier)) { ret = skl_check_nv12_aux_surface(plane_state); if (ret) return ret; @@ -5791,7 +5800,8 @@ static int skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, unsigned int scaler_user, int *scaler_id, int src_w, int src_h, int dst_w, int dst_h, - const struct drm_format_info *format, bool need_scaler) + const struct drm_format_info *format, + u64 modifier, bool need_scaler) { struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; @@ -5845,7 +5855,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, return 0; } - if (format && drm_format_info_is_yuv_semiplanar(format) && + if (format && intel_format_info_is_yuv_semiplanar(format, modifier) && (src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) { DRM_DEBUG_KMS("Planar YUV: src dimensions not met\n"); return -EINVAL; @@ -5897,7 +5907,8 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state) &state->scaler_state.scaler_id, state->pipe_src_w, state->pipe_src_h, adjusted_mode->crtc_hdisplay, - adjusted_mode->crtc_vdisplay, NULL, need_scaler); + adjusted_mode->crtc_vdisplay, NULL, 0, + need_scaler); } /** @@ -5922,7 +5933,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, /* Pre-gen11 and SDR planes always need a scaler for planar formats. */ if (!icl_is_hdr_plane(dev_priv, intel_plane->id) && - fb && drm_format_info_is_yuv_semiplanar(fb->format)) + fb && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) need_scaler = true; ret = skl_update_scaler(crtc_state, force_detach, @@ -5932,7 +5943,9 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, drm_rect_height(&plane_state->uapi.src) >> 16, drm_rect_width(&plane_state->uapi.dst), drm_rect_height(&plane_state->uapi.dst), - fb ? fb->format : NULL, need_scaler); + fb ? fb->format : NULL, + fb ? fb->modifier : 0, + need_scaler); if (ret || plane_state->scaler_id < 0) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index ff496cfbd4ab..0fef9263cddc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -601,6 +601,10 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv); void intel_display_print_error_state(struct drm_i915_error_state_buf *e, struct intel_display_error_state *error); +bool +intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, + uint64_t modifier); + /* modesetting */ void intel_modeset_init_hw(struct drm_i915_private *i915); int intel_modeset_init(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 0a298667b7c6..3f7b8f2ff671 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -417,7 +417,7 @@ skl_program_scaler(struct intel_plane *plane, 0, INT_MAX); /* TODO: handle sub-pixel coordinates */ - if (drm_format_info_is_yuv_semiplanar(fb->format) && + if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && !icl_is_hdr_plane(dev_priv, plane->id)) { y_hphase = skl_scaler_calc_phase(1, hscale, false); y_vphase = skl_scaler_calc_phase(1, vscale, false); @@ -2151,7 +2151,8 @@ static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_s int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; /* Display WA #1106 */ - if (drm_format_info_is_yuv_semiplanar(fb->format) && src_w & 3 && + if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && + src_w & 3 && (rotation == DRM_MODE_ROTATE_270 || rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) { DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n"); @@ -2171,7 +2172,7 @@ static int skl_plane_max_scale(struct drm_i915_private *dev_priv, * FIXME need to properly check this later. */ if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) || - !drm_format_info_is_yuv_semiplanar(fb->format)) + !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) return 0x30000 - 1; else return 0x20000 - 1; @@ -2233,7 +2234,7 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, plane_state->color_ctl = glk_plane_color_ctl(crtc_state, plane_state); - if (drm_format_info_is_yuv_semiplanar(fb->format) && + if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && icl_is_hdr_plane(dev_priv, plane->id)) /* Enable and use MPEG-2 chroma siting */ plane_state->cus_ctl = PLANE_CUS_ENABLE | diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 00f9f5187669..d690f713a2f1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4135,7 +4135,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, return 0; if (color_plane == 1 && - !drm_format_info_is_yuv_semiplanar(fb->format)) + !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) return 0; /* @@ -4559,7 +4559,8 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state, u32 interm_pbpl; /* only planar format has two planes */ - if (color_plane == 1 && !drm_format_info_is_yuv_semiplanar(format)) { + if (color_plane == 1 && + !intel_format_info_is_yuv_semiplanar(format, modifier)) { DRM_DEBUG_KMS("Non planar format have single plane\n"); return -EINVAL; } @@ -4571,7 +4572,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state, wp->x_tiled = modifier == I915_FORMAT_MOD_X_TILED; wp->rc_surface = modifier == I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS; - wp->is_planar = drm_format_info_is_yuv_semiplanar(format); + wp->is_planar = intel_format_info_is_yuv_semiplanar(format, modifier); wp->width = width; if (color_plane == 1 && wp->is_planar) -- cgit v1.2.3 From f5af1659d809e264d619e5f483fd8f47bced3b6a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 22 Dec 2019 21:02:54 +0000 Subject: drm/i915: Add a simple is-bound check before unbinding Only acquire the various atomic references required to unbind the vma if we do need to unbind the vma. Signed-off-by: Chris Wilson Acked-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20191222210256.2066451-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 983755bec76b..e9f82e9cb6ff 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -138,6 +138,10 @@ try_again: struct i915_address_space *vm = vma->vm; bool awake = false; + list_move_tail(&vma->obj_link, &still_in_list); + if (!i915_vma_is_bound(vma, I915_VMA_BIND_MASK)) + continue; + ret = -EAGAIN; if (!i915_vm_tryopen(vm)) break; @@ -153,7 +157,6 @@ try_again: } } - list_move_tail(&vma->obj_link, &still_in_list); spin_unlock(&obj->vma.lock); ret = -EBUSY; -- cgit v1.2.3 From 76f9764cc3d538435262dea885bf69fac2415402 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 22 Dec 2019 21:02:55 +0000 Subject: drm/i915: Introduce a vma.kref Start introducing a kref on i915_vma in order to protect the vma unbind (i915_gem_object_unbind) from a parallel destruction (i915_vma_parked). Later, we will use the refcount to manage all access and turn i915_vma into a first class container. Signed-off-by: Chris Wilson Cc: Imre Deak Acked-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20191222210256.2066451-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_object.c | 2 +- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 3 +-- drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 4 ++-- drivers/gpu/drm/i915/i915_gem.c | 27 ++++++++-------------- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 ++-- drivers/gpu/drm/i915/i915_vma.c | 9 +++++--- drivers/gpu/drm/i915/i915_vma.h | 25 +++++++++++++++++--- 7 files changed, 44 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index ddc82a7a34ff..46bacc82ddc4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -194,7 +194,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, GEM_BUG_ON(vma->obj != obj); spin_unlock(&obj->vma.lock); - i915_vma_destroy(vma); + __i915_vma_put(vma); spin_lock(&obj->vma.lock); } diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 497c367a79ca..2479395c1873 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1110,8 +1110,7 @@ static int __igt_write_huge(struct intel_context *ce, out_vma_unpin: i915_vma_unpin(vma); out_vma_close: - i915_vma_destroy(vma); - + __i915_vma_put(vma); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 591435c5f368..cbf796da64e3 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -163,7 +163,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, kunmap(p); out: - i915_vma_destroy(vma); + __i915_vma_put(vma); return err; } @@ -257,7 +257,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj, if (err) return err; - i915_vma_destroy(vma); + __i915_vma_put(vma); if (igt_timeout(end_time, "%s: timed out after tiling=%d stride=%d\n", diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e9f82e9cb6ff..9ddcf17230e6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -136,7 +136,6 @@ try_again: struct i915_vma, obj_link))) { struct i915_address_space *vm = vma->vm; - bool awake = false; list_move_tail(&vma->obj_link, &still_in_list); if (!i915_vma_is_bound(vma, I915_VMA_BIND_MASK)) @@ -147,26 +146,18 @@ try_again: break; /* Prevent vma being freed by i915_vma_parked as we unbind */ - if (intel_gt_pm_get_if_awake(vm->gt)) { - awake = true; - } else { - if (i915_vma_is_closed(vma)) { - spin_unlock(&obj->vma.lock); - i915_vma_parked(vm->gt); - goto err_vm; - } - } - + vma = __i915_vma_get(vma); spin_unlock(&obj->vma.lock); - ret = -EBUSY; - if (flags & I915_GEM_OBJECT_UNBIND_ACTIVE || - !i915_vma_is_active(vma)) - ret = i915_vma_unbind(vma); + if (vma) { + ret = -EBUSY; + if (flags & I915_GEM_OBJECT_UNBIND_ACTIVE || + !i915_vma_is_active(vma)) + ret = i915_vma_unbind(vma); + + __i915_vma_put(vma); + } - if (awake) - intel_gt_pm_put(vm->gt); -err_vm: i915_vm_close(vm); spin_lock(&obj->vma.lock); } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2ad2fc5efdbf..1efe58ad0ce9 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -534,7 +534,7 @@ void __i915_vm_close(struct i915_address_space *vm) atomic_and(~I915_VMA_PIN_MASK, &vma->flags); WARN_ON(__i915_vma_unbind(vma)); - i915_vma_destroy(vma); + __i915_vma_put(vma); i915_gem_object_put(obj); } @@ -1812,7 +1812,7 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm) { struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); - i915_vma_destroy(ppgtt->vma); + __i915_vma_put(ppgtt->vma); gen6_ppgtt_free_pd(ppgtt); free_scratch(vm); @@ -1895,6 +1895,7 @@ static struct i915_vma *pd_vma_create(struct gen6_ppgtt *ppgtt, int size) i915_active_init(&vma->active, NULL, NULL); + kref_init(&vma->ref); mutex_init(&vma->pages_mutex); vma->vm = i915_vm_get(&ggtt->vm); vma->ops = &pd_vma_ops; diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index f3ac837ba3b3..cbd783c31adb 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -114,6 +114,7 @@ vma_create(struct drm_i915_gem_object *obj, if (vma == NULL) return ERR_PTR(-ENOMEM); + kref_init(&vma->ref); mutex_init(&vma->pages_mutex); vma->vm = i915_vm_get(vm); vma->ops = &vm->vma_ops; @@ -1021,8 +1022,10 @@ void i915_vma_reopen(struct i915_vma *vma) __i915_vma_remove_closed(vma); } -void i915_vma_destroy(struct i915_vma *vma) +void i915_vma_release(struct kref *ref) { + struct i915_vma *vma = container_of(ref, typeof(*vma), ref); + if (drm_mm_node_allocated(&vma->node)) { mutex_lock(&vma->vm->mutex); atomic_and(~I915_VMA_PIN_MASK, &vma->flags); @@ -1072,7 +1075,7 @@ void i915_vma_parked(struct intel_gt *gt) spin_unlock_irq(>->closed_lock); if (obj) { - i915_vma_destroy(vma); + __i915_vma_put(vma); i915_gem_object_put(obj); } @@ -1236,7 +1239,7 @@ int __i915_vma_unbind(struct i915_vma *vma) i915_vma_detach(vma); vma_unbind_pages(vma); - drm_mm_remove_node(&vma->node); /* pairs with i915_vma_destroy() */ + drm_mm_remove_node(&vma->node); /* pairs with i915_vma_release() */ return 0; } diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 0e0b61c24551..5fffa3c58908 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -51,14 +51,19 @@ enum i915_cache_level; */ struct i915_vma { struct drm_mm_node node; - struct drm_i915_gem_object *obj; + struct i915_address_space *vm; const struct i915_vma_ops *ops; - struct i915_fence_reg *fence; + + struct drm_i915_gem_object *obj; struct dma_resv *resv; /** Alias of obj->resv */ + struct sg_table *pages; void __iomem *iomap; void *private; /* owned by creator */ + + struct i915_fence_reg *fence; + u64 size; u64 display_alignment; struct i915_page_sizes page_sizes; @@ -74,6 +79,7 @@ struct i915_vma { * handles (but same file) for execbuf, i.e. the number of aliases * that exist in the ctx->handle_vmas LUT for this vma. */ + struct kref ref; atomic_t open_count; atomic_t flags; /** @@ -336,7 +342,20 @@ int __must_check i915_vma_unbind(struct i915_vma *vma); void i915_vma_unlink_ctx(struct i915_vma *vma); void i915_vma_close(struct i915_vma *vma); void i915_vma_reopen(struct i915_vma *vma); -void i915_vma_destroy(struct i915_vma *vma); + +static inline struct i915_vma *__i915_vma_get(struct i915_vma *vma) +{ + if (kref_get_unless_zero(&vma->ref)) + return vma; + + return NULL; +} + +void i915_vma_release(struct kref *ref); +static inline void __i915_vma_put(struct i915_vma *vma) +{ + kref_put(&vma->ref, i915_vma_release); +} #define assert_vma_held(vma) dma_resv_assert_held((vma)->resv) -- cgit v1.2.3 From 6a8679c048eb104dbcc6aa43a0baa7450de46503 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 22 Dec 2019 23:35:58 +0000 Subject: drm/i915: Mark the GEM context link as RCU protected The only protection for intel_context.gem_cotext is granted by RCU, so annotate it as a rcu protected pointer and carefully dereference it in the few occasions we need to use it. Fixes: 9f3ccd40acf4 ("drm/i915: Drop GEM context as a direct link from i915_request") Signed-off-by: Chris Wilson Cc: Andi Shyti Acked-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20191222233558.2201901-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 ++-- drivers/gpu/drm/i915/gt/intel_context_types.h | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 26 ++++++++++++---- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 40 ++++++++++++++++--------- drivers/gpu/drm/i915/i915_request.c | 6 ++-- drivers/gpu/drm/i915/i915_request.h | 8 +++++ 7 files changed, 62 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 6167e68bbb25..dc90b044a217 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -212,8 +212,8 @@ context_get_vm_rcu(struct i915_gem_context *ctx) static void intel_context_set_gem(struct intel_context *ce, struct i915_gem_context *ctx) { - GEM_BUG_ON(ce->gem_context); - ce->gem_context = ctx; + GEM_BUG_ON(rcu_access_pointer(ce->gem_context)); + RCU_INIT_POINTER(ce->gem_context, ctx); if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) ce->ring = __intel_context_ring_size(SZ_16K); @@ -244,6 +244,7 @@ static void __free_engines(struct i915_gem_engines *e, unsigned int count) if (!e->engines[count]) continue; + RCU_INIT_POINTER(e->engines[count]->gem_context, NULL); intel_context_put(e->engines[count]); } kfree(e); diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 7dd03ad9826c..9527a659546c 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -44,7 +44,7 @@ struct intel_context { #define intel_context_inflight_count(ce) ptr_unmask_bits((ce)->inflight, 2) struct i915_address_space *vm; - struct i915_gem_context *gem_context; + struct i915_gem_context __rcu *gem_context; struct list_head signal_link; struct list_head signals; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index ab8213b90517..1c51296646e0 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -85,20 +85,27 @@ static bool mark_guilty(struct i915_request *rq) bool banned; int i; - ctx = rq->context->gem_context; + rcu_read_lock(); + ctx = rcu_dereference(rq->context->gem_context); + if (ctx && !kref_get_unless_zero(&ctx->ref)) + ctx = NULL; + rcu_read_unlock(); if (!ctx) return false; if (i915_gem_context_is_closed(ctx)) { intel_context_set_banned(rq->context); - return true; + banned = true; + goto out; } atomic_inc(&ctx->guilty_count); /* Cool contexts are too cool to be banned! (Used for reset testing.) */ - if (!i915_gem_context_is_bannable(ctx)) - return false; + if (!i915_gem_context_is_bannable(ctx)) { + banned = false; + goto out; + } dev_notice(ctx->i915->drm.dev, "%s context reset due to GPU hang\n", @@ -122,13 +129,20 @@ static bool mark_guilty(struct i915_request *rq) client_mark_guilty(ctx, banned); +out: + i915_gem_context_put(ctx); return banned; } static void mark_innocent(struct i915_request *rq) { - if (rq->context->gem_context) - atomic_inc(&rq->context->gem_context->active_count); + struct i915_gem_context *ctx; + + rcu_read_lock(); + ctx = rcu_dereference(rq->context->gem_context); + if (ctx) + atomic_inc(&ctx->active_count); + rcu_read_unlock(); } void __i915_request_reset(struct i915_request *rq, bool guilty) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 118170eb51b4..81f872f9ef03 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1550,7 +1550,7 @@ static int remap_l3_slice(struct i915_request *rq, int slice) static int remap_l3(struct i915_request *rq) { - struct i915_gem_context *ctx = rq->context->gem_context; + struct i915_gem_context *ctx = i915_request_gem_context(rq); int i, err; if (!ctx || !ctx->remap_slice) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 7e2cb063110c..fda0977d2059 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1221,7 +1221,7 @@ static void error_record_engine_registers(struct i915_gpu_state *error, static void record_request(const struct i915_request *request, struct drm_i915_error_request *erq) { - const struct i915_gem_context *ctx = request->context->gem_context; + const struct i915_gem_context *ctx; erq->flags = request->fence.flags; erq->context = request->fence.context; @@ -1231,7 +1231,13 @@ static void record_request(const struct i915_request *request, erq->start = i915_ggtt_offset(request->ring->vma); erq->head = request->head; erq->tail = request->tail; - erq->pid = ctx && ctx->pid ? pid_nr(ctx->pid) : 0; + + erq->pid = 0; + rcu_read_lock(); + ctx = rcu_dereference(request->context->gem_context); + if (ctx) + erq->pid = pid_nr(ctx->pid); + rcu_read_unlock(); } static void engine_record_requests(struct intel_engine_cs *engine, @@ -1298,28 +1304,34 @@ static void error_record_engine_execlists(const struct intel_engine_cs *engine, static bool record_context(struct drm_i915_error_context *e, const struct i915_request *rq) { - const struct i915_gem_context *ctx = rq->context->gem_context; + struct i915_gem_context *ctx; + struct task_struct *task; + bool capture; + rcu_read_lock(); + ctx = rcu_dereference(rq->context->gem_context); + if (ctx && !kref_get_unless_zero(&ctx->ref)) + ctx = NULL; + rcu_read_unlock(); if (!ctx) return false; - if (ctx->pid) { - struct task_struct *task; - - rcu_read_lock(); - task = pid_task(ctx->pid, PIDTYPE_PID); - if (task) { - strcpy(e->comm, task->comm); - e->pid = task->pid; - } - rcu_read_unlock(); + rcu_read_lock(); + task = pid_task(ctx->pid, PIDTYPE_PID); + if (task) { + strcpy(e->comm, task->comm); + e->pid = task->pid; } + rcu_read_unlock(); e->sched_attr = ctx->sched; e->guilty = atomic_read(&ctx->guilty_count); e->active = atomic_read(&ctx->active_count); - return i915_gem_context_no_error_capture(ctx); + capture = i915_gem_context_no_error_capture(ctx); + + i915_gem_context_put(ctx); + return capture; } struct capture_vma { diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 14a5a99284fa..44a0d1a950c5 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -76,7 +76,7 @@ static const char *i915_fence_get_timeline_name(struct dma_fence *fence) if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) return "signaled"; - ctx = to_request(fence)->context->gem_context; + ctx = i915_request_gem_context(to_request(fence)); if (!ctx) return "[" DRIVER_NAME "]"; @@ -1312,8 +1312,8 @@ void i915_request_add(struct i915_request *rq) prev = __i915_request_commit(rq); - if (rq->context->gem_context) - attr = rq->context->gem_context->sched; + if (rcu_access_pointer(rq->context->gem_context)) + attr = i915_request_gem_context(rq)->sched; /* * Boost actual workloads past semaphores! diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 0e4fe3205ce7..565322640378 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -28,6 +28,7 @@ #include #include +#include "gem/i915_gem_context_types.h" #include "gt/intel_context_types.h" #include "gt/intel_engine_types.h" #include "gt/intel_timeline_types.h" @@ -463,6 +464,13 @@ i915_request_timeline(struct i915_request *rq) lockdep_is_held(&rcu_access_pointer(rq->timeline)->mutex)); } +static inline struct i915_gem_context * +i915_request_gem_context(struct i915_request *rq) +{ + /* Valid only while the request is being constructed (or retired). */ + return rcu_dereference_protected(rq->context->gem_context, true); +} + static inline struct intel_timeline * i915_request_active_timeline(struct i915_request *rq) { -- cgit v1.2.3 From 3446c63a0f2a691fdc6fffaddc6e0c1285efc80c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 23 Dec 2019 19:08:14 +0200 Subject: drm/i915: Update DRIVER_DATE to 20191223 Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 95db8017f138..d05a968227f7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -110,8 +110,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20191101" -#define DRIVER_TIMESTAMP 1572604873 +#define DRIVER_DATE "20191223" +#define DRIVER_TIMESTAMP 1577120893 struct drm_i915_gem_object; -- cgit v1.2.3