From 5f4b091aa200caa118520b6918b94e019f532dcf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 19 Aug 2016 12:56:25 +0100 Subject: drm/i915: Restore debugfs/i915_gem_gtt back to its former glory The passed in flag that distinguishes i915_gem_pin_display from i915_gem_gtt is from node->info_ent->data not the data function parameter. Fixes: 6da8482936c7 ("drm/i915: Focus debugfs/i915_gem_pinned to show...") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160819115625.17688-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d0b4c74974be..67af3277811a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -499,7 +499,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); - bool show_pin_display_only = !!data; + bool show_pin_display_only = !!node->info_ent->data; struct drm_i915_gem_object *obj; u64 total_obj_size, total_gtt_size; int count, ret; -- cgit v1.2.1 From 14daa63b277b73a91ca084acee9e31365c7283e9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 22 Aug 2016 08:44:29 +0100 Subject: drm/i915: Stop marking the unaccessible scratch page as UC Since by design, if not entirely by practice, nothing is allowed to access the scratch page we use to background fill the VM, then we do not need to ensure that it is coherent between the CPU and GPU. set_pages_uc() does a stop_machine() after changing the PAT, and that significantly impacts upon context creation throughput. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160822074431.26872-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index b90fdcee992a..b3cd9e21c8da 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -422,16 +422,12 @@ static struct i915_page_scratch *alloc_scratch_page(struct drm_device *dev) return ERR_PTR(ret); } - set_pages_uc(px_page(sp), 1); - return sp; } static void free_scratch_page(struct drm_device *dev, struct i915_page_scratch *sp) { - set_pages_wb(px_page(sp), 1); - cleanup_px(dev, sp); kfree(sp); } -- cgit v1.2.1 From c75870d86f6a55a08ef0e67cf6cc25ae124ca9e7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 22 Aug 2016 10:55:22 +0200 Subject: drm/i915: Ensure consistent control flow __i915_gem_active_get_rcu This issue here is (I think) purely theoretical, since a compiler would need to be especially foolish to recompute the value of i915_gem_request_completed right after it was already used. Hence the additional barrier() is also not really a restriction. But I believe this to be at least permissible, and since our rcu trickery is a beast it's worth to annotate all the corner cases. Chris proposed to instead just wrap a READ_ONCE around request->fence.seqno in i915_gem_request_completed. But that has a measurable impact on code size, and everywhere we hold a full reference to the underlying request it's also not needed. And personally I'd like to have just enough barriers and locking needed for correctness, but not more - it makes it much easier in the future to understand what's going on. Since the busy ioctl has now fully embraced it's races there's no point annotating it there too. We really only need it in active_get_rcu, since that function _must_ deliver a correct snapshot of the active fences (and not chase something else). v2: Polish the comment a bit more (Chris). Cc: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1471856122-466-1-git-send-email-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/i915_gem_request.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 6c72bd8d9423..91014de8bfbc 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -472,6 +472,19 @@ __i915_gem_active_get_rcu(const struct i915_gem_active *active) if (!request || i915_gem_request_completed(request)) return NULL; + /* An especially silly compiler could decide to recompute the + * result of i915_gem_request_completed, more specifically + * re-emit the load for request->fence.seqno. A race would catch + * a later seqno value, which could flip the result from true to + * false. Which means part of the instructions below might not + * be executed, while later on instructions are executed. Due to + * barriers within the refcounting the inconsistency can't reach + * past the call to i915_gem_request_get_rcu, but not executing + * that while still executing i915_gem_request_put() creates + * havoc enough. Prevent this with a compiler barrier. + */ + barrier(); + request = i915_gem_request_get_rcu(request); /* What stops the following rcu_access_pointer() from occurring -- cgit v1.2.1 From 1f061316cf556fe07804ca2eb30f7807cffc3f53 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 17 Aug 2016 16:41:44 -0300 Subject: drm/i915: Call intel_fbc_pre_update() after pinning the new pageflip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_fbc_pre_update() depends upon the new state being already pinned in place in the Global GTT (primarily for both fencing which wants both an offset and a fence register, if assigned). This requires the call to intel_fbc_pre_update() be after intel_pin_and_fence_fb() - but commit e8216e502aca ("drm/i915/fbc: call intel_fbc_pre_update earlier during page flips") moved the code way too much up in its attempt to call it before the page flip. v2 (from Paulo): - Point the original bad commit. - Add a comment to maybe prevent further regressions. Fixes: e8216e502aca ("drm/i915/fbc: call intel_fbc_pre_update earlier...") Signed-off-by: Chris Wilson Signed-off-by: Paulo Zanoni Cc: Daniel Vetter Cc: Ville Syrjälä Cc: Maarten Lankhorst Cc: Patrik Jakobsson Cc: drm-intel-fixes@lists.freedesktop.org Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1471462904-842-1-git-send-email-paulo.r.zanoni@intel.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/i915/intel_display.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c81c89adaff3..3011b22e4b25 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12094,9 +12094,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, crtc->primary->fb = fb; update_state_fb(crtc->primary); - intel_fbc_pre_update(intel_crtc, intel_crtc->config, - to_intel_plane_state(primary->state)); - work->pending_flip_obj = i915_gem_object_get(obj); ret = i915_mutex_lock_interruptible(dev); @@ -12142,6 +12139,17 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->gtt_offset += intel_crtc->dspaddr_offset; work->rotation = crtc->primary->state->rotation; + /* + * There's the potential that the next frame will not be compatible with + * FBC, so we want to call pre_update() before the actual page flip. + * The problem is that pre_update() caches some information about the fb + * object, so we want to do this only after the object is pinned. Let's + * be on the safe side and do this immediately before scheduling the + * flip. + */ + intel_fbc_pre_update(intel_crtc, intel_crtc->config, + to_intel_plane_state(primary->state)); + if (mmio_flip) { INIT_WORK(&work->mmio_work, intel_mmio_flip_work_func); -- cgit v1.2.1 From 87660502f1a4d51fb043e89a45d30c9917787c22 Mon Sep 17 00:00:00 2001 From: Lyude Date: Wed, 17 Aug 2016 15:55:53 -0400 Subject: drm/i915/gen6+: Interpret mailbox error flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to add proper support for the SAGV, we need to be able to know what the cause of a failure to change the SAGV through the pcode mailbox was. The reasoning for this is that some very early pre-release Skylake machines don't actually allow you to control the SAGV on them, and indicate an invalid mailbox command was sent. This also might come in handy in the future for debugging. Changes since v1: - Add functions for interpreting gen6 mailbox error codes along with gen7+ error codes, and actually interpret those codes properly - Renamed patch to reflect new behavior Signed-off-by: Lyude Cc: Matt Roper Cc: Maarten Lankhorst Cc: Daniel Vetter Cc: Ville Syrjälä Cc: stable@vger.kernel.org Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471463761-26796-2-git-send-email-cpaul@redhat.com [mlankhorst: -ENOSYS -> -ENXIO for checkpatch] --- drivers/gpu/drm/i915/i915_reg.h | 9 ++++++ drivers/gpu/drm/i915/intel_pm.c | 71 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d4adf2806c50..7419fbfb145e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7123,6 +7123,15 @@ enum { #define GEN6_PCODE_MAILBOX _MMIO(0x138124) #define GEN6_PCODE_READY (1<<31) +#define GEN6_PCODE_ERROR_MASK 0xFF +#define GEN6_PCODE_SUCCESS 0x0 +#define GEN6_PCODE_ILLEGAL_CMD 0x1 +#define GEN6_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE 0x2 +#define GEN6_PCODE_TIMEOUT 0x3 +#define GEN6_PCODE_UNIMPLEMENTED_CMD 0xFF +#define GEN7_PCODE_TIMEOUT 0x2 +#define GEN7_PCODE_ILLEGAL_DATA 0x3 +#define GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE 0x10 #define GEN6_PCODE_WRITE_RC6VIDS 0x4 #define GEN6_PCODE_READ_RC6VIDS 0x5 #define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8a6751e14ab9..d0b745534585 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7659,8 +7659,53 @@ void intel_init_pm(struct drm_device *dev) } } +static inline int gen6_check_mailbox_status(struct drm_i915_private *dev_priv) +{ + uint32_t flags = + I915_READ_FW(GEN6_PCODE_MAILBOX) & GEN6_PCODE_ERROR_MASK; + + switch (flags) { + case GEN6_PCODE_SUCCESS: + return 0; + case GEN6_PCODE_UNIMPLEMENTED_CMD: + case GEN6_PCODE_ILLEGAL_CMD: + return -ENXIO; + case GEN6_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE: + return -EOVERFLOW; + case GEN6_PCODE_TIMEOUT: + return -ETIMEDOUT; + default: + MISSING_CASE(flags) + return 0; + } +} + +static inline int gen7_check_mailbox_status(struct drm_i915_private *dev_priv) +{ + uint32_t flags = + I915_READ_FW(GEN6_PCODE_MAILBOX) & GEN6_PCODE_ERROR_MASK; + + switch (flags) { + case GEN6_PCODE_SUCCESS: + return 0; + case GEN6_PCODE_ILLEGAL_CMD: + return -ENXIO; + case GEN7_PCODE_TIMEOUT: + return -ETIMEDOUT; + case GEN7_PCODE_ILLEGAL_DATA: + return -EINVAL; + case GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE: + return -EOVERFLOW; + default: + MISSING_CASE(flags); + return 0; + } +} + int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val) { + int status; + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); /* GEN6_PCODE_* are outside of the forcewake domain, we can @@ -7687,12 +7732,25 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val *val = I915_READ_FW(GEN6_PCODE_DATA); I915_WRITE_FW(GEN6_PCODE_DATA, 0); + if (INTEL_GEN(dev_priv) > 6) + status = gen7_check_mailbox_status(dev_priv); + else + status = gen6_check_mailbox_status(dev_priv); + + if (status) { + DRM_DEBUG_DRIVER("warning: pcode (read) mailbox access failed: %d\n", + status); + return status; + } + return 0; } int sandybridge_pcode_write(struct drm_i915_private *dev_priv, - u32 mbox, u32 val) + u32 mbox, u32 val) { + int status; + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); /* GEN6_PCODE_* are outside of the forcewake domain, we can @@ -7717,6 +7775,17 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, I915_WRITE_FW(GEN6_PCODE_DATA, 0); + if (INTEL_GEN(dev_priv) > 6) + status = gen7_check_mailbox_status(dev_priv); + else + status = gen6_check_mailbox_status(dev_priv); + + if (status) { + DRM_DEBUG_DRIVER("warning: pcode (write) mailbox access failed: %d\n", + status); + return status; + } + return 0; } -- cgit v1.2.1 From 656d1b89e5ffb83036ab0e2a24be7558f34365c7 Mon Sep 17 00:00:00 2001 From: Lyude Date: Wed, 17 Aug 2016 15:55:54 -0400 Subject: drm/i915/skl: Add support for the SAGV, fix underrun hangs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the watermark calculations for Skylake are still broken, we're apt to hitting underruns very easily under multi-monitor configurations. While it would be lovely if this was fixed, it's not. Another problem that's been coming from this however, is the mysterious issue of underruns causing full system hangs. An easy way to reproduce this with a skylake system: - Get a laptop with a skylake GPU, and hook up two external monitors to it - Move the cursor from the built-in LCD to one of the external displays as quickly as you can - You'll get a few pipe underruns, and eventually the entire system will just freeze. After doing a lot of investigation and reading through the bspec, I found the existence of the SAGV, which is responsible for adjusting the system agent voltage and clock frequencies depending on how much power we need. According to the bspec: "The display engine access to system memory is blocked during the adjustment time. SAGV defaults to enabled. Software must use the GT-driver pcode mailbox to disable SAGV when the display engine is not able to tolerate the blocking time." The rest of the bspec goes on to explain that software can simply leave the SAGV enabled, and disable it when we use interlaced pipes/have more then one pipe active. Sure enough, with this patchset the system hangs resulting from pipe underruns on Skylake have completely vanished on my T460s. Additionally, the bspec mentions turning off the SAGV with more then one pipe enabled as a workaround for display underruns. While this patch doesn't entirely fix that, it looks like it does improve the situation a little bit so it's likely this is going to be required to make watermarks on Skylake fully functional. This will still need additional work in the future: we shouldn't be enabling the SAGV if any of the currently enabled planes can't enable WM levels that introduce latencies >= 30 µs. Changes since v11: - Add skl_can_enable_sagv() - Make sure we don't enable SAGV when not all planes can enable watermarks >= the SAGV engine block time. I was originally going to save this for later, but I recently managed to run into a machine that was having problems with a single pipe configuration + SAGV. - Make comparisons to I915_SKL_SAGV_NOT_CONTROLLED explicit - Change I915_SAGV_DYNAMIC_FREQ to I915_SAGV_ENABLE - Move printks outside of mutexes - Don't print error messages twice Changes since v10: - Apparently sandybridge_pcode_read actually writes values and reads them back, despite it's misleading function name. This means we've been doing this mostly wrong and have been writing garbage to the SAGV control. Because of this, we no longer attempt to read the SAGV status during initialization (since there are no helpers for this). - mlankhorst noticed that this patch was breaking on some very early pre-release Skylake machines, which apparently don't allow you to disable the SAGV. To prevent machines from failing tests due to SAGV errors, if the first time we try to control the SAGV results in the mailbox indicating an invalid command, we just disable future attempts to control the SAGV state by setting dev_priv->skl_sagv_status to I915_SKL_SAGV_NOT_CONTROLLED and make a note of it in dmesg. - Move mutex_unlock() a little higher in skl_enable_sagv(). This doesn't actually fix anything, but lets us release the lock a little sooner since we're finished with it. Changes since v9: - Only enable/disable sagv on Skylake Changes since v8: - Add intel_state->modeset guard to the conditional for skl_enable_sagv() Changes since v7: - Remove GEN9_SAGV_LOW_FREQ, replace with GEN9_SAGV_IS_ENABLED (that's all we use it for anyway) - Use GEN9_SAGV_IS_ENABLED instead of 0x1 for clarification - Fix a styling error that snuck past me Changes since v6: - Protect skl_enable_sagv() with intel_state->modeset conditional in intel_atomic_commit_tail() Changes since v5: - Don't use is_power_of_2. Makes things confusing - Don't use the old state to figure out whether or not to enable/disable the sagv, use the new one - Split the loop in skl_disable_sagv into it's own function - Move skl_sagv_enable/disable() calls into intel_atomic_commit_tail() Changes since v4: - Use is_power_of_2 against active_crtcs to check whether we have > 1 pipe enabled - Fix skl_sagv_get_hw_state(): (temp & 0x1) indicates disabled, 0x0 enabled - Call skl_sagv_enable/disable() from pre/post-plane updates Changes since v3: - Use time_before() to compare timeout to jiffies Changes since v2: - Really apply minor style nitpicks to patch this time Changes since v1: - Added comments about this probably being one of the requirements to fixing Skylake's watermark issues - Minor style nitpicks from Matt Roper - Disable these functions on Broxton, since it doesn't have an SAGV Signed-off-by: Lyude Cc: Matt Roper Cc: Maarten Lankhorst Cc: Daniel Vetter Cc: Ville Syrjälä Cc: stable@vger.kernel.org Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471463761-26796-3-git-send-email-cpaul@redhat.com [mlankhorst: ENOSYS -> ENXIO, whitespace fixes] --- drivers/gpu/drm/i915/i915_drv.h | 7 ++ drivers/gpu/drm/i915/i915_reg.h | 4 + drivers/gpu/drm/i915/intel_display.c | 11 +++ drivers/gpu/drm/i915/intel_drv.h | 3 + drivers/gpu/drm/i915/intel_pm.c | 148 +++++++++++++++++++++++++++++++++++ 5 files changed, 173 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e6069057eb98..63e499337ad4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1956,6 +1956,13 @@ struct drm_i915_private { struct i915_suspend_saved_registers regfile; struct vlv_s0ix_state vlv_s0ix_state; + enum { + I915_SKL_SAGV_UNKNOWN = 0, + I915_SKL_SAGV_DISABLED, + I915_SKL_SAGV_ENABLED, + I915_SKL_SAGV_NOT_CONTROLLED + } skl_sagv_status; + struct { /* * Raw watermark latency values: diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7419fbfb145e..a29d707f0932 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7153,6 +7153,10 @@ enum { #define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17 #define DISPLAY_IPS_CONTROL 0x19 #define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A +#define GEN9_PCODE_SAGV_CONTROL 0x21 +#define GEN9_SAGV_DISABLE 0x0 +#define GEN9_SAGV_IS_DISABLED 0x1 +#define GEN9_SAGV_ENABLE 0x3 #define GEN6_PCODE_DATA _MMIO(0x138128) #define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8 #define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3011b22e4b25..e8fee41c9b81 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14145,6 +14145,13 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco)) dev_priv->display.modeset_commit_cdclk(state); + /* + * SKL workaround: bspec recommends we disable the SAGV when we + * have more then one pipe enabled + */ + if (IS_SKYLAKE(dev_priv) && !skl_can_enable_sagv(state)) + skl_disable_sagv(dev_priv); + intel_modeset_verify_disabled(dev); } @@ -14218,6 +14225,10 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state); } + if (IS_SKYLAKE(dev_priv) && intel_state->modeset && + skl_can_enable_sagv(state)) + skl_enable_sagv(dev_priv); + drm_atomic_helper_commit_hw_done(state); if (intel_state->modeset) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1c700b0c3cea..d203c77a2886 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1722,6 +1722,9 @@ void ilk_wm_get_hw_state(struct drm_device *dev); void skl_wm_get_hw_state(struct drm_device *dev); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb /* out */); +bool skl_can_enable_sagv(struct drm_atomic_state *state); +int skl_enable_sagv(struct drm_i915_private *dev_priv); +int skl_disable_sagv(struct drm_i915_private *dev_priv); uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); bool ilk_disable_lp_wm(struct drm_device *dev); int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d0b745534585..5cd4840b78a3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2860,6 +2860,7 @@ bool ilk_disable_lp_wm(struct drm_device *dev) #define SKL_DDB_SIZE 896 /* in blocks */ #define BXT_DDB_SIZE 512 +#define SKL_SAGV_BLOCK_TIME 30 /* µs */ /* * Return the index of a plane in the SKL DDB and wm result arrays. Primary @@ -2883,6 +2884,153 @@ skl_wm_plane_id(const struct intel_plane *plane) } } +/* + * SAGV dynamically adjusts the system agent voltage and clock frequencies + * depending on power and performance requirements. The display engine access + * to system memory is blocked during the adjustment time. Because of the + * blocking time, having this enabled can cause full system hangs and/or pipe + * underruns if we don't meet all of the following requirements: + * + * - <= 1 pipe enabled + * - All planes can enable watermarks for latencies >= SAGV engine block time + * - We're not using an interlaced display configuration + */ +int +skl_enable_sagv(struct drm_i915_private *dev_priv) +{ + int ret; + + if (dev_priv->skl_sagv_status == I915_SKL_SAGV_NOT_CONTROLLED || + dev_priv->skl_sagv_status == I915_SKL_SAGV_ENABLED) + return 0; + + DRM_DEBUG_KMS("Enabling the SAGV\n"); + mutex_lock(&dev_priv->rps.hw_lock); + + ret = sandybridge_pcode_write(dev_priv, GEN9_PCODE_SAGV_CONTROL, + GEN9_SAGV_ENABLE); + + /* We don't need to wait for the SAGV when enabling */ + mutex_unlock(&dev_priv->rps.hw_lock); + + /* + * Some skl systems, pre-release machines in particular, + * don't actually have an SAGV. + */ + if (ret == -ENXIO) { + DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); + dev_priv->skl_sagv_status = I915_SKL_SAGV_NOT_CONTROLLED; + return 0; + } else if (ret < 0) { + DRM_ERROR("Failed to enable the SAGV\n"); + return ret; + } + + dev_priv->skl_sagv_status = I915_SKL_SAGV_ENABLED; + return 0; +} + +static int +skl_do_sagv_disable(struct drm_i915_private *dev_priv) +{ + int ret; + uint32_t temp = GEN9_SAGV_DISABLE; + + ret = sandybridge_pcode_read(dev_priv, GEN9_PCODE_SAGV_CONTROL, + &temp); + if (ret) + return ret; + else + return temp & GEN9_SAGV_IS_DISABLED; +} + +int +skl_disable_sagv(struct drm_i915_private *dev_priv) +{ + int ret, result; + + if (dev_priv->skl_sagv_status == I915_SKL_SAGV_NOT_CONTROLLED || + dev_priv->skl_sagv_status == I915_SKL_SAGV_DISABLED) + return 0; + + DRM_DEBUG_KMS("Disabling the SAGV\n"); + mutex_lock(&dev_priv->rps.hw_lock); + + /* bspec says to keep retrying for at least 1 ms */ + ret = wait_for(result = skl_do_sagv_disable(dev_priv), 1); + mutex_unlock(&dev_priv->rps.hw_lock); + + if (ret == -ETIMEDOUT) { + DRM_ERROR("Request to disable SAGV timed out\n"); + return -ETIMEDOUT; + } + + /* + * Some skl systems, pre-release machines in particular, + * don't actually have an SAGV. + */ + if (result == -ENXIO) { + DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); + dev_priv->skl_sagv_status = I915_SKL_SAGV_NOT_CONTROLLED; + return 0; + } else if (result < 0) { + DRM_ERROR("Failed to disable the SAGV\n"); + return result; + } + + dev_priv->skl_sagv_status = I915_SKL_SAGV_DISABLED; + return 0; +} + +bool skl_can_enable_sagv(struct drm_atomic_state *state) +{ + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct drm_crtc *crtc; + enum pipe pipe; + int level, plane; + + /* + * SKL workaround: bspec recommends we disable the SAGV when we have + * more then one pipe enabled + * + * If there are no active CRTCs, no additional checks need be performed + */ + if (hweight32(intel_state->active_crtcs) == 0) + return true; + else if (hweight32(intel_state->active_crtcs) > 1) + return false; + + /* Since we're now guaranteed to only have one active CRTC... */ + pipe = ffs(intel_state->active_crtcs) - 1; + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + + if (crtc->state->mode.flags & DRM_MODE_FLAG_INTERLACE) + return false; + + for_each_plane(dev_priv, pipe, plane) { + /* Skip this plane if it's not enabled */ + if (intel_state->wm_results.plane[pipe][plane][0] == 0) + continue; + + /* Find the highest enabled wm level for this plane */ + for (level = ilk_wm_max_level(dev); + intel_state->wm_results.plane[pipe][plane][level] == 0; --level) + { } + + /* + * If any of the planes on this pipe don't enable wm levels + * that incur memory latencies higher then 30µs we can't enable + * the SAGV + */ + if (dev_priv->wm.skl_latency[level] < SKL_SAGV_BLOCK_TIME) + return false; + } + + return true; +} + static void skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, const struct intel_crtc_state *cstate, -- cgit v1.2.1 From 2722efb90b3420dee54b4cb3cdc7917efacc2dce Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 17 Aug 2016 15:55:55 -0400 Subject: drm/i915/gen9: Only copy WM results for changed pipes to skl_hw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we write watermark values to the hardware, those values are stored in dev_priv->wm.skl_hw. However with recent watermark changes, the results structure we're copying from only contains valid watermark and DDB values for the pipes that are actually changing; the values for other pipes remain 0. Thus a blind copy of the entire skl_wm_values structure will clobber the values for unchanged pipes...we need to be more selective and only copy over the values for the changing pipes. This mistake was hidden until recently due to another bug that caused us to erroneously re-calculate watermarks for all active pipes rather than changing pipes. Only when that bug was fixed was the impact of this bug discovered (e.g., modesets failing with "Requested display configuration exceeds system watermark limitations" messages and leaving watermarks non-functional, even ones initiated by intel_fbdev_restore_mode). Changes since v1: - Add a function for copying a pipe's wm values (skl_copy_wm_for_pipe()) so we can reuse this later Fixes: 734fa01f3a17 ("drm/i915/gen9: Calculate watermarks during atomic 'check' (v2)") Fixes: 9b6130227495 ("drm/i915/gen9: Re-allocate DDB only for changed pipes") Signed-off-by: Matt Roper Signed-off-by: Lyude Reviewed-by: Matt Roper Cc: stable@vger.kernel.org Cc: Maarten Lankhorst Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Radhakrishna Sripada Cc: Hans de Goede Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471463761-26796-4-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_pm.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5cd4840b78a3..177fdf3194f7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4117,6 +4117,24 @@ skl_compute_ddb(struct drm_atomic_state *state) return 0; } +static void +skl_copy_wm_for_pipe(struct skl_wm_values *dst, + struct skl_wm_values *src, + enum pipe pipe) +{ + dst->wm_linetime[pipe] = src->wm_linetime[pipe]; + memcpy(dst->plane[pipe], src->plane[pipe], + sizeof(dst->plane[pipe])); + memcpy(dst->plane_trans[pipe], src->plane_trans[pipe], + sizeof(dst->plane_trans[pipe])); + + dst->ddb.pipe[pipe] = src->ddb.pipe[pipe]; + memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe], + sizeof(dst->ddb.y_plane[pipe])); + memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], + sizeof(dst->ddb.plane[pipe])); +} + static int skl_compute_wm(struct drm_atomic_state *state) { @@ -4189,8 +4207,10 @@ static void skl_update_wm(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct skl_wm_values *results = &dev_priv->wm.skl_results; + struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw; struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal; + int pipe; if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0) return; @@ -4202,8 +4222,12 @@ static void skl_update_wm(struct drm_crtc *crtc) skl_write_wm_values(dev_priv, results); skl_flush_wm_values(dev_priv, results); - /* store the new configuration */ - dev_priv->wm.skl_hw = *results; + /* + * Store the new configuration (but only for the pipes that have + * changed; the other values weren't recomputed). + */ + for_each_pipe_masked(dev_priv, pipe, results->dirty_pipes) + skl_copy_wm_for_pipe(hw_vals, results, pipe); mutex_unlock(&dev_priv->wm.wm_mutex); } -- cgit v1.2.1 From 05a76d3d6ad1ee9f9814f88949cc9305fc165460 Mon Sep 17 00:00:00 2001 From: Lyude Date: Wed, 17 Aug 2016 15:55:57 -0400 Subject: drm/i915/skl: Ensure pipes with changed wms get added to the state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we're enabling a pipe, we'll need to modify the watermarks on all active planes. Since those planes won't be added to the state on their own, we need to add them ourselves. Signed-off-by: Lyude Reviewed-by: Matt Roper Cc: stable@vger.kernel.org Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Radhakrishna Sripada Cc: Hans de Goede Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471463761-26796-6-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_pm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 177fdf3194f7..5e3f17059bed 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4112,6 +4112,10 @@ skl_compute_ddb(struct drm_atomic_state *state) ret = skl_allocate_pipe_ddb(cstate, ddb); if (ret) return ret; + + ret = drm_atomic_add_affected_planes(state, &intel_crtc->base); + if (ret) + return ret; } return 0; -- cgit v1.2.1 From 536ab3ca19ef856e84389a155c5832c68559a28a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 15 Aug 2016 15:09:27 +0200 Subject: drm/i915: Fix botched merge that downgrades CSR versions. Merge commit 5e580523d9128a4d8 reverts the version bumping parts of commit 4aa7fb9c3c4fa0. Bump the versions again and request the specific firmware version. The currently recommended versions are: SKL 1.26, KBL 1.01 and BXT 1.07. Cc: Patrik Jakobsson Cc: Imre Deak Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97242 Cc: drm-intel-fixes@lists.freedesktop.org Fixes: 5e580523d912 ("Backmerge tag 'v4.7' into drm-next") Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471266567-22443-1-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/intel_csr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index fb27d187876c..1ea0e1f43397 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -34,15 +34,15 @@ * low-power state and comes back to normal. */ -#define I915_CSR_KBL "i915/kbl_dmc_ver1.bin" +#define I915_CSR_KBL "i915/kbl_dmc_ver1_01.bin" MODULE_FIRMWARE(I915_CSR_KBL); #define KBL_CSR_VERSION_REQUIRED CSR_VERSION(1, 1) -#define I915_CSR_SKL "i915/skl_dmc_ver1.bin" +#define I915_CSR_SKL "i915/skl_dmc_ver1_26.bin" MODULE_FIRMWARE(I915_CSR_SKL); -#define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 23) +#define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 26) -#define I915_CSR_BXT "i915/bxt_dmc_ver1.bin" +#define I915_CSR_BXT "i915/bxt_dmc_ver1_07.bin" MODULE_FIRMWARE(I915_CSR_BXT); #define BXT_CSR_VERSION_REQUIRED CSR_VERSION(1, 7) -- cgit v1.2.1 From 351c3b53e767b2512461843882f7c6baa8996c4b Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Mon, 22 Aug 2016 13:32:41 +0300 Subject: drm/i915: cosmetic fixes to i915_drv.h Fix minor whitespace issues plus a typo. Signed-off-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20160822103245.24069-2-david.weinehall@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 63e499337ad4..2089066b5b87 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2556,7 +2556,7 @@ struct drm_i915_cmd_table { BUILD_BUG(); \ __p; \ }) -#define INTEL_INFO(p) (&__I915__(p)->info) +#define INTEL_INFO(p) (&__I915__(p)->info) #define INTEL_GEN(p) (INTEL_INFO(p)->gen) #define INTEL_DEVID(p) (INTEL_INFO(p)->device_id) @@ -2850,7 +2850,7 @@ extern int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state); extern int i915_resume_switcheroo(struct drm_device *dev); int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, - int enable_ppgtt); + int enable_ppgtt); bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value); @@ -3787,7 +3787,7 @@ __raw_write(64, q) #undef __raw_write /* These are untraced mmio-accessors that are only valid to be used inside - * criticial sections inside IRQ handlers where forcewake is explicitly + * critical sections inside IRQ handlers where forcewake is explicitly * controlled. * Think twice, and think again, before using these. * Note: Should only be used between intel_uncore_forcewake_irqlock() and -- cgit v1.2.1 From c49d13ee13f709852cc05f9035df89e9ffa26108 Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Mon, 22 Aug 2016 13:32:42 +0300 Subject: drm/i915: consistent struct device naming We currently have a mix of struct device *device, struct device *kdev, and struct device *dev (the latter forcing us to refer to struct drm_device as something else than the normal dev). To simplify things, always use kdev when referring to struct device. v2: Replace the dev_to_drm_minor() macro with the inline function kdev_to_drm_minor(). Signed-off-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20160822103245.24069-3-david.weinehall@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 96 ++++++++++++++++----------------- drivers/gpu/drm/i915/i915_drv.h | 4 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 +-- drivers/gpu/drm/i915/i915_sysfs.c | 65 +++++++++++----------- drivers/gpu/drm/i915/intel_audio.c | 46 ++++++++-------- drivers/gpu/drm/i915/intel_runtime_pm.c | 37 +++++++------ 6 files changed, 128 insertions(+), 126 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 13ae340ef1f3..53f9535fb81e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -77,7 +77,7 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, const char *fmt, ...) { static bool shown_bug_once; - struct device *dev = dev_priv->drm.dev; + struct device *kdev = dev_priv->drm.dev; bool is_error = level[1] <= KERN_ERR[1]; bool is_debug = level[1] == KERN_DEBUG[1]; struct va_format vaf; @@ -91,11 +91,11 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, vaf.fmt = fmt; vaf.va = &args; - dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV", + dev_printk(level, kdev, "[" DRM_NAME ":%ps] %pV", __builtin_return_address(0), &vaf); if (is_error && !shown_bug_once) { - dev_notice(dev, "%s", FDO_BUG_MSG); + dev_notice(kdev, "%s", FDO_BUG_MSG); shown_bug_once = true; } @@ -1462,9 +1462,9 @@ out: return error; } -static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) +static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) { - struct drm_i915_private *dev_priv = to_i915(drm_dev); + struct drm_i915_private *dev_priv = to_i915(dev); bool fw_csr; int ret; @@ -1498,7 +1498,7 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) goto out; } - pci_disable_device(drm_dev->pdev); + pci_disable_device(dev->pdev); /* * During hibernation on some platforms the BIOS may try to access * the device even though it's already in D3 and hang the machine. So @@ -1512,7 +1512,7 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) * Acer Aspire 1830T */ if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6)) - pci_set_power_state(drm_dev->pdev, PCI_D3hot); + pci_set_power_state(dev->pdev, PCI_D3hot); dev_priv->suspended_to_idle = suspend_to_idle(dev_priv); @@ -1810,25 +1810,25 @@ error: return ret; } -static int i915_pm_suspend(struct device *dev) +static int i915_pm_suspend(struct device *kdev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct pci_dev *pdev = to_pci_dev(kdev); + struct drm_device *dev = pci_get_drvdata(pdev); - if (!drm_dev) { - dev_err(dev, "DRM not initialized, aborting suspend.\n"); + if (!dev) { + dev_err(kdev, "DRM not initialized, aborting suspend.\n"); return -ENODEV; } - if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - return i915_drm_suspend(drm_dev); + return i915_drm_suspend(dev); } -static int i915_pm_suspend_late(struct device *dev) +static int i915_pm_suspend_late(struct device *kdev) { - struct drm_device *drm_dev = &dev_to_i915(dev)->drm; + struct drm_device *dev = &kdev_to_i915(kdev)->drm; /* * We have a suspend ordering issue with the snd-hda driver also @@ -1839,57 +1839,57 @@ static int i915_pm_suspend_late(struct device *dev) * FIXME: This should be solved with a special hdmi sink device or * similar so that power domains can be employed. */ - if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - return i915_drm_suspend_late(drm_dev, false); + return i915_drm_suspend_late(dev, false); } -static int i915_pm_poweroff_late(struct device *dev) +static int i915_pm_poweroff_late(struct device *kdev) { - struct drm_device *drm_dev = &dev_to_i915(dev)->drm; + struct drm_device *dev = &kdev_to_i915(kdev)->drm; - if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - return i915_drm_suspend_late(drm_dev, true); + return i915_drm_suspend_late(dev, true); } -static int i915_pm_resume_early(struct device *dev) +static int i915_pm_resume_early(struct device *kdev) { - struct drm_device *drm_dev = &dev_to_i915(dev)->drm; + struct drm_device *dev = &kdev_to_i915(kdev)->drm; - if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - return i915_drm_resume_early(drm_dev); + return i915_drm_resume_early(dev); } -static int i915_pm_resume(struct device *dev) +static int i915_pm_resume(struct device *kdev) { - struct drm_device *drm_dev = &dev_to_i915(dev)->drm; + struct drm_device *dev = &kdev_to_i915(kdev)->drm; - if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) + if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - return i915_drm_resume(drm_dev); + return i915_drm_resume(dev); } /* freeze: before creating the hibernation_image */ -static int i915_pm_freeze(struct device *dev) +static int i915_pm_freeze(struct device *kdev) { - return i915_pm_suspend(dev); + return i915_pm_suspend(kdev); } -static int i915_pm_freeze_late(struct device *dev) +static int i915_pm_freeze_late(struct device *kdev) { int ret; - ret = i915_pm_suspend_late(dev); + ret = i915_pm_suspend_late(kdev); if (ret) return ret; - ret = i915_gem_freeze_late(dev_to_i915(dev)); + ret = i915_gem_freeze_late(kdev_to_i915(kdev)); if (ret) return ret; @@ -1897,25 +1897,25 @@ static int i915_pm_freeze_late(struct device *dev) } /* thaw: called after creating the hibernation image, but before turning off. */ -static int i915_pm_thaw_early(struct device *dev) +static int i915_pm_thaw_early(struct device *kdev) { - return i915_pm_resume_early(dev); + return i915_pm_resume_early(kdev); } -static int i915_pm_thaw(struct device *dev) +static int i915_pm_thaw(struct device *kdev) { - return i915_pm_resume(dev); + return i915_pm_resume(kdev); } /* restore: called after loading the hibernation image. */ -static int i915_pm_restore_early(struct device *dev) +static int i915_pm_restore_early(struct device *kdev) { - return i915_pm_resume_early(dev); + return i915_pm_resume_early(kdev); } -static int i915_pm_restore(struct device *dev) +static int i915_pm_restore(struct device *kdev) { - return i915_pm_resume(dev); + return i915_pm_resume(kdev); } /* @@ -2277,9 +2277,9 @@ static int vlv_resume_prepare(struct drm_i915_private *dev_priv, return ret; } -static int intel_runtime_suspend(struct device *device) +static int intel_runtime_suspend(struct device *kdev) { - struct pci_dev *pdev = to_pci_dev(device); + struct pci_dev *pdev = to_pci_dev(kdev); struct drm_device *dev = pci_get_drvdata(pdev); struct drm_i915_private *dev_priv = to_i915(dev); int ret; @@ -2305,7 +2305,7 @@ static int intel_runtime_suspend(struct device *device) * Bump the expiration timestamp, otherwise the suspend won't * be rescheduled. */ - pm_runtime_mark_last_busy(device); + pm_runtime_mark_last_busy(kdev); return -EAGAIN; } @@ -2384,9 +2384,9 @@ static int intel_runtime_suspend(struct device *device) return 0; } -static int intel_runtime_resume(struct device *device) +static int intel_runtime_resume(struct device *kdev) { - struct pci_dev *pdev = to_pci_dev(device); + struct pci_dev *pdev = to_pci_dev(kdev); struct drm_device *dev = pci_get_drvdata(pdev); struct drm_i915_private *dev_priv = to_i915(dev); int ret = 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2089066b5b87..79e67960ffc8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2064,9 +2064,9 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev) return container_of(dev, struct drm_i915_private, drm); } -static inline struct drm_i915_private *dev_to_i915(struct device *dev) +static inline struct drm_i915_private *kdev_to_i915(struct device *kdev) { - return to_i915(dev_get_drvdata(dev)); + return to_i915(dev_get_drvdata(kdev)); } static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index b3cd9e21c8da..d31ae3d0f83f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -326,16 +326,16 @@ static gen6_pte_t iris_pte_encode(dma_addr_t addr, static int __setup_page_dma(struct drm_device *dev, struct i915_page_dma *p, gfp_t flags) { - struct device *device = &dev->pdev->dev; + struct device *kdev = &dev->pdev->dev; p->page = alloc_page(flags); if (!p->page) return -ENOMEM; - p->daddr = dma_map_page(device, + p->daddr = dma_map_page(kdev, p->page, 0, 4096, PCI_DMA_BIDIRECTIONAL); - if (dma_mapping_error(device, p->daddr)) { + if (dma_mapping_error(kdev, p->daddr)) { __free_page(p->page); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index f1ffde7f7c0b..05cb95bf2f4b 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -32,7 +32,10 @@ #include "intel_drv.h" #include "i915_drv.h" -#define dev_to_drm_minor(d) dev_get_drvdata((d)) +static inline struct drm_minor *kdev_to_drm_minor(struct device *kdev) +{ + return dev_get_drvdata(kdev); +} #ifdef CONFIG_PM static u32 calc_residency(struct drm_device *dev, @@ -84,7 +87,7 @@ show_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf) static ssize_t show_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = dev_to_drm_minor(kdev); + struct drm_minor *dminor = kdev_to_drm_minor(kdev); u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p); return snprintf(buf, PAGE_SIZE, "%u\n", rc6p_residency); } @@ -92,7 +95,7 @@ show_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf) static ssize_t show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = dev_to_drm_minor(kdev); + struct drm_minor *dminor = kdev_to_drm_minor(kdev); u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp); return snprintf(buf, PAGE_SIZE, "%u\n", rc6pp_residency); } @@ -163,22 +166,22 @@ i915_l3_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t offset, size_t count) { - struct device *dev = kobj_to_dev(kobj); - struct drm_minor *dminor = dev_to_drm_minor(dev); - struct drm_device *drm_dev = dminor->dev; - struct drm_i915_private *dev_priv = to_i915(drm_dev); + struct device *kdev = kobj_to_dev(kobj); + struct drm_minor *dminor = kdev_to_drm_minor(kdev); + struct drm_device *dev = dminor->dev; + struct drm_i915_private *dev_priv = to_i915(dev); int slice = (int)(uintptr_t)attr->private; int ret; count = round_down(count, 4); - ret = l3_access_valid(drm_dev, offset); + ret = l3_access_valid(dev, offset); if (ret) return ret; count = min_t(size_t, GEN7_L3LOG_SIZE - offset, count); - ret = i915_mutex_lock_interruptible(drm_dev); + ret = i915_mutex_lock_interruptible(dev); if (ret) return ret; @@ -189,7 +192,7 @@ i915_l3_read(struct file *filp, struct kobject *kobj, else memset(buf, 0, count); - mutex_unlock(&drm_dev->struct_mutex); + mutex_unlock(&dev->struct_mutex); return count; } @@ -199,30 +202,30 @@ i915_l3_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t offset, size_t count) { - struct device *dev = kobj_to_dev(kobj); - struct drm_minor *dminor = dev_to_drm_minor(dev); - struct drm_device *drm_dev = dminor->dev; - struct drm_i915_private *dev_priv = to_i915(drm_dev); + struct device *kdev = kobj_to_dev(kobj); + struct drm_minor *dminor = kdev_to_drm_minor(kdev); + struct drm_device *dev = dminor->dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct i915_gem_context *ctx; u32 *temp = NULL; /* Just here to make handling failures easy */ int slice = (int)(uintptr_t)attr->private; int ret; - if (!HAS_HW_CONTEXTS(drm_dev)) + if (!HAS_HW_CONTEXTS(dev)) return -ENXIO; - ret = l3_access_valid(drm_dev, offset); + ret = l3_access_valid(dev, offset); if (ret) return ret; - ret = i915_mutex_lock_interruptible(drm_dev); + ret = i915_mutex_lock_interruptible(dev); if (ret) return ret; if (!dev_priv->l3_parity.remap_info[slice]) { temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); if (!temp) { - mutex_unlock(&drm_dev->struct_mutex); + mutex_unlock(&dev->struct_mutex); return -ENOMEM; } } @@ -240,7 +243,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, list_for_each_entry(ctx, &dev_priv->context_list, link) ctx->remap_slice |= (1<struct_mutex); + mutex_unlock(&dev->struct_mutex); return count; } @@ -266,7 +269,7 @@ static 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_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); int ret; @@ -298,7 +301,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev, static ssize_t gt_cur_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -309,7 +312,7 @@ 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_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_i915_private *dev_priv = to_i915(minor->dev); return snprintf(buf, PAGE_SIZE, "%d\n", @@ -321,7 +324,7 @@ static ssize_t gt_boost_freq_mhz_store(struct device *kdev, struct device_attribute *attr, const char *buf, size_t count) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); u32 val; @@ -346,7 +349,7 @@ static ssize_t gt_boost_freq_mhz_store(struct device *kdev, static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -357,7 +360,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -370,7 +373,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, struct device_attribute *attr, const char *buf, size_t count) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); u32 val; @@ -418,7 +421,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -431,7 +434,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, struct device_attribute *attr, const char *buf, size_t count) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); u32 val; @@ -490,7 +493,7 @@ static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); /* For now we have a static number of RP states */ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); u32 val; @@ -538,7 +541,7 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, { struct device *kdev = kobj_to_dev(kobj); - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; struct i915_error_state_file_priv error_priv; struct drm_i915_error_state_buf error_str; @@ -573,7 +576,7 @@ static ssize_t error_state_write(struct file *file, struct kobject *kobj, loff_t off, size_t count) { struct device *kdev = kobj_to_dev(kobj); - struct drm_minor *minor = dev_to_drm_minor(kdev); + struct drm_minor *minor = kdev_to_drm_minor(kdev); struct drm_device *dev = minor->dev; int ret; diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index d32f586f9c05..762572aeca23 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -581,26 +581,26 @@ void intel_init_audio_hooks(struct drm_i915_private *dev_priv) } } -static void i915_audio_component_get_power(struct device *dev) +static void i915_audio_component_get_power(struct device *kdev) { - intel_display_power_get(dev_to_i915(dev), POWER_DOMAIN_AUDIO); + intel_display_power_get(kdev_to_i915(kdev), POWER_DOMAIN_AUDIO); } -static void i915_audio_component_put_power(struct device *dev) +static void i915_audio_component_put_power(struct device *kdev) { - intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO); + intel_display_power_put(kdev_to_i915(kdev), POWER_DOMAIN_AUDIO); } -static void i915_audio_component_codec_wake_override(struct device *dev, +static void i915_audio_component_codec_wake_override(struct device *kdev, bool enable) { - struct drm_i915_private *dev_priv = dev_to_i915(dev); + struct drm_i915_private *dev_priv = kdev_to_i915(kdev); u32 tmp; if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)) return; - i915_audio_component_get_power(dev); + i915_audio_component_get_power(kdev); /* * Enable/disable generating the codec wake signal, overriding the @@ -618,13 +618,13 @@ static void i915_audio_component_codec_wake_override(struct device *dev, usleep_range(1000, 1500); } - i915_audio_component_put_power(dev); + i915_audio_component_put_power(kdev); } /* Get CDCLK in kHz */ -static int i915_audio_component_get_cdclk_freq(struct device *dev) +static int i915_audio_component_get_cdclk_freq(struct device *kdev) { - struct drm_i915_private *dev_priv = dev_to_i915(dev); + struct drm_i915_private *dev_priv = kdev_to_i915(kdev); if (WARN_ON_ONCE(!HAS_DDI(dev_priv))) return -ENODEV; @@ -632,10 +632,10 @@ static int i915_audio_component_get_cdclk_freq(struct device *dev) return dev_priv->cdclk_freq; } -static int i915_audio_component_sync_audio_rate(struct device *dev, +static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, int rate) { - struct drm_i915_private *dev_priv = dev_to_i915(dev); + struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_encoder *intel_encoder; struct intel_crtc *crtc; struct drm_display_mode *mode; @@ -652,7 +652,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, !IS_HASWELL(dev_priv)) return 0; - i915_audio_component_get_power(dev); + i915_audio_component_get_power(kdev); mutex_lock(&dev_priv->av_mutex); /* 1. get the pipe */ intel_encoder = dev_priv->dig_port_map[port]; @@ -703,15 +703,15 @@ static int i915_audio_component_sync_audio_rate(struct device *dev, unlock: mutex_unlock(&dev_priv->av_mutex); - i915_audio_component_put_power(dev); + i915_audio_component_put_power(kdev); return err; } -static int i915_audio_component_get_eld(struct device *dev, int port, +static int i915_audio_component_get_eld(struct device *kdev, int port, bool *enabled, unsigned char *buf, int max_bytes) { - struct drm_i915_private *dev_priv = dev_to_i915(dev); + struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_encoder *intel_encoder; struct intel_digital_port *intel_dig_port; const u8 *eld; @@ -745,11 +745,11 @@ static const struct i915_audio_component_ops i915_audio_component_ops = { .get_eld = i915_audio_component_get_eld, }; -static int i915_audio_component_bind(struct device *i915_dev, - struct device *hda_dev, void *data) +static int i915_audio_component_bind(struct device *i915_kdev, + struct device *hda_kdev, void *data) { struct i915_audio_component *acomp = data; - struct drm_i915_private *dev_priv = dev_to_i915(i915_dev); + struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev); int i; if (WARN_ON(acomp->ops || acomp->dev)) @@ -757,7 +757,7 @@ static int i915_audio_component_bind(struct device *i915_dev, drm_modeset_lock_all(&dev_priv->drm); acomp->ops = &i915_audio_component_ops; - acomp->dev = i915_dev; + acomp->dev = i915_kdev; BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) acomp->aud_sample_rate[i] = 0; @@ -767,11 +767,11 @@ static int i915_audio_component_bind(struct device *i915_dev, return 0; } -static void i915_audio_component_unbind(struct device *i915_dev, - struct device *hda_dev, void *data) +static void i915_audio_component_unbind(struct device *i915_kdev, + struct device *hda_kdev, void *data) { struct i915_audio_component *acomp = data; - struct drm_i915_private *dev_priv = dev_to_i915(i915_dev); + struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev); drm_modeset_lock_all(&dev_priv->drm); acomp->ops = NULL; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index a1d73c2de332..7686b7f1d599 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2288,7 +2288,7 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) */ void intel_power_domains_fini(struct drm_i915_private *dev_priv) { - struct device *device = &dev_priv->drm.pdev->dev; + struct device *kdev = &dev_priv->drm.pdev->dev; /* * The i915.ko module is still not prepared to be loaded when @@ -2310,7 +2310,7 @@ void intel_power_domains_fini(struct drm_i915_private *dev_priv) * the platform doesn't support runtime PM. */ if (!HAS_RUNTIME_PM(dev_priv)) - pm_runtime_put(device); + pm_runtime_put(kdev); } static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv) @@ -2652,9 +2652,9 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv) void intel_runtime_pm_get(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; - struct device *device = &dev->pdev->dev; + struct device *kdev = &dev->pdev->dev; - pm_runtime_get_sync(device); + pm_runtime_get_sync(kdev); atomic_inc(&dev_priv->pm.wakeref_count); assert_rpm_wakelock_held(dev_priv); @@ -2673,10 +2673,10 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; - struct device *device = &dev->pdev->dev; + struct device *kdev = &dev->pdev->dev; if (IS_ENABLED(CONFIG_PM)) { - int ret = pm_runtime_get_if_in_use(device); + int ret = pm_runtime_get_if_in_use(kdev); /* * In cases runtime PM is disabled by the RPM core and we get @@ -2715,10 +2715,10 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; - struct device *device = &dev->pdev->dev; + struct device *kdev = &dev->pdev->dev; assert_rpm_wakelock_held(dev_priv); - pm_runtime_get_noresume(device); + pm_runtime_get_noresume(kdev); atomic_inc(&dev_priv->pm.wakeref_count); } @@ -2734,14 +2734,14 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv) void intel_runtime_pm_put(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; - struct device *device = &dev->pdev->dev; + struct device *kdev = &dev->pdev->dev; assert_rpm_wakelock_held(dev_priv); if (atomic_dec_and_test(&dev_priv->pm.wakeref_count)) atomic_inc(&dev_priv->pm.atomic_seq); - pm_runtime_mark_last_busy(device); - pm_runtime_put_autosuspend(device); + pm_runtime_mark_last_busy(kdev); + pm_runtime_put_autosuspend(kdev); } /** @@ -2757,10 +2757,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv) void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; - struct device *device = &dev->pdev->dev; + struct device *kdev = &dev->pdev->dev; - pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */ - pm_runtime_mark_last_busy(device); + pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */ + pm_runtime_mark_last_busy(kdev); /* * Take a permanent reference to disable the RPM functionality and drop @@ -2769,10 +2769,10 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) * platforms without RPM support. */ if (!HAS_RUNTIME_PM(dev)) { - pm_runtime_dont_use_autosuspend(device); - pm_runtime_get_sync(device); + pm_runtime_dont_use_autosuspend(kdev); + pm_runtime_get_sync(kdev); } else { - pm_runtime_use_autosuspend(device); + pm_runtime_use_autosuspend(kdev); } /* @@ -2780,6 +2780,5 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) * We drop that here and will reacquire it during unloading in * intel_power_domains_fini(). */ - pm_runtime_put_autosuspend(device); + pm_runtime_put_autosuspend(kdev); } - -- cgit v1.2.1 From 694c2828459e1d048b79c42dd8decbafb099707d Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Mon, 22 Aug 2016 13:32:43 +0300 Subject: drm/i915: i915_sysfs.c cleanup Various cleanup for i915_sysfs.c; we now use dev_priv whenever possible. The kdev_to_drm_minor() helper function has been replaced by one that converts from struct device * to struct drm_i915_private *. We already have a seemingly identical helper (kdev_to_i915()) in i915_drv.h. But that one cannot be used here. Unlike the version in i915_drv.h, this helper reaches i915 through drm_minor. v2: Rename kdev_to_i915_dm() to kdev_minor_to_i915() (Chris) Signed-off-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20160822103245.24069-4-david.weinehall@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 4 +- drivers/gpu/drm/i915/i915_sysfs.c | 148 +++++++++++++++++--------------------- 3 files changed, 69 insertions(+), 87 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 53f9535fb81e..c316034aeda3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1133,7 +1133,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) /* Reveal our presence to userspace */ if (drm_dev_register(dev, 0) == 0) { i915_debugfs_register(dev_priv); - i915_setup_sysfs(dev); + i915_setup_sysfs(dev_priv); } else DRM_ERROR("Failed to register driver for userspace access!\n"); @@ -1170,7 +1170,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) acpi_video_unregister(); intel_opregion_unregister(dev_priv); - i915_teardown_sysfs(&dev_priv->drm); + i915_teardown_sysfs(dev_priv); i915_debugfs_unregister(dev_priv); drm_dev_unregister(&dev_priv->drm); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 79e67960ffc8..dd7d76a9e01b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3564,8 +3564,8 @@ extern int i915_save_state(struct drm_device *dev); extern int i915_restore_state(struct drm_device *dev); /* i915_sysfs.c */ -void i915_setup_sysfs(struct drm_device *dev_priv); -void i915_teardown_sysfs(struct drm_device *dev_priv); +void i915_setup_sysfs(struct drm_i915_private *dev_priv); +void i915_teardown_sysfs(struct drm_i915_private *dev_priv); /* intel_i2c.c */ extern int intel_setup_gmbus(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 05cb95bf2f4b..2d482f677f56 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -32,16 +32,16 @@ #include "intel_drv.h" #include "i915_drv.h" -static inline struct drm_minor *kdev_to_drm_minor(struct device *kdev) +static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev) { - return dev_get_drvdata(kdev); + struct drm_minor *minor = dev_get_drvdata(kdev); + return to_i915(minor->dev); } #ifdef CONFIG_PM -static u32 calc_residency(struct drm_device *dev, +static u32 calc_residency(struct drm_i915_private *dev_priv, i915_reg_t reg) { - struct drm_i915_private *dev_priv = to_i915(dev); u64 raw_time; /* 32b value may overflow during fixed point math */ u64 units = 128ULL, div = 100000ULL; u32 ret; @@ -52,13 +52,13 @@ static u32 calc_residency(struct drm_device *dev, intel_runtime_pm_get(dev_priv); /* On VLV and CHV, residency time is in CZ units rather than 1.28us */ - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { units = 1; div = dev_priv->czclk_freq; if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) units <<= 8; - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { units = 1; div = 1200; /* 833.33ns */ } @@ -79,32 +79,32 @@ show_rc6_mask(struct device *kdev, struct device_attribute *attr, char *buf) static ssize_t show_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = dev_get_drvdata(kdev); - u32 rc6_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6); return snprintf(buf, PAGE_SIZE, "%u\n", rc6_residency); } static ssize_t show_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = kdev_to_drm_minor(kdev); - u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p); return snprintf(buf, PAGE_SIZE, "%u\n", rc6p_residency); } static ssize_t show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = kdev_to_drm_minor(kdev); - u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp); return snprintf(buf, PAGE_SIZE, "%u\n", rc6pp_residency); } static ssize_t show_media_rc6_ms(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *dminor = dev_get_drvdata(kdev); - u32 rc6_residency = calc_residency(dminor->dev, VLV_GT_MEDIA_RC6); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6); return snprintf(buf, PAGE_SIZE, "%u\n", rc6_residency); } @@ -147,9 +147,9 @@ static struct attribute_group media_rc6_attr_group = { }; #endif -static int l3_access_valid(struct drm_device *dev, loff_t offset) +static int l3_access_valid(struct drm_i915_private *dev_priv, loff_t offset) { - if (!HAS_L3_DPF(dev)) + if (!HAS_L3_DPF(dev_priv)) return -EPERM; if (offset % 4 != 0) @@ -167,15 +167,14 @@ i915_l3_read(struct file *filp, struct kobject *kobj, loff_t offset, size_t count) { struct device *kdev = kobj_to_dev(kobj); - struct drm_minor *dminor = kdev_to_drm_minor(kdev); - struct drm_device *dev = dminor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + struct drm_device *dev = &dev_priv->drm; int slice = (int)(uintptr_t)attr->private; int ret; count = round_down(count, 4); - ret = l3_access_valid(dev, offset); + ret = l3_access_valid(dev_priv, offset); if (ret) return ret; @@ -203,18 +202,17 @@ i915_l3_write(struct file *filp, struct kobject *kobj, loff_t offset, size_t count) { struct device *kdev = kobj_to_dev(kobj); - struct drm_minor *dminor = kdev_to_drm_minor(kdev); - struct drm_device *dev = dminor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + struct drm_device *dev = &dev_priv->drm; struct i915_gem_context *ctx; u32 *temp = NULL; /* Just here to make handling failures easy */ int slice = (int)(uintptr_t)attr->private; int ret; - if (!HAS_HW_CONTEXTS(dev)) + if (!HAS_HW_CONTEXTS(dev_priv)) return -ENXIO; - ret = l3_access_valid(dev, offset); + ret = l3_access_valid(dev_priv, offset); if (ret) return ret; @@ -269,9 +267,7 @@ static 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_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); int ret; intel_runtime_pm_get(dev_priv); @@ -301,9 +297,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev, static ssize_t gt_cur_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, @@ -312,8 +306,7 @@ 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_minor *minor = kdev_to_drm_minor(kdev); - struct drm_i915_private *dev_priv = to_i915(minor->dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, @@ -324,9 +317,7 @@ static ssize_t gt_boost_freq_mhz_store(struct device *kdev, struct device_attribute *attr, const char *buf, size_t count) { - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); u32 val; ssize_t ret; @@ -349,9 +340,7 @@ static ssize_t gt_boost_freq_mhz_store(struct device *kdev, static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, @@ -360,9 +349,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, @@ -373,9 +360,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, struct device_attribute *attr, const char *buf, size_t count) { - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); u32 val; ssize_t ret; @@ -421,9 +406,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, @@ -434,9 +417,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, struct device_attribute *attr, const char *buf, size_t count) { - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); u32 val; ssize_t ret; @@ -493,9 +474,7 @@ static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); /* For now we have a static number of RP states */ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); u32 val; if (attr == &dev_attr_gt_RP0_freq_mhz) @@ -541,8 +520,8 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj, { struct device *kdev = kobj_to_dev(kobj); - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + struct drm_device *dev = &dev_priv->drm; struct i915_error_state_file_priv error_priv; struct drm_i915_error_state_buf error_str; ssize_t ret_count = 0; @@ -576,8 +555,8 @@ static ssize_t error_state_write(struct file *file, struct kobject *kobj, loff_t off, size_t count) { struct device *kdev = kobj_to_dev(kobj); - struct drm_minor *minor = kdev_to_drm_minor(kdev); - struct drm_device *dev = minor->dev; + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + struct drm_device *dev = &dev_priv->drm; int ret; DRM_DEBUG_DRIVER("Resetting error state\n"); @@ -600,37 +579,38 @@ static struct bin_attribute error_state_attr = { .write = error_state_write, }; -void i915_setup_sysfs(struct drm_device *dev) +void i915_setup_sysfs(struct drm_i915_private *dev_priv) { + struct device *kdev = dev_priv->drm.primary->kdev; int ret; #ifdef CONFIG_PM - if (HAS_RC6(dev)) { - ret = sysfs_merge_group(&dev->primary->kdev->kobj, + if (HAS_RC6(dev_priv)) { + ret = sysfs_merge_group(&kdev->kobj, &rc6_attr_group); if (ret) DRM_ERROR("RC6 residency sysfs setup failed\n"); } - if (HAS_RC6p(dev)) { - ret = sysfs_merge_group(&dev->primary->kdev->kobj, + if (HAS_RC6p(dev_priv)) { + ret = sysfs_merge_group(&kdev->kobj, &rc6p_attr_group); if (ret) DRM_ERROR("RC6p residency sysfs setup failed\n"); } - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { - ret = sysfs_merge_group(&dev->primary->kdev->kobj, + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + ret = sysfs_merge_group(&kdev->kobj, &media_rc6_attr_group); if (ret) DRM_ERROR("Media RC6 residency sysfs setup failed\n"); } #endif - if (HAS_L3_DPF(dev)) { - ret = device_create_bin_file(dev->primary->kdev, &dpf_attrs); + if (HAS_L3_DPF(dev_priv)) { + ret = device_create_bin_file(kdev, &dpf_attrs); if (ret) DRM_ERROR("l3 parity sysfs setup failed\n"); - if (NUM_L3_SLICES(dev) > 1) { - ret = device_create_bin_file(dev->primary->kdev, + if (NUM_L3_SLICES(dev_priv) > 1) { + ret = device_create_bin_file(kdev, &dpf_attrs_1); if (ret) DRM_ERROR("l3 parity slice 1 setup failed\n"); @@ -638,30 +618,32 @@ void i915_setup_sysfs(struct drm_device *dev) } ret = 0; - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) - ret = sysfs_create_files(&dev->primary->kdev->kobj, vlv_attrs); - else if (INTEL_INFO(dev)->gen >= 6) - ret = sysfs_create_files(&dev->primary->kdev->kobj, gen6_attrs); + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + ret = sysfs_create_files(&kdev->kobj, vlv_attrs); + else if (INTEL_GEN(dev_priv) >= 6) + ret = sysfs_create_files(&kdev->kobj, gen6_attrs); if (ret) DRM_ERROR("RPS sysfs setup failed\n"); - ret = sysfs_create_bin_file(&dev->primary->kdev->kobj, + ret = sysfs_create_bin_file(&kdev->kobj, &error_state_attr); if (ret) DRM_ERROR("error_state sysfs setup failed\n"); } -void i915_teardown_sysfs(struct drm_device *dev) +void i915_teardown_sysfs(struct drm_i915_private *dev_priv) { - sysfs_remove_bin_file(&dev->primary->kdev->kobj, &error_state_attr); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) - sysfs_remove_files(&dev->primary->kdev->kobj, vlv_attrs); + struct device *kdev = dev_priv->drm.primary->kdev; + + sysfs_remove_bin_file(&kdev->kobj, &error_state_attr); + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + sysfs_remove_files(&kdev->kobj, vlv_attrs); else - sysfs_remove_files(&dev->primary->kdev->kobj, gen6_attrs); - device_remove_bin_file(dev->primary->kdev, &dpf_attrs_1); - device_remove_bin_file(dev->primary->kdev, &dpf_attrs); + sysfs_remove_files(&kdev->kobj, gen6_attrs); + device_remove_bin_file(kdev, &dpf_attrs_1); + device_remove_bin_file(kdev, &dpf_attrs); #ifdef CONFIG_PM - sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6_attr_group); - sysfs_unmerge_group(&dev->primary->kdev->kobj, &rc6p_attr_group); + sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); + sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); #endif } -- cgit v1.2.1 From 52a05c302bcfe571aa4896118e3d22feb51ab1c7 Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Mon, 22 Aug 2016 13:32:44 +0300 Subject: drm/i915: pdev cleanup In an effort to simplify things for a future push of dev_priv instead of dev wherever possible, always take pdev via dev_priv where feasible, eliminating the direct access from dev. Right now this only eliminates a few cases of dev, but it also obviates that we pass dev into a lot of functions where dev_priv would be the more obvious choice. v2: Fixed one more place missing in the previous patch set Signed-off-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20160822103245.24069-5-david.weinehall@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 5 +-- drivers/gpu/drm/i915/i915_drv.c | 59 +++++++++++++++++++-------------- drivers/gpu/drm/i915/i915_gem_gtt.c | 10 +++--- drivers/gpu/drm/i915/i915_gem_stolen.c | 19 ++++++----- drivers/gpu/drm/i915/i915_gpu_error.c | 9 ++--- drivers/gpu/drm/i915/i915_suspend.c | 6 ++-- drivers/gpu/drm/i915/intel_display.c | 25 +++++++++----- drivers/gpu/drm/i915/intel_fbdev.c | 3 +- drivers/gpu/drm/i915/intel_guc_loader.c | 3 +- drivers/gpu/drm/i915/intel_i2c.c | 3 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 30 +++++++++-------- drivers/gpu/drm/i915/intel_sdvo.c | 4 ++- 12 files changed, 103 insertions(+), 73 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 67af3277811a..c82afb113f0a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2739,6 +2739,7 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; if (!HAS_RUNTIME_PM(dev_priv)) seq_puts(m, "Runtime power management not supported\n"); @@ -2753,8 +2754,8 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n"); #endif seq_printf(m, "PCI device power state: %s [%d]\n", - pci_power_name(dev_priv->drm.pdev->current_state), - dev_priv->drm.pdev->current_state); + pci_power_name(pdev->current_state), + pdev->current_state); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c316034aeda3..d22a1d8fe5b7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -232,6 +232,7 @@ static int i915_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; drm_i915_getparam_t *param = data; int value; @@ -242,10 +243,10 @@ static int i915_getparam(struct drm_device *dev, void *data, /* Reject all old ums/dri params. */ return -ENODEV; case I915_PARAM_CHIPSET_ID: - value = dev->pdev->device; + value = pdev->device; break; case I915_PARAM_REVISION: - value = dev->pdev->revision; + value = pdev->revision; break; case I915_PARAM_HAS_GEM: value = 1; @@ -516,7 +517,7 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_ pr_info("switched on\n"); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; /* i915 resume handler doesn't set to D0 */ - pci_set_power_state(dev->pdev, PCI_D0); + pci_set_power_state(pdev, PCI_D0); i915_resume_switcheroo(dev); dev->switch_power_state = DRM_SWITCH_POWER_ON; } else { @@ -585,6 +586,7 @@ static void i915_gem_fini(struct drm_device *dev) static int i915_load_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; int ret; if (i915_inject_load_failure()) @@ -601,13 +603,13 @@ static int i915_load_modeset_init(struct drm_device *dev) * then we do not take part in VGA arbitration and the * vga_client_register() fails with -ENODEV. */ - ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); + ret = vga_client_register(pdev, dev, NULL, i915_vga_set_decode); if (ret && ret != -ENODEV) goto out; intel_register_dsm_handler(); - ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops, false); + ret = vga_switcheroo_register_client(pdev, &i915_switcheroo_ops, false); if (ret) goto cleanup_vga_client; @@ -659,9 +661,9 @@ cleanup_irq: cleanup_csr: intel_csr_ucode_fini(dev_priv); intel_power_domains_fini(dev_priv); - vga_switcheroo_unregister_client(dev->pdev); + vga_switcheroo_unregister_client(pdev); cleanup_vga_client: - vga_client_register(dev->pdev, NULL, NULL, NULL); + vga_client_register(pdev, NULL, NULL, NULL); out: return ret; } @@ -881,6 +883,7 @@ static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) static int i915_mmio_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; int mmio_bar; int mmio_size; @@ -897,7 +900,7 @@ static int i915_mmio_setup(struct drm_device *dev) mmio_size = 512 * 1024; else mmio_size = 2 * 1024 * 1024; - dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, mmio_size); + dev_priv->regs = pci_iomap(pdev, mmio_bar, mmio_size); if (dev_priv->regs == NULL) { DRM_ERROR("failed to map registers\n"); @@ -913,9 +916,10 @@ static int i915_mmio_setup(struct drm_device *dev) static void i915_mmio_cleanup(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; intel_teardown_mchbar(dev); - pci_iounmap(dev->pdev, dev_priv->regs); + pci_iounmap(pdev, dev_priv->regs); } /** @@ -994,6 +998,7 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) */ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) { + struct pci_dev *pdev = dev_priv->drm.pdev; struct drm_device *dev = &dev_priv->drm; int ret; @@ -1032,11 +1037,11 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) goto out_ggtt; } - pci_set_master(dev->pdev); + pci_set_master(pdev); /* overlay on gen2 is broken and can't address above 1G */ if (IS_GEN2(dev)) { - ret = dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30)); if (ret) { DRM_ERROR("failed to set DMA mask\n"); @@ -1053,7 +1058,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) * which also needs to be handled carefully. */ if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) { - ret = dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32)); + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { DRM_ERROR("failed to set DMA mask\n"); @@ -1083,7 +1088,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) * stuck interrupts on some machines. */ if (!IS_I945G(dev) && !IS_I945GM(dev)) { - if (pci_enable_msi(dev->pdev) < 0) + if (pci_enable_msi(pdev) < 0) DRM_DEBUG_DRIVER("can't enable MSI"); } @@ -1101,10 +1106,10 @@ out_ggtt: */ static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; + struct pci_dev *pdev = dev_priv->drm.pdev; - if (dev->pdev->msi_enabled) - pci_disable_msi(dev->pdev); + if (pdev->msi_enabled) + pci_disable_msi(pdev); pm_qos_remove_request(&dev_priv->pm_qos); i915_ggtt_cleanup_hw(dev_priv); @@ -1274,6 +1279,7 @@ out_free_priv: void i915_driver_unload(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; intel_fbdev_fini(dev); @@ -1302,8 +1308,8 @@ void i915_driver_unload(struct drm_device *dev) kfree(dev_priv->vbt.lfp_lvds_vbt_mode); dev_priv->vbt.lfp_lvds_vbt_mode = NULL; - vga_switcheroo_unregister_client(dev->pdev); - vga_client_register(dev->pdev, NULL, NULL, NULL); + vga_switcheroo_unregister_client(pdev); + vga_client_register(pdev, NULL, NULL, NULL); intel_csr_ucode_fini(dev_priv); @@ -1400,6 +1406,7 @@ static bool suspend_to_idle(struct drm_i915_private *dev_priv) static int i915_drm_suspend(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; pci_power_t opregion_target_state; int error; @@ -1416,11 +1423,11 @@ static int i915_drm_suspend(struct drm_device *dev) drm_kms_helper_poll_disable(dev); - pci_save_state(dev->pdev); + pci_save_state(pdev); error = i915_gem_suspend(dev); if (error) { - dev_err(&dev->pdev->dev, + dev_err(&pdev->dev, "GEM idle failed, resume might fail\n"); goto out; } @@ -1465,6 +1472,7 @@ out: static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; bool fw_csr; int ret; @@ -1498,7 +1506,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) goto out; } - pci_disable_device(dev->pdev); + pci_disable_device(pdev); /* * During hibernation on some platforms the BIOS may try to access * the device even though it's already in D3 and hang the machine. So @@ -1512,7 +1520,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) * Acer Aspire 1830T */ if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6)) - pci_set_power_state(dev->pdev, PCI_D3hot); + pci_set_power_state(pdev, PCI_D3hot); dev_priv->suspended_to_idle = suspend_to_idle(dev_priv); @@ -1629,6 +1637,7 @@ static int i915_drm_resume(struct drm_device *dev) static int i915_drm_resume_early(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; int ret; /* @@ -1651,7 +1660,7 @@ static int i915_drm_resume_early(struct drm_device *dev) * the device powered we can also remove the following set power state * call. */ - ret = pci_set_power_state(dev->pdev, PCI_D0); + ret = pci_set_power_state(pdev, PCI_D0); if (ret) { DRM_ERROR("failed to set PCI D0 power state (%d)\n", ret); goto out; @@ -1670,12 +1679,12 @@ static int i915_drm_resume_early(struct drm_device *dev) * depend on the device enable refcount we can't anyway depend on them * disabling/enabling the device. */ - if (pci_enable_device(dev->pdev)) { + if (pci_enable_device(pdev)) { ret = -EIO; goto out; } - pci_set_master(dev->pdev); + pci_set_master(pdev); disable_rpm_wakeref_asserts(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index d31ae3d0f83f..eba0166c4df5 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -350,10 +350,12 @@ static int setup_page_dma(struct drm_device *dev, struct i915_page_dma *p) static void cleanup_page_dma(struct drm_device *dev, struct i915_page_dma *p) { + struct pci_dev *pdev = dev->pdev; + if (WARN_ON(!p->page)) return; - dma_unmap_page(&dev->pdev->dev, p->daddr, 4096, PCI_DMA_BIDIRECTIONAL); + dma_unmap_page(&pdev->dev, p->daddr, 4096, PCI_DMA_BIDIRECTIONAL); __free_page(p->page); memset(p, 0, sizeof(*p)); } @@ -2681,8 +2683,8 @@ static void ggtt_unbind_vma(struct i915_vma *vma) void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct device *kdev = &dev_priv->drm.pdev->dev; struct i915_ggtt *ggtt = &dev_priv->ggtt; if (unlikely(ggtt->do_idle_maps)) { @@ -2693,7 +2695,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) } } - dma_unmap_sg(&dev->pdev->dev, obj->pages->sgl, obj->pages->nents, + dma_unmap_sg(kdev, obj->pages->sgl, obj->pages->nents, PCI_DMA_BIDIRECTIONAL); } diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index aa050fa1e558..59989e8ee5dc 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -92,6 +92,7 @@ void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, static unsigned long i915_stolen_to_physical(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; struct i915_ggtt *ggtt = &dev_priv->ggtt; struct resource *r; u32 base; @@ -111,7 +112,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) if (INTEL_INFO(dev)->gen >= 3) { u32 bsm; - pci_read_config_dword(dev->pdev, INTEL_BSM, &bsm); + pci_read_config_dword(pdev, INTEL_BSM, &bsm); base = bsm & INTEL_BSM_MASK; } else if (IS_I865G(dev)) { @@ -119,7 +120,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) u16 toud = 0; u8 tmp; - pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0), + pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I845_ESMRAMC, &tmp); if (tmp & TSEG_ENABLE) { @@ -133,7 +134,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) } } - pci_bus_read_config_word(dev->pdev->bus, PCI_DEVFN(0, 0), + pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 0), I865_TOUD, &toud); base = (toud << 16) + tseg_size; @@ -142,13 +143,13 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) u32 tom; u8 tmp; - pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0), + pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I85X_ESMRAMC, &tmp); if (tmp & TSEG_ENABLE) tseg_size = MB(1); - pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 1), + pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 1), I85X_DRB3, &tmp); tom = tmp * MB(32); @@ -158,7 +159,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) u32 tom; u8 tmp; - pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0), + pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I845_ESMRAMC, &tmp); if (tmp & TSEG_ENABLE) { @@ -172,7 +173,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) } } - pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0), + pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I830_DRB3, &tmp); tom = tmp * MB(32); @@ -182,7 +183,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) u32 tom; u8 tmp; - pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0), + pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I830_ESMRAMC, &tmp); if (tmp & TSEG_ENABLE) { @@ -192,7 +193,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) tseg_size = KB(512); } - pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0), + pci_bus_read_config_byte(pdev->bus, PCI_DEVFN(0, 0), I830_DRB3, &tmp); tom = tmp * MB(32); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 41ec7a183c73..aed55e4f100f 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -336,6 +336,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, { struct drm_device *dev = error_priv->dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; struct drm_i915_error_state *error = error_priv->error; struct drm_i915_error_object *obj; int i, j, offset, elt; @@ -367,11 +368,11 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } err_printf(m, "Reset count: %u\n", error->reset_count); err_printf(m, "Suspend count: %u\n", error->suspend_count); - err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device); - err_printf(m, "PCI Revision: 0x%02x\n", dev->pdev->revision); + err_printf(m, "PCI ID: 0x%04x\n", pdev->device); + err_printf(m, "PCI Revision: 0x%02x\n", pdev->revision); err_printf(m, "PCI Subsystem: %04x:%04x\n", - dev->pdev->subsystem_vendor, - dev->pdev->subsystem_device); + pdev->subsystem_vendor, + pdev->subsystem_device); err_printf(m, "IOMMU enabled?: %d\n", error->iommu); if (HAS_CSR(dev)) { diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 4f272777b4f4..a0af170062b1 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -63,6 +63,7 @@ static void i915_restore_display(struct drm_device *dev) int i915_save_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; int i; mutex_lock(&dev->struct_mutex); @@ -70,7 +71,7 @@ int i915_save_state(struct drm_device *dev) i915_save_display(dev); if (IS_GEN4(dev)) - pci_read_config_word(dev->pdev, GCDGMBUS, + pci_read_config_word(pdev, GCDGMBUS, &dev_priv->regfile.saveGCDGMBUS); /* Cache mode state */ @@ -108,6 +109,7 @@ int i915_save_state(struct drm_device *dev) int i915_restore_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; int i; mutex_lock(&dev->struct_mutex); @@ -115,7 +117,7 @@ int i915_restore_state(struct drm_device *dev) i915_gem_restore_fences(dev); if (IS_GEN4(dev)) - pci_write_config_word(dev->pdev, GCDGMBUS, + pci_write_config_word(pdev, GCDGMBUS, dev_priv->regfile.saveGCDGMBUS); i915_restore_display(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e8fee41c9b81..d5d8fea8305b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7273,9 +7273,10 @@ static int i9xx_misc_get_display_clock_speed(struct drm_device *dev) static int pnv_get_display_clock_speed(struct drm_device *dev) { + struct pci_dev *pdev = dev->pdev; u16 gcfgc = 0; - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); + pci_read_config_word(pdev, GCFGC, &gcfgc); switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { case GC_DISPLAY_CLOCK_267_MHZ_PNV: @@ -7297,9 +7298,10 @@ static int pnv_get_display_clock_speed(struct drm_device *dev) static int i915gm_get_display_clock_speed(struct drm_device *dev) { + struct pci_dev *pdev = dev->pdev; u16 gcfgc = 0; - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); + pci_read_config_word(pdev, GCFGC, &gcfgc); if (gcfgc & GC_LOW_FREQUENCY_ENABLE) return 133333; @@ -7321,6 +7323,7 @@ static int i865_get_display_clock_speed(struct drm_device *dev) static int i85x_get_display_clock_speed(struct drm_device *dev) { + struct pci_dev *pdev = dev->pdev; u16 hpllcc = 0; /* @@ -7328,10 +7331,10 @@ static int i85x_get_display_clock_speed(struct drm_device *dev) * encoding is different :( * FIXME is this the right way to detect 852GM/852GMV? */ - if (dev->pdev->revision == 0x1) + if (pdev->revision == 0x1) return 133333; - pci_bus_read_config_word(dev->pdev->bus, + pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 3), HPLLCC, &hpllcc); /* Assume that the hardware is in the high speed state. This @@ -7432,10 +7435,11 @@ static unsigned int intel_hpll_vco(struct drm_device *dev) static int gm45_get_display_clock_speed(struct drm_device *dev) { + struct pci_dev *pdev = dev->pdev; unsigned int cdclk_sel, vco = intel_hpll_vco(dev); uint16_t tmp = 0; - pci_read_config_word(dev->pdev, GCFGC, &tmp); + pci_read_config_word(pdev, GCFGC, &tmp); cdclk_sel = (tmp >> 12) & 0x1; @@ -7454,6 +7458,7 @@ static int gm45_get_display_clock_speed(struct drm_device *dev) static int i965gm_get_display_clock_speed(struct drm_device *dev) { + struct pci_dev *pdev = dev->pdev; static const uint8_t div_3200[] = { 16, 10, 8 }; static const uint8_t div_4000[] = { 20, 12, 10 }; static const uint8_t div_5333[] = { 24, 16, 14 }; @@ -7461,7 +7466,7 @@ static int i965gm_get_display_clock_speed(struct drm_device *dev) unsigned int cdclk_sel, vco = intel_hpll_vco(dev); uint16_t tmp = 0; - pci_read_config_word(dev->pdev, GCFGC, &tmp); + pci_read_config_word(pdev, GCFGC, &tmp); cdclk_sel = ((tmp >> 8) & 0x1f) - 1; @@ -7491,6 +7496,7 @@ fail: static int g33_get_display_clock_speed(struct drm_device *dev) { + struct pci_dev *pdev = dev->pdev; static const uint8_t div_3200[] = { 12, 10, 8, 7, 5, 16 }; static const uint8_t div_4000[] = { 14, 12, 10, 8, 6, 20 }; static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 }; @@ -7499,7 +7505,7 @@ static int g33_get_display_clock_speed(struct drm_device *dev) unsigned int cdclk_sel, vco = intel_hpll_vco(dev); uint16_t tmp = 0; - pci_read_config_word(dev->pdev, GCFGC, &tmp); + pci_read_config_word(pdev, GCFGC, &tmp); cdclk_sel = (tmp >> 4) & 0x7; @@ -15991,15 +15997,16 @@ static void intel_init_quirks(struct drm_device *dev) static void i915_disable_vga(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; u8 sr1; i915_reg_t vga_reg = i915_vgacntrl_reg(dev); /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */ - vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); + vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); outb(SR01, VGA_SR_INDEX); sr1 = inb(VGA_SR_DATA); outb(sr1 | 1<<5, VGA_SR_DATA); - vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); + vga_put(pdev, VGA_RSRC_LEGACY_IO); udelay(300); I915_WRITE(vga_reg, VGA_DISP_DISABLE); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 4003e4908c09..b7098f98bb67 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -183,6 +183,7 @@ static int intelfb_create(struct drm_fb_helper *helper, struct intel_framebuffer *intel_fb = ifbdev->fb; struct drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; struct i915_ggtt *ggtt = &dev_priv->ggtt; struct fb_info *info; struct drm_framebuffer *fb; @@ -280,7 +281,7 @@ static int intelfb_create(struct drm_fb_helper *helper, ifbdev->vma = vma; mutex_unlock(&dev->struct_mutex); - vga_switcheroo_client_fb_set(dev->pdev, info); + vga_switcheroo_client_fb_set(pdev, info); return 0; out_destroy_fbi: diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 324812d69b70..e67d8de427d0 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -565,6 +565,7 @@ fail: static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) { + struct pci_dev *pdev = dev->pdev; struct drm_i915_gem_object *obj; const struct firmware *fw; struct guc_css_header *css; @@ -574,7 +575,7 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) DRM_DEBUG_DRIVER("before requesting firmware: GuC fw fetch status %s\n", intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status)); - err = request_firmware(&fw, guc_fw->guc_fw_path, &dev->pdev->dev); + err = request_firmware(&fw, guc_fw->guc_fw_path, &pdev->dev); if (err) goto fail; if (!fw) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 1f266d7df2ec..a4ca2052315e 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -633,6 +633,7 @@ static const struct i2c_algorithm gmbus_algorithm = { int intel_setup_gmbus(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + struct pci_dev *pdev = dev_priv->drm.pdev; struct intel_gmbus *bus; unsigned int pin; int ret; @@ -663,7 +664,7 @@ int intel_setup_gmbus(struct drm_device *dev) "i915 gmbus %s", get_gmbus_pin(dev_priv, pin)->name); - bus->adapter.dev.parent = &dev->pdev->dev; + bus->adapter.dev.parent = &pdev->dev; bus->dev_priv = dev_priv; bus->adapter.algo = &gmbus_algorithm; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 7686b7f1d599..6c11168facd6 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -287,6 +287,7 @@ void intel_display_set_init_power(struct drm_i915_private *dev_priv, */ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) { + struct pci_dev *pdev = dev_priv->drm.pdev; struct drm_device *dev = &dev_priv->drm; /* @@ -299,9 +300,9 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) * sure vgacon can keep working normally without triggering interrupts * and error messages. */ - vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); + vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); - vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); + vga_put(pdev, VGA_RSRC_LEGACY_IO); if (IS_BROADWELL(dev)) gen8_irq_power_well_post_enable(dev_priv, @@ -318,7 +319,7 @@ static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv) static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - struct drm_device *dev = &dev_priv->drm; + struct pci_dev *pdev = dev_priv->drm.pdev; /* * After we re-enable the power well, if we touch VGA register 0x3d5 @@ -331,9 +332,9 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, * and error messages. */ if (power_well->data == SKL_DISP_PW_2) { - vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); + vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); - vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); + vga_put(pdev, VGA_RSRC_LEGACY_IO); gen8_irq_power_well_post_enable(dev_priv, 1 << PIPE_C | 1 << PIPE_B); @@ -2651,8 +2652,8 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv) */ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; - struct device *kdev = &dev->pdev->dev; + struct pci_dev *pdev = dev_priv->drm.pdev; + struct device *kdev = &pdev->dev; pm_runtime_get_sync(kdev); @@ -2672,8 +2673,8 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) */ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; - struct device *kdev = &dev->pdev->dev; + struct pci_dev *pdev = dev_priv->drm.pdev; + struct device *kdev = &pdev->dev; if (IS_ENABLED(CONFIG_PM)) { int ret = pm_runtime_get_if_in_use(kdev); @@ -2714,8 +2715,8 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) */ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; - struct device *kdev = &dev->pdev->dev; + struct pci_dev *pdev = dev_priv->drm.pdev; + struct device *kdev = &pdev->dev; assert_rpm_wakelock_held(dev_priv); pm_runtime_get_noresume(kdev); @@ -2733,8 +2734,8 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv) */ void intel_runtime_pm_put(struct drm_i915_private *dev_priv) { - struct drm_device *dev = &dev_priv->drm; - struct device *kdev = &dev->pdev->dev; + struct pci_dev *pdev = dev_priv->drm.pdev; + struct device *kdev = &pdev->dev; assert_rpm_wakelock_held(dev_priv); if (atomic_dec_and_test(&dev_priv->pm.wakeref_count)) @@ -2756,8 +2757,9 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv) */ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) { + struct pci_dev *pdev = dev_priv->drm.pdev; struct drm_device *dev = &dev_priv->drm; - struct device *kdev = &dev->pdev->dev; + struct device *kdev = &pdev->dev; pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */ pm_runtime_mark_last_busy(kdev); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e378f35365a2..dd75510eba67 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2930,10 +2930,12 @@ static bool intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo, struct drm_device *dev) { + struct pci_dev *pdev = dev->pdev; + sdvo->ddc.owner = THIS_MODULE; sdvo->ddc.class = I2C_CLASS_DDC; snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy"); - sdvo->ddc.dev.parent = &dev->pdev->dev; + sdvo->ddc.dev.parent = &pdev->dev; sdvo->ddc.algo_data = sdvo; sdvo->ddc.algo = &intel_sdvo_ddc_proxy; -- cgit v1.2.1 From 36cdd0138b7f51f204df871c548b65ea2d59522d Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Mon, 22 Aug 2016 13:59:31 +0300 Subject: drm/i915: debugfs spring cleaning Just like with sysfs, we do some major overhaul. Pass dev_priv instead of dev to all feature macros (IS_, HAS_, INTEL_, etc.). This has the side effect that a bunch of functions now get dev_priv passed instead of dev. All calls to INTEL_INFO()->gen have been replaced with INTEL_GEN(). We want access to to_i915(node->minor->dev) in a lot of places, so add the node_to_i915() helper to accommodate for this. Finally, we have quite a few cases where we get a void * pointer, and need to cast it to drm_device *, only to run to_i915() on it. Add cast_to_i915() to do this. v2: Don't introduce extra dev (Chris) v3: Make pipe_crc_info have a pointer to drm_i915_private instead of drm_device. This saves a bit of space, since we never use drm_device anywhere in these functions. Also some minor fixup that I missed in the previous version. v4: Changed the code a bit so that dev_priv is passed directly to various functions, thus removing the need for the cast_to_i915() helper. Also did some additional cleanup. v5: Additional cleanup of newly introduced changes. v6: Rebase again because of conflict. Signed-off-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20160822105931.pcbe2lpsgzckzboa@boom Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 796 ++++++++++++++++-------------------- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- 3 files changed, 358 insertions(+), 442 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index c82afb113f0a..3054bd62c5fd 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -40,6 +40,11 @@ #include #include "i915_drv.h" +static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node) +{ + return to_i915(node->minor->dev); +} + /* As the drm_debugfs_init() routines are called before dev->dev_private is * allocated we need to hook into the minor for release. */ static int @@ -57,7 +62,7 @@ drm_add_fake_info_node(struct drm_minor *minor, node->minor = minor; node->dent = ent; - node->info_ent = (void *) key; + node->info_ent = (void *)key; mutex_lock(&minor->debugfs_lock); list_add(&node->list, &minor->debugfs_list); @@ -68,12 +73,11 @@ drm_add_fake_info_node(struct drm_minor *minor, static int i915_capabilities(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - const struct intel_device_info *info = INTEL_INFO(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + const struct intel_device_info *info = INTEL_INFO(dev_priv); - seq_printf(m, "gen: %d\n", info->gen); - seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev)); + seq_printf(m, "gen: %d\n", INTEL_GEN(dev_priv)); + seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv)); #define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x)) #define SEP_SEMICOLON ; DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON); @@ -155,7 +159,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) seq_printf(m, "] %x %s%s%s", i915_gem_active_get_seqno(&obj->last_write, &obj->base.dev->struct_mutex), - i915_cache_level_str(to_i915(obj->base.dev), obj->cache_level), + i915_cache_level_str(dev_priv, obj->cache_level), obj->dirty ? " dirty" : "", obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); if (obj->base.name) @@ -195,7 +199,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) } engine = i915_gem_active_get_engine(&obj->last_write, - &obj->base.dev->struct_mutex); + &dev_priv->drm.struct_mutex); if (engine) seq_printf(m, " (%s)", engine->name); @@ -221,9 +225,8 @@ static int obj_rank_by_stolen(void *priv, static int i915_gem_stolen_list_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct drm_i915_gem_object *obj; u64 total_obj_size, total_gtt_size; LIST_HEAD(stolen); @@ -365,29 +368,29 @@ static int per_file_ctx_stats(int id, void *ptr, void *data) static void print_context_stats(struct seq_file *m, struct drm_i915_private *dev_priv) { + struct drm_device *dev = &dev_priv->drm; struct file_stats stats; struct drm_file *file; memset(&stats, 0, sizeof(stats)); - mutex_lock(&dev_priv->drm.struct_mutex); + mutex_lock(&dev->struct_mutex); if (dev_priv->kernel_context) per_file_ctx_stats(0, dev_priv->kernel_context, &stats); - list_for_each_entry(file, &dev_priv->drm.filelist, lhead) { + list_for_each_entry(file, &dev->filelist, lhead) { struct drm_i915_file_private *fpriv = file->driver_priv; idr_for_each(&fpriv->context_idr, per_file_ctx_stats, &stats); } - mutex_unlock(&dev_priv->drm.struct_mutex); + mutex_unlock(&dev->struct_mutex); print_file_stats(m, "[k]contexts", stats); } -static int i915_gem_object_info(struct seq_file *m, void* data) +static int i915_gem_object_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct i915_ggtt *ggtt = &dev_priv->ggtt; u32 count, mapped_count, purgeable_count, dpy_count; u64 size, mapped_size, purgeable_size, dpy_size; @@ -497,8 +500,8 @@ static int i915_gem_object_info(struct seq_file *m, void* data) static int i915_gem_gtt_info(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(node); + struct drm_device *dev = &dev_priv->drm; bool show_pin_display_only = !!node->info_ent->data; struct drm_i915_gem_object *obj; u64 total_obj_size, total_gtt_size; @@ -531,9 +534,8 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data) static int i915_gem_pageflip_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_crtc *crtc; int ret; @@ -580,7 +582,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) intel_crtc_get_vblank_counter(crtc)); seq_printf(m, "%d prepares\n", atomic_read(&work->pending)); - if (INTEL_INFO(dev)->gen >= 4) + if (INTEL_GEN(dev_priv) >= 4) addr = I915_HI_DISPBASE(I915_READ(DSPSURF(crtc->plane))); else addr = I915_READ(DSPADDR(crtc->plane)); @@ -601,9 +603,8 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) static int i915_gem_batch_pool_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct drm_i915_gem_object *obj; struct intel_engine_cs *engine; int total = 0; @@ -646,9 +647,8 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) static int i915_gem_request_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; struct drm_i915_gem_request *req; int ret, any; @@ -713,9 +713,8 @@ static void i915_ring_seqno_info(struct seq_file *m, static int i915_gem_seqno_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; int ret; @@ -736,9 +735,8 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) static int i915_interrupt_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; int ret, i, pipe; @@ -747,7 +745,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) return ret; intel_runtime_pm_get(dev_priv); - if (IS_CHERRYVIEW(dev)) { + if (IS_CHERRYVIEW(dev_priv)) { seq_printf(m, "Master Interrupt Control:\t%08x\n", I915_READ(GEN8_MASTER_IRQ)); @@ -786,7 +784,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(GEN8_PCU_IIR)); seq_printf(m, "PCU interrupt enable:\t%08x\n", I915_READ(GEN8_PCU_IER)); - } else if (INTEL_INFO(dev)->gen >= 8) { + } else if (INTEL_GEN(dev_priv) >= 8) { seq_printf(m, "Master Interrupt Control:\t%08x\n", I915_READ(GEN8_MASTER_IRQ)); @@ -842,7 +840,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(GEN8_PCU_IIR)); seq_printf(m, "PCU interrupt enable:\t%08x\n", I915_READ(GEN8_PCU_IER)); - } else if (IS_VALLEYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv)) { seq_printf(m, "Display IER:\t%08x\n", I915_READ(VLV_IER)); seq_printf(m, "Display IIR:\t%08x\n", @@ -880,7 +878,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "DPINVGTT:\t%08x\n", I915_READ(DPINVGTT)); - } else if (!HAS_PCH_SPLIT(dev)) { + } else if (!HAS_PCH_SPLIT(dev_priv)) { seq_printf(m, "Interrupt enable: %08x\n", I915_READ(IER)); seq_printf(m, "Interrupt identity: %08x\n", @@ -912,7 +910,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(GTIMR)); } for_each_engine(engine, dev_priv) { - if (INTEL_INFO(dev)->gen >= 6) { + if (INTEL_GEN(dev_priv) >= 6) { seq_printf(m, "Graphics Interrupt mask (%s): %08x\n", engine->name, I915_READ_IMR(engine)); @@ -927,9 +925,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data) static int i915_gem_fence_regs_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; int i, ret; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -956,8 +953,7 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data) static int i915_hws_info(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(node); struct intel_engine_cs *engine; const u32 *hws; int i; @@ -999,16 +995,16 @@ i915_error_state_write(struct file *filp, static int i915_error_state_open(struct inode *inode, struct file *file) { - struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = inode->i_private; struct i915_error_state_file_priv *error_priv; error_priv = kzalloc(sizeof(*error_priv), GFP_KERNEL); if (!error_priv) return -ENOMEM; - error_priv->dev = dev; + error_priv->dev = &dev_priv->drm; - i915_error_state_get(dev, error_priv); + i915_error_state_get(&dev_priv->drm, error_priv); file->private_data = error_priv; @@ -1034,7 +1030,8 @@ static ssize_t i915_error_state_read(struct file *file, char __user *userbuf, ssize_t ret_count = 0; int ret; - ret = i915_error_state_buf_init(&error_str, to_i915(error_priv->dev), count, *pos); + ret = i915_error_state_buf_init(&error_str, + to_i915(error_priv->dev), count, *pos); if (ret) return ret; @@ -1067,16 +1064,15 @@ static const struct file_operations i915_error_state_fops = { static int i915_next_seqno_get(void *data, u64 *val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; int ret; - ret = mutex_lock_interruptible(&dev->struct_mutex); + ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex); if (ret) return ret; *val = dev_priv->next_seqno; - mutex_unlock(&dev->struct_mutex); + mutex_unlock(&dev_priv->drm.struct_mutex); return 0; } @@ -1084,7 +1080,8 @@ i915_next_seqno_get(void *data, u64 *val) static int i915_next_seqno_set(void *data, u64 val) { - struct drm_device *dev = data; + struct drm_i915_private *dev_priv = data; + struct drm_device *dev = &dev_priv->drm; int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -1103,14 +1100,13 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_fops, static int i915_frequency_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; int ret = 0; intel_runtime_pm_get(dev_priv); - if (IS_GEN5(dev)) { + if (IS_GEN5(dev_priv)) { u16 rgvswctl = I915_READ16(MEMSWCTL); u16 rgvstat = I915_READ16(MEMSTAT_ILK); @@ -1120,7 +1116,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) MEMSTAT_VID_SHIFT); seq_printf(m, "Current P-state: %d\n", (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { u32 freq_sts; mutex_lock(&dev_priv->rps.hw_lock); @@ -1147,7 +1143,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) "efficient (RPe) frequency: %d MHz\n", intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); mutex_unlock(&dev_priv->rps.hw_lock); - } else if (INTEL_INFO(dev)->gen >= 6) { + } else if (INTEL_GEN(dev_priv) >= 6) { u32 rp_state_limits; u32 gt_perf_status; u32 rp_state_cap; @@ -1159,7 +1155,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) int max_freq; rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { rp_state_cap = I915_READ(BXT_RP_STATE_CAP); gt_perf_status = I915_READ(BXT_GT_PERF_STATUS); } else { @@ -1175,11 +1171,11 @@ static int i915_frequency_info(struct seq_file *m, void *unused) intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); reqf = I915_READ(GEN6_RPNSWREQ); - if (IS_GEN9(dev)) + if (IS_GEN9(dev_priv)) reqf >>= 23; else { reqf &= ~GEN6_TURBO_DISABLE; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) reqf >>= 24; else reqf >>= 25; @@ -1197,9 +1193,9 @@ 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; - if (IS_GEN9(dev)) + if (IS_GEN9(dev_priv)) cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; - else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; else cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; @@ -1208,7 +1204,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); mutex_unlock(&dev->struct_mutex); - if (IS_GEN6(dev) || IS_GEN7(dev)) { + if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { pm_ier = I915_READ(GEN6_PMIER); pm_imr = I915_READ(GEN6_PMIMR); pm_isr = I915_READ(GEN6_PMISR); @@ -1226,7 +1222,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "pm_intr_keep: 0x%08x\n", dev_priv->rps.pm_intr_keep); seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); seq_printf(m, "Render p-state ratio: %d\n", - (gt_perf_status & (IS_GEN9(dev) ? 0x1ff00 : 0xff00)) >> 8); + (gt_perf_status & (IS_GEN9(dev_priv) ? 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", @@ -1255,22 +1251,22 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "Down threshold: %d%%\n", dev_priv->rps.down_threshold); - max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 0 : + max_freq = (IS_BROXTON(dev_priv) ? rp_state_cap >> 0 : rp_state_cap >> 16) & 0xff; - max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ? + max_freq *= (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); max_freq = (rp_state_cap & 0xff00) >> 8; - max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ? + max_freq *= (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); - max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 16 : + max_freq = (IS_BROXTON(dev_priv) ? rp_state_cap >> 16 : rp_state_cap >> 0) & 0xff; - max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ? + max_freq *= (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1); seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); @@ -1306,9 +1302,7 @@ out: static int i915_hangcheck_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_engine_cs *engine; u64 acthd[I915_NUM_ENGINES]; u32 seqno[I915_NUM_ENGINES]; @@ -1376,9 +1370,8 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) static int ironlake_drpc_info(struct seq_file *m) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; u32 rgvmodectl, rstdbyctl; u16 crstandvid; int ret; @@ -1444,9 +1437,7 @@ static int ironlake_drpc_info(struct seq_file *m) static int i915_forcewake_domains(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_uncore_forcewake_domain *fw_domain; spin_lock_irq(&dev_priv->uncore.lock); @@ -1462,9 +1453,7 @@ static int i915_forcewake_domains(struct seq_file *m, void *data) static int vlv_drpc_info(struct seq_file *m) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); u32 rpmodectl1, rcctl1, pw_status; intel_runtime_pm_get(dev_priv); @@ -1502,9 +1491,8 @@ static int vlv_drpc_info(struct seq_file *m) static int gen6_drpc_info(struct seq_file *m) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; u32 rpmodectl1, gt_core_status, rcctl1, rc6vids = 0; u32 gen9_powergate_enable = 0, gen9_powergate_status = 0; unsigned forcewake_count; @@ -1534,7 +1522,7 @@ static int gen6_drpc_info(struct seq_file *m) rpmodectl1 = I915_READ(GEN6_RP_CONTROL); rcctl1 = I915_READ(GEN6_RC_CONTROL); - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { gen9_powergate_enable = I915_READ(GEN9_PG_ENABLE); gen9_powergate_status = I915_READ(GEN9_PWRGT_DOMAIN_STATUS); } @@ -1556,7 +1544,7 @@ static int gen6_drpc_info(struct seq_file *m) yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); seq_printf(m, "RC6 Enabled: %s\n", yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE)); - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 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", @@ -1590,7 +1578,7 @@ static int gen6_drpc_info(struct seq_file *m) seq_printf(m, "Core Power Down: %s\n", yesno(gt_core_status & GEN6_CORE_CPD_STATE_MASK)); - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { seq_printf(m, "Render Power Well: %s\n", (gen9_powergate_status & GEN9_PWRGT_RENDER_STATUS_MASK) ? "Up" : "Down"); @@ -1620,12 +1608,11 @@ static int gen6_drpc_info(struct seq_file *m) static int i915_drpc_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = node_to_i915(m->private); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return vlv_drpc_info(m); - else if (INTEL_INFO(dev)->gen >= 6) + else if (INTEL_GEN(dev_priv) >= 6) return gen6_drpc_info(m); else return ironlake_drpc_info(m); @@ -1633,9 +1620,7 @@ static int i915_drpc_info(struct seq_file *m, void *unused) static int i915_frontbuffer_tracking(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); seq_printf(m, "FB tracking busy bits: 0x%08x\n", dev_priv->fb_tracking.busy_bits); @@ -1648,11 +1633,9 @@ static int i915_frontbuffer_tracking(struct seq_file *m, void *unused) static int i915_fbc_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); - if (!HAS_FBC(dev)) { + if (!HAS_FBC(dev_priv)) { seq_puts(m, "FBC unsupported on this chipset\n"); return 0; } @@ -1666,7 +1649,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused) seq_printf(m, "FBC disabled: %s\n", dev_priv->fbc.no_fbc_reason); - if (INTEL_INFO(dev_priv)->gen >= 7) + if (INTEL_GEN(dev_priv) >= 7) seq_printf(m, "Compressing: %s\n", yesno(I915_READ(FBC_STATUS2) & FBC_COMPRESSION_MASK)); @@ -1679,10 +1662,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused) static int i915_fbc_fc_get(void *data, u64 *val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; - if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev)) + if (INTEL_GEN(dev_priv) < 7 || !HAS_FBC(dev_priv)) return -ENODEV; *val = dev_priv->fbc.false_color; @@ -1692,11 +1674,10 @@ static int i915_fbc_fc_get(void *data, u64 *val) static int i915_fbc_fc_set(void *data, u64 val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; u32 reg; - if (INTEL_INFO(dev)->gen < 7 || !HAS_FBC(dev)) + if (INTEL_GEN(dev_priv) < 7 || !HAS_FBC(dev_priv)) return -ENODEV; mutex_lock(&dev_priv->fbc.lock); @@ -1718,11 +1699,9 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_fc_fops, static int i915_ips_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); - if (!HAS_IPS(dev)) { + if (!HAS_IPS(dev_priv)) { seq_puts(m, "not supported\n"); return 0; } @@ -1732,7 +1711,7 @@ static int i915_ips_status(struct seq_file *m, void *unused) seq_printf(m, "Enabled by kernel parameter: %s\n", yesno(i915.enable_ips)); - if (INTEL_INFO(dev)->gen >= 8) { + if (INTEL_GEN(dev_priv) >= 8) { seq_puts(m, "Currently: unknown\n"); } else { if (I915_READ(IPS_CTL) & IPS_ENABLE) @@ -1748,23 +1727,21 @@ static int i915_ips_status(struct seq_file *m, void *unused) static int i915_sr_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); bool sr_enabled = false; intel_runtime_pm_get(dev_priv); - if (HAS_PCH_SPLIT(dev)) + if (HAS_PCH_SPLIT(dev_priv)) sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN; - else if (IS_CRESTLINE(dev) || IS_G4X(dev) || - IS_I945G(dev) || IS_I945GM(dev)) + else if (IS_CRESTLINE(dev_priv) || IS_G4X(dev_priv) || + IS_I945G(dev_priv) || IS_I945GM(dev_priv)) sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN; - else if (IS_I915GM(dev)) + else if (IS_I915GM(dev_priv)) sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN; - else if (IS_PINEVIEW(dev)) + else if (IS_PINEVIEW(dev_priv)) sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN; - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN; intel_runtime_pm_put(dev_priv); @@ -1777,13 +1754,12 @@ static int i915_sr_status(struct seq_file *m, void *unused) static int i915_emon_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; unsigned long temp, chipset, gfx; int ret; - if (!IS_GEN5(dev)) + if (!IS_GEN5(dev_priv)) return -ENODEV; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -1805,14 +1781,12 @@ static int i915_emon_status(struct seq_file *m, void *unused) static int i915_ring_freq_table(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); int ret = 0; int gpu_freq, ia_freq; unsigned int max_gpu_freq, min_gpu_freq; - if (!HAS_CORE_RING_FREQ(dev)) { + if (!HAS_CORE_RING_FREQ(dev_priv)) { seq_puts(m, "unsupported on this chipset\n"); return 0; } @@ -1823,7 +1797,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) if (ret) goto out; - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { /* Convert GT frequency to 50 HZ units */ min_gpu_freq = dev_priv->rps.min_freq_softlimit / GEN9_FREQ_SCALER; @@ -1843,7 +1817,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) &ia_freq); seq_printf(m, "%d\t\t%d\t\t\t\t%d\n", intel_gpu_freq(dev_priv, (gpu_freq * - (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ? + (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ? GEN9_FREQ_SCALER : 1))), ((ia_freq >> 0) & 0xff) * 100, ((ia_freq >> 8) & 0xff) * 100); @@ -1858,9 +1832,8 @@ out: static int i915_opregion(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_opregion *opregion = &dev_priv->opregion; int ret; @@ -1879,10 +1852,7 @@ out: static int i915_vbt(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_opregion *opregion = &dev_priv->opregion; + struct intel_opregion *opregion = &node_to_i915(m->private)->opregion; if (opregion->vbt) seq_write(m, opregion->vbt, opregion->vbt_size); @@ -1892,8 +1862,8 @@ static int i915_vbt(struct seq_file *m, void *unused) static int i915_gem_framebuffer_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_framebuffer *fbdev_fb = NULL; struct drm_framebuffer *drm_fb; int ret; @@ -1903,8 +1873,8 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) return ret; #ifdef CONFIG_DRM_FBDEV_EMULATION - if (to_i915(dev)->fbdev) { - fbdev_fb = to_intel_framebuffer(to_i915(dev)->fbdev->helper.fb); + if (dev_priv->fbdev) { + fbdev_fb = to_intel_framebuffer(dev_priv->fbdev->helper.fb); seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", fbdev_fb->base.width, @@ -1949,9 +1919,8 @@ static void describe_ctx_ring(struct seq_file *m, struct intel_ring *ring) static int i915_context_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; struct i915_gem_context *ctx; int ret; @@ -2043,9 +2012,8 @@ static void i915_dump_lrc_obj(struct seq_file *m, static int i915_dump_lrc(struct seq_file *m, void *unused) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; struct i915_gem_context *ctx; int ret; @@ -2070,9 +2038,8 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) static int i915_execlists(struct seq_file *m, void *data) { - struct drm_info_node *node = (struct drm_info_node *)m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; u32 status_pointer; u8 read_pointer; @@ -2173,9 +2140,8 @@ static const char *swizzle_string(unsigned swizzle) static int i915_swizzle_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -2188,7 +2154,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data) seq_printf(m, "bit6 swizzle for Y-tiling = %s\n", swizzle_string(dev_priv->mm.bit_6_swizzle_y)); - if (IS_GEN3(dev) || IS_GEN4(dev)) { + if (IS_GEN3(dev_priv) || IS_GEN4(dev_priv)) { seq_printf(m, "DDC = 0x%08x\n", I915_READ(DCC)); seq_printf(m, "DDC2 = 0x%08x\n", @@ -2197,7 +2163,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data) I915_READ16(C0DRB3)); seq_printf(m, "C1DRB3 = 0x%04x\n", I915_READ16(C1DRB3)); - } else if (INTEL_INFO(dev)->gen >= 6) { + } else if (INTEL_GEN(dev_priv) >= 6) { seq_printf(m, "MAD_DIMM_C0 = 0x%08x\n", I915_READ(MAD_DIMM_C0)); seq_printf(m, "MAD_DIMM_C1 = 0x%08x\n", @@ -2206,7 +2172,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data) I915_READ(MAD_DIMM_C2)); seq_printf(m, "TILECTL = 0x%08x\n", I915_READ(TILECTL)); - if (INTEL_INFO(dev)->gen >= 8) + if (INTEL_GEN(dev_priv) >= 8) seq_printf(m, "GAMTARBMODE = 0x%08x\n", I915_READ(GAMTARBMODE)); else @@ -2246,9 +2212,9 @@ static int per_file_ctx(int id, void *ptr, void *data) return 0; } -static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) +static void gen8_ppgtt_info(struct seq_file *m, + struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_engine_cs *engine; struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; int i; @@ -2267,9 +2233,9 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) } } -static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) +static void gen6_ppgtt_info(struct seq_file *m, + struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_engine_cs *engine; if (IS_GEN6(dev_priv)) @@ -2301,9 +2267,8 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) static int i915_ppgtt_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct drm_file *file; int ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -2311,10 +2276,10 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) return ret; intel_runtime_pm_get(dev_priv); - if (INTEL_INFO(dev)->gen >= 8) - gen8_ppgtt_info(m, dev); - else if (INTEL_INFO(dev)->gen >= 6) - gen6_ppgtt_info(m, dev); + if (INTEL_GEN(dev_priv) >= 8) + gen8_ppgtt_info(m, dev_priv); + else if (INTEL_GEN(dev_priv) >= 6) + gen6_ppgtt_info(m, dev_priv); mutex_lock(&dev->filelist_mutex); list_for_each_entry_reverse(file, &dev->filelist, lhead) { @@ -2367,9 +2332,8 @@ static const char *rps_power_to_str(unsigned int power) static int i915_rps_boost_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct drm_file *file; seq_printf(m, "RPS enabled? %d\n", dev_priv->rps.enabled); @@ -2437,12 +2401,10 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) static int i915_llc(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); const bool edram = INTEL_GEN(dev_priv) > 8; - seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(dev))); + seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(dev_priv))); seq_printf(m, "%s: %lluMB\n", edram ? "eDRAM" : "eLLC", intel_uncore_edram_size(dev_priv)/1024/1024); @@ -2451,8 +2413,7 @@ static int i915_llc(struct seq_file *m, void *data) static int i915_guc_load_status_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_i915_private *dev_priv = to_i915(node->minor->dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; u32 tmp, i; @@ -2523,9 +2484,8 @@ static void i915_guc_client_info(struct seq_file *m, static int i915_guc_info(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_guc guc; struct i915_guc_client client = {}; struct intel_engine_cs *engine; @@ -2574,9 +2534,7 @@ static int i915_guc_info(struct seq_file *m, void *data) static int i915_guc_log_dump(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_i915_gem_object *obj; int i = 0, pg; @@ -2602,15 +2560,13 @@ static int i915_guc_log_dump(struct seq_file *m, void *data) static int i915_edp_psr_status(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); u32 psrperf = 0; u32 stat[3]; enum pipe pipe; bool enabled = false; - if (!HAS_PSR(dev)) { + if (!HAS_PSR(dev_priv)) { seq_puts(m, "PSR not supported\n"); return 0; } @@ -2627,7 +2583,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) seq_printf(m, "Re-enable work scheduled: %s\n", yesno(work_busy(&dev_priv->psr.work.work))); - if (HAS_DDI(dev)) + if (HAS_DDI(dev_priv)) enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE; else { for_each_pipe(dev_priv, pipe) { @@ -2644,7 +2600,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) seq_printf(m, "HW Enabled & Active bit: %s", yesno(enabled)); - if (!HAS_DDI(dev)) + if (!HAS_DDI(dev_priv)) for_each_pipe(dev_priv, pipe) { if ((stat[pipe] == VLV_EDP_PSR_ACTIVE_NORFB_UP) || (stat[pipe] == VLV_EDP_PSR_ACTIVE_SF_UPDATE)) @@ -2656,7 +2612,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) * VLV/CHV PSR has no kind of performance counter * SKL+ Perf counter is reset to 0 everytime DC state is entered */ - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { psrperf = I915_READ(EDP_PSR_PERF_CNT) & EDP_PSR_PERF_CNT_MASK; @@ -2670,8 +2626,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) static int i915_sink_crc(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_connector *connector; struct intel_dp *intel_dp = NULL; int ret; @@ -2710,13 +2666,11 @@ out: static int i915_energy_uJ(struct seq_file *m, void *data) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); u64 power; u32 units; - if (INTEL_INFO(dev)->gen < 6) + if (INTEL_GEN(dev_priv) < 6) return -ENODEV; intel_runtime_pm_get(dev_priv); @@ -2736,9 +2690,7 @@ static int i915_energy_uJ(struct seq_file *m, void *data) static int i915_runtime_pm_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct pci_dev *pdev = dev_priv->drm.pdev; if (!HAS_RUNTIME_PM(dev_priv)) @@ -2749,7 +2701,7 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) yesno(!intel_irqs_enabled(dev_priv))); #ifdef CONFIG_PM seq_printf(m, "Usage count: %d\n", - atomic_read(&dev->dev->power.usage_count)); + atomic_read(&dev_priv->drm.dev->power.usage_count)); #else seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n"); #endif @@ -2762,9 +2714,7 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) static int i915_power_domain_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct i915_power_domains *power_domains = &dev_priv->power_domains; int i; @@ -2797,12 +2747,10 @@ static int i915_power_domain_info(struct seq_file *m, void *unused) static int i915_dmc_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_csr *csr; - if (!HAS_CSR(dev)) { + if (!HAS_CSR(dev_priv)) { seq_puts(m, "not supported\n"); return 0; } @@ -2820,12 +2768,12 @@ static int i915_dmc_info(struct seq_file *m, void *unused) seq_printf(m, "version: %d.%d\n", CSR_VERSION_MAJOR(csr->version), CSR_VERSION_MINOR(csr->version)); - if (IS_SKYLAKE(dev) && csr->version >= CSR_VERSION(1, 6)) { + if (IS_SKYLAKE(dev_priv) && csr->version >= CSR_VERSION(1, 6)) { seq_printf(m, "DC3 -> DC5 count: %d\n", I915_READ(SKL_CSR_DC3_DC5_COUNT)); seq_printf(m, "DC5 -> DC6 count: %d\n", I915_READ(SKL_CSR_DC5_DC6_COUNT)); - } else if (IS_BROXTON(dev) && csr->version >= CSR_VERSION(1, 4)) { + } else if (IS_BROXTON(dev_priv) && csr->version >= CSR_VERSION(1, 4)) { seq_printf(m, "DC3 -> DC5 count: %d\n", I915_READ(BXT_CSR_DC3_DC5_COUNT)); } @@ -2862,8 +2810,8 @@ static void intel_encoder_info(struct seq_file *m, struct intel_crtc *intel_crtc, struct intel_encoder *intel_encoder) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; + 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; @@ -2889,8 +2837,8 @@ static void intel_encoder_info(struct seq_file *m, static void intel_crtc_info(struct seq_file *m, struct intel_crtc *intel_crtc) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; + 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; @@ -2988,12 +2936,11 @@ static void intel_connector_info(struct seq_file *m, intel_seq_print_mode(m, 2, mode); } -static bool cursor_active(struct drm_device *dev, int pipe) +static bool cursor_active(struct drm_i915_private *dev_priv, int pipe) { - struct drm_i915_private *dev_priv = to_i915(dev); u32 state; - if (IS_845G(dev) || IS_I865G(dev)) + if (IS_845G(dev_priv) || IS_I865G(dev_priv)) state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; else state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; @@ -3001,9 +2948,9 @@ static bool cursor_active(struct drm_device *dev, int pipe) return state; } -static bool cursor_position(struct drm_device *dev, int pipe, int *x, int *y) +static bool cursor_position(struct drm_i915_private *dev_priv, + int pipe, int *x, int *y) { - struct drm_i915_private *dev_priv = to_i915(dev); u32 pos; pos = I915_READ(CURPOS(pipe)); @@ -3016,7 +2963,7 @@ static bool cursor_position(struct drm_device *dev, int pipe, int *x, int *y) if (pos & (CURSOR_POS_SIGN << CURSOR_Y_SHIFT)) *y = -*y; - return cursor_active(dev, pipe); + return cursor_active(dev_priv, pipe); } static const char *plane_type(enum drm_plane_type type) @@ -3059,8 +3006,8 @@ static const char *plane_rotation(unsigned int rotation) static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_plane *intel_plane; for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { @@ -3122,9 +3069,8 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *intel_crtc) static int i915_display_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_crtc *crtc; struct drm_connector *connector; @@ -3148,7 +3094,7 @@ static int i915_display_info(struct seq_file *m, void *unused) if (pipe_config->base.active) { intel_crtc_info(m, crtc); - active = cursor_position(dev, crtc->pipe, &x, &y); + active = cursor_position(dev_priv, crtc->pipe, &x, &y); seq_printf(m, "\tcursor visible? %s, position (%d, %d), size %dx%d, addr 0x%08x, active? %s\n", yesno(crtc->cursor_base), x, y, crtc->base.cursor->state->crtc_w, @@ -3177,11 +3123,10 @@ static int i915_display_info(struct seq_file *m, void *unused) static int i915_semaphore_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; - int num_rings = INTEL_INFO(dev)->num_rings; + int num_rings = INTEL_INFO(dev_priv)->num_rings; enum intel_engine_id id; int j, ret; @@ -3195,7 +3140,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) return ret; intel_runtime_pm_get(dev_priv); - if (IS_BROADWELL(dev)) { + if (IS_BROADWELL(dev_priv)) { struct page *page; uint64_t *seqno; @@ -3250,9 +3195,8 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) static int i915_shared_dplls_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; int i; drm_modeset_lock_all(dev); @@ -3280,9 +3224,8 @@ static int i915_wa_registers(struct seq_file *m, void *unused) int i; int ret; struct intel_engine_cs *engine; - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct i915_workarounds *workarounds = &dev_priv->workarounds; enum intel_engine_id id; @@ -3318,15 +3261,14 @@ static int i915_wa_registers(struct seq_file *m, void *unused) static int i915_ddb_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct skl_ddb_allocation *ddb; struct skl_ddb_entry *entry; enum pipe pipe; int plane; - if (INTEL_INFO(dev)->gen < 9) + if (INTEL_GEN(dev_priv) < 9) return 0; drm_modeset_lock_all(dev); @@ -3356,7 +3298,8 @@ static int i915_ddb_info(struct seq_file *m, void *unused) } static void drrs_status_per_crtc(struct seq_file *m, - struct drm_device *dev, struct intel_crtc *intel_crtc) + struct drm_device *dev, + struct intel_crtc *intel_crtc) { struct drm_i915_private *dev_priv = to_i915(dev); struct i915_drrs *drrs = &dev_priv->drrs; @@ -3425,8 +3368,8 @@ static void drrs_status_per_crtc(struct seq_file *m, static int i915_drrs_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = m->private; - struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_crtc *intel_crtc; int active_crtc_cnt = 0; @@ -3449,14 +3392,14 @@ static int i915_drrs_status(struct seq_file *m, void *unused) struct pipe_crc_info { const char *name; - struct drm_device *dev; + struct drm_i915_private *dev_priv; enum pipe pipe; }; static int i915_dp_mst_info(struct seq_file *m, void *unused) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_device *dev = &dev_priv->drm; struct intel_encoder *intel_encoder; struct intel_digital_port *intel_dig_port; struct drm_connector *connector; @@ -3485,10 +3428,10 @@ static int i915_dp_mst_info(struct seq_file *m, void *unused) static int i915_pipe_crc_open(struct inode *inode, struct file *filep) { struct pipe_crc_info *info = inode->i_private; - struct drm_i915_private *dev_priv = to_i915(info->dev); + struct drm_i915_private *dev_priv = info->dev_priv; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; - if (info->pipe >= INTEL_INFO(info->dev)->num_pipes) + if (info->pipe >= INTEL_INFO(dev_priv)->num_pipes) return -ENODEV; spin_lock_irq(&pipe_crc->lock); @@ -3509,7 +3452,7 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep) static int i915_pipe_crc_release(struct inode *inode, struct file *filep) { struct pipe_crc_info *info = inode->i_private; - struct drm_i915_private *dev_priv = to_i915(info->dev); + struct drm_i915_private *dev_priv = info->dev_priv; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; spin_lock_irq(&pipe_crc->lock); @@ -3536,8 +3479,7 @@ i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, loff_t *pos) { struct pipe_crc_info *info = filep->private_data; - struct drm_device *dev = info->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = info->dev_priv; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; char buf[PIPE_CRC_BUFFER_LEN]; int n_entries; @@ -3633,11 +3575,11 @@ static struct pipe_crc_info i915_pipe_crc_data[I915_MAX_PIPES] = { static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor, enum pipe pipe) { - struct drm_device *dev = minor->dev; + struct drm_i915_private *dev_priv = to_i915(minor->dev); struct dentry *ent; struct pipe_crc_info *info = &i915_pipe_crc_data[pipe]; - info->dev = dev; + info->dev_priv = dev_priv; ent = debugfs_create_file(info->name, S_IRUGO, root, info, &i915_pipe_crc_fops); if (!ent) @@ -3667,8 +3609,7 @@ static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) static int display_crc_ctl_show(struct seq_file *m, void *data) { - struct drm_device *dev = m->private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = m->private; int i; for (i = 0; i < I915_MAX_PIPES; i++) @@ -3680,9 +3621,7 @@ static int display_crc_ctl_show(struct seq_file *m, void *data) static int display_crc_ctl_open(struct inode *inode, struct file *file) { - struct drm_device *dev = inode->i_private; - - return single_open(file, display_crc_ctl_show, dev); + return single_open(file, display_crc_ctl_show, inode->i_private); } static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, @@ -3705,9 +3644,11 @@ static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, return 0; } -static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, +static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, + enum pipe pipe, enum intel_pipe_crc_source *source) { + struct drm_device *dev = &dev_priv->drm; struct intel_encoder *encoder; struct intel_crtc *crtc; struct intel_digital_port *dig_port; @@ -3757,16 +3698,15 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, return ret; } -static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, +static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, enum pipe pipe, enum intel_pipe_crc_source *source, uint32_t *val) { - struct drm_i915_private *dev_priv = to_i915(dev); bool need_stable_symbols = false; if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); + int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source); if (ret) return ret; } @@ -3784,7 +3724,7 @@ static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, need_stable_symbols = true; break; case INTEL_PIPE_CRC_SOURCE_DP_D: - if (!IS_CHERRYVIEW(dev)) + if (!IS_CHERRYVIEW(dev_priv)) return -EINVAL; *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_VLV; need_stable_symbols = true; @@ -3828,16 +3768,15 @@ static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, return 0; } -static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, +static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, enum pipe pipe, enum intel_pipe_crc_source *source, uint32_t *val) { - struct drm_i915_private *dev_priv = to_i915(dev); bool need_stable_symbols = false; if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); + int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source); if (ret) return ret; } @@ -3847,24 +3786,24 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_I9XX; break; case INTEL_PIPE_CRC_SOURCE_TV: - if (!SUPPORTS_TV(dev)) + if (!SUPPORTS_TV(dev_priv)) return -EINVAL; *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_TV_PRE; break; case INTEL_PIPE_CRC_SOURCE_DP_B: - if (!IS_G4X(dev)) + if (!IS_G4X(dev_priv)) return -EINVAL; *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_G4X; need_stable_symbols = true; break; case INTEL_PIPE_CRC_SOURCE_DP_C: - if (!IS_G4X(dev)) + if (!IS_G4X(dev_priv)) return -EINVAL; *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_G4X; need_stable_symbols = true; break; case INTEL_PIPE_CRC_SOURCE_DP_D: - if (!IS_G4X(dev)) + if (!IS_G4X(dev_priv)) return -EINVAL; *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_G4X; need_stable_symbols = true; @@ -3888,7 +3827,7 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, if (need_stable_symbols) { uint32_t tmp = I915_READ(PORT_DFT2_G4X); - WARN_ON(!IS_G4X(dev)); + WARN_ON(!IS_G4X(dev_priv)); I915_WRITE(PORT_DFT_I9XX, I915_READ(PORT_DFT_I9XX) | DC_BALANCE_RESET); @@ -3904,10 +3843,9 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, return 0; } -static void vlv_undo_pipe_scramble_reset(struct drm_device *dev, +static void vlv_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t tmp = I915_READ(PORT_DFT2_G4X); switch (pipe) { @@ -3929,10 +3867,9 @@ static void vlv_undo_pipe_scramble_reset(struct drm_device *dev, } -static void g4x_undo_pipe_scramble_reset(struct drm_device *dev, +static void g4x_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv, enum pipe pipe) { - struct drm_i915_private *dev_priv = to_i915(dev); uint32_t tmp = I915_READ(PORT_DFT2_G4X); if (pipe == PIPE_A) @@ -3973,9 +3910,10 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, return 0; } -static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev, bool enable) +static void hsw_trans_edp_pipe_A_crc_wa(struct drm_i915_private *dev_priv, + bool enable) { - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_device *dev = &dev_priv->drm; struct intel_crtc *crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]); struct intel_crtc_state *pipe_config; @@ -4009,7 +3947,7 @@ out: drm_atomic_state_free(state); } -static int ivb_pipe_crc_ctl_reg(struct drm_device *dev, +static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, enum pipe pipe, enum intel_pipe_crc_source *source, uint32_t *val) @@ -4025,8 +3963,8 @@ static int ivb_pipe_crc_ctl_reg(struct drm_device *dev, *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; break; case INTEL_PIPE_CRC_SOURCE_PF: - if (IS_HASWELL(dev) && pipe == PIPE_A) - hsw_trans_edp_pipe_A_crc_wa(dev, true); + if (IS_HASWELL(dev_priv) && pipe == PIPE_A) + hsw_trans_edp_pipe_A_crc_wa(dev_priv, true); *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; break; @@ -4040,13 +3978,14 @@ static int ivb_pipe_crc_ctl_reg(struct drm_device *dev, return 0; } -static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, +static int pipe_crc_set_source(struct drm_i915_private *dev_priv, + enum pipe pipe, enum intel_pipe_crc_source source) { - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_device *dev = &dev_priv->drm; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, - pipe)); + struct intel_crtc *crtc = + to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); enum intel_display_power_domain power_domain; u32 val = 0; /* shut up gcc */ int ret; @@ -4064,16 +4003,16 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, return -EIO; } - if (IS_GEN2(dev)) + if (IS_GEN2(dev_priv)) ret = i8xx_pipe_crc_ctl_reg(&source, &val); - else if (INTEL_INFO(dev)->gen < 5) - ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val); - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) - ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val); - else if (IS_GEN5(dev) || IS_GEN6(dev)) + else if (INTEL_GEN(dev_priv) < 5) + ret = i9xx_pipe_crc_ctl_reg(dev_priv, pipe, &source, &val); + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + ret = vlv_pipe_crc_ctl_reg(dev_priv, pipe, &source, &val); + else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) ret = ilk_pipe_crc_ctl_reg(&source, &val); else - ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val); + ret = ivb_pipe_crc_ctl_reg(dev_priv, pipe, &source, &val); if (ret != 0) goto out; @@ -4137,12 +4076,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, kfree(entries); - if (IS_G4X(dev)) - g4x_undo_pipe_scramble_reset(dev, pipe); - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) - vlv_undo_pipe_scramble_reset(dev, pipe); - else if (IS_HASWELL(dev) && pipe == PIPE_A) - hsw_trans_edp_pipe_A_crc_wa(dev, false); + if (IS_G4X(dev_priv)) + g4x_undo_pipe_scramble_reset(dev_priv, pipe); + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + vlv_undo_pipe_scramble_reset(dev_priv, pipe); + else if (IS_HASWELL(dev_priv) && pipe == PIPE_A) + hsw_trans_edp_pipe_A_crc_wa(dev_priv, false); hsw_enable_ips(crtc); } @@ -4246,7 +4185,8 @@ display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s) return -EINVAL; } -static int display_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) +static int display_crc_ctl_parse(struct drm_i915_private *dev_priv, + char *buf, size_t len) { #define N_WORDS 3 int n_words; @@ -4277,14 +4217,14 @@ static int display_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) return -EINVAL; } - return pipe_crc_set_source(dev, pipe, source); + return pipe_crc_set_source(dev_priv, pipe, source); } static ssize_t display_crc_ctl_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { struct seq_file *m = file->private_data; - struct drm_device *dev = m->private; + struct drm_i915_private *dev_priv = m->private; char *tmpbuf; int ret; @@ -4307,7 +4247,7 @@ static ssize_t display_crc_ctl_write(struct file *file, const char __user *ubuf, } tmpbuf[len] = '\0'; - ret = display_crc_ctl_parse(dev, tmpbuf, len); + ret = display_crc_ctl_parse(dev_priv, tmpbuf, len); out: kfree(tmpbuf); @@ -4328,8 +4268,8 @@ static const struct file_operations i915_display_crc_ctl_fops = { }; static ssize_t i915_displayport_test_active_write(struct file *file, - const char __user *ubuf, - size_t len, loff_t *offp) + const char __user *ubuf, + size_t len, loff_t *offp) { char *input_buffer; int status = 0; @@ -4359,7 +4299,6 @@ static ssize_t i915_displayport_test_active_write(struct file *file, DRM_DEBUG_DRIVER("Copied %d bytes from user\n", (unsigned int)len); list_for_each_entry(connector, connector_list, head) { - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; @@ -4397,7 +4336,6 @@ static int i915_displayport_test_active_show(struct seq_file *m, void *data) struct intel_dp *intel_dp; list_for_each_entry(connector, connector_list, head) { - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; @@ -4417,11 +4355,12 @@ static int i915_displayport_test_active_show(struct seq_file *m, void *data) } static int i915_displayport_test_active_open(struct inode *inode, - struct file *file) + struct file *file) { - struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = inode->i_private; - return single_open(file, i915_displayport_test_active_show, dev); + return single_open(file, i915_displayport_test_active_show, + &dev_priv->drm); } static const struct file_operations i915_displayport_test_active_fops = { @@ -4441,7 +4380,6 @@ static int i915_displayport_test_data_show(struct seq_file *m, void *data) struct intel_dp *intel_dp; list_for_each_entry(connector, connector_list, head) { - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; @@ -4457,11 +4395,12 @@ static int i915_displayport_test_data_show(struct seq_file *m, void *data) return 0; } static int i915_displayport_test_data_open(struct inode *inode, - struct file *file) + struct file *file) { - struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = inode->i_private; - return single_open(file, i915_displayport_test_data_show, dev); + return single_open(file, i915_displayport_test_data_show, + &dev_priv->drm); } static const struct file_operations i915_displayport_test_data_fops = { @@ -4480,7 +4419,6 @@ static int i915_displayport_test_type_show(struct seq_file *m, void *data) struct intel_dp *intel_dp; list_for_each_entry(connector, connector_list, head) { - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) continue; @@ -4499,9 +4437,10 @@ static int i915_displayport_test_type_show(struct seq_file *m, void *data) static int i915_displayport_test_type_open(struct inode *inode, struct file *file) { - struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = inode->i_private; - return single_open(file, i915_displayport_test_type_show, dev); + return single_open(file, i915_displayport_test_type_show, + &dev_priv->drm); } static const struct file_operations i915_displayport_test_type_fops = { @@ -4514,13 +4453,14 @@ static const struct file_operations i915_displayport_test_type_fops = { static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) { - struct drm_device *dev = m->private; + struct drm_i915_private *dev_priv = m->private; + struct drm_device *dev = &dev_priv->drm; int level; int num_levels; - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) num_levels = 3; - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv)) num_levels = 1; else num_levels = ilk_wm_max_level(dev) + 1; @@ -4534,8 +4474,8 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) * - WM1+ latency values in 0.5us units * - latencies are in us on gen9/vlv/chv */ - if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev) || - IS_CHERRYVIEW(dev)) + if (INTEL_GEN(dev_priv) >= 9 || IS_VALLEYVIEW(dev_priv) || + IS_CHERRYVIEW(dev_priv)) latency *= 10; else if (level > 0) latency *= 5; @@ -4549,14 +4489,13 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) static int pri_wm_latency_show(struct seq_file *m, void *data) { - struct drm_device *dev = m->private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = m->private; const uint16_t *latencies; - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) latencies = dev_priv->wm.skl_latency; else - latencies = to_i915(dev)->wm.pri_latency; + latencies = dev_priv->wm.pri_latency; wm_latency_show(m, latencies); @@ -4565,14 +4504,13 @@ static int pri_wm_latency_show(struct seq_file *m, void *data) static int spr_wm_latency_show(struct seq_file *m, void *data) { - struct drm_device *dev = m->private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = m->private; const uint16_t *latencies; - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) latencies = dev_priv->wm.skl_latency; else - latencies = to_i915(dev)->wm.spr_latency; + latencies = dev_priv->wm.spr_latency; wm_latency_show(m, latencies); @@ -4581,14 +4519,13 @@ static int spr_wm_latency_show(struct seq_file *m, void *data) static int cur_wm_latency_show(struct seq_file *m, void *data) { - struct drm_device *dev = m->private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = m->private; const uint16_t *latencies; - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) latencies = dev_priv->wm.skl_latency; else - latencies = to_i915(dev)->wm.cur_latency; + latencies = dev_priv->wm.cur_latency; wm_latency_show(m, latencies); @@ -4597,48 +4534,49 @@ static int cur_wm_latency_show(struct seq_file *m, void *data) static int pri_wm_latency_open(struct inode *inode, struct file *file) { - struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = inode->i_private; - if (INTEL_INFO(dev)->gen < 5) + if (INTEL_GEN(dev_priv) < 5) return -ENODEV; - return single_open(file, pri_wm_latency_show, dev); + return single_open(file, pri_wm_latency_show, dev_priv); } static int spr_wm_latency_open(struct inode *inode, struct file *file) { - struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = inode->i_private; - if (HAS_GMCH_DISPLAY(dev)) + if (HAS_GMCH_DISPLAY(dev_priv)) return -ENODEV; - return single_open(file, spr_wm_latency_show, dev); + return single_open(file, spr_wm_latency_show, dev_priv); } static int cur_wm_latency_open(struct inode *inode, struct file *file) { - struct drm_device *dev = inode->i_private; + struct drm_i915_private *dev_priv = inode->i_private; - if (HAS_GMCH_DISPLAY(dev)) + if (HAS_GMCH_DISPLAY(dev_priv)) return -ENODEV; - return single_open(file, cur_wm_latency_show, dev); + return single_open(file, cur_wm_latency_show, dev_priv); } static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp, uint16_t wm[8]) { struct seq_file *m = file->private_data; - struct drm_device *dev = m->private; + struct drm_i915_private *dev_priv = m->private; + struct drm_device *dev = &dev_priv->drm; uint16_t new[8] = { 0 }; int num_levels; int level; int ret; char tmp[32]; - if (IS_CHERRYVIEW(dev)) + if (IS_CHERRYVIEW(dev_priv)) num_levels = 3; - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv)) num_levels = 1; else num_levels = ilk_wm_max_level(dev) + 1; @@ -4672,14 +4610,13 @@ static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { struct seq_file *m = file->private_data; - struct drm_device *dev = m->private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = m->private; uint16_t *latencies; - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) latencies = dev_priv->wm.skl_latency; else - latencies = to_i915(dev)->wm.pri_latency; + latencies = dev_priv->wm.pri_latency; return wm_latency_write(file, ubuf, len, offp, latencies); } @@ -4688,14 +4625,13 @@ static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { struct seq_file *m = file->private_data; - struct drm_device *dev = m->private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = m->private; uint16_t *latencies; - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) latencies = dev_priv->wm.skl_latency; else - latencies = to_i915(dev)->wm.spr_latency; + latencies = dev_priv->wm.spr_latency; return wm_latency_write(file, ubuf, len, offp, latencies); } @@ -4704,14 +4640,13 @@ static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { struct seq_file *m = file->private_data; - struct drm_device *dev = m->private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = m->private; uint16_t *latencies; - if (INTEL_INFO(dev)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) latencies = dev_priv->wm.skl_latency; else - latencies = to_i915(dev)->wm.cur_latency; + latencies = dev_priv->wm.cur_latency; return wm_latency_write(file, ubuf, len, offp, latencies); } @@ -4746,8 +4681,7 @@ static const struct file_operations i915_cur_wm_latency_fops = { static int i915_wedged_get(void *data, u64 *val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; *val = i915_terminally_wedged(&dev_priv->gpu_error); @@ -4757,8 +4691,7 @@ i915_wedged_get(void *data, u64 *val) static int i915_wedged_set(void *data, u64 val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; /* * There is no safeguard against this debugfs entry colliding @@ -4788,8 +4721,7 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_wedged_fops, static int i915_ring_missed_irq_get(void *data, u64 *val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; *val = dev_priv->gpu_error.missed_irq_rings; return 0; @@ -4798,8 +4730,8 @@ i915_ring_missed_irq_get(void *data, u64 *val) static int i915_ring_missed_irq_set(void *data, u64 val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; + struct drm_device *dev = &dev_priv->drm; int ret; /* Lock against concurrent debugfs callers */ @@ -4819,8 +4751,7 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_missed_irq_fops, static int i915_ring_test_irq_get(void *data, u64 *val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; *val = dev_priv->gpu_error.test_irq_rings; @@ -4830,8 +4761,7 @@ i915_ring_test_irq_get(void *data, u64 *val) static int i915_ring_test_irq_set(void *data, u64 val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; val &= INTEL_INFO(dev_priv)->ring_mask; DRM_DEBUG_DRIVER("Masking interrupts on rings 0x%08llx\n", val); @@ -4863,8 +4793,8 @@ i915_drop_caches_get(void *data, u64 *val) static int i915_drop_caches_set(void *data, u64 val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; + struct drm_device *dev = &dev_priv->drm; int ret; DRM_DEBUG("Dropping caches: 0x%08llx\n", val); @@ -4903,10 +4833,9 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_drop_caches_fops, static int i915_max_freq_get(void *data, u64 *val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; - if (INTEL_INFO(dev)->gen < 6) + if (INTEL_GEN(dev_priv) < 6) return -ENODEV; *val = intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit); @@ -4916,12 +4845,11 @@ i915_max_freq_get(void *data, u64 *val) static int i915_max_freq_set(void *data, u64 val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; u32 hw_max, hw_min; int ret; - if (INTEL_INFO(dev)->gen < 6) + if (INTEL_GEN(dev_priv) < 6) return -ENODEV; DRM_DEBUG_DRIVER("Manually setting max freq to %llu\n", val); @@ -4959,8 +4887,7 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_max_freq_fops, static int i915_min_freq_get(void *data, u64 *val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; if (INTEL_GEN(dev_priv) < 6) return -ENODEV; @@ -4972,8 +4899,7 @@ i915_min_freq_get(void *data, u64 *val) static int i915_min_freq_set(void *data, u64 val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; u32 hw_max, hw_min; int ret; @@ -4994,7 +4920,8 @@ i915_min_freq_set(void *data, u64 val) hw_max = dev_priv->rps.max_freq; hw_min = dev_priv->rps.min_freq; - if (val < hw_min || val > hw_max || val > dev_priv->rps.max_freq_softlimit) { + if (val < hw_min || + val > hw_max || val > dev_priv->rps.max_freq_softlimit) { mutex_unlock(&dev_priv->rps.hw_lock); return -EINVAL; } @@ -5015,12 +4942,12 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_min_freq_fops, static int i915_cache_sharing_get(void *data, u64 *val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; + struct drm_device *dev = &dev_priv->drm; u32 snpcr; int ret; - if (!(IS_GEN6(dev) || IS_GEN7(dev))) + if (!(IS_GEN6(dev_priv) || IS_GEN7(dev_priv))) return -ENODEV; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -5031,7 +4958,7 @@ i915_cache_sharing_get(void *data, u64 *val) snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); intel_runtime_pm_put(dev_priv); - mutex_unlock(&dev_priv->drm.struct_mutex); + mutex_unlock(&dev->struct_mutex); *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT; @@ -5041,11 +4968,10 @@ i915_cache_sharing_get(void *data, u64 *val) static int i915_cache_sharing_set(void *data, u64 val) { - struct drm_device *dev = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = data; u32 snpcr; - if (!(IS_GEN6(dev) || IS_GEN7(dev))) + if (!(IS_GEN6(dev_priv) || IS_GEN7(dev_priv))) return -ENODEV; if (val > 3) @@ -5076,10 +5002,9 @@ struct sseu_dev_status { unsigned int eu_per_subslice; }; -static void cherryview_sseu_device_status(struct drm_device *dev, +static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, struct sseu_dev_status *stat) { - struct drm_i915_private *dev_priv = to_i915(dev); int ss_max = 2; int ss; u32 sig1[ss_max], sig2[ss_max]; @@ -5108,16 +5033,15 @@ static void cherryview_sseu_device_status(struct drm_device *dev, stat->subslice_total = stat->subslice_per_slice; } -static void gen9_sseu_device_status(struct drm_device *dev, +static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, struct sseu_dev_status *stat) { - struct drm_i915_private *dev_priv = to_i915(dev); int s_max = 3, ss_max = 4; int s, ss; u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2]; /* BXT has a single slice and at most 3 subslices. */ - if (IS_BROXTON(dev)) { + if (IS_BROXTON(dev_priv)) { s_max = 1; ss_max = 3; } @@ -5146,18 +5070,18 @@ static void gen9_sseu_device_status(struct drm_device *dev, stat->slice_total++; - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) - ss_cnt = INTEL_INFO(dev)->subslice_per_slice; + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) + ss_cnt = INTEL_INFO(dev_priv)->subslice_per_slice; for (ss = 0; ss < ss_max; ss++) { unsigned int eu_cnt; - if (IS_BROXTON(dev) && + if (IS_BROXTON(dev_priv) && !(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss)))) /* skip disabled subslice */ continue; - if (IS_BROXTON(dev)) + if (IS_BROXTON(dev_priv)) ss_cnt++; eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & @@ -5173,25 +5097,24 @@ static void gen9_sseu_device_status(struct drm_device *dev, } } -static void broadwell_sseu_device_status(struct drm_device *dev, +static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, struct sseu_dev_status *stat) { - struct drm_i915_private *dev_priv = to_i915(dev); - int s; u32 slice_info = I915_READ(GEN8_GT_SLICE_INFO); + int s; stat->slice_total = hweight32(slice_info & GEN8_LSLICESTAT_MASK); if (stat->slice_total) { - stat->subslice_per_slice = INTEL_INFO(dev)->subslice_per_slice; + stat->subslice_per_slice = INTEL_INFO(dev_priv)->subslice_per_slice; stat->subslice_total = stat->slice_total * stat->subslice_per_slice; - stat->eu_per_subslice = INTEL_INFO(dev)->eu_per_subslice; + stat->eu_per_subslice = INTEL_INFO(dev_priv)->eu_per_subslice; stat->eu_total = stat->eu_per_subslice * stat->subslice_total; /* subtract fused off EU(s) from enabled slice(s) */ for (s = 0; s < stat->slice_total; s++) { - u8 subslice_7eu = INTEL_INFO(dev)->subslice_7eu[s]; + u8 subslice_7eu = INTEL_INFO(dev_priv)->subslice_7eu[s]; stat->eu_total -= hweight8(subslice_7eu); } @@ -5200,47 +5123,45 @@ static void broadwell_sseu_device_status(struct drm_device *dev, static int i915_sseu_status(struct seq_file *m, void *unused) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_i915_private *dev_priv = to_i915(node->minor->dev); - struct drm_device *dev = &dev_priv->drm; + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct sseu_dev_status stat; - if (INTEL_INFO(dev)->gen < 8) + if (INTEL_GEN(dev_priv) < 8) return -ENODEV; seq_puts(m, "SSEU Device Info\n"); seq_printf(m, " Available Slice Total: %u\n", - INTEL_INFO(dev)->slice_total); + INTEL_INFO(dev_priv)->slice_total); seq_printf(m, " Available Subslice Total: %u\n", - INTEL_INFO(dev)->subslice_total); + INTEL_INFO(dev_priv)->subslice_total); seq_printf(m, " Available Subslice Per Slice: %u\n", - INTEL_INFO(dev)->subslice_per_slice); + INTEL_INFO(dev_priv)->subslice_per_slice); seq_printf(m, " Available EU Total: %u\n", - INTEL_INFO(dev)->eu_total); + INTEL_INFO(dev_priv)->eu_total); seq_printf(m, " Available EU Per Subslice: %u\n", - INTEL_INFO(dev)->eu_per_subslice); - seq_printf(m, " Has Pooled EU: %s\n", yesno(HAS_POOLED_EU(dev))); - if (HAS_POOLED_EU(dev)) + INTEL_INFO(dev_priv)->eu_per_subslice); + seq_printf(m, " Has Pooled EU: %s\n", yesno(HAS_POOLED_EU(dev_priv))); + if (HAS_POOLED_EU(dev_priv)) seq_printf(m, " Min EU in pool: %u\n", - INTEL_INFO(dev)->min_eu_in_pool); + INTEL_INFO(dev_priv)->min_eu_in_pool); seq_printf(m, " Has Slice Power Gating: %s\n", - yesno(INTEL_INFO(dev)->has_slice_pg)); + yesno(INTEL_INFO(dev_priv)->has_slice_pg)); seq_printf(m, " Has Subslice Power Gating: %s\n", - yesno(INTEL_INFO(dev)->has_subslice_pg)); + yesno(INTEL_INFO(dev_priv)->has_subslice_pg)); seq_printf(m, " Has EU Power Gating: %s\n", - yesno(INTEL_INFO(dev)->has_eu_pg)); + yesno(INTEL_INFO(dev_priv)->has_eu_pg)); seq_puts(m, "SSEU Device Status\n"); memset(&stat, 0, sizeof(stat)); intel_runtime_pm_get(dev_priv); - if (IS_CHERRYVIEW(dev)) { - cherryview_sseu_device_status(dev, &stat); - } else if (IS_BROADWELL(dev)) { - broadwell_sseu_device_status(dev, &stat); - } else if (INTEL_INFO(dev)->gen >= 9) { - gen9_sseu_device_status(dev, &stat); + if (IS_CHERRYVIEW(dev_priv)) { + cherryview_sseu_device_status(dev_priv, &stat); + } else if (IS_BROADWELL(dev_priv)) { + broadwell_sseu_device_status(dev_priv, &stat); + } else if (INTEL_GEN(dev_priv) >= 9) { + gen9_sseu_device_status(dev_priv, &stat); } intel_runtime_pm_put(dev_priv); @@ -5261,10 +5182,9 @@ static int i915_sseu_status(struct seq_file *m, void *unused) static int i915_forcewake_open(struct inode *inode, struct file *file) { - struct drm_device *dev = inode->i_private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = inode->i_private; - if (INTEL_INFO(dev)->gen < 6) + if (INTEL_GEN(dev_priv) < 6) return 0; intel_runtime_pm_get(dev_priv); @@ -5275,10 +5195,9 @@ static int i915_forcewake_open(struct inode *inode, struct file *file) static int i915_forcewake_release(struct inode *inode, struct file *file) { - struct drm_device *dev = inode->i_private; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = inode->i_private; - if (INTEL_INFO(dev)->gen < 6) + if (INTEL_GEN(dev_priv) < 6) return 0; intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); @@ -5295,12 +5214,11 @@ static const struct file_operations i915_forcewake_fops = { static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor) { - struct drm_device *dev = minor->dev; struct dentry *ent; ent = debugfs_create_file("i915_forcewake_user", S_IRUSR, - root, dev, + root, to_i915(minor->dev), &i915_forcewake_fops); if (!ent) return -ENOMEM; @@ -5313,12 +5231,11 @@ static int i915_debugfs_create(struct dentry *root, const char *name, const struct file_operations *fops) { - struct drm_device *dev = minor->dev; struct dentry *ent; ent = debugfs_create_file(name, S_IRUGO | S_IWUSR, - root, dev, + root, to_i915(minor->dev), fops); if (!ent) return -ENOMEM; @@ -5405,9 +5322,8 @@ static const struct i915_debugfs_files { {"i915_dp_test_active", &i915_displayport_test_active_fops} }; -void intel_display_crc_init(struct drm_device *dev) +void intel_display_crc_init(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); enum pipe pipe; for_each_pipe(dev_priv, pipe) { @@ -5455,7 +5371,7 @@ void i915_debugfs_unregister(struct drm_i915_private *dev_priv) drm_debugfs_remove_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor); - drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops, + drm_debugfs_remove_files((struct drm_info_list *)&i915_forcewake_fops, 1, minor); for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) { @@ -5467,7 +5383,7 @@ void i915_debugfs_unregister(struct drm_i915_private *dev_priv) for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) { struct drm_info_list *info_list = - (struct drm_info_list *) i915_debugfs_files[i].fops; + (struct drm_info_list *)i915_debugfs_files[i].fops; drm_debugfs_remove_files(info_list, 1, minor); } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index d22a1d8fe5b7..5a7c0c2e57d8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -851,7 +851,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, intel_init_audio_hooks(dev_priv); i915_gem_load_init(&dev_priv->drm); - intel_display_crc_init(&dev_priv->drm); + intel_display_crc_init(dev_priv); intel_device_info_dump(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dd7d76a9e01b..41e4178aa434 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3514,7 +3514,7 @@ static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_objec int i915_debugfs_register(struct drm_i915_private *dev_priv); void i915_debugfs_unregister(struct drm_i915_private *dev_priv); int i915_debugfs_connector_add(struct drm_connector *connector); -void intel_display_crc_init(struct drm_device *dev); +void intel_display_crc_init(struct drm_i915_private *dev_priv); #else static inline int i915_debugfs_register(struct drm_i915_private *dev_priv) {return 0;} static inline void i915_debugfs_unregister(struct drm_i915_private *dev_priv) {} -- cgit v1.2.1 From 8bcdd0f756b7bf13c340a319ad6748ed6386a944 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 22 Aug 2016 08:44:30 +0100 Subject: drm/i915: Embed the scratch page struct into each VM As the scratch page is no longer shared between all VM, and each has their own, forgo the small allocation and simply embed the scratch page struct into the i915_address_space. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160822074431.26872-2-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen Acked-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_gem_gtt.c | 76 +++++++++++++++---------------------- drivers/gpu/drm/i915/i915_gem_gtt.h | 6 +-- 2 files changed, 32 insertions(+), 50 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index eba0166c4df5..b947fb9f0d44 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -409,29 +409,16 @@ static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p, fill_page_dma(dev, p, v); } -static struct i915_page_scratch *alloc_scratch_page(struct drm_device *dev) +static int +setup_scratch_page(struct drm_device *dev, struct i915_page_dma *scratch) { - struct i915_page_scratch *sp; - int ret; - - sp = kzalloc(sizeof(*sp), GFP_KERNEL); - if (sp == NULL) - return ERR_PTR(-ENOMEM); - - ret = __setup_page_dma(dev, px_base(sp), GFP_DMA32 | __GFP_ZERO); - if (ret) { - kfree(sp); - return ERR_PTR(ret); - } - - return sp; + return __setup_page_dma(dev, scratch, GFP_DMA32 | __GFP_ZERO); } -static void free_scratch_page(struct drm_device *dev, - struct i915_page_scratch *sp) +static void cleanup_scratch_page(struct drm_device *dev, + struct i915_page_dma *scratch) { - cleanup_px(dev, sp); - kfree(sp); + cleanup_page_dma(dev, scratch); } static struct i915_page_table *alloc_pt(struct drm_device *dev) @@ -477,7 +464,7 @@ static void gen8_initialize_pt(struct i915_address_space *vm, { gen8_pte_t scratch_pte; - scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), + scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, true); fill_px(vm->dev, pt, scratch_pte); @@ -488,9 +475,9 @@ static void gen6_initialize_pt(struct i915_address_space *vm, { gen6_pte_t scratch_pte; - WARN_ON(px_dma(vm->scratch_page) == 0); + WARN_ON(vm->scratch_page.daddr == 0); - scratch_pte = vm->pte_encode(px_dma(vm->scratch_page), + scratch_pte = vm->pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, true, 0); fill32_px(vm->dev, pt, scratch_pte); @@ -774,7 +761,7 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm, bool use_scratch) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), + gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, use_scratch); if (!USES_FULL_48BIT_PPGTT(vm->dev)) { @@ -880,9 +867,9 @@ static int gen8_init_scratch(struct i915_address_space *vm) struct drm_device *dev = vm->dev; int ret; - vm->scratch_page = alloc_scratch_page(dev); - if (IS_ERR(vm->scratch_page)) - return PTR_ERR(vm->scratch_page); + ret = setup_scratch_page(dev, &vm->scratch_page); + if (ret) + return ret; vm->scratch_pt = alloc_pt(dev); if (IS_ERR(vm->scratch_pt)) { @@ -916,7 +903,7 @@ free_pd: free_pt: free_pt(dev, vm->scratch_pt); free_scratch_page: - free_scratch_page(dev, vm->scratch_page); + cleanup_scratch_page(dev, &vm->scratch_page); return ret; } @@ -960,7 +947,7 @@ static void gen8_free_scratch(struct i915_address_space *vm) free_pdp(dev, vm->scratch_pdp); free_pd(dev, vm->scratch_pd); free_pt(dev, vm->scratch_pt); - free_scratch_page(dev, vm->scratch_page); + cleanup_scratch_page(dev, &vm->scratch_page); } static void gen8_ppgtt_cleanup_3lvl(struct drm_device *dev, @@ -1457,7 +1444,7 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) struct i915_address_space *vm = &ppgtt->base; uint64_t start = ppgtt->base.start; uint64_t length = ppgtt->base.total; - gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), + gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, true); if (!USES_FULL_48BIT_PPGTT(vm->dev)) { @@ -1574,7 +1561,7 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) uint32_t pte, pde; uint32_t start = ppgtt->base.start, length = ppgtt->base.total; - scratch_pte = vm->pte_encode(px_dma(vm->scratch_page), + scratch_pte = vm->pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, true, 0); gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde) { @@ -1799,7 +1786,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, unsigned first_pte = first_entry % GEN6_PTES; unsigned last_pte, i; - scratch_pte = vm->pte_encode(px_dma(vm->scratch_page), + scratch_pte = vm->pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, true, 0); while (num_entries) { @@ -1945,14 +1932,15 @@ unwind_out: static int gen6_init_scratch(struct i915_address_space *vm) { struct drm_device *dev = vm->dev; + int ret; - vm->scratch_page = alloc_scratch_page(dev); - if (IS_ERR(vm->scratch_page)) - return PTR_ERR(vm->scratch_page); + ret = setup_scratch_page(dev, &vm->scratch_page); + if (ret) + return ret; vm->scratch_pt = alloc_pt(dev); if (IS_ERR(vm->scratch_pt)) { - free_scratch_page(dev, vm->scratch_page); + cleanup_scratch_page(dev, &vm->scratch_page); return PTR_ERR(vm->scratch_pt); } @@ -1966,7 +1954,7 @@ static void gen6_free_scratch(struct i915_address_space *vm) struct drm_device *dev = vm->dev; free_pt(dev, vm->scratch_pt); - free_scratch_page(dev, vm->scratch_page); + cleanup_scratch_page(dev, &vm->scratch_page); } static void gen6_ppgtt_cleanup(struct i915_address_space *vm) @@ -2507,7 +2495,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page), + scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, use_scratch); for (i = 0; i < num_entries; i++) @@ -2539,7 +2527,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = vm->pte_encode(px_dma(vm->scratch_page), + scratch_pte = vm->pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, use_scratch, 0); for (i = 0; i < num_entries; i++) @@ -2892,8 +2880,8 @@ static size_t gen9_get_stolen_size(u16 gen9_gmch_ctl) static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) { struct pci_dev *pdev = ggtt->base.dev->pdev; - struct i915_page_scratch *scratch_page; phys_addr_t phys_addr; + int ret; /* For Modern GENs the PTEs and register space are split in the BAR */ phys_addr = pci_resource_start(pdev, 0) + pci_resource_len(pdev, 0) / 2; @@ -2914,16 +2902,14 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return -ENOMEM; } - scratch_page = alloc_scratch_page(ggtt->base.dev); - if (IS_ERR(scratch_page)) { + ret = setup_scratch_page(ggtt->base.dev, &ggtt->base.scratch_page); + if (ret) { DRM_ERROR("Scratch setup failed\n"); /* iounmap will also get called at remove, but meh */ iounmap(ggtt->gsm); - return PTR_ERR(scratch_page); + return ret; } - ggtt->base.scratch_page = scratch_page; - return 0; } @@ -3005,7 +2991,7 @@ static void gen6_gmch_remove(struct i915_address_space *vm) struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); iounmap(ggtt->gsm); - free_scratch_page(vm->dev, vm->scratch_page); + cleanup_scratch_page(vm->dev, &vm->scratch_page); } static int gen8_gmch_probe(struct i915_ggtt *ggtt) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index a9aec25535ac..ec78be2f8c77 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -312,10 +312,6 @@ struct i915_page_dma { #define px_page(px) (px_base(px)->page) #define px_dma(px) (px_base(px)->daddr) -struct i915_page_scratch { - struct i915_page_dma base; -}; - struct i915_page_table { struct i915_page_dma base; @@ -361,7 +357,7 @@ struct i915_address_space { bool closed; - struct i915_page_scratch *scratch_page; + struct i915_page_dma scratch_page; struct i915_page_table *scratch_pt; struct i915_page_directory *scratch_pd; struct i915_page_directory_pointer *scratch_pdp; /* GEN8+ & 48b PPGTT */ -- cgit v1.2.1 From bb8f9cffad4469e3daa4d3759d5b6cc72939ab45 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 22 Aug 2016 08:44:31 +0100 Subject: drm/i915: Allow DMA pagetables to use highmem As we never need to directly access the pages we allocate for scratch and the pagetables, and always remap them into the GTT through the dma remapper, we do not need to limit the allocations to lowmem i.e. we can pass in the __GFP_HIGHMEM flag to the page allocation. For backwards compatibility, e.g. certain old GPUs not liking highmem for certain functions that may be accidentally mapped to the scratch page by userspace, keep the GMCH probe as only allocating from DMA32. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160822074431.26872-3-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem_gtt.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index b947fb9f0d44..570e7311a419 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -32,6 +32,8 @@ #include "i915_trace.h" #include "intel_drv.h" +#define I915_GFP_DMA (GFP_KERNEL | __GFP_HIGHMEM) + /** * DOC: Global GTT views * @@ -345,7 +347,7 @@ static int __setup_page_dma(struct drm_device *dev, static int setup_page_dma(struct drm_device *dev, struct i915_page_dma *p) { - return __setup_page_dma(dev, p, GFP_KERNEL); + return __setup_page_dma(dev, p, I915_GFP_DMA); } static void cleanup_page_dma(struct drm_device *dev, struct i915_page_dma *p) @@ -410,9 +412,11 @@ static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p, } static int -setup_scratch_page(struct drm_device *dev, struct i915_page_dma *scratch) +setup_scratch_page(struct drm_device *dev, + struct i915_page_dma *scratch, + gfp_t gfp) { - return __setup_page_dma(dev, scratch, GFP_DMA32 | __GFP_ZERO); + return __setup_page_dma(dev, scratch, gfp | __GFP_ZERO); } static void cleanup_scratch_page(struct drm_device *dev, @@ -867,7 +871,7 @@ static int gen8_init_scratch(struct i915_address_space *vm) struct drm_device *dev = vm->dev; int ret; - ret = setup_scratch_page(dev, &vm->scratch_page); + ret = setup_scratch_page(dev, &vm->scratch_page, I915_GFP_DMA); if (ret) return ret; @@ -1934,7 +1938,7 @@ static int gen6_init_scratch(struct i915_address_space *vm) struct drm_device *dev = vm->dev; int ret; - ret = setup_scratch_page(dev, &vm->scratch_page); + ret = setup_scratch_page(dev, &vm->scratch_page, I915_GFP_DMA); if (ret) return ret; @@ -2902,7 +2906,9 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return -ENOMEM; } - ret = setup_scratch_page(ggtt->base.dev, &ggtt->base.scratch_page); + ret = setup_scratch_page(ggtt->base.dev, + &ggtt->base.scratch_page, + GFP_DMA32); if (ret) { DRM_ERROR("Scratch setup failed\n"); /* iounmap will also get called at remove, but meh */ -- cgit v1.2.1 From 34730fed9fd54e893ec0177c97a509de3ee0a5a4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 20 Aug 2016 15:54:08 +0100 Subject: drm/i915: Ignore stuck requests when considering hangs If the engine isn't being retired (worker starvation?) then it is possible for us to repeatedly observe that between consecutive hangchecks the seqno on the ring to be the same and there remain unretired requests. Ignore these completely and only regard the engine as busy for the purpose of hang detection (not stall detection) if there are outstanding breadcrumbs. In recent history we have looked at using both the request and seqno as indication of activity on the engine, but that was reduced to just inspecting seqno in commit cffa781e5907 ("drm/i915: Simplify check for idleness in hangcheck"). However, in commit dcff85c8443e ("drm/i915: Enable i915_gem_wait_for_idle() without holding struct_mutex"), I made the decision to use the new common lockless function, under the assumption that request retirement was more frequent than hangcheck and so we would not have a stuck busy check. The flaw there was in forgetting that we accumulate the hang score, and so successive checks seeing a stuck request, albeit with the GPU advancing elsewhere and so not necessary the same stuck request, would eventually trigger the hang. Fixes: dcff85c8443e ("drm/i915: Enable i915_gem_wait_for_idle()...") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160820145408.32180-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_irq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ebb83d5a448b..7610eca4f687 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3079,6 +3079,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) bool busy = intel_engine_has_waiter(engine); u64 acthd; u32 seqno; + u32 submit; semaphore_clear_deadlocks(dev_priv); @@ -3094,9 +3095,10 @@ static void i915_hangcheck_elapsed(struct work_struct *work) acthd = intel_engine_get_active_head(engine); seqno = intel_engine_get_seqno(engine); + submit = READ_ONCE(engine->last_submitted_seqno); if (engine->hangcheck.seqno == seqno) { - if (!intel_engine_is_active(engine)) { + if (i915_seqno_passed(seqno, submit)) { engine->hangcheck.action = HANGCHECK_IDLE; if (busy) { /* Safeguard against driver failure */ -- cgit v1.2.1 From 637ee29eff53fd718a454aacd3b7190cb4e15df8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 22 Aug 2016 14:28:20 +0100 Subject: drm/i915: Fix nesting of filelist_mutex vs struct_mutex in i915_ppgtt_info An unlikely ABBA deadlock in debugfs that no one has reported. [ 284.922349] ====================================================== [ 284.922355] [ INFO: possible circular locking dependency detected ] [ 284.922361] 4.8.0-rc2+ #430 Tainted: G W [ 284.922366] ------------------------------------------------------- [ 284.922371] cat/1197 is trying to acquire lock: [ 284.922376] (&dev->filelist_mutex){+.+...}, at: [] i915_ppgtt_info+0x82/0x390 [i915] [ 284.922423] [ 284.922423] but task is already holding lock: [ 284.922429] (&dev->struct_mutex){+.+.+.}, at: [] i915_ppgtt_info+0x35/0x390 [i915] [ 284.922465] [ 284.922465] which lock already depends on the new lock. [ 284.922465] [ 284.922471] [ 284.922471] the existing dependency chain (in reverse order) is: [ 284.922477] -> #1 (&dev->struct_mutex){+.+.+.}: [ 284.922493] [] lock_acquire+0x60/0x80 [ 284.922505] [] mutex_lock_nested+0x5f/0x360 [ 284.922520] [] print_context_stats+0x37/0xf0 [i915] [ 284.922549] [] i915_gem_object_info+0x265/0x490 [i915] [ 284.922581] [] seq_read+0xe1/0x3b0 [ 284.922592] [] full_proxy_read+0x83/0xb0 [ 284.922604] [] __vfs_read+0x23/0x110 [ 284.922616] [] vfs_read+0x89/0x110 [ 284.922626] [] SyS_read+0x44/0xa0 [ 284.922636] [] entry_SYSCALL_64_fastpath+0x1c/0xac [ 284.922648] -> #0 (&dev->filelist_mutex){+.+...}: [ 284.922667] [] __lock_acquire+0x10fc/0x1270 [ 284.922678] [] lock_acquire+0x60/0x80 [ 284.922689] [] mutex_lock_nested+0x5f/0x360 [ 284.922701] [] i915_ppgtt_info+0x82/0x390 [i915] [ 284.922729] [] seq_read+0xe1/0x3b0 [ 284.922739] [] full_proxy_read+0x83/0xb0 [ 284.922750] [] __vfs_read+0x23/0x110 [ 284.922761] [] vfs_read+0x89/0x110 [ 284.922771] [] SyS_read+0x44/0xa0 [ 284.922781] [] entry_SYSCALL_64_fastpath+0x1c/0xac [ 284.922793] [ 284.922793] other info that might help us debug this: [ 284.922793] [ 284.922809] Possible unsafe locking scenario: [ 284.922809] [ 284.922818] CPU0 CPU1 [ 284.922825] ---- ---- [ 284.922831] lock(&dev->struct_mutex); [ 284.922842] lock(&dev->filelist_mutex); [ 284.922854] lock(&dev->struct_mutex); [ 284.922865] lock(&dev->filelist_mutex); [ 284.922875] [ 284.922875] *** DEADLOCK *** [ 284.922875] [ 284.922888] 3 locks held by cat/1197: [ 284.922895] #0: (debugfs_srcu){......}, at: [] full_proxy_read+0x0/0xb0 [ 284.922919] #1: (&p->lock){+.+.+.}, at: [] seq_read+0x38/0x3b0 [ 284.922942] #2: (&dev->struct_mutex){+.+.+.}, at: [] i915_ppgtt_info+0x35/0x390 [i915] [ 284.922983] Fixes: 1d2ac403ae3b ("drm: Protect dev->filelist with its own mutex") Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160822132820.21725-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3054bd62c5fd..0f6116fd91d8 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2270,10 +2270,13 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_device *dev = &dev_priv->drm; struct drm_file *file; + int ret; - int ret = mutex_lock_interruptible(&dev->struct_mutex); + mutex_lock(&dev->filelist_mutex); + ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) - return ret; + goto out_unlock; + intel_runtime_pm_get(dev_priv); if (INTEL_GEN(dev_priv) >= 8) @@ -2281,7 +2284,6 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) else if (INTEL_GEN(dev_priv) >= 6) gen6_ppgtt_info(m, dev_priv); - mutex_lock(&dev->filelist_mutex); list_for_each_entry_reverse(file, &dev->filelist, lhead) { struct drm_i915_file_private *file_priv = file->driver_priv; struct task_struct *task; @@ -2289,19 +2291,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) task = get_pid_task(file->pid, PIDTYPE_PID); if (!task) { ret = -ESRCH; - goto out_unlock; + goto out_rpm; } seq_printf(m, "\nproc: %s\n", task->comm); put_task_struct(task); idr_for_each(&file_priv->context_idr, per_file_ctx, (void *)(unsigned long)m); } -out_unlock: - mutex_unlock(&dev->filelist_mutex); +out_rpm: intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); - +out_unlock: + mutex_unlock(&dev->filelist_mutex); return ret; } -- cgit v1.2.1 From 4e6c2d58ba8649a6b505fc1461ccdedc583c3e36 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 19 Aug 2016 17:45:02 +0100 Subject: drm/i915: Take forcewake once for the entire GMBUS transaction As we do many register reads within a very short period of time, hold the GMBUS powerwell from start to finish. Signed-off-by: Chris Wilson Cc: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20160819164503.17845-1-chris@chris-wilson.co.uk Reviewed-by: David Weinehall --- drivers/gpu/drm/i915/intel_i2c.c | 131 +++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 68 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index a4ca2052315e..79aab9ad6faa 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -255,67 +255,59 @@ intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin) algo->data = bus; } -static int -gmbus_wait_hw_status(struct drm_i915_private *dev_priv, - u32 gmbus2_status, - u32 gmbus4_irq_en) +static int gmbus_wait(struct drm_i915_private *dev_priv, u32 status, u32 irq_en) { - int i; - u32 gmbus2 = 0; DEFINE_WAIT(wait); - - if (!HAS_GMBUS_IRQ(dev_priv)) - gmbus4_irq_en = 0; + u32 gmbus2; + int ret; /* Important: The hw handles only the first bit, so set only one! Since * we also need to check for NAKs besides the hw ready/idle signal, we - * need to wake up periodically and check that ourselves. */ - I915_WRITE(GMBUS4, gmbus4_irq_en); - - for (i = 0; i < msecs_to_jiffies_timeout(50); i++) { - prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait, - TASK_UNINTERRUPTIBLE); + * need to wake up periodically and check that ourselves. + */ + if (!HAS_GMBUS_IRQ(dev_priv)) + irq_en = 0; - gmbus2 = I915_READ_NOTRACE(GMBUS2); - if (gmbus2 & (GMBUS_SATOER | gmbus2_status)) - break; + add_wait_queue(&dev_priv->gmbus_wait_queue, &wait); + I915_WRITE_FW(GMBUS4, irq_en); - schedule_timeout(1); - } - finish_wait(&dev_priv->gmbus_wait_queue, &wait); + status |= GMBUS_SATOER; + ret = wait_for_us((gmbus2 = I915_READ_FW(GMBUS2)) & status, 2); + if (ret) + ret = wait_for((gmbus2 = I915_READ_FW(GMBUS2)) & status, 50); - I915_WRITE(GMBUS4, 0); + I915_WRITE_FW(GMBUS4, 0); + remove_wait_queue(&dev_priv->gmbus_wait_queue, &wait); if (gmbus2 & GMBUS_SATOER) return -ENXIO; - if (gmbus2 & gmbus2_status) - return 0; - return -ETIMEDOUT; + + return ret; } static int gmbus_wait_idle(struct drm_i915_private *dev_priv) { + DEFINE_WAIT(wait); + u32 irq_enable; int ret; - if (!HAS_GMBUS_IRQ(dev_priv)) - return intel_wait_for_register(dev_priv, - GMBUS2, GMBUS_ACTIVE, 0, - 10); - /* Important: The hw handles only the first bit, so set only one! */ - I915_WRITE(GMBUS4, GMBUS_IDLE_EN); + irq_enable = 0; + if (HAS_GMBUS_IRQ(dev_priv)) + irq_enable = GMBUS_IDLE_EN; - ret = wait_event_timeout(dev_priv->gmbus_wait_queue, - (I915_READ_NOTRACE(GMBUS2) & GMBUS_ACTIVE) == 0, - msecs_to_jiffies_timeout(10)); + add_wait_queue(&dev_priv->gmbus_wait_queue, &wait); + I915_WRITE_FW(GMBUS4, irq_enable); - I915_WRITE(GMBUS4, 0); + ret = intel_wait_for_register_fw(dev_priv, + GMBUS2, GMBUS_ACTIVE, 0, + 10); - if (ret) - return 0; - else - return -ETIMEDOUT; + I915_WRITE_FW(GMBUS4, 0); + remove_wait_queue(&dev_priv->gmbus_wait_queue, &wait); + + return ret; } static int @@ -323,22 +315,21 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv, unsigned short addr, u8 *buf, unsigned int len, u32 gmbus1_index) { - I915_WRITE(GMBUS1, - gmbus1_index | - GMBUS_CYCLE_WAIT | - (len << GMBUS_BYTE_COUNT_SHIFT) | - (addr << GMBUS_SLAVE_ADDR_SHIFT) | - GMBUS_SLAVE_READ | GMBUS_SW_RDY); + I915_WRITE_FW(GMBUS1, + gmbus1_index | + GMBUS_CYCLE_WAIT | + (len << GMBUS_BYTE_COUNT_SHIFT) | + (addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_READ | GMBUS_SW_RDY); while (len) { int ret; u32 val, loop = 0; - ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY, - GMBUS_HW_RDY_EN); + ret = gmbus_wait(dev_priv, GMBUS_HW_RDY, GMBUS_HW_RDY_EN); if (ret) return ret; - val = I915_READ(GMBUS3); + val = I915_READ_FW(GMBUS3); do { *buf++ = val & 0xff; val >>= 8; @@ -385,12 +376,12 @@ gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv, len -= 1; } - I915_WRITE(GMBUS3, val); - I915_WRITE(GMBUS1, - GMBUS_CYCLE_WAIT | - (chunk_size << GMBUS_BYTE_COUNT_SHIFT) | - (addr << GMBUS_SLAVE_ADDR_SHIFT) | - GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); + I915_WRITE_FW(GMBUS3, val); + I915_WRITE_FW(GMBUS1, + GMBUS_CYCLE_WAIT | + (chunk_size << GMBUS_BYTE_COUNT_SHIFT) | + (addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); while (len) { int ret; @@ -399,10 +390,9 @@ gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv, val |= *buf++ << (8 * loop); } while (--len && ++loop < 4); - I915_WRITE(GMBUS3, val); + I915_WRITE_FW(GMBUS3, val); - ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY, - GMBUS_HW_RDY_EN); + ret = gmbus_wait(dev_priv, GMBUS_HW_RDY, GMBUS_HW_RDY_EN); if (ret) return ret; } @@ -460,13 +450,13 @@ gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs) /* GMBUS5 holds 16-bit index */ if (gmbus5) - I915_WRITE(GMBUS5, gmbus5); + I915_WRITE_FW(GMBUS5, gmbus5); ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index); /* Clear GMBUS5 after each index transfer */ if (gmbus5) - I915_WRITE(GMBUS5, 0); + I915_WRITE_FW(GMBUS5, 0); return ret; } @@ -478,11 +468,15 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) struct intel_gmbus, adapter); struct drm_i915_private *dev_priv = bus->dev_priv; + const unsigned int fw = + intel_uncore_forcewake_for_reg(dev_priv, GMBUS0, + FW_REG_READ | FW_REG_WRITE); int i = 0, inc, try = 0; int ret = 0; + intel_uncore_forcewake_get(dev_priv, fw); retry: - I915_WRITE(GMBUS0, bus->reg0); + I915_WRITE_FW(GMBUS0, bus->reg0); for (; i < num; i += inc) { inc = 1; @@ -496,8 +490,8 @@ retry: } if (!ret) - ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE, - GMBUS_HW_WAIT_EN); + ret = gmbus_wait(dev_priv, + GMBUS_HW_WAIT_PHASE, GMBUS_HW_WAIT_EN); if (ret == -ETIMEDOUT) goto timeout; else if (ret) @@ -508,7 +502,7 @@ retry: * a STOP on the very first cycle. To simplify the code we * unconditionally generate the STOP condition with an additional gmbus * cycle. */ - I915_WRITE(GMBUS1, GMBUS_CYCLE_STOP | GMBUS_SW_RDY); + I915_WRITE_FW(GMBUS1, GMBUS_CYCLE_STOP | GMBUS_SW_RDY); /* Mark the GMBUS interface as disabled after waiting for idle. * We will re-enable it at the start of the next xfer, @@ -519,7 +513,7 @@ retry: adapter->name); ret = -ETIMEDOUT; } - I915_WRITE(GMBUS0, 0); + I915_WRITE_FW(GMBUS0, 0); ret = ret ?: i; goto out; @@ -548,9 +542,9 @@ clear_err: * of resetting the GMBUS controller and so clearing the * BUS_ERROR raised by the slave's NAK. */ - I915_WRITE(GMBUS1, GMBUS_SW_CLR_INT); - I915_WRITE(GMBUS1, 0); - I915_WRITE(GMBUS0, 0); + I915_WRITE_FW(GMBUS1, GMBUS_SW_CLR_INT); + I915_WRITE_FW(GMBUS1, 0); + I915_WRITE_FW(GMBUS0, 0); DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n", adapter->name, msgs[i].addr, @@ -573,7 +567,7 @@ clear_err: timeout: DRM_DEBUG_KMS("GMBUS [%s] timed out, falling back to bit banging on pin %d\n", bus->adapter.name, bus->reg0 & 0xff); - I915_WRITE(GMBUS0, 0); + I915_WRITE_FW(GMBUS0, 0); /* * Hardware may not support GMBUS over these pins? Try GPIO bitbanging @@ -582,6 +576,7 @@ timeout: ret = -EAGAIN; out: + intel_uncore_forcewake_put(dev_priv, fw); return ret; } -- cgit v1.2.1 From a79e8cc7926d08378fe30666df2f7bc8b0a80689 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:00 +0200 Subject: drm/i915: handle DP_MST correctly in bxt_get_dpll No idea if it supports it, but this is the minimum required from get_dpll. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dpll_mgr.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 5c1f2d235ffa..655a5b382cf9 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1535,7 +1535,8 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, vco = best_clock.vco; } else if (encoder->type == INTEL_OUTPUT_DP || - encoder->type == INTEL_OUTPUT_EDP) { + encoder->type == INTEL_OUTPUT_EDP || + encoder->type == INTEL_OUTPUT_DP_MST) { int i; clk_div = bxt_dp_clk_val[0]; @@ -1611,7 +1612,12 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, crtc_state->dpll_hw_state.pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger; - intel_dig_port = enc_to_dig_port(&encoder->base); + if (encoder->type == INTEL_OUTPUT_DP_MST) { + struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); + + intel_dig_port = intel_mst->primary; + } else + intel_dig_port = enc_to_dig_port(&encoder->base); /* 1:1 mapping between ports and PLLs */ i = (enum intel_dpll_id) intel_dig_port->port; -- cgit v1.2.1 From 4a80655827afa661b77b2950dce77079c0bb0e11 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:01 +0200 Subject: drm/i915: Pass atomic state to crtc enable/disable functions This is required for supporting nonblocking modesets. Iterating over the connector list will no longer be allowed when we don't hold connection_mutex, so we have to use the atomic state. Fix disable_noatomic by populating the minimal state required to disable a connector. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-3-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 ++-- drivers/gpu/drm/i915/intel_display.c | 56 ++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 41e4178aa434..ff96b7a69e6c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -510,8 +510,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 drm_crtc *crtc); - void (*crtc_disable)(struct drm_crtc *crtc); + void (*crtc_enable)(struct intel_crtc_state *pipe_config, + struct drm_atomic_state *old_state); + void (*crtc_disable)(struct intel_crtc_state *old_crtc_state, + struct drm_atomic_state *old_state); void (*audio_codec_enable)(struct drm_connector *connector, struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d5d8fea8305b..c4db59521cf5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5154,15 +5154,15 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask intel_frontbuffer_flip(to_i915(dev), INTEL_FRONTBUFFER_ALL_MASK(pipe)); } -static void ironlake_crtc_enable(struct drm_crtc *crtc) +static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, + struct drm_atomic_state *old_state) { + struct drm_crtc *crtc = pipe_config->base.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); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; - struct intel_crtc_state *pipe_config = - to_intel_crtc_state(crtc->state); if (WARN_ON(intel_crtc->active)) return; @@ -5251,16 +5251,16 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc) return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A; } -static void haswell_crtc_enable(struct drm_crtc *crtc) +static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, + struct drm_atomic_state *old_state) { + struct drm_crtc *crtc = pipe_config->base.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); struct intel_encoder *encoder; int pipe = intel_crtc->pipe, hsw_workaround_pipe; enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; - struct intel_crtc_state *pipe_config = - to_intel_crtc_state(crtc->state); if (WARN_ON(intel_crtc->active)) return; @@ -5390,8 +5390,10 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force) } } -static void ironlake_crtc_disable(struct drm_crtc *crtc) +static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, + struct drm_atomic_state *old_state) { + struct drm_crtc *crtc = old_crtc_state->base.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); @@ -5453,8 +5455,10 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); } -static void haswell_crtc_disable(struct drm_crtc *crtc) +static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, + struct drm_atomic_state *old_state) { + struct drm_crtc *crtc = old_crtc_state->base.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); @@ -6558,14 +6562,14 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state) intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A); } -static void valleyview_crtc_enable(struct drm_crtc *crtc) +static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, + struct drm_atomic_state *old_state) { + struct drm_crtc *crtc = pipe_config->base.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); struct intel_encoder *encoder; - struct intel_crtc_state *pipe_config = - to_intel_crtc_state(crtc->state); int pipe = intel_crtc->pipe; if (WARN_ON(intel_crtc->active)) @@ -6629,14 +6633,14 @@ static void i9xx_set_pll_dividers(struct intel_crtc *crtc) I915_WRITE(FP1(crtc->pipe), crtc->config->dpll_hw_state.fp1); } -static void i9xx_crtc_enable(struct drm_crtc *crtc) +static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, + struct drm_atomic_state *old_state) { + struct drm_crtc *crtc = pipe_config->base.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); struct intel_encoder *encoder; - struct intel_crtc_state *pipe_config = - to_intel_crtc_state(crtc->state); enum pipe pipe = intel_crtc->pipe; if (WARN_ON(intel_crtc->active)) @@ -6692,8 +6696,10 @@ static void i9xx_pfit_disable(struct intel_crtc *crtc) I915_WRITE(PFIT_CONTROL, 0); } -static void i9xx_crtc_disable(struct drm_crtc *crtc) +static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, + struct drm_atomic_state *old_state) { + struct drm_crtc *crtc = old_crtc_state->base.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); @@ -6745,6 +6751,9 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = to_i915(crtc->dev); enum intel_display_power_domain domain; unsigned long domains; + struct drm_atomic_state *state; + struct intel_crtc_state *crtc_state; + int ret; if (!intel_crtc->active) return; @@ -6758,7 +6767,18 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) to_intel_plane_state(crtc->primary->state)->base.visible = false; } - dev_priv->display.crtc_disable(crtc); + state = drm_atomic_state_alloc(crtc->dev); + state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; + + /* Everything's already locked, -EDEADLK can't happen. */ + 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); + + dev_priv->display.crtc_disable(crtc_state, state); + + drm_atomic_state_free(state); DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", crtc->base.id, crtc->name); @@ -14122,7 +14142,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) if (old_crtc_state->active) { intel_crtc_disable_planes(crtc, old_crtc_state->plane_mask); - dev_priv->display.crtc_disable(crtc); + dev_priv->display.crtc_disable(to_intel_crtc_state(old_crtc_state), state); intel_crtc->active = false; intel_fbc_disable(intel_crtc); intel_disable_shared_dpll(intel_crtc); @@ -14170,7 +14190,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) if (modeset && crtc->state->active) { update_scanline_offset(to_intel_crtc(crtc)); - dev_priv->display.crtc_enable(crtc); + dev_priv->display.crtc_enable(pipe_config, state); } /* Complete events for now disable pipes here. */ -- cgit v1.2.1 From c376399c83e63b820af80ec7ede298855abd6697 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:02 +0200 Subject: drm/i915: Remove unused mode_set hook from encoder Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-4-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d203c77a2886..1d2beebe597e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -209,7 +209,6 @@ struct intel_encoder { void (*pre_pll_enable)(struct intel_encoder *); void (*pre_enable)(struct intel_encoder *); void (*enable)(struct intel_encoder *); - void (*mode_set)(struct intel_encoder *intel_encoder); void (*disable)(struct intel_encoder *); void (*post_disable)(struct intel_encoder *); void (*post_pll_disable)(struct intel_encoder *); -- cgit v1.2.1 From fb1c98b181ae139412eca6b7ef727b655b6125da Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:03 +0200 Subject: drm/i915: Walk over encoders in crtc enable/disable using atomic state. This cleans up another possible use of the connector list, encoder->crtc is legacy state and should not be used. With the atomic state as argument it's easy to find the encoder from the connector it belongs to. intel_opregion_notify_encoder is a noop for !HAS_DDI, so it's harmless to unconditionally include it in encoder enable/disable. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-5-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 190 ++++++++++++++++++++++++----------- 1 file changed, 134 insertions(+), 56 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c4db59521cf5..ed187e94b02d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5154,6 +5154,123 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask intel_frontbuffer_flip(to_i915(dev), INTEL_FRONTBUFFER_ALL_MASK(pipe)); } +static void intel_encoders_pre_pll_enable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_connector_state *old_conn_state; + struct drm_connector *conn; + int i; + + for_each_connector_in_state(old_state, conn, old_conn_state, i) { + struct drm_connector_state *conn_state = conn->state; + struct intel_encoder *encoder = + to_intel_encoder(conn_state->best_encoder); + + if (conn_state->crtc != crtc) + continue; + + if (encoder->pre_pll_enable) + encoder->pre_pll_enable(encoder); + } +} + +static void intel_encoders_pre_enable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_connector_state *old_conn_state; + struct drm_connector *conn; + int i; + + for_each_connector_in_state(old_state, conn, old_conn_state, i) { + struct drm_connector_state *conn_state = conn->state; + struct intel_encoder *encoder = + to_intel_encoder(conn_state->best_encoder); + + if (conn_state->crtc != crtc) + continue; + + if (encoder->pre_enable) + encoder->pre_enable(encoder); + } +} + +static void intel_encoders_enable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_connector_state *old_conn_state; + struct drm_connector *conn; + int i; + + for_each_connector_in_state(old_state, conn, old_conn_state, i) { + struct drm_connector_state *conn_state = conn->state; + struct intel_encoder *encoder = + to_intel_encoder(conn_state->best_encoder); + + if (conn_state->crtc != crtc) + continue; + + encoder->enable(encoder); + intel_opregion_notify_encoder(encoder, true); + } +} + +static void intel_encoders_disable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_connector_state *old_conn_state; + struct drm_connector *conn; + int i; + + for_each_connector_in_state(old_state, conn, old_conn_state, i) { + struct intel_encoder *encoder = + to_intel_encoder(old_conn_state->best_encoder); + + if (old_conn_state->crtc != crtc) + continue; + + intel_opregion_notify_encoder(encoder, false); + encoder->disable(encoder); + } +} + +static void intel_encoders_post_disable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_connector_state *old_conn_state; + struct drm_connector *conn; + int i; + + for_each_connector_in_state(old_state, conn, old_conn_state, i) { + struct intel_encoder *encoder = + to_intel_encoder(old_conn_state->best_encoder); + + if (old_conn_state->crtc != crtc) + continue; + + if (encoder->post_disable) + encoder->post_disable(encoder); + } +} + +static void intel_encoders_post_pll_disable(struct drm_crtc *crtc, + struct drm_atomic_state *old_state) +{ + struct drm_connector_state *old_conn_state; + struct drm_connector *conn; + int i; + + for_each_connector_in_state(old_state, conn, old_conn_state, i) { + struct intel_encoder *encoder = + to_intel_encoder(old_conn_state->best_encoder); + + if (old_conn_state->crtc != crtc) + continue; + + if (encoder->post_pll_disable) + encoder->post_pll_disable(encoder); + } +} + static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, struct drm_atomic_state *old_state) { @@ -5161,7 +5278,6 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_encoder *encoder; int pipe = intel_crtc->pipe; if (WARN_ON(intel_crtc->active)) @@ -5200,9 +5316,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc->active = true; - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->pre_enable) - encoder->pre_enable(encoder); + intel_encoders_pre_enable(crtc, old_state); if (intel_crtc->config->has_pch_encoder) { /* Note: FDI PLL enabling _must_ be done before we enable the @@ -5232,8 +5346,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) - encoder->enable(encoder); + intel_encoders_enable(crtc, old_state); if (HAS_PCH_CPT(dev)) cpt_verify_modeset(dev, intel_crtc->pipe); @@ -5258,7 +5371,6 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_encoder *encoder; int pipe = intel_crtc->pipe, hsw_workaround_pipe; enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; @@ -5269,9 +5381,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, false); - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->pre_pll_enable) - encoder->pre_pll_enable(encoder); + intel_encoders_pre_pll_enable(crtc, old_state); if (intel_crtc->config->shared_dpll) intel_enable_shared_dpll(intel_crtc); @@ -5309,10 +5419,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, else intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - for_each_encoder_on_crtc(dev, crtc, encoder) { - if (encoder->pre_enable) - encoder->pre_enable(encoder); - } + intel_encoders_pre_enable(crtc, old_state); if (intel_crtc->config->has_pch_encoder) dev_priv->display.fdi_link_train(crtc); @@ -5353,10 +5460,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) { - encoder->enable(encoder); - intel_opregion_notify_encoder(encoder, true); - } + intel_encoders_enable(crtc, old_state); if (intel_crtc->config->has_pch_encoder) { intel_wait_for_vblank(dev, pipe); @@ -5397,7 +5501,6 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_encoder *encoder; int pipe = intel_crtc->pipe; /* @@ -5410,8 +5513,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); } - for_each_encoder_on_crtc(dev, crtc, encoder) - encoder->disable(encoder); + intel_encoders_disable(crtc, old_state); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -5423,9 +5525,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, if (intel_crtc->config->has_pch_encoder) ironlake_fdi_disable(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->post_disable) - encoder->post_disable(encoder); + intel_encoders_post_disable(crtc, old_state); if (intel_crtc->config->has_pch_encoder) { ironlake_disable_pch_transcoder(dev_priv, pipe); @@ -5462,17 +5562,13 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_encoder *encoder; enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; if (intel_crtc->config->has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, false); - for_each_encoder_on_crtc(dev, crtc, encoder) { - intel_opregion_notify_encoder(encoder, false); - encoder->disable(encoder); - } + intel_encoders_disable(crtc, old_state); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -5495,9 +5591,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, if (!transcoder_is_dsi(cpu_transcoder)) intel_ddi_disable_pipe_clock(intel_crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->post_disable) - encoder->post_disable(encoder); + intel_encoders_post_disable(crtc, old_state); if (intel_crtc->config->has_pch_encoder) { lpt_disable_pch_transcoder(dev_priv); @@ -6569,7 +6663,6 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_encoder *encoder; int pipe = intel_crtc->pipe; if (WARN_ON(intel_crtc->active)) @@ -6594,9 +6687,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->pre_pll_enable) - encoder->pre_pll_enable(encoder); + intel_encoders_pre_pll_enable(crtc, old_state); if (IS_CHERRYVIEW(dev)) { chv_prepare_pll(intel_crtc, intel_crtc->config); @@ -6606,9 +6697,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, vlv_enable_pll(intel_crtc, intel_crtc->config); } - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->pre_enable) - encoder->pre_enable(encoder); + intel_encoders_pre_enable(crtc, old_state); i9xx_pfit_enable(intel_crtc); @@ -6620,8 +6709,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) - encoder->enable(encoder); + intel_encoders_enable(crtc, old_state); } static void i9xx_set_pll_dividers(struct intel_crtc *crtc) @@ -6640,7 +6728,6 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_encoder *encoder; enum pipe pipe = intel_crtc->pipe; if (WARN_ON(intel_crtc->active)) @@ -6661,9 +6748,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, if (!IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->pre_enable) - encoder->pre_enable(encoder); + intel_encoders_pre_enable(crtc, old_state); i9xx_enable_pll(intel_crtc); @@ -6677,8 +6762,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) - encoder->enable(encoder); + intel_encoders_enable(crtc, old_state); } static void i9xx_pfit_disable(struct intel_crtc *crtc) @@ -6703,7 +6787,6 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_encoder *encoder; int pipe = intel_crtc->pipe; /* @@ -6713,8 +6796,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, if (IS_GEN2(dev)) intel_wait_for_vblank(dev, pipe); - for_each_encoder_on_crtc(dev, crtc, encoder) - encoder->disable(encoder); + intel_encoders_disable(crtc, old_state); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -6723,9 +6805,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, i9xx_pfit_disable(intel_crtc); - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->post_disable) - encoder->post_disable(encoder); + intel_encoders_post_disable(crtc, old_state); if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) { if (IS_CHERRYVIEW(dev)) @@ -6736,9 +6816,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, i9xx_disable_pll(intel_crtc); } - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->post_pll_disable) - encoder->post_pll_disable(encoder); + intel_encoders_post_pll_disable(crtc, old_state); if (!IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); -- cgit v1.2.1 From fd6bbda9c7a46bec6462878787335d2ac6294040 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:04 +0200 Subject: drm/i915: Pass crtc_state and connector_state to encoder functions This is mostly code churn, with exception of a few places: - intel_display.c has changes in intel_sanitize_encoder - intel_ddi.c has intel_ddi_fdi_disable calling intel_ddi_post_disable, and required a function change. Also affects intel_display.c - intel_dp_mst.c passes a NULL crtc_state and conn_state to intel_ddi_post_disable for shutting down the real encoder. If we would pass conn_state, then conn_state->connector != intel_dig_port->connector and conn_state->best_encoder != to_intel_encoder(intel_dig_port). We also shouldn't pass crtc_state, because in that case the disabling sequence may potentially be different depending on which crtc is disabled last. Nice way to introduce bugs. No other functional changes are done, diff stat is already huge. Each encoder type will need to be fixed to use the atomic states separately. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-6-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 18 +++++-- drivers/gpu/drm/i915/intel_ddi.c | 31 +++++++---- drivers/gpu/drm/i915/intel_display.c | 102 ++++++++++++++++++++--------------- drivers/gpu/drm/i915/intel_dp.c | 48 ++++++++++++----- drivers/gpu/drm/i915/intel_dp_mst.c | 20 +++++-- drivers/gpu/drm/i915/intel_drv.h | 28 +++++++--- drivers/gpu/drm/i915/intel_dsi.c | 16 ++++-- drivers/gpu/drm/i915/intel_dvo.c | 12 +++-- drivers/gpu/drm/i915/intel_hdmi.c | 72 ++++++++++++++++++------- drivers/gpu/drm/i915/intel_lvds.c | 29 +++++++--- drivers/gpu/drm/i915/intel_sdvo.c | 22 +++++--- drivers/gpu/drm/i915/intel_tv.c | 12 +++-- 12 files changed, 284 insertions(+), 126 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 827b6ef4e9ae..6e6c4bde105a 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -193,21 +193,29 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) I915_WRITE(crt->adpa_reg, adpa); } -static void intel_disable_crt(struct intel_encoder *encoder) +static void intel_disable_crt(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF); } -static void pch_disable_crt(struct intel_encoder *encoder) +static void pch_disable_crt(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { } -static void pch_post_disable_crt(struct intel_encoder *encoder) +static void pch_post_disable_crt(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { - intel_disable_crt(encoder); + intel_disable_crt(encoder, old_crtc_state, old_conn_state); } -static void intel_enable_crt(struct intel_encoder *encoder) +static void intel_enable_crt(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { intel_crt_set_dpms(encoder, DRM_MODE_DPMS_ON); } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index c2df4e429b19..66feb1eafc93 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1611,7 +1611,9 @@ void intel_ddi_clk_select(struct intel_encoder *encoder, } } -static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) +static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_encoder *encoder = &intel_encoder->base; struct drm_i915_private *dev_priv = to_i915(encoder->dev); @@ -1663,7 +1665,9 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) } } -static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) +static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct drm_encoder *encoder = &intel_encoder->base; struct drm_device *dev = encoder->dev; @@ -1673,6 +1677,8 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) uint32_t val; bool wait = false; + /* old_crtc_state and old_conn_state are NULL when called from DP_MST */ + val = I915_READ(DDI_BUF_CTL(port)); if (val & DDI_BUF_CTL_ENABLE) { val &= ~DDI_BUF_CTL_ENABLE; @@ -1708,7 +1714,9 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder) } } -static void intel_enable_ddi(struct intel_encoder *intel_encoder) +static void intel_enable_ddi(struct intel_encoder *intel_encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = encoder->crtc; @@ -1746,7 +1754,9 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder) } } -static void intel_disable_ddi(struct intel_encoder *intel_encoder) +static void intel_disable_ddi(struct intel_encoder *intel_encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct drm_encoder *encoder = &intel_encoder->base; struct drm_crtc *crtc = encoder->crtc; @@ -2052,7 +2062,9 @@ bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, } } -static void bxt_ddi_pre_pll_enable(struct intel_encoder *encoder) +static void bxt_ddi_pre_pll_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); @@ -2141,10 +2153,11 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) udelay(600); } -void intel_ddi_fdi_disable(struct drm_crtc *crtc) +void intel_ddi_fdi_disable(struct intel_encoder *intel_encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); + struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); uint32_t val; /* @@ -2157,7 +2170,7 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc) val &= ~FDI_RX_ENABLE; I915_WRITE(FDI_RX_CTL(PIPE_A), val); - intel_ddi_post_disable(intel_encoder); + intel_ddi_post_disable(intel_encoder, old_crtc_state, old_conn_state); val = I915_READ(FDI_RX_MISC(PIPE_A)); val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ed187e94b02d..554b3f69f4a5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5155,6 +5155,7 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask } static void intel_encoders_pre_pll_enable(struct drm_crtc *crtc, + struct intel_crtc_state *crtc_state, struct drm_atomic_state *old_state) { struct drm_connector_state *old_conn_state; @@ -5170,11 +5171,12 @@ static void intel_encoders_pre_pll_enable(struct drm_crtc *crtc, continue; if (encoder->pre_pll_enable) - encoder->pre_pll_enable(encoder); + encoder->pre_pll_enable(encoder, crtc_state, conn_state); } } static void intel_encoders_pre_enable(struct drm_crtc *crtc, + struct intel_crtc_state *crtc_state, struct drm_atomic_state *old_state) { struct drm_connector_state *old_conn_state; @@ -5190,11 +5192,12 @@ static void intel_encoders_pre_enable(struct drm_crtc *crtc, continue; if (encoder->pre_enable) - encoder->pre_enable(encoder); + encoder->pre_enable(encoder, crtc_state, conn_state); } } static void intel_encoders_enable(struct drm_crtc *crtc, + struct intel_crtc_state *crtc_state, struct drm_atomic_state *old_state) { struct drm_connector_state *old_conn_state; @@ -5209,12 +5212,13 @@ static void intel_encoders_enable(struct drm_crtc *crtc, if (conn_state->crtc != crtc) continue; - encoder->enable(encoder); + encoder->enable(encoder, crtc_state, conn_state); intel_opregion_notify_encoder(encoder, true); } } static void intel_encoders_disable(struct drm_crtc *crtc, + struct intel_crtc_state *old_crtc_state, struct drm_atomic_state *old_state) { struct drm_connector_state *old_conn_state; @@ -5229,11 +5233,12 @@ static void intel_encoders_disable(struct drm_crtc *crtc, continue; intel_opregion_notify_encoder(encoder, false); - encoder->disable(encoder); + encoder->disable(encoder, old_crtc_state, old_conn_state); } } static void intel_encoders_post_disable(struct drm_crtc *crtc, + struct intel_crtc_state *old_crtc_state, struct drm_atomic_state *old_state) { struct drm_connector_state *old_conn_state; @@ -5248,11 +5253,12 @@ static void intel_encoders_post_disable(struct drm_crtc *crtc, continue; if (encoder->post_disable) - encoder->post_disable(encoder); + encoder->post_disable(encoder, old_crtc_state, old_conn_state); } } static void intel_encoders_post_pll_disable(struct drm_crtc *crtc, + struct intel_crtc_state *old_crtc_state, struct drm_atomic_state *old_state) { struct drm_connector_state *old_conn_state; @@ -5267,7 +5273,7 @@ static void intel_encoders_post_pll_disable(struct drm_crtc *crtc, continue; if (encoder->post_pll_disable) - encoder->post_pll_disable(encoder); + encoder->post_pll_disable(encoder, old_crtc_state, old_conn_state); } } @@ -5316,7 +5322,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc->active = true; - intel_encoders_pre_enable(crtc, old_state); + intel_encoders_pre_enable(crtc, pipe_config, old_state); if (intel_crtc->config->has_pch_encoder) { /* Note: FDI PLL enabling _must_ be done before we enable the @@ -5346,7 +5352,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); - intel_encoders_enable(crtc, old_state); + intel_encoders_enable(crtc, pipe_config, old_state); if (HAS_PCH_CPT(dev)) cpt_verify_modeset(dev, intel_crtc->pipe); @@ -5381,7 +5387,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, false); - intel_encoders_pre_pll_enable(crtc, old_state); + intel_encoders_pre_pll_enable(crtc, pipe_config, old_state); if (intel_crtc->config->shared_dpll) intel_enable_shared_dpll(intel_crtc); @@ -5419,7 +5425,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, else intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_encoders_pre_enable(crtc, old_state); + intel_encoders_pre_enable(crtc, pipe_config, old_state); if (intel_crtc->config->has_pch_encoder) dev_priv->display.fdi_link_train(crtc); @@ -5460,7 +5466,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); - intel_encoders_enable(crtc, old_state); + intel_encoders_enable(crtc, pipe_config, old_state); if (intel_crtc->config->has_pch_encoder) { intel_wait_for_vblank(dev, pipe); @@ -5513,7 +5519,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false); } - intel_encoders_disable(crtc, old_state); + intel_encoders_disable(crtc, old_crtc_state, old_state); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -5525,7 +5531,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, if (intel_crtc->config->has_pch_encoder) ironlake_fdi_disable(crtc); - intel_encoders_post_disable(crtc, old_state); + intel_encoders_post_disable(crtc, old_crtc_state, old_state); if (intel_crtc->config->has_pch_encoder) { ironlake_disable_pch_transcoder(dev_priv, pipe); @@ -5568,7 +5574,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, false); - intel_encoders_disable(crtc, old_state); + intel_encoders_disable(crtc, old_crtc_state, old_state); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -5591,12 +5597,26 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, if (!transcoder_is_dsi(cpu_transcoder)) intel_ddi_disable_pipe_clock(intel_crtc); - intel_encoders_post_disable(crtc, old_state); + intel_encoders_post_disable(crtc, old_crtc_state, old_state); if (intel_crtc->config->has_pch_encoder) { + struct drm_connector_state *old_conn_state; + struct drm_connector *conn; + int i; + lpt_disable_pch_transcoder(dev_priv); lpt_disable_iclkip(dev_priv); - intel_ddi_fdi_disable(crtc); + + for_each_connector_in_state(old_state, conn, old_conn_state, i) + if (old_conn_state->crtc == crtc) { + struct intel_encoder *encoder = + to_intel_encoder(old_conn_state->best_encoder); + + intel_ddi_fdi_disable(encoder, + old_crtc_state, + old_conn_state); + break; + } intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, true); @@ -6687,7 +6707,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(crtc, old_state); + intel_encoders_pre_pll_enable(crtc, pipe_config, old_state); if (IS_CHERRYVIEW(dev)) { chv_prepare_pll(intel_crtc, intel_crtc->config); @@ -6697,7 +6717,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, vlv_enable_pll(intel_crtc, intel_crtc->config); } - intel_encoders_pre_enable(crtc, old_state); + intel_encoders_pre_enable(crtc, pipe_config, old_state); i9xx_pfit_enable(intel_crtc); @@ -6709,7 +6729,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); - intel_encoders_enable(crtc, old_state); + intel_encoders_enable(crtc, pipe_config, old_state); } static void i9xx_set_pll_dividers(struct intel_crtc *crtc) @@ -6748,7 +6768,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, if (!IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_encoders_pre_enable(crtc, old_state); + intel_encoders_pre_enable(crtc, pipe_config, old_state); i9xx_enable_pll(intel_crtc); @@ -6762,7 +6782,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); - intel_encoders_enable(crtc, old_state); + intel_encoders_enable(crtc, pipe_config, old_state); } static void i9xx_pfit_disable(struct intel_crtc *crtc) @@ -6796,7 +6816,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, if (IS_GEN2(dev)) intel_wait_for_vblank(dev, pipe); - intel_encoders_disable(crtc, old_state); + intel_encoders_disable(crtc, old_crtc_state, old_state); drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); @@ -6805,7 +6825,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, i9xx_pfit_disable(intel_crtc); - intel_encoders_post_disable(crtc, old_state); + intel_encoders_post_disable(crtc, old_crtc_state, old_state); if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) { if (IS_CHERRYVIEW(dev)) @@ -6816,7 +6836,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, i9xx_disable_pll(intel_crtc); } - intel_encoders_post_pll_disable(crtc, old_state); + intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state); if (!IS_GEN2(dev)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); @@ -16386,17 +16406,6 @@ static bool intel_crtc_has_encoders(struct intel_crtc *crtc) return false; } -static bool intel_encoder_has_connectors(struct intel_encoder *encoder) -{ - struct drm_device *dev = encoder->base.dev; - struct intel_connector *connector; - - for_each_connector_on_encoder(dev, &encoder->base, connector) - return true; - - return false; -} - static bool has_pch_trancoder(struct drm_i915_private *dev_priv, enum transcoder pch_transcoder) { @@ -16500,6 +16509,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) { struct intel_connector *connector; struct drm_device *dev = encoder->base.dev; + bool found_connector = false; /* We need to check both for a crtc link (meaning that the * encoder is active and trying to read from a pipe) and the @@ -16507,7 +16517,12 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) bool has_active_crtc = encoder->base.crtc && to_intel_crtc(encoder->base.crtc)->active; - if (intel_encoder_has_connectors(encoder) && !has_active_crtc) { + for_each_connector_on_encoder(dev, &encoder->base, connector) { + found_connector = true; + break; + } + + if (found_connector && !has_active_crtc) { DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n", encoder->base.base.id, encoder->base.name); @@ -16516,12 +16531,14 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) * fallout from our resume register restoring. Disable * the encoder manually again. */ if (encoder->base.crtc) { + struct drm_crtc_state *crtc_state = encoder->base.crtc->state; + DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n", encoder->base.base.id, encoder->base.name); - encoder->disable(encoder); + encoder->disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state); if (encoder->post_disable) - encoder->post_disable(encoder); + encoder->post_disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state); } encoder->base.crtc = NULL; @@ -16529,12 +16546,9 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) * a bug in one of the get_hw_state functions. Or someplace else * in our code, like the register restore mess on resume. Clamp * things to off as a safer default. */ - for_each_intel_connector(dev, connector) { - if (connector->encoder != encoder) - continue; - connector->base.dpms = DRM_MODE_DPMS_OFF; - connector->base.encoder = NULL; - } + + connector->base.dpms = DRM_MODE_DPMS_OFF; + connector->base.encoder = NULL; } /* Enabled encoders without active connectors will be fixed in * the crtc fixup. */ diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 364db908c191..30cbc7e2887f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2473,7 +2473,9 @@ static void intel_dp_get_config(struct intel_encoder *encoder, } } -static void intel_disable_dp(struct intel_encoder *encoder) +static void intel_disable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -2497,7 +2499,9 @@ static void intel_disable_dp(struct intel_encoder *encoder) intel_dp_link_down(intel_dp); } -static void ilk_post_disable_dp(struct intel_encoder *encoder) +static void ilk_post_disable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = dp_to_dig_port(intel_dp)->port; @@ -2509,14 +2513,18 @@ static void ilk_post_disable_dp(struct intel_encoder *encoder) ironlake_edp_pll_off(intel_dp); } -static void vlv_post_disable_dp(struct intel_encoder *encoder) +static void vlv_post_disable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); intel_dp_link_down(intel_dp); } -static void chv_post_disable_dp(struct intel_encoder *encoder) +static void chv_post_disable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -2690,7 +2698,9 @@ static void intel_enable_dp(struct intel_encoder *encoder) } } -static void g4x_enable_dp(struct intel_encoder *encoder) +static void g4x_enable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); @@ -2698,7 +2708,9 @@ static void g4x_enable_dp(struct intel_encoder *encoder) intel_edp_backlight_on(intel_dp); } -static void vlv_enable_dp(struct intel_encoder *encoder) +static void vlv_enable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); @@ -2706,7 +2718,9 @@ static void vlv_enable_dp(struct intel_encoder *encoder) intel_psr_enable(intel_dp); } -static void g4x_pre_enable_dp(struct intel_encoder *encoder) +static void g4x_pre_enable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = dp_to_dig_port(intel_dp)->port; @@ -2821,21 +2835,27 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); } -static void vlv_pre_enable_dp(struct intel_encoder *encoder) +static void vlv_pre_enable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { vlv_phy_pre_encoder_enable(encoder); intel_enable_dp(encoder); } -static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) +static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { intel_dp_prepare(encoder); vlv_phy_pre_pll_enable(encoder); } -static void chv_pre_enable_dp(struct intel_encoder *encoder) +static void chv_pre_enable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { chv_phy_pre_encoder_enable(encoder); @@ -2845,14 +2865,18 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) chv_phy_release_cl2_override(encoder); } -static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) +static void chv_dp_pre_pll_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { intel_dp_prepare(encoder); chv_phy_pre_pll_enable(encoder); } -static void chv_dp_post_pll_disable(struct intel_encoder *encoder) +static void chv_dp_post_pll_disable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { chv_phy_post_pll_disable(encoder); } diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 629337dbca3d..8f7594ef39a9 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -92,7 +92,9 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, } -static void intel_mst_disable_dp(struct intel_encoder *encoder) +static void intel_mst_disable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + 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; @@ -109,7 +111,9 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder) } } -static void intel_mst_post_disable_dp(struct intel_encoder *encoder) +static void intel_mst_post_disable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + 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; @@ -128,12 +132,16 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder) intel_mst->connector = NULL; if (intel_dp->active_mst_links == 0) { - intel_dig_port->base.post_disable(&intel_dig_port->base); + intel_dig_port->base.post_disable(&intel_dig_port->base, + NULL, NULL); + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); } } -static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) +static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; @@ -200,7 +208,9 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); } -static void intel_mst_enable_dp(struct intel_encoder *encoder) +static void intel_mst_enable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1d2beebe597e..37f36358c877 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -206,12 +206,24 @@ struct intel_encoder { void (*hot_plug)(struct intel_encoder *); bool (*compute_config)(struct intel_encoder *, struct intel_crtc_state *); - void (*pre_pll_enable)(struct intel_encoder *); - void (*pre_enable)(struct intel_encoder *); - void (*enable)(struct intel_encoder *); - void (*disable)(struct intel_encoder *); - void (*post_disable)(struct intel_encoder *); - void (*post_pll_disable)(struct intel_encoder *); + void (*pre_pll_enable)(struct intel_encoder *, + struct intel_crtc_state *, + struct drm_connector_state *); + void (*pre_enable)(struct intel_encoder *, + struct intel_crtc_state *, + struct drm_connector_state *); + void (*enable)(struct intel_encoder *, + struct intel_crtc_state *, + struct drm_connector_state *); + void (*disable)(struct intel_encoder *, + struct intel_crtc_state *, + struct drm_connector_state *); + void (*post_disable)(struct intel_encoder *, + struct intel_crtc_state *, + struct drm_connector_state *); + void (*post_pll_disable)(struct intel_encoder *, + struct intel_crtc_state *, + struct drm_connector_state *); /* Read out the current hw state of this connector, returning true if * the encoder is active. If the encoder is enabled it also set the pipe * it is connected to in the pipe parameter. */ @@ -1139,7 +1151,9 @@ bool intel_ddi_pll_select(struct intel_crtc *crtc, void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp); bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); -void intel_ddi_fdi_disable(struct drm_crtc *crtc); +void intel_ddi_fdi_disable(struct intel_encoder *, + struct intel_crtc_state *, + struct drm_connector_state *); void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); struct intel_encoder * diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index de8e9fb51595..107b70c19333 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -535,7 +535,9 @@ static void intel_dsi_enable(struct intel_encoder *encoder) static void intel_dsi_prepare(struct intel_encoder *intel_encoder); -static void intel_dsi_pre_enable(struct intel_encoder *encoder) +static void intel_dsi_pre_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -582,7 +584,9 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) intel_dsi_enable(encoder); } -static void intel_dsi_enable_nop(struct intel_encoder *encoder) +static void intel_dsi_enable_nop(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { DRM_DEBUG_KMS("\n"); @@ -592,7 +596,9 @@ static void intel_dsi_enable_nop(struct intel_encoder *encoder) */ } -static void intel_dsi_pre_disable(struct intel_encoder *encoder) +static void intel_dsi_pre_disable(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port; @@ -694,7 +700,9 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) intel_disable_dsi_pll(encoder); } -static void intel_dsi_post_disable(struct intel_encoder *encoder) +static void intel_dsi_post_disable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 47bdf9dad0d3..52dde9b71ca5 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -174,7 +174,9 @@ static void intel_dvo_get_config(struct intel_encoder *encoder, pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; } -static void intel_disable_dvo(struct intel_encoder *encoder) +static void intel_disable_dvo(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); @@ -186,7 +188,9 @@ static void intel_disable_dvo(struct intel_encoder *encoder) I915_READ(dvo_reg); } -static void intel_enable_dvo(struct intel_encoder *encoder) +static void intel_enable_dvo(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); @@ -253,7 +257,9 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder, return true; } -static void intel_dvo_pre_enable(struct intel_encoder *encoder) +static void intel_dvo_pre_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4df9f384910c..560eff9a3694 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -985,7 +985,9 @@ static void intel_enable_hdmi_audio(struct intel_encoder *encoder) intel_audio_codec_enable(encoder); } -static void g4x_enable_hdmi(struct intel_encoder *encoder) +static void g4x_enable_hdmi(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1006,7 +1008,9 @@ static void g4x_enable_hdmi(struct intel_encoder *encoder) intel_enable_hdmi_audio(encoder); } -static void ibx_enable_hdmi(struct intel_encoder *encoder) +static void ibx_enable_hdmi(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1055,7 +1059,9 @@ static void ibx_enable_hdmi(struct intel_encoder *encoder) intel_enable_hdmi_audio(encoder); } -static void cpt_enable_hdmi(struct intel_encoder *encoder) +static void cpt_enable_hdmi(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1108,11 +1114,15 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder) intel_enable_hdmi_audio(encoder); } -static void vlv_enable_hdmi(struct intel_encoder *encoder) +static void vlv_enable_hdmi(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { } -static void intel_disable_hdmi(struct intel_encoder *encoder) +static void intel_disable_hdmi(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1164,17 +1174,21 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); } -static void g4x_disable_hdmi(struct intel_encoder *encoder) +static void g4x_disable_hdmi(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); if (crtc->config->has_audio) intel_audio_codec_disable(encoder); - intel_disable_hdmi(encoder); + intel_disable_hdmi(encoder, old_crtc_state, old_conn_state); } -static void pch_disable_hdmi(struct intel_encoder *encoder) +static void pch_disable_hdmi(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); @@ -1182,9 +1196,11 @@ static void pch_disable_hdmi(struct intel_encoder *encoder) intel_audio_codec_disable(encoder); } -static void pch_post_disable_hdmi(struct intel_encoder *encoder) +static void pch_post_disable_hdmi(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { - intel_disable_hdmi(encoder); + intel_disable_hdmi(encoder, old_crtc_state, old_conn_state); } static int intel_hdmi_source_max_tmds_clock(struct drm_i915_private *dev_priv) @@ -1638,7 +1654,9 @@ done: return 0; } -static void intel_hdmi_pre_enable(struct intel_encoder *encoder) +static void intel_hdmi_pre_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); @@ -1651,7 +1669,9 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder) adjusted_mode); } -static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) +static void vlv_hdmi_pre_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct intel_hdmi *intel_hdmi = &dport->hdmi; @@ -1671,37 +1691,47 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) intel_crtc->config->has_hdmi_sink, adjusted_mode); - g4x_enable_hdmi(encoder); + g4x_enable_hdmi(encoder, pipe_config, conn_state); vlv_wait_port_ready(dev_priv, dport, 0x0); } -static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) +static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { intel_hdmi_prepare(encoder); vlv_phy_pre_pll_enable(encoder); } -static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) +static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { intel_hdmi_prepare(encoder); chv_phy_pre_pll_enable(encoder); } -static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder) +static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { chv_phy_post_pll_disable(encoder); } -static void vlv_hdmi_post_disable(struct intel_encoder *encoder) +static void vlv_hdmi_post_disable(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { /* Reset lanes to avoid HDMI flicker (VLV w/a) */ vlv_phy_reset_lanes(encoder); } -static void chv_hdmi_post_disable(struct intel_encoder *encoder) +static void chv_hdmi_post_disable(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1714,7 +1744,9 @@ static void chv_hdmi_post_disable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } -static void chv_hdmi_pre_enable(struct intel_encoder *encoder) +static void chv_hdmi_pre_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct intel_hdmi *intel_hdmi = &dport->hdmi; @@ -1734,7 +1766,7 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) intel_crtc->config->has_hdmi_sink, adjusted_mode); - g4x_enable_hdmi(encoder); + g4x_enable_hdmi(encoder, pipe_config, conn_state); vlv_wait_port_ready(dev_priv, dport, 0x0); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 668eabb0ba1b..f8e55df98883 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -230,7 +230,9 @@ static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv, I915_WRITE(PP_DIVISOR(0), val); } -static void intel_pre_enable_lvds(struct intel_encoder *encoder) +static void intel_pre_enable_lvds(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -306,7 +308,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder) /** * Sets the power state for the panel. */ -static void intel_enable_lvds(struct intel_encoder *encoder) +static void intel_enable_lvds(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); @@ -324,7 +328,9 @@ static void intel_enable_lvds(struct intel_encoder *encoder) intel_panel_enable_backlight(intel_connector); } -static void intel_disable_lvds(struct intel_encoder *encoder) +static void intel_disable_lvds(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct drm_device *dev = encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); @@ -338,7 +344,10 @@ static void intel_disable_lvds(struct intel_encoder *encoder) POSTING_READ(lvds_encoder->reg); } -static void gmch_disable_lvds(struct intel_encoder *encoder) +static void gmch_disable_lvds(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) + { struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct intel_connector *intel_connector = @@ -346,10 +355,12 @@ static void gmch_disable_lvds(struct intel_encoder *encoder) intel_panel_disable_backlight(intel_connector); - intel_disable_lvds(encoder); + intel_disable_lvds(encoder, old_crtc_state, old_conn_state); } -static void pch_disable_lvds(struct intel_encoder *encoder) +static void pch_disable_lvds(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); struct intel_connector *intel_connector = @@ -358,9 +369,11 @@ static void pch_disable_lvds(struct intel_encoder *encoder) intel_panel_disable_backlight(intel_connector); } -static void pch_post_disable_lvds(struct intel_encoder *encoder) +static void pch_post_disable_lvds(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { - intel_disable_lvds(encoder); + intel_disable_lvds(encoder, old_crtc_state, old_conn_state); } static enum drm_mode_status diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index dd75510eba67..cff4e9dcf4be 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1192,7 +1192,9 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, return true; } -static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder) +static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state) { struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1434,7 +1436,9 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, pipe_config->pixel_multiplier, encoder_pixel_multiplier); } -static void intel_disable_sdvo(struct intel_encoder *encoder) +static void intel_disable_sdvo(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_sdvo *intel_sdvo = to_sdvo(encoder); @@ -1477,16 +1481,22 @@ static void intel_disable_sdvo(struct intel_encoder *encoder) } } -static void pch_disable_sdvo(struct intel_encoder *encoder) +static void pch_disable_sdvo(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { } -static void pch_post_disable_sdvo(struct intel_encoder *encoder) +static void pch_post_disable_sdvo(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { - intel_disable_sdvo(encoder); + intel_disable_sdvo(encoder, old_crtc_state, old_conn_state); } -static void intel_enable_sdvo(struct intel_encoder *encoder) +static void intel_enable_sdvo(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 49136ad5473e..440ce7933573 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -838,7 +838,9 @@ intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) } static void -intel_enable_tv(struct intel_encoder *encoder) +intel_enable_tv(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -851,7 +853,9 @@ intel_enable_tv(struct intel_encoder *encoder) } static void -intel_disable_tv(struct intel_encoder *encoder) +intel_disable_tv(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -1010,7 +1014,9 @@ static void set_color_conversion(struct drm_i915_private *dev_priv, color_conversion->av); } -static void intel_tv_pre_enable(struct intel_encoder *encoder) +static void intel_tv_pre_enable(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); -- cgit v1.2.1 From 0a478c27db43ad6a0e229ff1b922a16d2eae9701 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:05 +0200 Subject: drm/i915: Make encoder->compute_config take the connector state Some places iterate over connector_state to find the right connector, pass it along as argument. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-7-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 3 ++- drivers/gpu/drm/i915/intel_ddi.c | 7 ++++--- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 3 ++- drivers/gpu/drm/i915/intel_dp_mst.c | 4 ++-- drivers/gpu/drm/i915/intel_drv.h | 9 ++++++--- drivers/gpu/drm/i915/intel_dsi.c | 3 ++- drivers/gpu/drm/i915/intel_dvo.c | 3 ++- drivers/gpu/drm/i915/intel_hdmi.c | 3 ++- drivers/gpu/drm/i915/intel_lvds.c | 3 ++- drivers/gpu/drm/i915/intel_sdvo.c | 3 ++- drivers/gpu/drm/i915/intel_tv.c | 3 ++- 12 files changed, 29 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6e6c4bde105a..8fe36d049d2f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -261,7 +261,8 @@ intel_crt_mode_valid(struct drm_connector *connector, } static bool intel_crt_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 66feb1eafc93..b23872839fe0 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2285,7 +2285,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, } static bool intel_ddi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int type = encoder->type; @@ -2298,9 +2299,9 @@ static bool intel_ddi_compute_config(struct intel_encoder *encoder, pipe_config->cpu_transcoder = TRANSCODER_EDP; if (type == INTEL_OUTPUT_HDMI) - ret = intel_hdmi_compute_config(encoder, pipe_config); + ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state); else - ret = intel_dp_compute_config(encoder, pipe_config); + ret = intel_dp_compute_config(encoder, pipe_config, conn_state); if (IS_BROXTON(dev_priv) && ret) pipe_config->lane_lat_optim_mask = diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 554b3f69f4a5..f44858d2650e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13042,7 +13042,7 @@ encoder_retry: encoder = to_intel_encoder(connector_state->best_encoder); - if (!(encoder->compute_config(encoder, pipe_config))) { + if (!(encoder->compute_config(encoder, pipe_config, connector_state))) { DRM_DEBUG_KMS("Encoder config failure\n"); goto fail; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 30cbc7e2887f..9bf71f5579bb 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1463,7 +1463,8 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, bool intel_dp_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 8f7594ef39a9..5b5878e3bf6e 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -31,7 +31,8 @@ #include static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; @@ -54,7 +55,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, */ lane_count = drm_dp_max_lane_count(intel_dp->dpcd); - pipe_config->lane_count = lane_count; pipe_config->pipe_bpp = 24; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 37f36358c877..0b72eed5861f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -205,7 +205,8 @@ struct intel_encoder { unsigned int cloneable; void (*hot_plug)(struct intel_encoder *); bool (*compute_config)(struct intel_encoder *, - struct intel_crtc_state *); + struct intel_crtc_state *, + struct drm_connector_state *); void (*pre_pll_enable)(struct intel_encoder *, struct intel_crtc_state *, struct drm_connector_state *); @@ -1389,7 +1390,8 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder); void intel_dp_encoder_destroy(struct drm_encoder *encoder); int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc); bool intel_dp_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config); + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state); bool intel_dp_is_edp(struct drm_device *dev, enum port port); enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd); @@ -1514,7 +1516,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector); struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); bool intel_hdmi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config); + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state); void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 107b70c19333..1a2e1dcbff1a 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -312,7 +312,8 @@ static inline bool is_cmd_mode(struct intel_dsi *intel_dsi) } static bool intel_dsi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 52dde9b71ca5..141483fdcf7b 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -239,7 +239,8 @@ intel_dvo_mode_valid(struct drm_connector *connector, } static bool intel_dvo_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_dvo *intel_dvo = enc_to_dvo(encoder); const struct drm_display_mode *fixed_mode = diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 560eff9a3694..1a116a6a1817 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1301,7 +1301,8 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) } bool intel_hdmi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct drm_device *dev = encoder->base.dev; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f8e55df98883..29d45b099e51 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -395,7 +395,8 @@ intel_lvds_mode_valid(struct drm_connector *connector, } static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct drm_device *dev = intel_encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index cff4e9dcf4be..e3bc8d4bb781 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1125,7 +1125,8 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config) } static bool intel_sdvo_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_sdvo *intel_sdvo = to_sdvo(encoder); struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 440ce7933573..d960e4866595 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -912,7 +912,8 @@ intel_tv_get_config(struct intel_encoder *encoder, static bool intel_tv_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) { struct intel_tv *intel_tv = enc_to_tv(encoder); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); -- cgit v1.2.1 From 1189e4f4d8818b438d5cdbd7d45a2c0ed6170671 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:06 +0200 Subject: drm/i915: Remove unused loop from intel_dp_mst_compute_config Now that conn_state is passed in as argument to compute_config, it's guaranteed that there is a connector for the argument. The code that looks for the connector is now dead, and completely unused. Delete it. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-8-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp_mst.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 5b5878e3bf6e..482dd07f5182 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -38,12 +38,9 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_digital_port *intel_dig_port = intel_mst->primary; struct intel_dp *intel_dp = &intel_dig_port->dp; struct drm_atomic_state *state; - int bpp, i; + int bpp; int lane_count, slots; const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - struct drm_connector *drm_connector; - struct intel_connector *connector, *found = NULL; - struct drm_connector_state *connector_state; int mst_pbn; pipe_config->dp_encoder_is_mst = true; @@ -62,20 +59,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, state = pipe_config->base.state; - for_each_connector_in_state(state, drm_connector, connector_state, i) { - connector = to_intel_connector(drm_connector); - - if (connector_state->best_encoder == &encoder->base) { - found = connector; - break; - } - } - - if (!found) { - DRM_ERROR("can't find connector\n"); - return false; - } - mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp); pipe_config->pbn = mst_pbn; -- cgit v1.2.1 From 225cc348409e7d9ea19f2bd7e1898b652a0b0b81 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:07 +0200 Subject: drm/i915: Convert intel_crt to use atomic state Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-9-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 8fe36d049d2f..1daf2d9c937e 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -143,13 +143,15 @@ static void hsw_crt_get_config(struct intel_encoder *encoder, /* Note: The caller is required to filter out dpms modes not supported by the * platform. */ -static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) +static void intel_crt_set_dpms(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + int mode) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crt *crt = intel_encoder_to_crt(encoder); - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; u32 adpa; if (INTEL_INFO(dev)->gen >= 5) @@ -197,7 +199,7 @@ static void intel_disable_crt(struct intel_encoder *encoder, struct intel_crtc_state *old_crtc_state, struct drm_connector_state *old_conn_state) { - intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF); + intel_crt_set_dpms(encoder, old_crtc_state, DRM_MODE_DPMS_OFF); } static void pch_disable_crt(struct intel_encoder *encoder, @@ -217,7 +219,7 @@ static void intel_enable_crt(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - intel_crt_set_dpms(encoder, DRM_MODE_DPMS_ON); + intel_crt_set_dpms(encoder, pipe_config, DRM_MODE_DPMS_ON); } static enum drm_mode_status -- cgit v1.2.1 From ae9a911bb0aa229787b49393758be34c610167fc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:08 +0200 Subject: drm/i915: Convert intel_dvo to use atomic state Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-10-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dvo.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 141483fdcf7b..642c5550a1e5 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -194,13 +194,12 @@ static void intel_enable_dvo(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dvo *intel_dvo = enc_to_dvo(encoder); - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg; u32 temp = I915_READ(dvo_reg); intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, - &crtc->config->base.mode, - &crtc->config->base.adjusted_mode); + &pipe_config->base.mode, + &pipe_config->base.adjusted_mode); I915_WRITE(dvo_reg, temp | DVO_ENABLE); I915_READ(dvo_reg); @@ -262,10 +261,9 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; + 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; struct intel_dvo *intel_dvo = enc_to_dvo(encoder); int pipe = crtc->pipe; u32 dvo_val; -- cgit v1.2.1 From 5eff0edf32a063bddcf7d3c44199c685e66360cd Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:09 +0200 Subject: drm/i915: Convert intel_dsi to use atomic state Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-11-git-send-email-maarten.lankhorst@linux.intel.com [mlankhorst: Unbreak bxt_dsi_get_pipe_config] Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 1a2e1dcbff1a..b2e3d3a334f7 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -534,16 +534,15 @@ static void intel_dsi_enable(struct intel_encoder *encoder) intel_panel_enable_backlight(intel_dsi->attached_connector); } -static void intel_dsi_prepare(struct intel_encoder *intel_encoder); +static void intel_dsi_prepare(struct intel_encoder *intel_encoder, + struct intel_crtc_state *pipe_config); static void intel_dsi_pre_enable(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + 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 *crtc = to_intel_crtc(encoder->base.crtc); enum port port; DRM_DEBUG_KMS("\n"); @@ -553,9 +552,9 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder, * lock. It needs to be fully powered down to fix it. */ intel_disable_dsi_pll(encoder); - intel_enable_dsi_pll(encoder, crtc->config); + intel_enable_dsi_pll(encoder, pipe_config); - intel_dsi_prepare(encoder); + intel_dsi_prepare(encoder, pipe_config); /* Panel Enable over CRC PMIC */ if (intel_dsi->gpio_panel) @@ -828,6 +827,7 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, u16 crtc_htotal_sw, crtc_hsync_start_sw, crtc_hsync_end_sw, crtc_hblank_start_sw, crtc_hblank_end_sw; + /* FIXME: hw readout should not depend on SW state */ intel_crtc = to_intel_crtc(encoder->base.crtc); adjusted_mode_sw = &intel_crtc->config->base.adjusted_mode; @@ -1113,14 +1113,15 @@ static u32 pixel_format_to_reg(enum mipi_dsi_pixel_format fmt) } } -static void intel_dsi_prepare(struct intel_encoder *intel_encoder) +static void intel_dsi_prepare(struct intel_encoder *intel_encoder, + struct intel_crtc_state *pipe_config) { 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(encoder->crtc); + 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 = &intel_crtc->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; enum port port; unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); u32 val, tmp; @@ -1357,7 +1358,7 @@ static int intel_dsi_set_property(struct drm_connector *connector, intel_connector->panel.fitting_mode = val; } - crtc = intel_attached_encoder(connector)->base.crtc; + crtc = connector->state->crtc; if (crtc && crtc->state->enable) { /* * If the CRTC is enabled, the display will be changed -- cgit v1.2.1 From f9fe053064a0b8dcb7b252b1148f060fc6586a4e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:10 +0200 Subject: drm/i915: Convert intel_sdvo to use atomic state Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-12-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e3bc8d4bb781..c551024d4871 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1003,24 +1003,22 @@ static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, } static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo, - const struct drm_display_mode *adjusted_mode) + struct intel_crtc_state *pipe_config) { uint8_t sdvo_data[HDMI_INFOFRAME_SIZE(AVI)]; - struct drm_crtc *crtc = intel_sdvo->base.base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); union hdmi_infoframe frame; int ret; ssize_t len; ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - adjusted_mode); + &pipe_config->base.adjusted_mode); if (ret < 0) { DRM_ERROR("couldn't fill AVI infoframe\n"); return false; } if (intel_sdvo->rgb_quant_range_selectable) { - if (intel_crtc->config->limited_color_range) + if (pipe_config->limited_color_range) frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED; else @@ -1199,18 +1197,15 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, { struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(intel_encoder->base.crtc); - const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; - struct drm_display_mode *mode = &crtc->config->base.mode; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; + struct drm_display_mode *mode = &crtc_state->base.mode; struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder); u32 sdvox; struct intel_sdvo_in_out_map in_out; struct intel_sdvo_dtd input_dtd, output_dtd; int rate; - if (!mode) - return; - /* First, set the input mapping for the first input to our controlled * output. This is only correct if we're a single-input device, in * which case the first input is the output from the appropriate SDVO @@ -1243,11 +1238,11 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, if (!intel_sdvo_set_target_input(intel_sdvo)) return; - if (crtc->config->has_hdmi_sink) { + if (crtc_state->has_hdmi_sink) { intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI); intel_sdvo_set_colorimetry(intel_sdvo, SDVO_COLORIMETRY_RGB256); - intel_sdvo_set_avi_infoframe(intel_sdvo, adjusted_mode); + intel_sdvo_set_avi_infoframe(intel_sdvo, crtc_state); } else intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_DVI); @@ -1263,7 +1258,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, DRM_INFO("Setting input timings on %s failed\n", SDVO_NAME(intel_sdvo)); - switch (crtc->config->pixel_multiplier) { + switch (crtc_state->pixel_multiplier) { default: WARN(1, "unknown pixel multiplier specified\n"); case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break; @@ -1278,7 +1273,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, /* The real mode polarity is set by the SDVO commands, using * struct intel_sdvo_dtd. */ sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH; - if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) + if (!HAS_PCH_SPLIT(dev) && crtc_state->limited_color_range) sdvox |= HDMI_COLOR_RANGE_16_235; if (INTEL_INFO(dev)->gen < 5) sdvox |= SDVO_BORDER_ENABLE; @@ -1304,7 +1299,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { /* done in crtc_mode_set as it lives inside the dpll register */ } else { - sdvox |= (crtc->config->pixel_multiplier - 1) + sdvox |= (crtc_state->pixel_multiplier - 1) << SDVO_PORT_MULTIPLY_SHIFT; } -- cgit v1.2.1 From d468e21e8c4f79dcc171b1f66dbb4e66c8ff53d7 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:11 +0200 Subject: drm/i915: Convert intel_lvds to use atomic state Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-13-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter [mlankhorst: Small fixup wrt register renames.] --- drivers/gpu/drm/i915/intel_lvds.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 29d45b099e51..4987d972e60a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -235,17 +235,16 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; + 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; int pipe = crtc->pipe; u32 temp; - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev_priv)) { assert_fdi_rx_pll_disabled(dev_priv, pipe); assert_shared_dpll_disabled(dev_priv, - crtc->config->shared_dpll); + pipe_config->shared_dpll); } else { assert_pll_disabled(dev_priv, pipe); } @@ -255,7 +254,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, temp = lvds_encoder->init_lvds_val; temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; - if (HAS_PCH_CPT(dev)) { + if (HAS_PCH_CPT(dev_priv)) { temp &= ~PORT_TRANS_SEL_MASK; temp |= PORT_TRANS_SEL_CPT(pipe); } else { @@ -268,7 +267,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, /* set the corresponsding LVDS_BORDER bit */ temp &= ~LVDS_BORDER_ENABLE; - temp |= crtc->config->gmch_pfit.lvds_border_bits; + temp |= pipe_config->gmch_pfit.lvds_border_bits; /* Set the B0-B3 data pairs corresponding to whether we're going to * set the DPLLs for dual-channel mode or not. */ @@ -291,7 +290,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, if (IS_GEN4(dev_priv)) { /* Bspec wording suggests that LVDS port dithering only exists * for 18bpp panels. */ - if (crtc->config->dither && crtc->config->pipe_bpp == 18) + if (pipe_config->dither && pipe_config->pipe_bpp == 18) temp |= LVDS_ENABLE_DITHER; else temp &= ~LVDS_ENABLE_DITHER; @@ -332,9 +331,8 @@ static void intel_disable_lvds(struct intel_encoder *encoder, struct intel_crtc_state *old_crtc_state, struct drm_connector_state *old_conn_state) { - struct drm_device *dev = encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~PANEL_POWER_ON); if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000)) -- cgit v1.2.1 From 1e7bfa0b0e845d5e6984eb0dcdfd150c900d30b3 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:12 +0200 Subject: drm/i915: Convert intel_dp_mst to use atomic state Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-14-git-send-email-maarten.lankhorst@linux.intel.com [mlankhorst: Address bikeshed.] Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp_mst.c | 49 ++++++++++++++----------------------- 1 file changed, 18 insertions(+), 31 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 482dd07f5182..29ba4f6bd01f 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -82,11 +82,13 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, 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; + struct intel_connector *connector = + to_intel_connector(old_conn_state->connector); int ret; DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); - drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port); + drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port); ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); if (ret) { @@ -101,6 +103,8 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, 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; + struct intel_connector *connector = + to_intel_connector(old_conn_state->connector); DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); @@ -109,7 +113,7 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, /* and this can also fail */ drm_dp_update_payload_part2(&intel_dp->mst_mgr); - drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port); + drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port); intel_dp->active_mst_links--; @@ -129,43 +133,28 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, 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; - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = intel_dig_port->port; + struct intel_connector *connector = + to_intel_connector(conn_state->connector); int ret; uint32_t temp; - struct intel_connector *found = NULL, *connector; int slots; - struct drm_crtc *crtc = encoder->base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - for_each_intel_connector(dev, connector) { - if (connector->base.state->best_encoder == &encoder->base) { - found = connector; - break; - } - } - - if (!found) { - DRM_ERROR("can't find connector\n"); - return; - } /* MST encoders are bound to a crtc, not to a connector, * force the mapping here for get_hw_state. */ - found->encoder = encoder; + connector->encoder = encoder; + intel_mst->connector = connector; DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); - intel_mst->connector = found; - if (intel_dp->active_mst_links == 0) { - intel_ddi_clk_select(&intel_dig_port->base, intel_crtc->config); + intel_ddi_clk_select(&intel_dig_port->base, pipe_config); intel_prepare_dp_ddi_buffers(&intel_dig_port->base); - intel_dp_set_link_params(intel_dp, intel_crtc->config); + intel_dp_set_link_params(intel_dp, pipe_config); intel_ddi_init_dp_buf_reg(&intel_dig_port->base); @@ -176,8 +165,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, } ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, - intel_mst->connector->port, - intel_crtc->config->pbn, &slots); + connector->port, + pipe_config->pbn, &slots); if (ret == false) { DRM_ERROR("failed to allocate vcpi\n"); return; @@ -198,8 +187,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder, 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; - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = intel_dig_port->port; int ret; @@ -232,9 +220,8 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder, { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - 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 drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; u32 temp, flags = 0; -- cgit v1.2.1 From 85cb48a1651ee7cbc49468776d3078418f7827c5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:13 +0200 Subject: drm/i915: Convert intel_dp to use atomic state Slightly less straightforward. Some of the drrs calls are done from workers or from intel_ddi.c, pass along crtc_state when we can, or crtc->config when we can't. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-15-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 4 +- drivers/gpu/drm/i915/intel_dp.c | 123 ++++++++++++++++++--------------------- drivers/gpu/drm/i915/intel_drv.h | 6 +- 3 files changed, 64 insertions(+), 69 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index b23872839fe0..309ba7bc19ad 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1745,7 +1745,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder, intel_edp_backlight_on(intel_dp); intel_psr_enable(intel_dp); - intel_edp_drrs_enable(intel_dp); + intel_edp_drrs_enable(intel_dp, pipe_config); } if (intel_crtc->config->has_audio) { @@ -1773,7 +1773,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder, if (type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - intel_edp_drrs_disable(intel_dp); + intel_edp_drrs_disable(intel_dp, old_crtc_state); intel_psr_disable(intel_dp); intel_edp_backlight_off(intel_dp); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9bf71f5579bb..f3e17cdc4436 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1648,16 +1648,17 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, intel_dp->link_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST); } -static void intel_dp_prepare(struct intel_encoder *encoder) +static void intel_dp_prepare(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = dp_to_dig_port(intel_dp)->port; struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; + const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - intel_dp_set_link_params(intel_dp, crtc->config); + intel_dp_set_link_params(intel_dp, pipe_config); /* * There are four kinds of DP registers: @@ -1683,7 +1684,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder) /* Handle DP bits in common between all three register formats */ intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; - intel_dp->DP |= DP_PORT_WIDTH(crtc->config->lane_count); + intel_dp->DP |= DP_PORT_WIDTH(pipe_config->lane_count); /* Split out the IBX/CPU vs CPT settings */ @@ -1711,7 +1712,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder) I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); } else { if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && - !IS_CHERRYVIEW(dev) && crtc->config->limited_color_range) + !IS_CHERRYVIEW(dev) && pipe_config->limited_color_range) intel_dp->DP |= DP_COLOR_RANGE_16_235; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -2250,10 +2251,10 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state) #define assert_edp_pll_enabled(d) assert_edp_pll((d), true) #define assert_edp_pll_disabled(d) assert_edp_pll((d), false) -static void ironlake_edp_pll_on(struct intel_dp *intel_dp) +static void ironlake_edp_pll_on(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config) { - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); assert_pipe_disabled(dev_priv, crtc->pipe); @@ -2261,11 +2262,11 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp) assert_edp_pll_disabled(dev_priv); DRM_DEBUG_KMS("enabling eDP PLL for clock %d\n", - crtc->config->port_clock); + pipe_config->port_clock); intel_dp->DP &= ~DP_PLL_FREQ_MASK; - if (crtc->config->port_clock == 162000) + if (pipe_config->port_clock == 162000) intel_dp->DP |= DP_PLL_FREQ_162MHZ; else intel_dp->DP |= DP_PLL_FREQ_270MHZ; @@ -2479,13 +2480,12 @@ static void intel_disable_dp(struct intel_encoder *encoder, struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct drm_device *dev = encoder->base.dev; - struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (crtc->config->has_audio) + if (old_crtc_state->has_audio) intel_audio_codec_disable(encoder); - if (HAS_PSR(dev) && !HAS_DDI(dev)) + if (HAS_PSR(dev_priv) && !HAS_DDI(dev_priv)) intel_psr_disable(intel_dp); /* Make sure the panel is off before trying to change the mode. But also @@ -2496,7 +2496,7 @@ static void intel_disable_dp(struct intel_encoder *encoder, intel_edp_panel_off(intel_dp); /* disable the port before the pipe on g4x */ - if (INTEL_INFO(dev)->gen < 5) + if (INTEL_GEN(dev_priv) < 5) intel_dp_link_down(intel_dp); } @@ -2625,12 +2625,11 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, } } -static void intel_dp_enable_port(struct intel_dp *intel_dp) +static void intel_dp_enable_port(struct intel_dp *intel_dp, + struct intel_crtc_state *old_crtc_state) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = - to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); /* enable with pattern 1 (as per spec) */ _intel_dp_set_link_train(intel_dp, &intel_dp->DP, @@ -2646,14 +2645,15 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp) * fail when the power sequencer is freshly used for this port. */ intel_dp->DP |= DP_PORT_EN; - if (crtc->config->has_audio) + if (old_crtc_state->has_audio) intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; I915_WRITE(intel_dp->output_reg, intel_dp->DP); POSTING_READ(intel_dp->output_reg); } -static void intel_enable_dp(struct intel_encoder *encoder) +static void intel_enable_dp(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -2670,7 +2670,7 @@ static void intel_enable_dp(struct intel_encoder *encoder) if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) vlv_init_panel_power_sequencer(intel_dp); - intel_dp_enable_port(intel_dp); + intel_dp_enable_port(intel_dp, pipe_config); edp_panel_vdd_on(intel_dp); edp_panel_on(intel_dp); @@ -2682,7 +2682,7 @@ static void intel_enable_dp(struct intel_encoder *encoder) unsigned int lane_mask = 0x0; if (IS_CHERRYVIEW(dev)) - lane_mask = intel_dp_unused_lane_mask(crtc->config->lane_count); + lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count); vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp), lane_mask); @@ -2692,7 +2692,7 @@ static void intel_enable_dp(struct intel_encoder *encoder) intel_dp_start_link_train(intel_dp); intel_dp_stop_link_train(intel_dp); - if (crtc->config->has_audio) { + if (pipe_config->has_audio) { DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", pipe_name(pipe)); intel_audio_codec_enable(encoder); @@ -2705,7 +2705,7 @@ static void g4x_enable_dp(struct intel_encoder *encoder, { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - intel_enable_dp(encoder); + intel_enable_dp(encoder, pipe_config); intel_edp_backlight_on(intel_dp); } @@ -2726,11 +2726,11 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = dp_to_dig_port(intel_dp)->port; - intel_dp_prepare(encoder); + intel_dp_prepare(encoder, pipe_config); /* Only ilk+ has port A */ if (port == PORT_A) - ironlake_edp_pll_on(intel_dp); + ironlake_edp_pll_on(intel_dp, pipe_config); } static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) @@ -2842,14 +2842,14 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder, { vlv_phy_pre_encoder_enable(encoder); - intel_enable_dp(encoder); + intel_enable_dp(encoder, pipe_config); } static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - intel_dp_prepare(encoder); + intel_dp_prepare(encoder, pipe_config); vlv_phy_pre_pll_enable(encoder); } @@ -2860,7 +2860,7 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder, { chv_phy_pre_encoder_enable(encoder); - intel_enable_dp(encoder); + intel_enable_dp(encoder, pipe_config); /* Second common lane will stay alive on its own now */ chv_phy_release_cl2_override(encoder); @@ -2870,7 +2870,7 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { - intel_dp_prepare(encoder); + intel_dp_prepare(encoder, pipe_config); chv_phy_pre_pll_enable(encoder); } @@ -5057,14 +5057,14 @@ static void intel_dp_pps_init(struct drm_device *dev, * * The caller of this function needs to take a lock on dev_priv->drrs. */ -static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) +static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, + struct intel_crtc_state *crtc_state, + int refresh_rate) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_encoder *encoder; struct intel_digital_port *dig_port = NULL; struct intel_dp *intel_dp = dev_priv->drrs.dp; - struct intel_crtc_state *config = NULL; - struct intel_crtc *intel_crtc = NULL; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); enum drrs_refresh_rate_type index = DRRS_HIGH_RR; if (refresh_rate <= 0) { @@ -5091,8 +5091,6 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) return; } - config = intel_crtc->config; - if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) { DRM_DEBUG_KMS("Only Seamless DRRS supported.\n"); return; @@ -5108,12 +5106,12 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) return; } - if (!intel_crtc->active) { + if (!crtc_state->base.active) { DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n"); return; } - if (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev)) { + if (INTEL_GEN(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) { switch (index) { case DRRS_HIGH_RR: intel_dp_set_m_n(intel_crtc, M1_N1); @@ -5125,18 +5123,18 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) default: DRM_ERROR("Unsupported refreshrate type\n"); } - } else if (INTEL_INFO(dev)->gen > 6) { - i915_reg_t reg = PIPECONF(intel_crtc->config->cpu_transcoder); + } else if (INTEL_GEN(dev_priv) > 6) { + i915_reg_t reg = PIPECONF(crtc_state->cpu_transcoder); u32 val; val = I915_READ(reg); if (index > DRRS_HIGH_RR) { - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV; else val |= PIPECONF_EDP_RR_MODE_SWITCH; } else { - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV; else val &= ~PIPECONF_EDP_RR_MODE_SWITCH; @@ -5155,15 +5153,13 @@ static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) * * Initializes frontbuffer_bits and drrs.dp */ -void intel_edp_drrs_enable(struct intel_dp *intel_dp) +void intel_edp_drrs_enable(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_crtc *crtc = dig_port->base.base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->config->has_drrs) { + if (!crtc_state->has_drrs) { DRM_DEBUG_KMS("Panel doesn't support DRRS\n"); return; } @@ -5187,15 +5183,13 @@ unlock: * @intel_dp: DP struct * */ -void intel_edp_drrs_disable(struct intel_dp *intel_dp) +void intel_edp_drrs_disable(struct intel_dp *intel_dp, + struct intel_crtc_state *old_crtc_state) { struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_crtc *crtc = dig_port->base.base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->config->has_drrs) + if (!old_crtc_state->has_drrs) return; mutex_lock(&dev_priv->drrs.mutex); @@ -5205,9 +5199,8 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp) } if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) - intel_dp_set_drrs_state(&dev_priv->drm, - intel_dp->attached_connector->panel. - fixed_mode->vrefresh); + intel_dp_set_drrs_state(dev_priv, old_crtc_state, + intel_dp->attached_connector->panel.fixed_mode->vrefresh); dev_priv->drrs.dp = NULL; mutex_unlock(&dev_priv->drrs.mutex); @@ -5236,10 +5229,12 @@ static void intel_edp_drrs_downclock_work(struct work_struct *work) if (dev_priv->drrs.busy_frontbuffer_bits) goto unlock; - if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR) - intel_dp_set_drrs_state(&dev_priv->drm, - intel_dp->attached_connector->panel. - downclock_mode->vrefresh); + if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR) { + struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc; + + intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, + intel_dp->attached_connector->panel.downclock_mode->vrefresh); + } unlock: mutex_unlock(&dev_priv->drrs.mutex); @@ -5280,9 +5275,8 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, /* invalidate means busy screen hence upclock */ if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) - intel_dp_set_drrs_state(&dev_priv->drm, - dev_priv->drrs.dp->attached_connector->panel. - fixed_mode->vrefresh); + intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, + dev_priv->drrs.dp->attached_connector->panel.fixed_mode->vrefresh); mutex_unlock(&dev_priv->drrs.mutex); } @@ -5324,9 +5318,8 @@ void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, /* flush means busy screen hence upclock */ if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) - intel_dp_set_drrs_state(&dev_priv->drm, - dev_priv->drrs.dp->attached_connector->panel. - fixed_mode->vrefresh); + intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, + dev_priv->drrs.dp->attached_connector->panel.fixed_mode->vrefresh); /* * flush also means no more activity hence schedule downclock, if all diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0b72eed5861f..6480c5984bf9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1409,8 +1409,10 @@ void intel_dp_hot_plug(struct intel_encoder *intel_encoder); void intel_power_sequencer_reset(struct drm_i915_private *dev_priv); uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes); void intel_plane_destroy(struct drm_plane *plane); -void intel_edp_drrs_enable(struct intel_dp *intel_dp); -void intel_edp_drrs_disable(struct intel_dp *intel_dp); +void intel_edp_drrs_enable(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state); +void intel_edp_drrs_disable(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state); void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, -- cgit v1.2.1 From 1f0017f6f377cf87a227fd5222ad06e2d52be12c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 9 Aug 2016 17:04:14 +0200 Subject: drm/i915: Use more atomic state in intel_color.c crtc_state is already passed around, use it instead of crtc->config. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1470755054-32699-16-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_color.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index bc0fef3d3335..95a72771eea6 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -100,13 +100,14 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int i, pipe = intel_crtc->pipe; uint16_t coeffs[9] = { 0, }; + struct intel_crtc_state *intel_crtc_state = to_intel_crtc_state(crtc_state); if (crtc_state->ctm) { struct drm_color_ctm *ctm = (struct drm_color_ctm *)crtc_state->ctm->data; uint64_t input[9] = { 0, }; - if (intel_crtc->config->limited_color_range) { + if (intel_crtc_state->limited_color_range) { ctm_mult_by_limited(input, ctm->matrix); } else { for (i = 0; i < ARRAY_SIZE(input); i++) @@ -158,7 +159,7 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state) * into consideration. */ for (i = 0; i < 3; i++) { - if (intel_crtc->config->limited_color_range) + if (intel_crtc_state->limited_color_range) coeffs[i * 3 + i] = I9XX_CSC_COEFF_LIMITED_RANGE; else @@ -182,7 +183,7 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state) if (INTEL_INFO(dev)->gen > 6) { uint16_t postoff = 0; - if (intel_crtc->config->limited_color_range) + if (intel_crtc_state->limited_color_range) postoff = (16 * (1 << 12) / 255) & 0x1fff; I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff); @@ -193,7 +194,7 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state) } else { uint32_t mode = CSC_MODE_YUV_TO_RGB; - if (intel_crtc->config->limited_color_range) + if (intel_crtc_state->limited_color_range) mode |= CSC_BLACK_SCREEN_OFFSET; I915_WRITE(PIPE_CSC_MODE(pipe), mode); @@ -263,7 +264,8 @@ void intel_color_set_csc(struct drm_crtc_state *crtc_state) /* Loads the legacy palette/gamma unit for the CRTC. */ static void i9xx_load_luts_internal(struct drm_crtc *crtc, - struct drm_property_blob *blob) + struct drm_property_blob *blob, + struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -272,7 +274,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, int i; if (HAS_GMCH_DISPLAY(dev)) { - if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) assert_dsi_pll_enabled(dev_priv); else assert_pll_enabled(dev_priv, pipe); @@ -305,7 +307,8 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, static void i9xx_load_luts(struct drm_crtc_state *crtc_state) { - i9xx_load_luts_internal(crtc_state->crtc, crtc_state->gamma_lut); + i9xx_load_luts_internal(crtc_state->crtc, crtc_state->gamma_lut, + to_intel_crtc_state(crtc_state)); } /* Loads the legacy palette/gamma unit for the CRTC on Haswell. */ @@ -323,7 +326,7 @@ static void haswell_load_luts(struct drm_crtc_state *crtc_state) * Workaround : Do not read or write the pipe palette/gamma data while * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. */ - if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled && + if (IS_HASWELL(dev) && intel_crtc_state->ips_enabled && (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) { hsw_disable_ips(intel_crtc); reenable_ips = true; @@ -436,7 +439,8 @@ static void cherryview_load_luts(struct drm_crtc_state *state) /* Turn off degamma/gamma on CGM block. */ I915_WRITE(CGM_PIPE_MODE(pipe), (state->ctm ? CGM_PIPE_MODE_CSC : 0)); - i9xx_load_luts_internal(crtc, state->gamma_lut); + i9xx_load_luts_internal(crtc, state->gamma_lut, + to_intel_crtc_state(state)); return; } @@ -479,7 +483,7 @@ static void cherryview_load_luts(struct drm_crtc_state *state) * Also program a linear LUT in the legacy block (behind the * CGM block). */ - i9xx_load_luts_internal(crtc, NULL); + i9xx_load_luts_internal(crtc, NULL, to_intel_crtc_state(state)); } void intel_color_load_luts(struct drm_crtc_state *crtc_state) -- cgit v1.2.1 From 62e0fb880123c98793e5c3ba8355501b0305e92e Mon Sep 17 00:00:00 2001 From: Lyude Date: Mon, 22 Aug 2016 12:50:08 -0400 Subject: drm/i915/skl: Update plane watermarks atomically during plane updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Ville for suggesting this as a potential solution to pipe underruns on Skylake. On Skylake all of the registers for configuring planes, including the registers for configuring their watermarks, are double buffered. New values written to them won't take effect until said registers are "armed", which is done by writing to the PLANE_SURF (or in the case of cursor planes, the CURBASE register) register. With this in mind, up until now we've been updating watermarks on skl like this: non-modeset { - calculate (during atomic check phase) - finish_atomic_commit: - intel_pre_plane_update: - intel_update_watermarks() - {vblank happens; new watermarks + old plane values => underrun } - drm_atomic_helper_commit_planes_on_crtc: - start vblank evasion - write new plane registers - end vblank evasion } or modeset { - calculate (during atomic check phase) - finish_atomic_commit: - crtc_enable: - intel_update_watermarks() - {vblank happens; new watermarks + old plane values => underrun } - drm_atomic_helper_commit_planes_on_crtc: - start vblank evasion - write new plane registers - end vblank evasion } Now we update watermarks atomically like this: non-modeset { - calculate (during atomic check phase) - finish_atomic_commit: - intel_pre_plane_update: - intel_update_watermarks() (wm values aren't written yet) - drm_atomic_helper_commit_planes_on_crtc: - start vblank evasion - write new plane registers - write new wm values - end vblank evasion } modeset { - calculate (during atomic check phase) - finish_atomic_commit: - crtc_enable: - intel_update_watermarks() (actual wm values aren't written yet) - drm_atomic_helper_commit_planes_on_crtc: - start vblank evasion - write new plane registers - write new wm values - end vblank evasion } So this patch moves all of the watermark writes into the right place; inside of the vblank evasion where we update all of the registers for each plane. While this patch doesn't fix everything, it does allow us to update the watermark values in the way the hardware expects us to. Changes since original patch series: - Remove mutex_lock/mutex_unlock since they don't do anything and we're not touching global state - Move skl_write_cursor_wm/skl_write_plane_wm functions into intel_pm.c, make externally visible - Add skl_write_plane_wm calls to skl_update_plane - Fix conditional for for loop in skl_write_plane_wm (level < max_level should be level <= max_level) - Make diagram in commit more accurate to what's actually happening - Add Fixes: Changes since v1: - Use IS_GEN9() instead of IS_SKYLAKE() since these fixes apply to more then just Skylake - Update description to make it clear this patch doesn't fix everything - Check if pipes were actually changed before writing watermarks Changes since v2: - Write PIPE_WM_LINETIME during vblank evasion Changes since v3: - Rebase against new SAGV patch changes Changes since v4: - Add a parameter to choose what skl_wm_values struct to use when writing new plane watermarks Changes since v5: - Remove cursor ddb entry write in skl_write_cursor_wm(), defer until patch 6 - Write WM_LINETIME in intel_begin_crtc_commit() Changes since v6: - Remove redundant dirty_pipes check in skl_write_plane_wm (we check this in all places where we call this function, and it was supposed to have been removed earlier anyway) - In i9xx_update_cursor(), use dev_priv->info.gen >= 9 instead of IS_GEN9(dev_priv). We do this everywhere else and I'd imagine this needs to be done for gen10 as well Changes since v7: - Fix rebase fail (unused variable obj) - Make struct skl_wm_values *wm const - Fix indenting - Use INTEL_GEN() instead of dev_priv->info.gen Changes since v8: - Don't forget calls to skl_write_plane_wm() when disabling planes - Use INTEL_GEN(), not INTEL_INFO()->gen in intel_begin_crtc_commit() Fixes: 2d41c0b59afc ("drm/i915/skl: SKL Watermark Computation") Signed-off-by: Lyude Reviewed-by: Matt Roper Cc: stable@vger.kernel.org Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Radhakrishna Sripada Cc: Hans de Goede Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471884608-10671-1-git-send-email-cpaul@redhat.com Link: http://patchwork.freedesktop.org/patch/msgid/1471884608-10671-1-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_display.c | 21 +++++++++++++-- drivers/gpu/drm/i915/intel_drv.h | 5 ++++ drivers/gpu/drm/i915/intel_pm.c | 50 ++++++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_sprite.c | 9 +++++++ 4 files changed, 67 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f44858d2650e..2dd2c0e9ae32 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3377,6 +3377,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane, struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_framebuffer *fb = plane_state->base.fb; + const struct skl_wm_values *wm = &dev_priv->wm.skl_results; int pipe = intel_crtc->pipe; u32 plane_ctl; unsigned int rotation = plane_state->base.rotation; @@ -3410,6 +3411,9 @@ static void skylake_update_primary_plane(struct drm_plane *plane, intel_crtc->adjusted_x = src_x; intel_crtc->adjusted_y = src_y; + if (wm->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) + skl_write_plane_wm(intel_crtc, wm, 0); + I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); I915_WRITE(PLANE_OFFSET(pipe, 0), (src_y << 16) | src_x); I915_WRITE(PLANE_STRIDE(pipe, 0), stride); @@ -3441,7 +3445,10 @@ static void skylake_disable_primary_plane(struct drm_plane *primary, { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); - int pipe = to_intel_crtc(crtc)->pipe; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + + skl_write_plane_wm(intel_crtc, &dev_priv->wm.skl_results, 0); I915_WRITE(PLANE_CTL(pipe, 0), 0); I915_WRITE(PLANE_SURF(pipe, 0), 0); @@ -10814,9 +10821,13 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + const struct skl_wm_values *wm = &dev_priv->wm.skl_results; int pipe = intel_crtc->pipe; uint32_t cntl = 0; + if (INTEL_GEN(dev_priv) >= 9 && wm->dirty_pipes & drm_crtc_mask(crtc)) + skl_write_cursor_wm(intel_crtc, wm); + if (plane_state && plane_state->base.visible) { cntl = MCURSOR_GAMMA_ENABLE; switch (plane_state->base.crtc_w) { @@ -14740,10 +14751,12 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc_state *old_intel_state = to_intel_crtc_state(old_crtc_state); bool modeset = needs_modeset(crtc->state); + enum pipe pipe = intel_crtc->pipe; /* Perform vblank evasion around commit operation */ intel_pipe_update_start(intel_crtc); @@ -14758,8 +14771,12 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, if (to_intel_crtc_state(crtc->state)->update_pipe) intel_update_pipe_config(intel_crtc, old_intel_state); - else if (INTEL_INFO(dev)->gen >= 9) + else if (INTEL_GEN(dev_priv) >= 9) { skl_detach_scalers(intel_crtc); + + I915_WRITE(PIPE_WM_LINETIME(pipe), + dev_priv->wm.skl_hw.wm_linetime[pipe]); + } } static void intel_finish_crtc_commit(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6480c5984bf9..690fa463a6bc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1743,6 +1743,11 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, bool skl_can_enable_sagv(struct drm_atomic_state *state); int skl_enable_sagv(struct drm_i915_private *dev_priv); int skl_disable_sagv(struct drm_i915_private *dev_priv); +void skl_write_cursor_wm(struct intel_crtc *intel_crtc, + const struct skl_wm_values *wm); +void skl_write_plane_wm(struct intel_crtc *intel_crtc, + const struct skl_wm_values *wm, + int plane); uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); bool ilk_disable_lp_wm(struct drm_device *dev); int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5e3f17059bed..2f4438d4af55 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3836,6 +3836,39 @@ static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, I915_WRITE(reg, 0); } +void skl_write_plane_wm(struct intel_crtc *intel_crtc, + const struct skl_wm_values *wm, + int plane) +{ + struct drm_crtc *crtc = &intel_crtc->base; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + int level, max_level = ilk_wm_max_level(dev); + enum pipe pipe = intel_crtc->pipe; + + for (level = 0; level <= max_level; level++) { + I915_WRITE(PLANE_WM(pipe, plane, level), + wm->plane[pipe][plane][level]); + } + I915_WRITE(PLANE_WM_TRANS(pipe, plane), wm->plane_trans[pipe][plane]); +} + +void skl_write_cursor_wm(struct intel_crtc *intel_crtc, + const struct skl_wm_values *wm) +{ + struct drm_crtc *crtc = &intel_crtc->base; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + int level, max_level = ilk_wm_max_level(dev); + enum pipe pipe = intel_crtc->pipe; + + for (level = 0; level <= max_level; level++) { + I915_WRITE(CUR_WM(pipe, level), + wm->plane[pipe][PLANE_CURSOR][level]); + } + I915_WRITE(CUR_WM_TRANS(pipe), wm->plane_trans[pipe][PLANE_CURSOR]); +} + static void skl_write_wm_values(struct drm_i915_private *dev_priv, const struct skl_wm_values *new) { @@ -3843,7 +3876,7 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv, struct intel_crtc *crtc; for_each_intel_crtc(dev, crtc) { - int i, level, max_level = ilk_wm_max_level(dev); + int i; enum pipe pipe = crtc->pipe; if ((new->dirty_pipes & drm_crtc_mask(&crtc->base)) == 0) @@ -3851,21 +3884,6 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv, if (!crtc->active) continue; - I915_WRITE(PIPE_WM_LINETIME(pipe), new->wm_linetime[pipe]); - - for (level = 0; level <= max_level; level++) { - for (i = 0; i < intel_num_planes(crtc); i++) - I915_WRITE(PLANE_WM(pipe, i, level), - new->plane[pipe][i][level]); - I915_WRITE(CUR_WM(pipe, level), - new->plane[pipe][PLANE_CURSOR][level]); - } - for (i = 0; i < intel_num_planes(crtc); i++) - I915_WRITE(PLANE_WM_TRANS(pipe, i), - new->plane_trans[pipe][i]); - I915_WRITE(CUR_WM_TRANS(pipe), - new->plane_trans[pipe][PLANE_CURSOR]); - for (i = 0; i < intel_num_planes(crtc); i++) { skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, i), diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 366900dcde34..0df783a66bfb 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -203,6 +203,9 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *intel_plane = to_intel_plane(drm_plane); struct drm_framebuffer *fb = plane_state->base.fb; + const struct skl_wm_values *wm = &dev_priv->wm.skl_results; + struct drm_crtc *crtc = crtc_state->base.crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); const int pipe = intel_plane->pipe; const int plane = intel_plane->plane + 1; u32 plane_ctl; @@ -228,6 +231,9 @@ skl_update_plane(struct drm_plane *drm_plane, plane_ctl |= skl_plane_ctl_rotation(rotation); + if (wm->dirty_pipes & drm_crtc_mask(crtc)) + skl_write_plane_wm(intel_crtc, wm, plane); + if (key->flags) { I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value); I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value); @@ -286,6 +292,9 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) const int pipe = intel_plane->pipe; const int plane = intel_plane->plane + 1; + skl_write_plane_wm(to_intel_crtc(crtc), &dev_priv->wm.skl_results, + plane); + I915_WRITE(PLANE_CTL(pipe, plane), 0); I915_WRITE(PLANE_SURF(pipe, plane), 0); -- cgit v1.2.1 From 496b0fc370caaf4072c19ac9120bf5c58f057d59 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 23 Aug 2016 16:18:07 +0200 Subject: drm/i915: Create a intel_encoder_find_connector helper function. This makes the code in intel_sanitize_encoder slightly more readable. This was meant to be addressed in fd6bbda9c7a4, but I missed that review comment. Fixes: fd6bbda9c7a4 ("drm/i915: Pass crtc_state and connector_state to encoder functions") Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471961888-10771-1-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter [mlankhorst: Fix unused variable reported by kbuild.] --- drivers/gpu/drm/i915/intel_display.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2dd2c0e9ae32..b747402ab310 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -16423,6 +16423,17 @@ static bool intel_crtc_has_encoders(struct intel_crtc *crtc) return false; } +static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct intel_connector *connector; + + for_each_connector_on_encoder(dev, &encoder->base, connector) + return connector; + + return NULL; +} + static bool has_pch_trancoder(struct drm_i915_private *dev_priv, enum transcoder pch_transcoder) { @@ -16525,8 +16536,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) static void intel_sanitize_encoder(struct intel_encoder *encoder) { struct intel_connector *connector; - struct drm_device *dev = encoder->base.dev; - bool found_connector = false; /* We need to check both for a crtc link (meaning that the * encoder is active and trying to read from a pipe) and the @@ -16534,12 +16543,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) bool has_active_crtc = encoder->base.crtc && to_intel_crtc(encoder->base.crtc)->active; - for_each_connector_on_encoder(dev, &encoder->base, connector) { - found_connector = true; - break; - } - - if (found_connector && !has_active_crtc) { + connector = intel_encoder_find_connector(encoder); + if (connector && !has_active_crtc) { DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n", encoder->base.base.id, encoder->base.name); -- cgit v1.2.1 From b70765463665e26cfc44359547923fdfd1d75b62 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 23 Aug 2016 16:18:08 +0200 Subject: drm/i915: Cleanup crt disable sequence on hsw+ Instead of iterating overthe connectors manually, run the last part of DDI disabling inside the crt post disable function. This was meant to be addressed before submitting the other commit, but I missed the review comments. Fixes: fd6bbda9c7a4 ("drm/i915: Pass crtc_state and connector_state to encoder functions") Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471961888-10771-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter [mlankhorst: Fix extra whitespace between functions.] --- drivers/gpu/drm/i915/intel_crt.c | 15 ++++++++ drivers/gpu/drm/i915/intel_ddi.c | 66 ++++++++++++++++++------------------ drivers/gpu/drm/i915/intel_display.c | 25 ++------------ drivers/gpu/drm/i915/intel_drv.h | 8 +++-- 4 files changed, 56 insertions(+), 58 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 1daf2d9c937e..dfbcf16b41df 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -215,6 +215,20 @@ static void pch_post_disable_crt(struct intel_encoder *encoder, intel_disable_crt(encoder, old_crtc_state, old_conn_state); } +static void hsw_post_disable_crt(struct intel_encoder *encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + pch_post_disable_crt(encoder, old_crtc_state, old_conn_state); + + lpt_disable_pch_transcoder(dev_priv); + lpt_disable_iclkip(dev_priv); + + intel_ddi_fdi_post_disable(encoder, old_crtc_state, old_conn_state); +} + static void intel_enable_crt(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -905,6 +919,7 @@ void intel_crt_init(struct drm_device *dev) if (HAS_DDI(dev)) { crt->base.get_config = hsw_crt_get_config; crt->base.get_hw_state = intel_ddi_get_hw_state; + crt->base.post_disable = hsw_post_disable_crt; } else { crt->base.get_config = intel_crt_get_config; crt->base.get_hw_state = intel_crt_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 309ba7bc19ad..ce369c2e96a0 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1714,6 +1714,39 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, } } +void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state) +{ + struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); + uint32_t val; + + /* + * Bspec lists this as both step 13 (before DDI_BUF_CTL disable) + * and step 18 (after clearing PORT_CLK_SEL). Based on a BUN, + * step 13 is the correct place for it. Step 18 is where it was + * originally before the BUN. + */ + val = I915_READ(FDI_RX_CTL(PIPE_A)); + val &= ~FDI_RX_ENABLE; + I915_WRITE(FDI_RX_CTL(PIPE_A), val); + + intel_ddi_post_disable(intel_encoder, old_crtc_state, old_conn_state); + + val = I915_READ(FDI_RX_MISC(PIPE_A)); + val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); + val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); + I915_WRITE(FDI_RX_MISC(PIPE_A), val); + + val = I915_READ(FDI_RX_CTL(PIPE_A)); + val &= ~FDI_PCDCLK; + I915_WRITE(FDI_RX_CTL(PIPE_A), val); + + val = I915_READ(FDI_RX_CTL(PIPE_A)); + val &= ~FDI_RX_PLL_ENABLE; + I915_WRITE(FDI_RX_CTL(PIPE_A), val); +} + static void intel_enable_ddi(struct intel_encoder *intel_encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -2153,39 +2186,6 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) udelay(600); } -void intel_ddi_fdi_disable(struct intel_encoder *intel_encoder, - struct intel_crtc_state *old_crtc_state, - struct drm_connector_state *old_conn_state) -{ - struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); - uint32_t val; - - /* - * Bspec lists this as both step 13 (before DDI_BUF_CTL disable) - * and step 18 (after clearing PORT_CLK_SEL). Based on a BUN, - * step 13 is the correct place for it. Step 18 is where it was - * originally before the BUN. - */ - val = I915_READ(FDI_RX_CTL(PIPE_A)); - val &= ~FDI_RX_ENABLE; - I915_WRITE(FDI_RX_CTL(PIPE_A), val); - - intel_ddi_post_disable(intel_encoder, old_crtc_state, old_conn_state); - - val = I915_READ(FDI_RX_MISC(PIPE_A)); - val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); - val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); - I915_WRITE(FDI_RX_MISC(PIPE_A), val); - - val = I915_READ(FDI_RX_CTL(PIPE_A)); - val &= ~FDI_PCDCLK; - I915_WRITE(FDI_RX_CTL(PIPE_A), val); - - val = I915_READ(FDI_RX_CTL(PIPE_A)); - val &= ~FDI_RX_PLL_ENABLE; - I915_WRITE(FDI_RX_CTL(PIPE_A), val); -} - void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b747402ab310..6684099d49c6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1907,7 +1907,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, } } -static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) +void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) { u32 val; @@ -4292,7 +4292,7 @@ static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) return 0; } -static void lpt_disable_iclkip(struct drm_i915_private *dev_priv) +void lpt_disable_iclkip(struct drm_i915_private *dev_priv) { u32 temp; @@ -5606,28 +5606,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_encoders_post_disable(crtc, old_crtc_state, old_state); - if (intel_crtc->config->has_pch_encoder) { - struct drm_connector_state *old_conn_state; - struct drm_connector *conn; - int i; - - lpt_disable_pch_transcoder(dev_priv); - lpt_disable_iclkip(dev_priv); - - for_each_connector_in_state(old_state, conn, old_conn_state, i) - if (old_conn_state->crtc == crtc) { - struct intel_encoder *encoder = - to_intel_encoder(old_conn_state->best_encoder); - - intel_ddi_fdi_disable(encoder, - old_crtc_state, - old_conn_state); - break; - } - + if (old_crtc_state->has_pch_encoder) intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, true); - } } static void i9xx_pfit_enable(struct intel_crtc *crtc) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 690fa463a6bc..f241a47b6e3a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1137,6 +1137,9 @@ void intel_crt_reset(struct drm_encoder *encoder); /* intel_ddi.c */ void intel_ddi_clk_select(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config); +void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, + struct intel_crtc_state *old_crtc_state, + struct drm_connector_state *old_conn_state); void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder); void hsw_fdi_link_train(struct drm_crtc *crtc); void intel_ddi_init(struct drm_device *dev, enum port port); @@ -1152,9 +1155,6 @@ bool intel_ddi_pll_select(struct intel_crtc *crtc, void intel_ddi_set_pipe_settings(struct drm_crtc *crtc); void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp); bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); -void intel_ddi_fdi_disable(struct intel_encoder *, - struct intel_crtc_state *, - struct drm_connector_state *); void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); struct intel_encoder * @@ -1185,6 +1185,8 @@ void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco); void intel_update_rawclk(struct drm_i915_private *dev_priv); int vlv_get_cck_clock(struct drm_i915_private *dev_priv, const char *name, u32 reg, int ref_freq); +void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv); +void lpt_disable_iclkip(struct drm_i915_private *dev_priv); extern const struct drm_plane_funcs intel_plane_funcs; void intel_init_display_hooks(struct drm_i915_private *dev_priv); unsigned int intel_fb_xy_to_linear(int x, int y, -- cgit v1.2.1 From 8f76aa0ebe0b7787afe768d9df80031e832d2520 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 23 Aug 2016 10:25:58 +0100 Subject: drm/i915/dvo: Remove dangling call to drm_encoder_cleanup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we hit the error path, we have never called drm_encoder_init() and so have nothing to cleanup. Doing so hits a null dereference: [ 10.066261] BUG: unable to handle kernel NULL pointer dereference at 00000104 [ 10.066273] IP: [] mutex_lock+0xa/0x15 [ 10.066287] *pde = 00000000 [ 10.066295] Oops: 0002 [#1] [ 10.066302] Modules linked in: i915(+) video i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm iTCO_wdt iTCO_vendor_support ppdev evdev snd_intel8x0 snd_ac97_codec ac97_bus psmouse snd_pcm snd_timer snd pcspkr uhci_hcd ehci_pci soundcore sr_mod ehci_hcd serio_raw i2c_i801 usbcore i2c_smbus cdrom lpc_ich mfd_core rng_core e100 mii floppy parport_pc parport acpi_cpufreq button processor usb_common eeprom lm85 hwmon_vid autofs4 [ 10.066378] CPU: 0 PID: 132 Comm: systemd-udevd Not tainted 4.8.0-rc3-00013-gef0e1ea #34 [ 10.066389] Hardware name: MicroLink /D865GLC , BIOS BF86510A.86A.0077.P25.0508040031 08/04/2005 [ 10.066401] task: f62db800 task.stack: f5970000 [ 10.066409] EIP: 0060:[] EFLAGS: 00010286 CPU: 0 [ 10.066417] EIP is at mutex_lock+0xa/0x15 [ 10.066424] EAX: 00000104 EBX: 00000104 ECX: 00000000 EDX: 80000000 [ 10.066432] ESI: 00000000 EDI: 00000104 EBP: f5be8000 ESP: f5971b58 [ 10.066439] DS: 007b ES: 007b FS: 0000 GS: 00e0 SS: 0068 [ 10.066446] CR0: 80050033 CR2: 00000104 CR3: 35945000 CR4: 000006d0 [ 10.066453] Stack: [ 10.066459] f503d740 f824dddf 00000000 f61170c0 f61170c0 f82371ae f850f40e 00000001 [ 10.066476] f61170c0 f5971bcc f5be8000 f9c2d401 00000001 f8236fcc 00000001 00000000 [ 10.066491] f5144014 f5be8104 00000008 f9c5267c 00000007 f61170c0 f5144400 f9c4ff00 [ 10.066507] Call Trace: [ 10.066526] [] ? drm_modeset_lock_all+0x27/0xb3 [drm] [ 10.066545] [] ? drm_encoder_cleanup+0x1a/0x132 [drm] [ 10.066559] [] ? drm_atomic_helper_connector_reset+0x3f/0x5c [drm_kms_helper] [ 10.066644] [] ? intel_dvo_init+0x569/0x788 [i915] [ 10.066663] [] ? drm_encoder_init+0x43/0x20b [drm] [ 10.066734] [] ? intel_modeset_init+0x1436/0x17dd [i915] [ 10.066791] [] ? i915_driver_load+0x85a/0x15d3 [i915] [ 10.066846] [] ? i915_driver_open+0x5/0x5 [i915] [ 10.066857] [] ? firmware_map_add_entry.part.2+0xc/0xc [ 10.066868] [] ? pci_device_probe+0x8e/0x11c [ 10.066878] [] ? driver_probe_device+0x1db/0x62e [ 10.066888] [] ? kernfs_new_node+0x29/0x9c [ 10.066897] [] ? pci_match_device+0xd9/0x161 [ 10.066905] [] ? kernfs_create_dir_ns+0x42/0x88 [ 10.066914] [] ? __driver_attach+0xe6/0x11b [ 10.066924] [] ? kobject_add_internal+0x1bb/0x44f [ 10.066933] [] ? driver_probe_device+0x62e/0x62e [ 10.066941] [] ? bus_for_each_dev+0x46/0x7f [ 10.066950] [] ? driver_attach+0x1a/0x34 [ 10.066958] [] ? driver_probe_device+0x62e/0x62e [ 10.066966] [] ? bus_add_driver+0x217/0x32a [ 10.066975] [] ? 0xf8403000 [ 10.066982] [] ? driver_register+0x5f/0x108 [ 10.066991] [] ? do_one_initcall+0x49/0x1f6 [ 10.067000] [] ? pick_next_task_fair+0x14b/0x2a3 [ 10.067008] [] ? __schedule+0x15c/0x4fe [ 10.067016] [] ? preempt_schedule_common+0x19/0x3c [ 10.067027] [] ? do_init_module+0x17/0x230 [ 10.067035] [] ? _cond_resched+0x12/0x1a [ 10.067044] [] ? kmem_cache_alloc+0x8f/0x11f [ 10.067052] [] ? do_init_module+0x17/0x230 [ 10.067060] [] ? kfree+0x137/0x203 [ 10.067068] [] ? do_init_module+0x76/0x230 [ 10.067078] [] ? load_module+0x2a39/0x333f [ 10.067087] [] ? SyS_finit_module+0x96/0xd5 [ 10.067096] [] ? vm_mmap_pgoff+0x79/0xa0 [ 10.067105] [] ? do_fast_syscall_32+0xb5/0x1b0 [ 10.067114] [] ? sysenter_past_esp+0x47/0x75 [ 10.067121] Code: c8 f7 76 c1 e8 8e cc d2 ff e9 45 fe ff ff 66 90 66 90 66 90 66 90 90 ff 00 7f 05 e8 4e 0c 00 00 c3 53 89 c3 e8 75 ec ff ff 89 d8 08 79 05 e8 fa 0a 00 00 5b c3 53 89 c3 85 c0 74 1b 8b 03 83 [ 10.067180] EIP: [] mutex_lock+0xa/0x15 SS:ESP 0068:f5971b58 [ 10.067190] CR2: 0000000000000104 [ 10.067222] ---[ end trace 049f1f09da45a856 ]--- Reported-by: Meelis Roos Fixes: 580d8ed522e0 ("drm/i915: Give encoders useful names") Reviewed-by: David Weinehall Signed-off-by: Chris Wilson Cc: Ville Syrjälä Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/20160823092558.14931-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_dvo.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 642c5550a1e5..2e452c505e7e 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -559,7 +559,6 @@ void intel_dvo_init(struct drm_device *dev) return; } - drm_encoder_cleanup(&intel_encoder->base); kfree(intel_dvo); kfree(intel_connector); } -- cgit v1.2.1 From d1a3a036637aac0e473f602347f879afcf91236c Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 23 Aug 2016 16:00:44 +0100 Subject: drm/i915: free intel_fb We need to free the allocated intel_fb in the error path, not intel_fb->base. Otherwise we risk calling kfree with a non-kmalloc'd address, which is bound to give us grief at some point. Signed-off-by: Matthew Auld Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1471964444-24460-1-git-send-email-matthew.auld@intel.com --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6684099d49c6..fc953739af69 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9777,7 +9777,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, return; error: - kfree(fb); + kfree(intel_fb); } static void ironlake_get_pfit_config(struct intel_crtc *crtc, -- cgit v1.2.1 From 8b0878a0a3a8da26a9766a2d3abd8768c21b4121 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Thu, 4 Aug 2016 13:48:35 -0700 Subject: drm/i915/dp: Add debug messages to print DP link training pattern Currently we do not print the training pattern used in any of the DP link training stages. Including this piece of information in debug messages will help debugging. Also, use the wrapper intel_dp_program_link_training_pattern() in intel_dp_enable_port() instead of implementing it. v2: Downgraded log level from error to debug (Chris) Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Chris Wilson Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1470343716-5574-2-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f3e17cdc4436..a3c7dd8fd406 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2551,6 +2551,10 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = to_i915(dev); enum port port = intel_dig_port->port; + if (dp_train_pat & DP_TRAINING_PATTERN_MASK) + DRM_DEBUG_KMS("Using DP training pattern TPS%d\n", + dp_train_pat & DP_TRAINING_PATTERN_MASK); + if (HAS_DDI(dev)) { uint32_t temp = I915_READ(DP_TP_CTL(port)); @@ -2592,7 +2596,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, *DP |= DP_LINK_TRAIN_PAT_2_CPT; break; case DP_TRAINING_PATTERN_3: - DRM_ERROR("DP training pattern 3 not supported\n"); + DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); *DP |= DP_LINK_TRAIN_PAT_2_CPT; break; } @@ -2617,7 +2621,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, if (IS_CHERRYVIEW(dev)) { *DP |= DP_LINK_TRAIN_PAT_3_CHV; } else { - DRM_ERROR("DP training pattern 3 not supported\n"); + DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); *DP |= DP_LINK_TRAIN_PAT_2; } break; @@ -2632,11 +2636,8 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = to_i915(dev); /* enable with pattern 1 (as per spec) */ - _intel_dp_set_link_train(intel_dp, &intel_dp->DP, - DP_TRAINING_PATTERN_1); - I915_WRITE(intel_dp->output_reg, intel_dp->DP); - POSTING_READ(intel_dp->output_reg); + intel_dp_program_link_training_pattern(intel_dp, DP_TRAINING_PATTERN_1); /* * Magic for VLV/CHV. We _must_ first set up the register -- cgit v1.2.1 From 8ab5de2e005854e27bb67a3220efdbb0ef151e07 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Thu, 4 Aug 2016 13:48:36 -0700 Subject: drm/i915/dp: Dump DP link status when link training stages fail A full dump of link status can be handy in debugging link training failures. Let's add that to the debug messages when link training fails. v2: Removing unrelated clean up (Jani) Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Chris Wilson Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1470343716-5574-3-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_dp_link_training.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index 60fb39cd220b..0deebed71a26 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -23,6 +23,15 @@ #include "intel_drv.h" +static void +intel_dp_dump_link_status(const uint8_t link_status[DP_LINK_STATUS_SIZE]) +{ + + DRM_DEBUG_KMS("ln0_1:0x%x ln2_3:0x%x align:0x%x sink:0x%x adj_req0_1:0x%x adj_req2_3:0x%x", + link_status[0], link_status[1], link_status[2], + link_status[3], link_status[4], link_status[5]); +} + static void intel_get_adjust_train(struct intel_dp *intel_dp, const uint8_t link_status[DP_LINK_STATUS_SIZE]) @@ -168,6 +177,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) ++loop_tries; if (loop_tries == 5) { DRM_ERROR("too many full retries, give up\n"); + intel_dp_dump_link_status(link_status); break; } intel_dp_reset_link_train(intel_dp, @@ -254,6 +264,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) if (cr_tries > 5) { DRM_ERROR("failed to train DP, aborting\n"); + intel_dp_dump_link_status(link_status); break; } -- cgit v1.2.1 From 38cb2ecaf56fac390bd337f5f8140dc4bc34c27e Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Wed, 10 Aug 2016 23:41:13 -0700 Subject: drm/i915: Eliminate redundant local variable definition No functional change, just clean up. Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Chris Wilson Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1470897673-29292-3-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 762572aeca23..a421171bd2ed 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -359,9 +359,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - struct intel_digital_port *intel_dig_port = - enc_to_dig_port(&encoder->base); - enum port port = intel_dig_port->port; + enum port port = enc_to_dig_port(&encoder->base)->port; enum pipe pipe = intel_crtc->pipe; uint32_t tmp, eldv; i915_reg_t aud_config, aud_cntrl_st2; @@ -407,13 +405,10 @@ static void ilk_audio_codec_enable(struct drm_connector *connector, { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - struct intel_digital_port *intel_dig_port = - enc_to_dig_port(&encoder->base); - enum port port = intel_dig_port->port; + enum port port = enc_to_dig_port(&encoder->base)->port; enum pipe pipe = intel_crtc->pipe; uint8_t *eld = connector->eld; - uint32_t eldv; - uint32_t tmp; + uint32_t tmp, eldv; int len, i; i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; -- cgit v1.2.1 From c82dd8848479d27dec3f05e9a0980a83fcadca8b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 24 Aug 2016 19:00:53 +0100 Subject: Revert "drm/i915/fbc: Allow on unfenced surfaces, for recent gen" This reverts commit 8678fdaf396c ("drm/i915/fbc: Allow on unfenced surfaces, for recent gen") as Skylake has issues with unfenced FBC tracking (and yes Skylake doesn't even enable FBC yet). Paulo would like to do a full review of all existing workarounds to see if any more are missing prior to allowing FBC on unfenced surfaces. In the meantime lets hope that all framebuffers are idle and naturally fit within the mappable aperture. Requested-by: Paulo Zanoni Fixes: 8678fdaf396c ("drm/i915/fbc: Allow on unfenced surfaces..."); Cc: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/20160824180053.24239-1-chris@chris-wilson.co.uk Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_fbc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index bf8b22ad9aed..faa67624e1ed 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -799,10 +799,8 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) */ if (cache->fb.tiling_mode != I915_TILING_X || cache->fb.fence_reg == I915_FENCE_REG_NONE) { - if (INTEL_GEN(dev_priv) < 5) { - fbc->no_fbc_reason = "framebuffer not tiled or fenced"; - return false; - } + fbc->no_fbc_reason = "framebuffer not tiled or fenced"; + return false; } if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) && cache->plane.rotation != DRM_ROTATE_0) { -- cgit v1.2.1 From 79cf219a6a2ecf553587fae41b117d8c49cc0a55 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 24 Aug 2016 11:16:07 +0100 Subject: drm/i915: Suppress DRM_ERROR for D_COMP write on Haswell The D_COMP (render decompression) register write is followed by a status check and another error (either that the decompression shutdown or the lpll is enabled). Since we are followed by another, more pertinent, error we can reduce the pcode timeout to a debug and squelch a sporadic error message during suspend. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97465 Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160824101607.13671-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fc953739af69..16a6e1896286 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10022,7 +10022,7 @@ static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val) mutex_lock(&dev_priv->rps.hw_lock); if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val)) - DRM_ERROR("Failed to write to D_COMP\n"); + DRM_DEBUG_KMS("Failed to write to D_COMP\n"); mutex_unlock(&dev_priv->rps.hw_lock); } else { I915_WRITE(D_COMP_BDW, val); -- cgit v1.2.1 From abc80abde5bd5962a4ec4e126ab7867c0b5fd195 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 24 Aug 2016 10:27:01 +0100 Subject: drm/i915: Force RC6 restore after system resume and reset In order for the RC6 autoenable worker to take any action, RC6 first must be disabled. Upon resume or reset, the sw state may be stale and so we require a forced restore. Fixes: b7137e0cf1e5 ("drm/i915: Defer enabling rc6 til after we submit...") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Sagar Arun Kamble Link: http://patchwork.freedesktop.org/patch/msgid/20160824092701.19178-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5a7c0c2e57d8..fc9273215286 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1560,6 +1560,7 @@ static int i915_drm_resume(struct drm_device *dev) int ret; disable_rpm_wakeref_asserts(dev_priv); + intel_sanitize_gt_powersave(dev_priv); ret = i915_ggtt_enable_hw(dev_priv); if (ret) @@ -1809,6 +1810,7 @@ int i915_reset(struct drm_i915_private *dev_priv) * previous concerns that it doesn't respond well to some forms * of re-init after reset. */ + intel_sanitize_gt_powersave(dev_priv); intel_autoenable_gt_powersave(dev_priv); return 0; -- cgit v1.2.1 From bc5ca47c0af4f949ba889e666b7da65569e36093 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 25 Aug 2016 08:23:14 +0100 Subject: drm/i915: Restore lost "Initialized i915" welcome message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A side effect of removing the midlayer from driver loading was the loss of a useful message announcing to userspace that i915 had successfully started, e.g.: [drm] Initialized i915 1.6.0 20160425 for 0000:00:02.0 on minor 0 Reported-by: Timo Aaltonen Signed-off-by: Chris Wilson Fixes: 8f460e2c78f2 ("drm/i915: Demidlayer driver loading") Cc: Daniel Vetter Cc: Ville Syrjälä Cc: drm-intel-fixes@lists.freedesktop.org Link: http://patchwork.freedesktop.org/patch/msgid/20160825072314.17402-1-chris@chris-wilson.co.uk Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index fc9273215286..1d2230f7b749 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1255,6 +1255,11 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) intel_runtime_pm_enable(dev_priv); + /* Everything is in place, we can now relax! */ + DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", + driver.name, driver.major, driver.minor, driver.patchlevel, + driver.date, pci_name(pdev), dev_priv->drm.primary->index); + intel_runtime_pm_put(dev_priv); return 0; -- cgit v1.2.1 From 896e5bb022bce64e29ce2e1b2fc2a7476d311a15 Mon Sep 17 00:00:00 2001 From: Lyude Date: Wed, 24 Aug 2016 07:48:09 +0200 Subject: drm/i915: Move CRTC updating in atomic_commit into it's own hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we have to write ddb allocations at the same time as we do other plane updates, we're going to need to be able to control the order in which we execute modesets on each pipe. The easiest way to do this is to just factor this section of intel_atomic_commit_tail() (intel_atomic_commit() for stable branches) into it's own function, and add an appropriate display function hook for it. Based off of Matt Rope's suggestions Changes since v1: - Drop pipe_config->base.active check in intel_update_crtcs() since we check that before calling the function Signed-off-by: Lyude Reviewed-by: Matt Roper [omitting CC for stable, since this patch will need to be changed for such backports first] Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Radhakrishna Sripada Cc: Hans de Goede Signed-off-by: Lyude Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471961565-28540-1-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/intel_display.c | 74 +++++++++++++++++++++++++----------- 2 files changed, 54 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ff96b7a69e6c..04b4fd6c32e4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -514,6 +514,8 @@ struct drm_i915_display_funcs { struct drm_atomic_state *old_state); void (*crtc_disable)(struct intel_crtc_state *old_crtc_state, struct drm_atomic_state *old_state); + void (*update_crtcs)(struct drm_atomic_state *state, + unsigned int *crtc_vblank_mask); void (*audio_codec_enable)(struct drm_connector *connector, struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 16a6e1896286..30372f9fcf66 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14173,6 +14173,52 @@ static bool needs_vblank_wait(struct intel_crtc_state *crtc_state) return false; } +static void intel_update_crtc(struct drm_crtc *crtc, + struct drm_atomic_state *state, + struct drm_crtc_state *old_crtc_state, + unsigned int *crtc_vblank_mask) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->state); + bool modeset = needs_modeset(crtc->state); + + if (modeset) { + update_scanline_offset(intel_crtc); + dev_priv->display.crtc_enable(pipe_config, state); + } else { + intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); + } + + if (drm_atomic_get_existing_plane_state(state, crtc->primary)) { + intel_fbc_enable( + intel_crtc, pipe_config, + to_intel_plane_state(crtc->primary->state)); + } + + drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); + + if (needs_vblank_wait(pipe_config)) + *crtc_vblank_mask |= drm_crtc_mask(crtc); +} + +static void intel_update_crtcs(struct drm_atomic_state *state, + unsigned int *crtc_vblank_mask) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + int i; + + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + if (!crtc->state->active) + continue; + + intel_update_crtc(crtc, state, old_crtc_state, + crtc_vblank_mask); + } +} + static void intel_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; @@ -14271,17 +14317,9 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) intel_modeset_verify_disabled(dev); } - /* Now enable the clocks, plane, pipe, and connectors that we set up. */ + /* Complete the events for pipes that have now been disabled */ for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); bool modeset = needs_modeset(crtc->state); - struct intel_crtc_state *pipe_config = - to_intel_crtc_state(crtc->state); - - if (modeset && crtc->state->active) { - update_scanline_offset(to_intel_crtc(crtc)); - dev_priv->display.crtc_enable(pipe_config, state); - } /* Complete events for now disable pipes here. */ if (modeset && !crtc->state->active && crtc->state->event) { @@ -14291,21 +14329,11 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) crtc->state->event = NULL; } - - if (!modeset) - intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); - - if (crtc->state->active && - drm_atomic_get_existing_plane_state(state, crtc->primary)) - intel_fbc_enable(intel_crtc, pipe_config, to_intel_plane_state(crtc->primary->state)); - - if (crtc->state->active) - drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); - - if (pipe_config->base.active && needs_vblank_wait(pipe_config)) - crtc_vblank_mask |= 1 << i; } + /* Now enable the clocks, plane, pipe, and connectors that we set up. */ + dev_priv->display.update_crtcs(state, &crtc_vblank_mask); + /* FIXME: We should call drm_atomic_helper_commit_hw_done() here * already, but still need the state for the delayed optimization. To * fix this: @@ -15823,6 +15851,8 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) dev_priv->display.crtc_disable = i9xx_crtc_disable; } + dev_priv->display.update_crtcs = intel_update_crtcs; + /* Returns the core display clock speed */ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) dev_priv->display.get_display_clock_speed = -- cgit v1.2.1 From 27082493e9c6371b05370a619ab9d2877c5f4726 Mon Sep 17 00:00:00 2001 From: Lyude Date: Wed, 24 Aug 2016 07:48:10 +0200 Subject: drm/i915/skl: Update DDB values atomically with wms/plane attrs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we can hook into update_crtcs and control the order in which we update CRTCs at each modeset, we can finish the final step of fixing Skylake's watermark handling by performing DDB updates at the same time as plane updates and watermark updates. The first major change in this patch is skl_update_crtcs(), which handles ensuring that we order each CRTC update in our atomic commits properly so that they honor the DDB flush order. The second major change in this patch is the order in which we flush the pipes. While the previous order may have worked, it can't be used in this approach since it no longer will do the right thing. For example, using the old ddb flush order: We have pipes A, B, and C enabled, and we're disabling C. Initial ddb allocation looks like this: | A | B |xxxxxxx| Since we're performing the ddb updates after performing any CRTC disablements in intel_atomic_commit_tail(), the space to the right of pipe B is unallocated. 1. Flush pipes with new allocation contained into old space. None apply, so we skip this 2. Flush pipes having their allocation reduced, but overlapping with a previous allocation. None apply, so we also skip this 3. Flush pipes that got more space allocated. This applies to A and B, giving us the following update order: A, B This is wrong, since updating pipe A first will cause it to overlap with B and potentially burst into flames. Our new order (see the code comments for details) would update the pipes in the proper order: B, A. As well, we calculate the order for each DDB update during the check phase, and reference it later in the commit phase when we hit skl_update_crtcs(). This long overdue patch fixes the rest of the underruns on Skylake. Changes since v1: - Add skl_ddb_entry_write() for cursor into skl_write_cursor_wm() Changes since v2: - Use the method for updating CRTCs that Ville suggested - In skl_update_wm(), only copy the watermarks for the crtc that was passed to us Changes since v3: - Small comment fix in skl_ddb_allocation_overlaps() Changes since v4: - Remove the second loop in intel_update_crtcs() and use Ville's suggestion for updating the ddb allocations in the right order - Get rid of the second loop and just use the ddb state as it updates to determine what order to update everything in (thanks for the suggestion Ville) - Simplify skl_ddb_allocation_overlaps() - Split actual overlap checking into it's own helper Fixes: 0e8fb7ba7ca5 ("drm/i915/skl: Flush the WM configuration") Fixes: 8211bd5bdf5e ("drm/i915/skl: Program the DDB allocation") [omitting CC for stable, since this patch will need to be changed for such backports first] Testcase: kms_cursor_legacy Testcase: plane-all-modeset-transition Signed-off-by: Lyude Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Radhakrishna Sripada Cc: Hans de Goede Cc: Matt Roper Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1471961565-28540-2-git-send-email-cpaul@redhat.com --- drivers/gpu/drm/i915/intel_display.c | 93 +++++++++++++--- drivers/gpu/drm/i915/intel_drv.h | 7 ++ drivers/gpu/drm/i915/intel_pm.c | 200 ++++++++--------------------------- 3 files changed, 132 insertions(+), 168 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 30372f9fcf66..a388ed547f73 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13458,16 +13458,23 @@ static void verify_wm_state(struct drm_crtc *crtc, hw_entry->start, hw_entry->end); } - /* cursor */ - hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR]; - sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR]; - - if (!skl_ddb_entry_equal(hw_entry, sw_entry)) { - DRM_ERROR("mismatch in DDB state pipe %c cursor " - "(expected (%u,%u), found (%u,%u))\n", - pipe_name(pipe), - sw_entry->start, sw_entry->end, - hw_entry->start, hw_entry->end); + /* + * cursor + * If the cursor plane isn't active, we may not have updated it's ddb + * allocation. In that case since the ddb allocation will be updated + * once the plane becomes visible, we can skip this check + */ + if (intel_crtc->cursor_addr) { + hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR]; + sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR]; + + if (!skl_ddb_entry_equal(hw_entry, sw_entry)) { + DRM_ERROR("mismatch in DDB state pipe %c cursor " + "(expected (%u,%u), found (%u,%u))\n", + pipe_name(pipe), + sw_entry->start, sw_entry->end, + hw_entry->start, hw_entry->end); + } } } @@ -14219,6 +14226,65 @@ static void intel_update_crtcs(struct drm_atomic_state *state, } } +static void skl_update_crtcs(struct drm_atomic_state *state, + unsigned int *crtc_vblank_mask) +{ + struct drm_device *dev = state->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; + struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; + unsigned int updated = 0; + bool progress; + enum pipe pipe; + + /* + * Whenever the number of active pipes changes, we need to make sure we + * update the pipes in the right order so that their ddb allocations + * never overlap with eachother inbetween CRTC updates. Otherwise we'll + * cause pipe underruns and other bad stuff. + */ + do { + int i; + progress = false; + + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + bool vbl_wait = false; + unsigned int cmask = drm_crtc_mask(crtc); + pipe = to_intel_crtc(crtc)->pipe; + + if (updated & cmask || !crtc->state->active) + continue; + if (skl_ddb_allocation_overlaps(state, cur_ddb, new_ddb, + pipe)) + continue; + + updated |= cmask; + + /* + * 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_allocation_equals(cur_ddb, new_ddb, pipe) && + !crtc->state->active_changed && + intel_state->wm_results.dirty_pipes != updated) + vbl_wait = true; + + intel_update_crtc(crtc, state, old_crtc_state, + crtc_vblank_mask); + + if (vbl_wait) + intel_wait_for_vblank(dev, pipe); + + progress = true; + } + } while (progress); +} + static void intel_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; @@ -15851,8 +15917,6 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) dev_priv->display.crtc_disable = i9xx_crtc_disable; } - dev_priv->display.update_crtcs = intel_update_crtcs; - /* Returns the core display clock speed */ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) dev_priv->display.get_display_clock_speed = @@ -15942,6 +16006,11 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) skl_modeset_calc_cdclk; } + if (dev_priv->info.gen >= 9) + dev_priv->display.update_crtcs = skl_update_crtcs; + else + dev_priv->display.update_crtcs = intel_update_crtcs; + switch (INTEL_INFO(dev_priv)->gen) { case 2: dev_priv->display.queue_flip = intel_gen2_queue_flip; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f241a47b6e3a..debbc1b5b0f9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1745,6 +1745,13 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, bool skl_can_enable_sagv(struct drm_atomic_state *state); int skl_enable_sagv(struct drm_i915_private *dev_priv); int skl_disable_sagv(struct drm_i915_private *dev_priv); +bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, + const struct skl_ddb_allocation *new, + enum pipe pipe); +bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, + const struct skl_ddb_allocation *old, + const struct skl_ddb_allocation *new, + enum pipe pipe); void skl_write_cursor_wm(struct intel_crtc *intel_crtc, const struct skl_wm_values *wm); void skl_write_plane_wm(struct intel_crtc *intel_crtc, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2f4438d4af55..729d952174d8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3851,6 +3851,11 @@ void skl_write_plane_wm(struct intel_crtc *intel_crtc, wm->plane[pipe][plane][level]); } I915_WRITE(PLANE_WM_TRANS(pipe, plane), wm->plane_trans[pipe][plane]); + + skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane), + &wm->ddb.plane[pipe][plane]); + skl_ddb_entry_write(dev_priv, PLANE_NV12_BUF_CFG(pipe, plane), + &wm->ddb.y_plane[pipe][plane]); } void skl_write_cursor_wm(struct intel_crtc *intel_crtc, @@ -3867,170 +3872,46 @@ void skl_write_cursor_wm(struct intel_crtc *intel_crtc, wm->plane[pipe][PLANE_CURSOR][level]); } I915_WRITE(CUR_WM_TRANS(pipe), wm->plane_trans[pipe][PLANE_CURSOR]); -} - -static void skl_write_wm_values(struct drm_i915_private *dev_priv, - const struct skl_wm_values *new) -{ - struct drm_device *dev = &dev_priv->drm; - struct intel_crtc *crtc; - - for_each_intel_crtc(dev, crtc) { - int i; - enum pipe pipe = crtc->pipe; - - if ((new->dirty_pipes & drm_crtc_mask(&crtc->base)) == 0) - continue; - if (!crtc->active) - continue; - - for (i = 0; i < intel_num_planes(crtc); i++) { - skl_ddb_entry_write(dev_priv, - PLANE_BUF_CFG(pipe, i), - &new->ddb.plane[pipe][i]); - skl_ddb_entry_write(dev_priv, - PLANE_NV12_BUF_CFG(pipe, i), - &new->ddb.y_plane[pipe][i]); - } - skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe), - &new->ddb.plane[pipe][PLANE_CURSOR]); - } + skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe), + &wm->ddb.plane[pipe][PLANE_CURSOR]); } -/* - * When setting up a new DDB allocation arrangement, we need to correctly - * sequence the times at which the new allocations for the pipes are taken into - * account or we'll have pipes fetching from space previously allocated to - * another pipe. - * - * Roughly the sequence looks like: - * 1. re-allocate the pipe(s) with the allocation being reduced and not - * overlapping with a previous light-up pipe (another way to put it is: - * pipes with their new allocation strickly included into their old ones). - * 2. re-allocate the other pipes that get their allocation reduced - * 3. allocate the pipes having their allocation increased - * - * Steps 1. and 2. are here to take care of the following case: - * - Initially DDB looks like this: - * | B | C | - * - enable pipe A. - * - pipe B has a reduced DDB allocation that overlaps with the old pipe C - * allocation - * | A | B | C | - * - * We need to sequence the re-allocation: C, B, A (and not B, C, A). - */ - -static void -skl_wm_flush_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, int pass) +bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, + const struct skl_ddb_allocation *new, + enum pipe pipe) { - int plane; - - DRM_DEBUG_KMS("flush pipe %c (pass %d)\n", pipe_name(pipe), pass); - - for_each_plane(dev_priv, pipe, plane) { - I915_WRITE(PLANE_SURF(pipe, plane), - I915_READ(PLANE_SURF(pipe, plane))); - } - I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe))); + return new->pipe[pipe].start == old->pipe[pipe].start && + new->pipe[pipe].end == old->pipe[pipe].end; } -static bool -skl_ddb_allocation_included(const struct skl_ddb_allocation *old, - const struct skl_ddb_allocation *new, - enum pipe pipe) +static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, + const struct skl_ddb_entry *b) { - uint16_t old_size, new_size; - - old_size = skl_ddb_entry_size(&old->pipe[pipe]); - new_size = skl_ddb_entry_size(&new->pipe[pipe]); - - return old_size != new_size && - new->pipe[pipe].start >= old->pipe[pipe].start && - new->pipe[pipe].end <= old->pipe[pipe].end; + return a->start < b->end && b->start < a->end; } -static void skl_flush_wm_values(struct drm_i915_private *dev_priv, - struct skl_wm_values *new_values) +bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, + const struct skl_ddb_allocation *old, + const struct skl_ddb_allocation *new, + enum pipe pipe) { - struct drm_device *dev = &dev_priv->drm; - struct skl_ddb_allocation *cur_ddb, *new_ddb; - bool reallocated[I915_MAX_PIPES] = {}; - struct intel_crtc *crtc; - enum pipe pipe; - - new_ddb = &new_values->ddb; - cur_ddb = &dev_priv->wm.skl_hw.ddb; - - /* - * First pass: flush the pipes with the new allocation contained into - * the old space. - * - * We'll wait for the vblank on those pipes to ensure we can safely - * re-allocate the freed space without this pipe fetching from it. - */ - for_each_intel_crtc(dev, crtc) { - if (!crtc->active) - continue; - - pipe = crtc->pipe; - - if (!skl_ddb_allocation_included(cur_ddb, new_ddb, pipe)) - continue; - - skl_wm_flush_pipe(dev_priv, pipe, 1); - intel_wait_for_vblank(dev, pipe); - - reallocated[pipe] = true; - } - - - /* - * Second pass: flush the pipes that are having their allocation - * reduced, but overlapping with a previous allocation. - * - * Here as well we need to wait for the vblank to make sure the freed - * space is not used anymore. - */ - for_each_intel_crtc(dev, crtc) { - if (!crtc->active) - continue; + struct drm_device *dev = state->dev; + struct intel_crtc *intel_crtc; + enum pipe otherp; - pipe = crtc->pipe; + for_each_intel_crtc(dev, intel_crtc) { + otherp = intel_crtc->pipe; - if (reallocated[pipe]) + if (otherp == pipe) continue; - if (skl_ddb_entry_size(&new_ddb->pipe[pipe]) < - skl_ddb_entry_size(&cur_ddb->pipe[pipe])) { - skl_wm_flush_pipe(dev_priv, pipe, 2); - intel_wait_for_vblank(dev, pipe); - reallocated[pipe] = true; - } + if (skl_ddb_entries_overlap(&new->pipe[pipe], + &old->pipe[otherp])) + return true; } - /* - * Third pass: flush the pipes that got more space allocated. - * - * We don't need to actively wait for the update here, next vblank - * will just get more DDB space with the correct WM values. - */ - for_each_intel_crtc(dev, crtc) { - if (!crtc->active) - continue; - - pipe = crtc->pipe; - - /* - * At this point, only the pipes more space than before are - * left to re-allocate. - */ - if (reallocated[pipe]) - continue; - - skl_wm_flush_pipe(dev_priv, pipe, 3); - } + return false; } static int skl_update_pipe_wm(struct drm_crtc_state *cstate, @@ -4232,7 +4113,7 @@ static void skl_update_wm(struct drm_crtc *crtc) struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw; struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal; - int pipe; + enum pipe pipe = intel_crtc->pipe; if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0) return; @@ -4241,15 +4122,22 @@ static void skl_update_wm(struct drm_crtc *crtc) mutex_lock(&dev_priv->wm.wm_mutex); - skl_write_wm_values(dev_priv, results); - skl_flush_wm_values(dev_priv, results); - /* - * Store the new configuration (but only for the pipes that have - * changed; the other values weren't recomputed). + * If this pipe isn't active already, we're going to be enabling it + * very soon. Since it's safe to update a pipe's ddb allocation while + * the pipe's shut off, just do so here. Already active pipes will have + * their watermarks updated once we update their planes. */ - for_each_pipe_masked(dev_priv, pipe, results->dirty_pipes) - skl_copy_wm_for_pipe(hw_vals, results, pipe); + if (crtc->state->active_changed) { + int plane; + + for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) + skl_write_plane_wm(intel_crtc, results, plane); + + skl_write_cursor_wm(intel_crtc, results); + } + + skl_copy_wm_for_pipe(hw_vals, results, pipe); mutex_unlock(&dev_priv->wm.wm_mutex); } -- cgit v1.2.1 From 4cc6907501ed2393a70ad92a30e00dc54c536e50 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 25 Aug 2016 19:05:19 +0100 Subject: drm/i915: Add I915_PARAM_MMAP_GTT_VERSION to advertise unlimited mmaps Now that we have working partial VMA and faulting support for all objects, including fence support, advertise to userspace that it can take advantage of unlimited GGTT mmaps. v2: Make room in the kerneldoc for a more detailed explanation of the limitations of the GTT mmap interface. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Joonas Lahtinen Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20160825180519.11341-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 7 ++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 53 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1d2230f7b749..47fe07283d88 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -355,6 +355,13 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_MIN_EU_IN_POOL: value = INTEL_INFO(dev)->min_eu_in_pool; break; + case I915_PARAM_MMAP_GTT_VERSION: + /* Though we've started our numbering from 1, and so class all + * earlier versions as 0, in effect their value is undefined as + * the ioctl will report EINVAL for the unknown param! + */ + value = i915_gem_mmap_gtt_version(); + break; default: DRM_DEBUG("Unknown parameter %d\n", param->param); return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 04b4fd6c32e4..9fdaf23336df 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3218,6 +3218,7 @@ int i915_gem_dumb_create(struct drm_file *file_priv, struct drm_mode_create_dumb *args); int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev, uint32_t handle, uint64_t *offset); +int i915_gem_mmap_gtt_version(void); void i915_gem_track_fb(struct drm_i915_gem_object *old, struct drm_i915_gem_object *new, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 04607d4115d6..d37b44126942 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1679,6 +1679,56 @@ static unsigned int tile_row_pages(struct drm_i915_gem_object *obj) return size >> PAGE_SHIFT; } +/** + * i915_gem_mmap_gtt_version - report the current feature set for GTT mmaps + * + * A history of the GTT mmap interface: + * + * 0 - Everything had to fit into the GTT. Both parties of a memcpy had to + * aligned and suitable for fencing, and still fit into the available + * mappable space left by the pinned display objects. A classic problem + * we called the page-fault-of-doom where we would ping-pong between + * two objects that could not fit inside the GTT and so the memcpy + * would page one object in at the expense of the other between every + * single byte. + * + * 1 - Objects can be any size, and have any compatible fencing (X Y, or none + * as set via i915_gem_set_tiling() [DRM_I915_GEM_SET_TILING]). If the + * object is too large for the available space (or simply too large + * for the mappable aperture!), a view is created instead and faulted + * into userspace. (This view is aligned and sized appropriately for + * fenced access.) + * + * Restrictions: + * + * * snoopable objects cannot be accessed via the GTT. It can cause machine + * hangs on some architectures, corruption on others. An attempt to service + * a GTT page fault from a snoopable object will generate a SIGBUS. + * + * * the object must be able to fit into RAM (physical memory, though no + * limited to the mappable aperture). + * + * + * Caveats: + * + * * a new GTT page fault will synchronize rendering from the GPU and flush + * all data to system memory. Subsequent access will not be synchronized. + * + * * all mappings are revoked on runtime device suspend. + * + * * there are only 8, 16 or 32 fence registers to share between all users + * (older machines require fence register for display and blitter access + * as well). Contention of the fence registers will cause the previous users + * to be unmapped and any new access will generate new page faults. + * + * * running out of memory while servicing a fault may generate a SIGBUS, + * rather than the expected SIGSEGV. + */ +int i915_gem_mmap_gtt_version(void) +{ + return 1; +} + /** * i915_gem_fault - fault a page into the GTT * @area: CPU VMA in question @@ -1694,6 +1744,9 @@ static unsigned int tile_row_pages(struct drm_i915_gem_object *obj) * 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). */ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf) { -- cgit v1.2.1 From ecbd6781b27799cccd6ba647868d1b5341c9523d Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Tue, 23 Aug 2016 12:23:56 +0300 Subject: drm/i915/debugfs: Add panel delays for eDP The eDP backlight and panel enable/disable delays are quite useful to know when measuring time consumed by suspend/resume, and while the information is printed to the kernel log as debug messages, having this information in debugfs makes things easier. Signed-off-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20160823092356.7610-1-david.weinehall@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_debugfs.c | 42 +++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0f6116fd91d8..25af80e9d62e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -5465,6 +5465,40 @@ static const struct file_operations i915_dpcd_fops = { .release = single_release, }; +static int i915_panel_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct intel_dp *intel_dp = + enc_to_intel_dp(&intel_attached_encoder(connector)->base); + + if (connector->status != connector_status_connected) + return -ENODEV; + + seq_printf(m, "Panel power up delay: %d\n", + intel_dp->panel_power_up_delay); + seq_printf(m, "Panel power down delay: %d\n", + intel_dp->panel_power_down_delay); + seq_printf(m, "Backlight on delay: %d\n", + intel_dp->backlight_on_delay); + seq_printf(m, "Backlight off delay: %d\n", + intel_dp->backlight_off_delay); + + return 0; +} + +static int i915_panel_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_panel_show, inode->i_private); +} + +static const struct file_operations i915_panel_fops = { + .owner = THIS_MODULE, + .open = i915_panel_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /** * i915_debugfs_connector_add - add i915 specific connector debugfs files * @connector: pointer to a registered drm_connector @@ -5484,8 +5518,12 @@ int i915_debugfs_connector_add(struct drm_connector *connector) if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector->connector_type == DRM_MODE_CONNECTOR_eDP) - debugfs_create_file("i915_dpcd", S_IRUGO, root, connector, - &i915_dpcd_fops); + debugfs_create_file("i915_dpcd", S_IRUGO, root, + connector, &i915_dpcd_fops); + + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) + debugfs_create_file("i915_panel_timings", S_IRUGO, root, + connector, &i915_panel_fops); return 0; } -- cgit v1.2.1 From 7850d1c35344c7bd6a357240f2f9f60fc2c097b5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 26 Aug 2016 11:59:26 +0100 Subject: drm/i915: Add GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE to SNB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the CI test machines, SNB also uses the GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE value to report a bad GEN6_PCODE_MIN_FREQ_TABLE request. [ 157.744641] WARNING: CPU: 5 PID: 9238 at drivers/gpu/drm/i915/intel_pm.c:7760 sandybridge_pcode_write+0x141/0x200 [i915] [ 157.744642] Missing switch case (16) in gen6_check_mailbox_status [ 157.744642] Modules linked in: snd_hda_intel i915 ax88179_178a usbnet mii x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic snd_hda_codec snd_hwdep snd_hda_core mei_me lpc_ich snd_pcm mei broadcom bcm_phy_lib tg3 ptp pps_core [last unloaded: vgem] [ 157.744658] CPU: 5 PID: 9238 Comm: drv_hangman Tainted: G U W 4.8.0-rc3-CI-CI_DRM_1589+ #1 [ 157.744658] Hardware name: Dell Inc. XPS 8300 /0Y2MRG, BIOS A06 10/17/2011 [ 157.744659] 0000000000000000 ffff88011f093a98 ffffffff81426415 ffff88011f093ae8 [ 157.744662] 0000000000000000 ffff88011f093ad8 ffffffff8107d2a6 00001e50810d3c9f [ 157.744663] ffff880128680000 0000000000000008 0000000000000000 ffff88012868a650 [ 157.744665] Call Trace: [ 157.744669] [] dump_stack+0x67/0x92 [ 157.744672] [] __warn+0xc6/0xe0 [ 157.744673] [] warn_slowpath_fmt+0x4a/0x50 [ 157.744685] [] sandybridge_pcode_write+0x141/0x200 [i915] [ 157.744697] [] intel_enable_gt_powersave+0x64a/0x1330 [i915] [ 157.744712] [] ? i9xx_emit_request+0x1b/0x80 [i915] [ 157.744725] [] __i915_add_request+0x1e3/0x370 [i915] [ 157.744738] [] i915_gem_do_execbuffer.isra.16+0xced/0x1b80 [i915] [ 157.744740] [] ? __might_fault+0x3e/0x90 [ 157.744752] [] i915_gem_execbuffer2+0xc2/0x2a0 [i915] [ 157.744753] [] drm_ioctl+0x207/0x4c0 [ 157.744765] [] ? i915_gem_execbuffer+0x360/0x360 [i915] [ 157.744767] [] ? debug_lockdep_rcu_enabled+0x1d/0x20 [ 157.744769] [] do_vfs_ioctl+0x8e/0x680 [ 157.744770] [] ? __might_fault+0x87/0x90 [ 157.744771] [] ? __might_fault+0x3e/0x90 [ 157.744773] [] ? trace_hardirqs_on_caller+0x122/0x1b0 [ 157.744774] [] SyS_ioctl+0x3c/0x70 [ 157.744776] [] entry_SYSCALL_64_fastpath+0x1c/0xac Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97491 Fixes: 87660502f1a4 ("drm/i915/gen6+: Interpret mailbox error flags") Signed-off-by: Chris Wilson Cc: Lyude Cc: Matt Roper Cc: Maarten Lankhorst Cc: Daniel Vetter Cc: Ville Syrjälä Cc: stable@vger.kernel.org Link: http://patchwork.freedesktop.org/patch/msgid/20160826105926.3413-1-chris@chris-wilson.co.uk Acked-by: Mika Kuoppala --- drivers/gpu/drm/i915/intel_pm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 729d952174d8..aba6fd036c4e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7753,6 +7753,7 @@ static inline int gen6_check_mailbox_status(struct drm_i915_private *dev_priv) case GEN6_PCODE_ILLEGAL_CMD: return -ENXIO; case GEN6_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE: + case GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE: return -EOVERFLOW; case GEN6_PCODE_TIMEOUT: return -ETIMEDOUT; -- cgit v1.2.1 From f7978a0c581a8a840a28306f8da43e06e7fef3bf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 22 Aug 2016 09:03:36 +0100 Subject: drm/i915: Allow the user to pass a context to any ring With full-ppgtt, we want the user to have full control over their memory layout, with a separate instance per context. Forcing them to use a shared memory layout for !RCS not only duplicates the amount of work we have to do, but also defeats the memory segregation on offer. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160822080350.4964-4-chris@chris-wilson.co.uk Reviewed-by: John Harrison Reviewed-by: Thomas Daniel Acked-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 601156c353cc..57d096aef548 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1253,12 +1253,9 @@ static struct i915_gem_context * i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, struct intel_engine_cs *engine, const u32 ctx_id) { - struct i915_gem_context *ctx = NULL; + struct i915_gem_context *ctx; struct i915_ctx_hang_stats *hs; - if (engine->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE) - return ERR_PTR(-EINVAL); - ctx = i915_gem_context_lookup(file->driver_priv, ctx_id); if (IS_ERR(ctx)) return ctx; -- cgit v1.2.1 From f6407193dd9d9e29fc94b7f6943c517cbee314bb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 27 Aug 2016 08:54:00 +0100 Subject: drm/i915: Tidy reporting busy status during i915_gem_retire_requests() As we know by inspection whether any engine is still busy as we retire all the requests, we can pass that information back via return value rather than check again afterwards. v2: A little more polish missed in patch splitting Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160827075401.16470-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 1a215320cefb..5e55270bb2de 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -749,16 +749,18 @@ complete: return ret; } -static void engine_retire_requests(struct intel_engine_cs *engine) +static bool engine_retire_requests(struct intel_engine_cs *engine) { struct drm_i915_gem_request *request, *next; list_for_each_entry_safe(request, next, &engine->request_list, link) { if (!i915_gem_request_completed(request)) - break; + return false; i915_gem_request_retire(request); } + + return true; } void i915_gem_retire_requests(struct drm_i915_private *dev_priv) @@ -772,11 +774,9 @@ void i915_gem_retire_requests(struct drm_i915_private *dev_priv) GEM_BUG_ON(!dev_priv->gt.awake); - for_each_engine(engine, dev_priv) { - engine_retire_requests(engine); - if (!intel_engine_is_active(engine)) + for_each_engine_masked(engine, dev_priv, dev_priv->gt.active_engines) + if (engine_retire_requests(engine)) dev_priv->gt.active_engines &= ~intel_engine_flag(engine); - } if (dev_priv->gt.active_engines == 0) queue_delayed_work(dev_priv->wq, -- cgit v1.2.1 From bafb0fced98c7c135389b455faab380beac47ccc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 27 Aug 2016 08:54:01 +0100 Subject: drm/i915: Make for_each_engine_masked() more compact and quicker Rather than walk the full array of engines checking whether each is in the mask in turn, we can use the mask to jump to the right engines. This should quicker for a sparse array of engines or mask, whilst generating smaller code: text data bss dec hex filename 1251010 4579 800 1256389 132bc5 drivers/gpu/drm/i915/i915.ko 1250530 4579 800 1255909 1329e5 drivers/gpu/drm/i915/i915.ko The downside is that we have to pass in a temporary, alas no C99 iterators yet. [P.S. Joonas doesn't like having to pass extra temporaries into the macro, and even less that I called them tmp. As yet, we haven't found a macro that avoids passing in a temporary that is smaller. We probably will get C99 iterators first!] Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160827075401.16470-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 15 +++++++++------ drivers/gpu/drm/i915/i915_gem_request.c | 3 ++- drivers/gpu/drm/i915/i915_guc_submission.c | 3 ++- drivers/gpu/drm/i915/i915_irq.c | 3 ++- drivers/gpu/drm/i915/intel_uncore.c | 9 ++++++--- 5 files changed, 21 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9fdaf23336df..77a5478043e7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2093,13 +2093,16 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) for_each_if (((id__) = (engine__)->id, \ intel_engine_initialized(engine__))) +#define __mask_next_bit(mask) ({ \ + int __idx = ffs(mask) - 1; \ + mask &= ~BIT(__idx); \ + __idx; \ +}) + /* Iterator over subset of engines selected by mask */ -#define for_each_engine_masked(engine__, dev_priv__, mask__) \ - for ((engine__) = &(dev_priv__)->engine[0]; \ - (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \ - (engine__)++) \ - for_each_if (((mask__) & intel_engine_flag(engine__)) && \ - intel_engine_initialized(engine__)) +#define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ + for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \ + tmp__ ? (engine__ = &(dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; ) enum hdmi_force_audio { HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 5e55270bb2de..9cc08a1e43c6 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -766,6 +766,7 @@ static bool engine_retire_requests(struct intel_engine_cs *engine) void i915_gem_retire_requests(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; + unsigned int tmp; lockdep_assert_held(&dev_priv->drm.struct_mutex); @@ -774,7 +775,7 @@ void i915_gem_retire_requests(struct drm_i915_private *dev_priv) GEM_BUG_ON(!dev_priv->gt.awake); - for_each_engine_masked(engine, dev_priv, dev_priv->gt.active_engines) + for_each_engine_masked(engine, dev_priv, dev_priv->gt.active_engines, tmp) if (engine_retire_requests(engine)) dev_priv->gt.active_engines &= ~intel_engine_flag(engine); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index e4369411f07d..32699a744aca 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -330,6 +330,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, struct i915_gem_context *ctx = client->owner; struct guc_context_desc desc; struct sg_table *sg; + unsigned int tmp; u32 gfx_addr; memset(&desc, 0, sizeof(desc)); @@ -339,7 +340,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, desc.priority = client->priority; desc.db_id = client->doorbell_id; - for_each_engine_masked(engine, dev_priv, client->engines) { + for_each_engine_masked(engine, dev_priv, client->engines, tmp) { struct intel_context *ce = &ctx->engine[engine->id]; uint32_t guc_engine_id = engine->guc_id; struct guc_execlist_context *lrc = &desc.lrc[guc_engine_id]; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7610eca4f687..82358d4e0cc2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3169,6 +3169,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) if (hung) { char msg[80]; + unsigned int tmp; int len; /* If some rings hung but others were still busy, only @@ -3178,7 +3179,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) hung &= ~stuck; len = scnprintf(msg, sizeof(msg), "%s on ", stuck == hung ? "No progress" : "Hang"); - for_each_engine_masked(engine, dev_priv, hung) + for_each_engine_masked(engine, dev_priv, hung, tmp) len += scnprintf(msg + len, sizeof(msg) - len, "%s, ", engine->name); msg[len-2] = '\0'; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 43f833901b8e..e9f68cd56e32 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1597,8 +1597,10 @@ static int gen6_reset_engines(struct drm_i915_private *dev_priv, if (engine_mask == ALL_ENGINES) { hw_mask = GEN6_GRDOM_FULL; } else { + unsigned int tmp; + hw_mask = 0; - for_each_engine_masked(engine, dev_priv, engine_mask) + for_each_engine_masked(engine, dev_priv, engine_mask, tmp) hw_mask |= hw_engine_mask[engine->id]; } @@ -1714,15 +1716,16 @@ static int gen8_reset_engines(struct drm_i915_private *dev_priv, unsigned engine_mask) { struct intel_engine_cs *engine; + unsigned int tmp; - for_each_engine_masked(engine, dev_priv, engine_mask) + for_each_engine_masked(engine, dev_priv, engine_mask, tmp) if (gen8_request_engine_reset(engine)) goto not_ready; return gen6_reset_engines(dev_priv, engine_mask); not_ready: - for_each_engine_masked(engine, dev_priv, engine_mask) + for_each_engine_masked(engine, dev_priv, engine_mask, tmp) gen8_unrequest_engine_reset(engine); return -EIO; -- cgit v1.2.1 From 6720ce18d45987b1a57edb0e36123d1bc9bc85a2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 25 Aug 2016 15:04:11 +0300 Subject: drm/i915: remove leftover for_each_intel_crtc_masked The last user of for_each_intel_crtc_masked macro was removed in commit 0a9ab303b87a94115e361a7f3a15d9f481bc453b Author: Ander Conselvan de Oliveira Date: Tue Apr 21 17:13:04 2015 +0300 drm/i915: Remove all *_pipes flags from modeset Get rid of the unused macro. Cc: Ander Conselvan de Oliveira Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1472126651-13825-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_display.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a388ed547f73..2c05a4c6018f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13122,12 +13122,6 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2) return false; } -#define for_each_intel_crtc_masked(dev, mask, intel_crtc) \ - list_for_each_entry((intel_crtc), \ - &(dev)->mode_config.crtc_list, \ - base.head) \ - for_each_if (mask & (1 <<(intel_crtc)->pipe)) - static bool intel_compare_m_n(unsigned int m, unsigned int n, unsigned int m2, unsigned int n2, @@ -14579,8 +14573,6 @@ out: drm_atomic_state_free(state); } -#undef for_each_intel_crtc_masked - /* * FIXME: Remove this once i915 is fully DRIVER_ATOMIC by calling * drm_atomic_helper_legacy_gamma_set() directly. -- cgit v1.2.1 From e896402c37c1352095758f58c1e7d53d3269baa6 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 25 Aug 2016 11:07:02 +0200 Subject: drm/i915: Add missing parameter to intel_dp_set_drrs_state documentation. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1472116022-17598-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_dp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a3c7dd8fd406..df0773afb7f5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5049,6 +5049,7 @@ static void intel_dp_pps_init(struct drm_device *dev, /** * intel_dp_set_drrs_state - program registers for RR switch to take effect * @dev: DRM device + * @crtc_state: a pointer to the active intel_crtc_state * @refresh_rate: RR to be programmed * * This function gets called when refresh rate (RR) has to be changed from -- cgit v1.2.1 From ce5e2ac1a47ee4a13a05e2400c520f7de9b4becd Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 25 Aug 2016 11:07:01 +0200 Subject: drm/i915: Fix intel_display_crc_init for !DEBUGFS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mentioned commit changes intel_display_crc_init to take a dev_priv, but forgets to change the stub. Cc: David Weinehall Fixes: 36cdd0138b7f ("drm/i915: debugfs spring cleaning") Signed-off-by: Maarten Lankhorst Reported-and-by: Kim Lidström Link: http://patchwork.freedesktop.org/patch/msgid/1472116022-17598-1-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Chris Wilson Reviewed-by: David Weinehall --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 77a5478043e7..c413587895cf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3528,7 +3528,7 @@ static inline int i915_debugfs_register(struct drm_i915_private *dev_priv) {retu static inline void i915_debugfs_unregister(struct drm_i915_private *dev_priv) {} static inline int i915_debugfs_connector_add(struct drm_connector *connector) { return 0; } -static inline void intel_display_crc_init(struct drm_device *dev) {} +static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {} #endif /* i915_gpu_error.c */ -- cgit v1.2.1 From 46e69f3982f6ed0f2575ee11649bc77b7a89fd3e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 23 Aug 2016 10:10:05 +0200 Subject: drm/i915/backlight: handle enabled but zero duty cycle at module load Don't consider enabled but zero duty cycle backlight disabled. Clamp level between min and max for sanity. Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1471939811-9817-1-git-send-email-maarten.lankhorst@linux.intel.com Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/intel_panel.c | 40 +++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 96c65d77e886..c10e9b0405e8 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1430,10 +1430,11 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus panel->backlight.min = get_backlight_min_vbt(connector); val = lpt_get_backlight(connector); - panel->backlight.level = intel_panel_compute_brightness(connector, val); + val = intel_panel_compute_brightness(connector, val); + panel->backlight.level = clamp(val, panel->backlight.min, + panel->backlight.max); - panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) && - panel->backlight.level != 0; + panel->backlight.enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE; return 0; } @@ -1459,11 +1460,13 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus panel->backlight.min = get_backlight_min_vbt(connector); val = pch_get_backlight(connector); - panel->backlight.level = intel_panel_compute_brightness(connector, val); + val = intel_panel_compute_brightness(connector, val); + panel->backlight.level = clamp(val, panel->backlight.min, + panel->backlight.max); cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && - (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0; + (pch_ctl1 & BLM_PCH_PWM_ENABLE); return 0; } @@ -1498,9 +1501,11 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu panel->backlight.min = get_backlight_min_vbt(connector); val = i9xx_get_backlight(connector); - panel->backlight.level = intel_panel_compute_brightness(connector, val); + val = intel_panel_compute_brightness(connector, val); + panel->backlight.level = clamp(val, panel->backlight.min, + panel->backlight.max); - panel->backlight.enabled = panel->backlight.level != 0; + panel->backlight.enabled = val != 0; return 0; } @@ -1530,10 +1535,11 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu panel->backlight.min = get_backlight_min_vbt(connector); val = i9xx_get_backlight(connector); - panel->backlight.level = intel_panel_compute_brightness(connector, val); + val = intel_panel_compute_brightness(connector, val); + panel->backlight.level = clamp(val, panel->backlight.min, + panel->backlight.max); - panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && - panel->backlight.level != 0; + panel->backlight.enabled = ctl2 & BLM_PWM_ENABLE; return 0; } @@ -1562,10 +1568,11 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe panel->backlight.min = get_backlight_min_vbt(connector); val = _vlv_get_backlight(dev_priv, pipe); - panel->backlight.level = intel_panel_compute_brightness(connector, val); + val = intel_panel_compute_brightness(connector, val); + panel->backlight.level = clamp(val, panel->backlight.min, + panel->backlight.max); - panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && - panel->backlight.level != 0; + panel->backlight.enabled = ctl2 & BLM_PWM_ENABLE; return 0; } @@ -1607,10 +1614,11 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) return -ENODEV; val = bxt_get_backlight(connector); - panel->backlight.level = intel_panel_compute_brightness(connector, val); + val = intel_panel_compute_brightness(connector, val); + panel->backlight.level = clamp(val, panel->backlight.min, + panel->backlight.max); - panel->backlight.enabled = (pwm_ctl & BXT_BLC_PWM_ENABLE) && - panel->backlight.level != 0; + panel->backlight.enabled = pwm_ctl & BXT_BLC_PWM_ENABLE; return 0; } -- cgit v1.2.1 From 5423adf1d4c692ff300f9f4262e2d5241d4fe561 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 31 Aug 2016 11:01:36 +0200 Subject: drm/i915: Fix other intel_dp warnings too. Signed-off-by: Maarten Lankhorst Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index df0773afb7f5..e4a25668ccf6 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5048,7 +5048,7 @@ static void intel_dp_pps_init(struct drm_device *dev, /** * intel_dp_set_drrs_state - program registers for RR switch to take effect - * @dev: DRM device + * @dev_priv: i915 device * @crtc_state: a pointer to the active intel_crtc_state * @refresh_rate: RR to be programmed * @@ -5152,6 +5152,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, /** * intel_edp_drrs_enable - init drrs struct if supported * @intel_dp: DP struct + * @crtc_state: A pointer to the active crtc state. * * Initializes frontbuffer_bits and drrs.dp */ @@ -5183,6 +5184,7 @@ unlock: /** * intel_edp_drrs_disable - Disable DRRS * @intel_dp: DP struct + * @old_crtc_state: Pointer to old crtc_state. * */ void intel_edp_drrs_disable(struct intel_dp *intel_dp, -- cgit v1.2.1 From 6f633402847635817fd5eddb2d0e0a50cd521c1e Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Thu, 1 Sep 2016 14:58:21 +0300 Subject: drm/i915: Use atomic for dev_priv->mm.bsd_engine_dispatch_index Use atomic type and operands for dev_priv->mm.bsd_engine_dispatch_index to avoid one struct_mutex locking scenario. Cc: Chris Wilson Cc: Imre Deak Cc: Zhao Yakui Cc: Daniel Vetter Signed-off-by: Joonas Lahtinen Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1472731101-21982-1-git-send-email-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 ++ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 10 +++------- 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c413587895cf..43d5298b821f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1338,7 +1338,7 @@ struct i915_gem_mm { bool interruptible; /* the indicator for dispatch video commands on two BSD rings */ - unsigned int bsd_engine_dispatch_index; + atomic_t bsd_engine_dispatch_index; /** Bit 6 swizzling required for X tiling */ uint32_t bit_6_swizzle_x; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d37b44126942..2401818171f5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4622,6 +4622,8 @@ i915_gem_load_init(struct drm_device *dev) dev_priv->mm.interruptible = true; + atomic_set(&dev_priv->mm.bsd_engine_dispatch_index, 0); + spin_lock_init(&dev_priv->fb_tracking.lock); } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 57d096aef548..9432d4ce9ffb 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1535,13 +1535,9 @@ gen8_dispatch_bsd_engine(struct drm_i915_private *dev_priv, struct drm_i915_file_private *file_priv = file->driver_priv; /* Check whether the file_priv has already selected one ring. */ - if ((int)file_priv->bsd_engine < 0) { - /* If not, use the ping-pong mechanism to select one. */ - mutex_lock(&dev_priv->drm.struct_mutex); - file_priv->bsd_engine = dev_priv->mm.bsd_engine_dispatch_index; - dev_priv->mm.bsd_engine_dispatch_index ^= 1; - mutex_unlock(&dev_priv->drm.struct_mutex); - } + if ((int)file_priv->bsd_engine < 0) + file_priv->bsd_engine = atomic_fetch_xor(1, + &dev_priv->mm.bsd_engine_dispatch_index); return file_priv->bsd_engine; } -- cgit v1.2.1 From c4a8a7c718d282c95b46ed78b35662451af4306e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 2 Sep 2016 08:34:08 +0200 Subject: drm/i915: Update DRIVER_DATE to 20160902 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 43d5298b821f..d01d066c2d17 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -70,7 +70,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20160822" +#define DRIVER_DATE "20160902" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v1.2.1 From 662d19e78b2c0a955879f487755e6a70a5e0226a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 1 Sep 2016 21:55:10 +0100 Subject: drm/i915: Drop mutex around clearing error state The error state itself is guarded by a spinlock (admittedly even that is overkill for a single pointer!) and doesn't require us to take the struct_mutex in the debugfs/sysfs interface. Removing the struct_mutex removes one more potential blockage when trying to debug a deadlock. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160901205510.31307-1-chris@chris-wilson.co.uk Reviewed-by: David Weinehall private_data; - struct drm_device *dev = error_priv->dev; - int ret; DRM_DEBUG_DRIVER("Resetting error state\n"); - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - - i915_destroy_error_state(dev); - mutex_unlock(&dev->struct_mutex); + i915_destroy_error_state(error_priv->dev); return cnt; } diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 2d482f677f56..1012eeea1324 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -556,17 +556,9 @@ static ssize_t error_state_write(struct file *file, struct kobject *kobj, { struct device *kdev = kobj_to_dev(kobj); struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct drm_device *dev = &dev_priv->drm; - int ret; DRM_DEBUG_DRIVER("Resetting error state\n"); - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - - i915_destroy_error_state(dev); - mutex_unlock(&dev->struct_mutex); + i915_destroy_error_state(&dev_priv->drm); return count; } -- cgit v1.2.1 From 16162470023627776d503795d08aa5a797ce40a2 Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Fri, 2 Sep 2016 13:46:17 +0300 Subject: drm/i915: Cleanup i915_param() Rather than having a separate case for each value where we just return a hardcoded value = 1, we lump them all together and rely on the awesome case-fallthrough feature of C. Fix all feature macros to pass dev_priv instead of dev while at it, and use INTEL_GEN() instead of INTEL_INFO()->gen. Signed-off-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/20160902104617.29089-1-david.weinehall@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 87 +++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 55 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 47fe07283d88..24543079af95 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -248,22 +248,12 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_REVISION: value = pdev->revision; break; - case I915_PARAM_HAS_GEM: - value = 1; - break; case I915_PARAM_NUM_FENCES_AVAIL: value = dev_priv->num_fence_regs; break; case I915_PARAM_HAS_OVERLAY: value = dev_priv->overlay ? 1 : 0; break; - case I915_PARAM_HAS_PAGEFLIPPING: - value = 1; - break; - case I915_PARAM_HAS_EXECBUF2: - /* depends on GEM */ - value = 1; - break; case I915_PARAM_HAS_BSD: value = intel_engine_initialized(&dev_priv->engine[VCS]); break; @@ -276,67 +266,34 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_BSD2: value = intel_engine_initialized(&dev_priv->engine[VCS2]); break; - case I915_PARAM_HAS_RELAXED_FENCING: - value = 1; - break; - case I915_PARAM_HAS_COHERENT_RINGS: - value = 1; - break; case I915_PARAM_HAS_EXEC_CONSTANTS: - value = INTEL_INFO(dev)->gen >= 4; - break; - case I915_PARAM_HAS_RELAXED_DELTA: - value = 1; - break; - case I915_PARAM_HAS_GEN7_SOL_RESET: - value = 1; + value = INTEL_GEN(dev_priv) >= 4; break; case I915_PARAM_HAS_LLC: - value = HAS_LLC(dev); + value = HAS_LLC(dev_priv); break; case I915_PARAM_HAS_WT: - value = HAS_WT(dev); + value = HAS_WT(dev_priv); break; case I915_PARAM_HAS_ALIASING_PPGTT: - value = USES_PPGTT(dev); - break; - case I915_PARAM_HAS_WAIT_TIMEOUT: - value = 1; + value = USES_PPGTT(dev_priv); break; case I915_PARAM_HAS_SEMAPHORES: value = i915.semaphores; break; - case I915_PARAM_HAS_PRIME_VMAP_FLUSH: - value = 1; - break; case I915_PARAM_HAS_SECURE_BATCHES: value = capable(CAP_SYS_ADMIN); break; - case I915_PARAM_HAS_PINNED_BATCHES: - value = 1; - break; - case I915_PARAM_HAS_EXEC_NO_RELOC: - value = 1; - break; - case I915_PARAM_HAS_EXEC_HANDLE_LUT: - value = 1; - break; case I915_PARAM_CMD_PARSER_VERSION: value = i915_cmd_parser_get_version(dev_priv); break; - case I915_PARAM_HAS_COHERENT_PHYS_GTT: - value = 1; - break; - case I915_PARAM_MMAP_VERSION: - value = 1; - break; case I915_PARAM_SUBSLICE_TOTAL: - value = INTEL_INFO(dev)->subslice_total; + value = INTEL_INFO(dev_priv)->subslice_total; if (!value) return -ENODEV; break; case I915_PARAM_EU_TOTAL: - value = INTEL_INFO(dev)->eu_total; + value = INTEL_INFO(dev_priv)->eu_total; if (!value) return -ENODEV; break; @@ -344,16 +301,13 @@ static int i915_getparam(struct drm_device *dev, void *data, value = i915.enable_hangcheck && intel_has_gpu_reset(dev_priv); break; case I915_PARAM_HAS_RESOURCE_STREAMER: - value = HAS_RESOURCE_STREAMER(dev); - break; - case I915_PARAM_HAS_EXEC_SOFTPIN: - value = 1; + value = HAS_RESOURCE_STREAMER(dev_priv); break; case I915_PARAM_HAS_POOLED_EU: - value = HAS_POOLED_EU(dev); + value = HAS_POOLED_EU(dev_priv); break; case I915_PARAM_MIN_EU_IN_POOL: - value = INTEL_INFO(dev)->min_eu_in_pool; + value = INTEL_INFO(dev_priv)->min_eu_in_pool; break; case I915_PARAM_MMAP_GTT_VERSION: /* Though we've started our numbering from 1, and so class all @@ -362,6 +316,29 @@ static int i915_getparam(struct drm_device *dev, void *data, */ value = i915_gem_mmap_gtt_version(); break; + case I915_PARAM_MMAP_VERSION: + /* Remember to bump this if the version changes! */ + case I915_PARAM_HAS_GEM: + case I915_PARAM_HAS_PAGEFLIPPING: + case I915_PARAM_HAS_EXECBUF2: /* depends on GEM */ + case I915_PARAM_HAS_RELAXED_FENCING: + case I915_PARAM_HAS_COHERENT_RINGS: + case I915_PARAM_HAS_RELAXED_DELTA: + case I915_PARAM_HAS_GEN7_SOL_RESET: + case I915_PARAM_HAS_WAIT_TIMEOUT: + case I915_PARAM_HAS_PRIME_VMAP_FLUSH: + case I915_PARAM_HAS_PINNED_BATCHES: + case I915_PARAM_HAS_EXEC_NO_RELOC: + case I915_PARAM_HAS_EXEC_HANDLE_LUT: + case I915_PARAM_HAS_COHERENT_PHYS_GTT: + case I915_PARAM_HAS_EXEC_SOFTPIN: + /* For the time being all of these are always true; + * if some supported hardware does not have one of these + * features this value needs to be provided from + * INTEL_INFO(), a feature macro, or similar. + */ + value = 1; + break; default: DRM_DEBUG("Unknown parameter %d\n", param->param); return -EINVAL; -- cgit v1.2.1 From 915490d5f1cc10663f9a58240e44b84c0f33728f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 31 Aug 2016 19:13:01 +0300 Subject: drm/i915: sseu: Move sseu_dev_status to i915_drv.h The data in this struct is provided both by getting the slice/subslice/eu features available on a given platform and the actual runtime state of these same features which depends on the HW's current power saving state. Atm members of this struct are duplicated in sseu_dev_status and intel_device_info. For clarity and code reuse we can share one struct for both of the above purposes. This patch only moves the struct to the header file, the next patch will convert users of intel_device_info to use this struct too. Instead of unsigned int u8 is used now, which is big enough and is used anyway in intel_device_info. No functional change. v2: - s/stat/sseu/ based on the new struct name (Ben) Reviewed-by: Robert Bragg (v1) Reviewed-by: Ben Widawsky (v1) Tested-by: Ben Widawsky (v1) Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1472659987-10417-2-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 79 +++++++++++++++++-------------------- drivers/gpu/drm/i915/i915_drv.h | 8 ++++ 2 files changed, 45 insertions(+), 42 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index c224702d7431..e9468c6bebf5 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4988,16 +4988,8 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops, i915_cache_sharing_get, i915_cache_sharing_set, "%llu\n"); -struct sseu_dev_status { - unsigned int slice_total; - unsigned int subslice_total; - unsigned int subslice_per_slice; - unsigned int eu_total; - unsigned int eu_per_subslice; -}; - static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, - struct sseu_dev_status *stat) + struct sseu_dev_info *sseu) { int ss_max = 2; int ss; @@ -5015,20 +5007,21 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, /* skip disabled subslice */ continue; - stat->slice_total = 1; - stat->subslice_per_slice++; + sseu->slice_total = 1; + sseu->subslice_per_slice++; eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) + ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) + ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) + ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2); - stat->eu_total += eu_cnt; - stat->eu_per_subslice = max(stat->eu_per_subslice, eu_cnt); + sseu->eu_total += eu_cnt; + sseu->eu_per_subslice = max_t(unsigned int, + sseu->eu_per_subslice, eu_cnt); } - stat->subslice_total = stat->subslice_per_slice; + sseu->subslice_total = sseu->subslice_per_slice; } static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, - struct sseu_dev_status *stat) + struct sseu_dev_info *sseu) { int s_max = 3, ss_max = 4; int s, ss; @@ -5062,7 +5055,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, /* skip disabled slice */ continue; - stat->slice_total++; + sseu->slice_total++; if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) ss_cnt = INTEL_INFO(dev_priv)->subslice_per_slice; @@ -5080,37 +5073,39 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & eu_mask[ss%2]); - stat->eu_total += eu_cnt; - stat->eu_per_subslice = max(stat->eu_per_subslice, - eu_cnt); + sseu->eu_total += eu_cnt; + sseu->eu_per_subslice = max_t(unsigned int, + sseu->eu_per_subslice, + eu_cnt); } - stat->subslice_total += ss_cnt; - stat->subslice_per_slice = max(stat->subslice_per_slice, - ss_cnt); + sseu->subslice_total += ss_cnt; + sseu->subslice_per_slice = max_t(unsigned int, + sseu->subslice_per_slice, + ss_cnt); } } static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, - struct sseu_dev_status *stat) + struct sseu_dev_info *sseu) { u32 slice_info = I915_READ(GEN8_GT_SLICE_INFO); int s; - stat->slice_total = hweight32(slice_info & GEN8_LSLICESTAT_MASK); + sseu->slice_total = hweight32(slice_info & GEN8_LSLICESTAT_MASK); - if (stat->slice_total) { - stat->subslice_per_slice = INTEL_INFO(dev_priv)->subslice_per_slice; - stat->subslice_total = stat->slice_total * - stat->subslice_per_slice; - stat->eu_per_subslice = INTEL_INFO(dev_priv)->eu_per_subslice; - stat->eu_total = stat->eu_per_subslice * stat->subslice_total; + if (sseu->slice_total) { + sseu->subslice_per_slice = INTEL_INFO(dev_priv)->subslice_per_slice; + sseu->subslice_total = sseu->slice_total * + sseu->subslice_per_slice; + sseu->eu_per_subslice = INTEL_INFO(dev_priv)->eu_per_subslice; + sseu->eu_total = sseu->eu_per_subslice * sseu->subslice_total; /* subtract fused off EU(s) from enabled slice(s) */ - for (s = 0; s < stat->slice_total; s++) { + for (s = 0; s < sseu->slice_total; s++) { u8 subslice_7eu = INTEL_INFO(dev_priv)->subslice_7eu[s]; - stat->eu_total -= hweight8(subslice_7eu); + sseu->eu_total -= hweight8(subslice_7eu); } } } @@ -5118,7 +5113,7 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, static int i915_sseu_status(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct sseu_dev_status stat; + struct sseu_dev_info sseu; if (INTEL_GEN(dev_priv) < 8) return -ENODEV; @@ -5146,30 +5141,30 @@ static int i915_sseu_status(struct seq_file *m, void *unused) yesno(INTEL_INFO(dev_priv)->has_eu_pg)); seq_puts(m, "SSEU Device Status\n"); - memset(&stat, 0, sizeof(stat)); + memset(&sseu, 0, sizeof(sseu)); intel_runtime_pm_get(dev_priv); if (IS_CHERRYVIEW(dev_priv)) { - cherryview_sseu_device_status(dev_priv, &stat); + cherryview_sseu_device_status(dev_priv, &sseu); } else if (IS_BROADWELL(dev_priv)) { - broadwell_sseu_device_status(dev_priv, &stat); + broadwell_sseu_device_status(dev_priv, &sseu); } else if (INTEL_GEN(dev_priv) >= 9) { - gen9_sseu_device_status(dev_priv, &stat); + gen9_sseu_device_status(dev_priv, &sseu); } intel_runtime_pm_put(dev_priv); seq_printf(m, " Enabled Slice Total: %u\n", - stat.slice_total); + sseu.slice_total); seq_printf(m, " Enabled Subslice Total: %u\n", - stat.subslice_total); + sseu.subslice_total); seq_printf(m, " Enabled Subslice Per Slice: %u\n", - stat.subslice_per_slice); + sseu.subslice_per_slice); seq_printf(m, " Enabled EU Total: %u\n", - stat.eu_total); + sseu.eu_total); seq_printf(m, " Enabled EU Per Subslice: %u\n", - stat.eu_per_subslice); + sseu.eu_per_subslice); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d01d066c2d17..ac63e3585242 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -671,6 +671,14 @@ struct intel_csr { #define DEFINE_FLAG(name) u8 name:1 #define SEP_SEMICOLON ; +struct sseu_dev_info { + u8 slice_total; + u8 subslice_total; + u8 subslice_per_slice; + u8 eu_total; + u8 eu_per_subslice; +}; + struct intel_device_info { u32 display_mmio_offset; u16 device_id; -- cgit v1.2.1 From 43b6799814ca1f29ba35a712c59cbef293573d53 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 31 Aug 2016 19:13:02 +0300 Subject: drm/i915: sseu: Use sseu_dev_info in device info Move all slice/subslice/eu related properties to the sseu_dev_info struct. No functional change. v2: - s/info/sseu/ based on the new struct name. (Ben) Reviewed-by: Robert Bragg (v1) Reviewed-by: Ben Widawsky (v1) Tested-by: Ben Widawsky (v1) Signed-off-by: Imre Deak --- drivers/gpu/drm/i915/i915_debugfs.c | 29 +++++---- drivers/gpu/drm/i915/i915_drv.c | 6 +- drivers/gpu/drm/i915/i915_drv.h | 18 +++--- drivers/gpu/drm/i915/intel_device_info.c | 102 ++++++++++++++++--------------- drivers/gpu/drm/i915/intel_lrc.c | 14 ++--- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 +- 7 files changed, 88 insertions(+), 87 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e9468c6bebf5..91fcc6390b2c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -5058,7 +5058,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, sseu->slice_total++; if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) - ss_cnt = INTEL_INFO(dev_priv)->subslice_per_slice; + ss_cnt = INTEL_INFO(dev_priv)->sseu.subslice_per_slice; for (ss = 0; ss < ss_max; ss++) { unsigned int eu_cnt; @@ -5095,15 +5095,18 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, sseu->slice_total = hweight32(slice_info & GEN8_LSLICESTAT_MASK); if (sseu->slice_total) { - sseu->subslice_per_slice = INTEL_INFO(dev_priv)->subslice_per_slice; + sseu->subslice_per_slice = + INTEL_INFO(dev_priv)->sseu.subslice_per_slice; sseu->subslice_total = sseu->slice_total * sseu->subslice_per_slice; - sseu->eu_per_subslice = INTEL_INFO(dev_priv)->eu_per_subslice; + sseu->eu_per_subslice = + INTEL_INFO(dev_priv)->sseu.eu_per_subslice; sseu->eu_total = sseu->eu_per_subslice * sseu->subslice_total; /* subtract fused off EU(s) from enabled slice(s) */ for (s = 0; s < sseu->slice_total; s++) { - u8 subslice_7eu = INTEL_INFO(dev_priv)->subslice_7eu[s]; + u8 subslice_7eu = + INTEL_INFO(dev_priv)->sseu.subslice_7eu[s]; sseu->eu_total -= hweight8(subslice_7eu); } @@ -5120,25 +5123,25 @@ static int i915_sseu_status(struct seq_file *m, void *unused) seq_puts(m, "SSEU Device Info\n"); seq_printf(m, " Available Slice Total: %u\n", - INTEL_INFO(dev_priv)->slice_total); + INTEL_INFO(dev_priv)->sseu.slice_total); seq_printf(m, " Available Subslice Total: %u\n", - INTEL_INFO(dev_priv)->subslice_total); + INTEL_INFO(dev_priv)->sseu.subslice_total); seq_printf(m, " Available Subslice Per Slice: %u\n", - INTEL_INFO(dev_priv)->subslice_per_slice); + INTEL_INFO(dev_priv)->sseu.subslice_per_slice); seq_printf(m, " Available EU Total: %u\n", - INTEL_INFO(dev_priv)->eu_total); + INTEL_INFO(dev_priv)->sseu.eu_total); seq_printf(m, " Available EU Per Subslice: %u\n", - INTEL_INFO(dev_priv)->eu_per_subslice); + INTEL_INFO(dev_priv)->sseu.eu_per_subslice); seq_printf(m, " Has Pooled EU: %s\n", yesno(HAS_POOLED_EU(dev_priv))); if (HAS_POOLED_EU(dev_priv)) seq_printf(m, " Min EU in pool: %u\n", - INTEL_INFO(dev_priv)->min_eu_in_pool); + INTEL_INFO(dev_priv)->sseu.min_eu_in_pool); seq_printf(m, " Has Slice Power Gating: %s\n", - yesno(INTEL_INFO(dev_priv)->has_slice_pg)); + yesno(INTEL_INFO(dev_priv)->sseu.has_slice_pg)); seq_printf(m, " Has Subslice Power Gating: %s\n", - yesno(INTEL_INFO(dev_priv)->has_subslice_pg)); + yesno(INTEL_INFO(dev_priv)->sseu.has_subslice_pg)); seq_printf(m, " Has EU Power Gating: %s\n", - yesno(INTEL_INFO(dev_priv)->has_eu_pg)); + yesno(INTEL_INFO(dev_priv)->sseu.has_eu_pg)); seq_puts(m, "SSEU Device Status\n"); memset(&sseu, 0, sizeof(sseu)); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 24543079af95..5e22105b728f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -288,12 +288,12 @@ static int i915_getparam(struct drm_device *dev, void *data, value = i915_cmd_parser_get_version(dev_priv); break; case I915_PARAM_SUBSLICE_TOTAL: - value = INTEL_INFO(dev_priv)->subslice_total; + value = INTEL_INFO(dev_priv)->sseu.subslice_total; if (!value) return -ENODEV; break; case I915_PARAM_EU_TOTAL: - value = INTEL_INFO(dev_priv)->eu_total; + value = INTEL_INFO(dev_priv)->sseu.eu_total; if (!value) return -ENODEV; break; @@ -307,7 +307,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = HAS_POOLED_EU(dev_priv); break; case I915_PARAM_MIN_EU_IN_POOL: - value = INTEL_INFO(dev_priv)->min_eu_in_pool; + value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool; break; case I915_PARAM_MMAP_GTT_VERSION: /* Though we've started our numbering from 1, and so class all diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ac63e3585242..0b62d36414bd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -677,6 +677,12 @@ struct sseu_dev_info { u8 subslice_per_slice; u8 eu_total; u8 eu_per_subslice; + u8 min_eu_in_pool; + /* For each slice, which subslice(s) has(have) 7 EUs (bitfield)? */ + u8 subslice_7eu[3]; + u8 has_slice_pg:1; + u8 has_subslice_pg:1; + u8 has_eu_pg:1; }; struct intel_device_info { @@ -696,17 +702,7 @@ struct intel_device_info { int cursor_offsets[I915_MAX_PIPES]; /* Slice/subslice/EU info */ - u8 slice_total; - u8 subslice_total; - u8 subslice_per_slice; - u8 eu_total; - u8 eu_per_subslice; - u8 min_eu_in_pool; - /* For each slice, which subslice(s) has(have) 7 EUs (bitfield)? */ - u8 subslice_7eu[3]; - u8 has_slice_pg:1; - u8 has_subslice_pg:1; - u8 has_eu_pg:1; + struct sseu_dev_info sseu; struct color_luts { u16 degamma_lut_size; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index cba137f9ad3e..5db357110ea1 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -46,48 +46,49 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv) static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) { - struct intel_device_info *info = mkwrite_device_info(dev_priv); + struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; u32 fuse, eu_dis; fuse = I915_READ(CHV_FUSE_GT); - info->slice_total = 1; + sseu->slice_total = 1; if (!(fuse & CHV_FGT_DISABLE_SS0)) { - info->subslice_per_slice++; + sseu->subslice_per_slice++; eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK | CHV_FGT_EU_DIS_SS0_R1_MASK); - info->eu_total += 8 - hweight32(eu_dis); + sseu->eu_total += 8 - hweight32(eu_dis); } if (!(fuse & CHV_FGT_DISABLE_SS1)) { - info->subslice_per_slice++; + sseu->subslice_per_slice++; eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK | CHV_FGT_EU_DIS_SS1_R1_MASK); - info->eu_total += 8 - hweight32(eu_dis); + sseu->eu_total += 8 - hweight32(eu_dis); } - info->subslice_total = info->subslice_per_slice; + sseu->subslice_total = sseu->subslice_per_slice; /* * CHV expected to always have a uniform distribution of EU * across subslices. */ - info->eu_per_subslice = info->subslice_total ? - info->eu_total / info->subslice_total : + sseu->eu_per_subslice = sseu->subslice_total ? + sseu->eu_total / sseu->subslice_total : 0; /* * CHV supports subslice power gating on devices with more than * one subslice, and supports EU power gating on devices with * more than one EU pair per subslice. */ - info->has_slice_pg = 0; - info->has_subslice_pg = (info->subslice_total > 1); - info->has_eu_pg = (info->eu_per_subslice > 2); + sseu->has_slice_pg = 0; + sseu->has_subslice_pg = (sseu->subslice_total > 1); + sseu->has_eu_pg = (sseu->eu_per_subslice > 2); } static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) { struct intel_device_info *info = mkwrite_device_info(dev_priv); + struct sseu_dev_info *sseu = &info->sseu; int s_max = 3, ss_max = 4, eu_max = 8; int s, ss; u32 fuse2, s_enable, ss_disable, eu_disable; @@ -97,13 +98,13 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >> GEN9_F2_SS_DIS_SHIFT; - info->slice_total = hweight32(s_enable); + sseu->slice_total = hweight32(s_enable); /* * The subslice disable field is global, i.e. it applies * to each of the enabled slices. */ - info->subslice_per_slice = ss_max - hweight32(ss_disable); - info->subslice_total = info->slice_total * info->subslice_per_slice; + sseu->subslice_per_slice = ss_max - hweight32(ss_disable); + sseu->subslice_total = sseu->slice_total * sseu->subslice_per_slice; /* * Iterate through enabled slices and subslices to @@ -131,9 +132,9 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) * subslices if they are unbalanced. */ if (eu_per_ss == 7) - info->subslice_7eu[s] |= BIT(ss); + sseu->subslice_7eu[s] |= BIT(ss); - info->eu_total += eu_per_ss; + sseu->eu_total += eu_per_ss; } } @@ -144,9 +145,9 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) * recovery. BXT is expected to be perfectly uniform in EU * distribution. */ - info->eu_per_subslice = info->subslice_total ? - DIV_ROUND_UP(info->eu_total, - info->subslice_total) : 0; + sseu->eu_per_subslice = sseu->subslice_total ? + DIV_ROUND_UP(sseu->eu_total, + sseu->subslice_total) : 0; /* * SKL supports slice power gating on devices with more than * one slice, and supports EU power gating on devices with @@ -155,12 +156,12 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) * supports EU power gating on devices with more than one EU * pair per subslice. */ - info->has_slice_pg = + sseu->has_slice_pg = (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && - info->slice_total > 1; - info->has_subslice_pg = - IS_BROXTON(dev_priv) && info->subslice_total > 1; - info->has_eu_pg = info->eu_per_subslice > 2; + sseu->slice_total > 1; + sseu->has_subslice_pg = + IS_BROXTON(dev_priv) && sseu->subslice_total > 1; + sseu->has_eu_pg = sseu->eu_per_subslice > 2; if (IS_BROXTON(dev_priv)) { #define IS_SS_DISABLED(_ss_disable, ss) (_ss_disable & BIT(ss)) @@ -171,19 +172,19 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) * doesn't affect if the device has all 3 subslices enabled. */ /* WaEnablePooledEuFor2x6:bxt */ - info->has_pooled_eu = ((info->subslice_per_slice == 3) || - (info->subslice_per_slice == 2 && + info->has_pooled_eu = ((sseu->subslice_per_slice == 3) || + (sseu->subslice_per_slice == 2 && INTEL_REVID(dev_priv) < BXT_REVID_C0)); - info->min_eu_in_pool = 0; + sseu->min_eu_in_pool = 0; if (info->has_pooled_eu) { if (IS_SS_DISABLED(ss_disable, 0) || IS_SS_DISABLED(ss_disable, 2)) - info->min_eu_in_pool = 3; + sseu->min_eu_in_pool = 3; else if (IS_SS_DISABLED(ss_disable, 1)) - info->min_eu_in_pool = 6; + sseu->min_eu_in_pool = 6; else - info->min_eu_in_pool = 9; + sseu->min_eu_in_pool = 9; } #undef IS_SS_DISABLED } @@ -191,7 +192,7 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) { - struct intel_device_info *info = mkwrite_device_info(dev_priv); + struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; const int s_max = 3, ss_max = 3, eu_max = 8; int s, ss; u32 fuse2, eu_disable[s_max], s_enable, ss_disable; @@ -208,14 +209,14 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) << (32 - GEN8_EU_DIS1_S2_SHIFT)); - info->slice_total = hweight32(s_enable); + sseu->slice_total = hweight32(s_enable); /* * The subslice disable field is global, i.e. it applies * to each of the enabled slices. */ - info->subslice_per_slice = ss_max - hweight32(ss_disable); - info->subslice_total = info->slice_total * info->subslice_per_slice; + sseu->subslice_per_slice = ss_max - hweight32(ss_disable); + sseu->subslice_total = sseu->slice_total * sseu->subslice_per_slice; /* * Iterate through enabled slices and subslices to @@ -239,9 +240,9 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) * Record which subslices have 7 EUs. */ if (eu_max - n_disabled == 7) - info->subslice_7eu[s] |= 1 << ss; + sseu->subslice_7eu[s] |= 1 << ss; - info->eu_total += eu_max - n_disabled; + sseu->eu_total += eu_max - n_disabled; } } @@ -250,16 +251,16 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) * subslices with the exception that any one EU in any one subslice may * be fused off for die recovery. */ - info->eu_per_subslice = info->subslice_total ? - DIV_ROUND_UP(info->eu_total, info->subslice_total) : 0; + sseu->eu_per_subslice = sseu->subslice_total ? + DIV_ROUND_UP(sseu->eu_total, sseu->subslice_total) : 0; /* * BDW supports slice power gating on devices with more than * one slice. */ - info->has_slice_pg = (info->slice_total > 1); - info->has_subslice_pg = 0; - info->has_eu_pg = 0; + sseu->has_slice_pg = (sseu->slice_total > 1); + sseu->has_subslice_pg = 0; + sseu->has_eu_pg = 0; } /* @@ -374,15 +375,16 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) info->has_snoop = false; - DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total); - DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total); - DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice); - DRM_DEBUG_DRIVER("EU total: %u\n", info->eu_total); - DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->eu_per_subslice); + DRM_DEBUG_DRIVER("slice total: %u\n", info->sseu.slice_total); + DRM_DEBUG_DRIVER("subslice total: %u\n", info->sseu.subslice_total); + DRM_DEBUG_DRIVER("subslice per slice: %u\n", + info->sseu.subslice_per_slice); + DRM_DEBUG_DRIVER("EU total: %u\n", info->sseu.eu_total); + DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->sseu.eu_per_subslice); DRM_DEBUG_DRIVER("has slice power gating: %s\n", - info->has_slice_pg ? "y" : "n"); + info->sseu.has_slice_pg ? "y" : "n"); DRM_DEBUG_DRIVER("has subslice power gating: %s\n", - info->has_subslice_pg ? "y" : "n"); + info->sseu.has_subslice_pg ? "y" : "n"); DRM_DEBUG_DRIVER("has EU power gating: %s\n", - info->has_eu_pg ? "y" : "n"); + info->sseu.has_eu_pg ? "y" : "n"); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 6b49df4316f4..3b076e2bffd4 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1896,24 +1896,24 @@ make_rpcs(struct drm_i915_private *dev_priv) * must make an explicit request through RPCS for full * enablement. */ - if (INTEL_INFO(dev_priv)->has_slice_pg) { + if (INTEL_INFO(dev_priv)->sseu.has_slice_pg) { rpcs |= GEN8_RPCS_S_CNT_ENABLE; - rpcs |= INTEL_INFO(dev_priv)->slice_total << + rpcs |= INTEL_INFO(dev_priv)->sseu.slice_total << GEN8_RPCS_S_CNT_SHIFT; rpcs |= GEN8_RPCS_ENABLE; } - if (INTEL_INFO(dev_priv)->has_subslice_pg) { + if (INTEL_INFO(dev_priv)->sseu.has_subslice_pg) { rpcs |= GEN8_RPCS_SS_CNT_ENABLE; - rpcs |= INTEL_INFO(dev_priv)->subslice_per_slice << + rpcs |= INTEL_INFO(dev_priv)->sseu.subslice_per_slice << GEN8_RPCS_SS_CNT_SHIFT; rpcs |= GEN8_RPCS_ENABLE; } - if (INTEL_INFO(dev_priv)->has_eu_pg) { - rpcs |= INTEL_INFO(dev_priv)->eu_per_subslice << + if (INTEL_INFO(dev_priv)->sseu.has_eu_pg) { + rpcs |= INTEL_INFO(dev_priv)->sseu.eu_per_subslice << GEN8_RPCS_EU_MIN_SHIFT; - rpcs |= INTEL_INFO(dev_priv)->eu_per_subslice << + rpcs |= INTEL_INFO(dev_priv)->sseu.eu_per_subslice << GEN8_RPCS_EU_MAX_SHIFT; rpcs |= GEN8_RPCS_ENABLE; } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index aba6fd036c4e..4f833a077089 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5632,7 +5632,7 @@ static int cherryview_rps_max_freq(struct drm_i915_private *dev_priv) val = vlv_punit_read(dev_priv, FB_GFX_FMAX_AT_VMAX_FUSE); - switch (INTEL_INFO(dev_priv)->eu_total) { + switch (INTEL_INFO(dev_priv)->sseu.eu_total) { case 8: /* (2 * 4) config */ rp0 = (val >> FB_GFX_FMAX_AT_VMAX_2SS4EU_FUSE_SHIFT); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index cc5bcd14b6df..4472752812cb 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -951,7 +951,7 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *engine) * Only consider slices where one, and only one, subslice has 7 * EUs */ - if (!is_power_of_2(dev_priv->info.subslice_7eu[i])) + if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i])) continue; /* @@ -960,7 +960,7 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *engine) * * -> 0 <= ss <= 3; */ - ss = ffs(dev_priv->info.subslice_7eu[i]) - 1; + ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1; vals[i] = 3 - ss; } -- cgit v1.2.1 From 615d8908ac9c723d8666bde44a7acc85af0baace Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 31 Aug 2016 19:13:03 +0300 Subject: drm/i915: sseu: Simplify debugfs status/info printing Reviewed-by: Robert Bragg Reviewed-by: Ben Widawsky Tested-by: Ben Widawsky Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1472659987-10417-4-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 64 ++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 30 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 91fcc6390b2c..cbd9c7625450 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -5113,6 +5113,38 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, } } +static void i915_print_sseu_info(struct seq_file *m, bool is_available_info, + const struct sseu_dev_info *sseu) +{ + struct drm_i915_private *dev_priv = node_to_i915(m->private); + const char *type = is_available_info ? "Available" : "Enabled"; + + seq_printf(m, " %s Slice Total: %u\n", type, + sseu->slice_total); + seq_printf(m, " %s Subslice Total: %u\n", type, + sseu->subslice_total); + seq_printf(m, " %s Subslice Per Slice: %u\n", type, + sseu->subslice_per_slice); + seq_printf(m, " %s EU Total: %u\n", type, + sseu->eu_total); + seq_printf(m, " %s EU Per Subslice: %u\n", type, + sseu->eu_per_subslice); + + if (!is_available_info) + return; + + seq_printf(m, " Has Pooled EU: %s\n", yesno(HAS_POOLED_EU(dev_priv))); + if (HAS_POOLED_EU(dev_priv)) + seq_printf(m, " Min EU in pool: %u\n", sseu->min_eu_in_pool); + + seq_printf(m, " Has Slice Power Gating: %s\n", + yesno(sseu->has_slice_pg)); + seq_printf(m, " Has Subslice Power Gating: %s\n", + yesno(sseu->has_subslice_pg)); + seq_printf(m, " Has EU Power Gating: %s\n", + yesno(sseu->has_eu_pg)); +} + static int i915_sseu_status(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -5122,26 +5154,7 @@ static int i915_sseu_status(struct seq_file *m, void *unused) return -ENODEV; seq_puts(m, "SSEU Device Info\n"); - seq_printf(m, " Available Slice Total: %u\n", - INTEL_INFO(dev_priv)->sseu.slice_total); - seq_printf(m, " Available Subslice Total: %u\n", - INTEL_INFO(dev_priv)->sseu.subslice_total); - seq_printf(m, " Available Subslice Per Slice: %u\n", - INTEL_INFO(dev_priv)->sseu.subslice_per_slice); - seq_printf(m, " Available EU Total: %u\n", - INTEL_INFO(dev_priv)->sseu.eu_total); - seq_printf(m, " Available EU Per Subslice: %u\n", - INTEL_INFO(dev_priv)->sseu.eu_per_subslice); - seq_printf(m, " Has Pooled EU: %s\n", yesno(HAS_POOLED_EU(dev_priv))); - if (HAS_POOLED_EU(dev_priv)) - seq_printf(m, " Min EU in pool: %u\n", - INTEL_INFO(dev_priv)->sseu.min_eu_in_pool); - seq_printf(m, " Has Slice Power Gating: %s\n", - yesno(INTEL_INFO(dev_priv)->sseu.has_slice_pg)); - seq_printf(m, " Has Subslice Power Gating: %s\n", - yesno(INTEL_INFO(dev_priv)->sseu.has_subslice_pg)); - seq_printf(m, " Has EU Power Gating: %s\n", - yesno(INTEL_INFO(dev_priv)->sseu.has_eu_pg)); + i915_print_sseu_info(m, true, &INTEL_INFO(dev_priv)->sseu); seq_puts(m, "SSEU Device Status\n"); memset(&sseu, 0, sizeof(sseu)); @@ -5158,16 +5171,7 @@ static int i915_sseu_status(struct seq_file *m, void *unused) intel_runtime_pm_put(dev_priv); - seq_printf(m, " Enabled Slice Total: %u\n", - sseu.slice_total); - seq_printf(m, " Enabled Subslice Total: %u\n", - sseu.subslice_total); - seq_printf(m, " Enabled Subslice Per Slice: %u\n", - sseu.subslice_per_slice); - seq_printf(m, " Enabled EU Total: %u\n", - sseu.eu_total); - seq_printf(m, " Enabled EU Per Subslice: %u\n", - sseu.eu_per_subslice); + i915_print_sseu_info(m, false, &sseu); return 0; } -- cgit v1.2.1 From f08a0c9234c86cf0249a5edd58a7abf69617f29f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 31 Aug 2016 19:13:04 +0300 Subject: drm/i915: sseu: Convert slice count field to mask In an upcoming patch we'll need the actual mask of slices in addition to their count, so replace the count field with a mask. v2: - Use hweight8() on u8 typed vars instead of hweight32(). (Ben) Reviewed-by: Robert Bragg (v1) Reviewed-by: Ben Widawsky (v1) Tested-by: Ben Widawsky (v1) Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1472659987-10417-5-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 14 +++++++------- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_device_info.c | 29 ++++++++++++++--------------- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 4 files changed, 23 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index cbd9c7625450..0ba28a8ad669 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -5007,7 +5007,7 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, /* skip disabled subslice */ continue; - sseu->slice_total = 1; + sseu->slice_mask = BIT(0); sseu->subslice_per_slice++; eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) + ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) + @@ -5055,7 +5055,7 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, /* skip disabled slice */ continue; - sseu->slice_total++; + sseu->slice_mask |= BIT(s); if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) ss_cnt = INTEL_INFO(dev_priv)->sseu.subslice_per_slice; @@ -5092,19 +5092,19 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, u32 slice_info = I915_READ(GEN8_GT_SLICE_INFO); int s; - sseu->slice_total = hweight32(slice_info & GEN8_LSLICESTAT_MASK); + sseu->slice_mask = slice_info & GEN8_LSLICESTAT_MASK; - if (sseu->slice_total) { + if (sseu->slice_mask) { sseu->subslice_per_slice = INTEL_INFO(dev_priv)->sseu.subslice_per_slice; - sseu->subslice_total = sseu->slice_total * + sseu->subslice_total = hweight8(sseu->slice_mask) * sseu->subslice_per_slice; sseu->eu_per_subslice = INTEL_INFO(dev_priv)->sseu.eu_per_subslice; sseu->eu_total = sseu->eu_per_subslice * sseu->subslice_total; /* subtract fused off EU(s) from enabled slice(s) */ - for (s = 0; s < sseu->slice_total; s++) { + for (s = 0; s < hweight8(sseu->slice_mask); s++) { u8 subslice_7eu = INTEL_INFO(dev_priv)->sseu.subslice_7eu[s]; @@ -5120,7 +5120,7 @@ static void i915_print_sseu_info(struct seq_file *m, bool is_available_info, const char *type = is_available_info ? "Available" : "Enabled"; seq_printf(m, " %s Slice Total: %u\n", type, - sseu->slice_total); + hweight8(sseu->slice_mask)); seq_printf(m, " %s Subslice Total: %u\n", type, sseu->subslice_total); seq_printf(m, " %s Subslice Per Slice: %u\n", type, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0b62d36414bd..1ebc5ba69e34 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -672,7 +672,7 @@ struct intel_csr { #define SEP_SEMICOLON ; struct sseu_dev_info { - u8 slice_total; + u8 slice_mask; u8 subslice_total; u8 subslice_per_slice; u8 eu_total; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 5db357110ea1..139d5298cde5 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -51,7 +51,7 @@ static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) fuse = I915_READ(CHV_FUSE_GT); - sseu->slice_total = 1; + sseu->slice_mask = BIT(0); if (!(fuse & CHV_FGT_DISABLE_SS0)) { sseu->subslice_per_slice++; @@ -91,27 +91,27 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) struct sseu_dev_info *sseu = &info->sseu; int s_max = 3, ss_max = 4, eu_max = 8; int s, ss; - u32 fuse2, s_enable, ss_disable, eu_disable; + u32 fuse2, ss_disable, eu_disable; u8 eu_mask = 0xff; fuse2 = I915_READ(GEN8_FUSE2); - s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; + sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >> GEN9_F2_SS_DIS_SHIFT; - sseu->slice_total = hweight32(s_enable); /* * The subslice disable field is global, i.e. it applies * to each of the enabled slices. */ sseu->subslice_per_slice = ss_max - hweight32(ss_disable); - sseu->subslice_total = sseu->slice_total * sseu->subslice_per_slice; + sseu->subslice_total = hweight8(sseu->slice_mask) * + sseu->subslice_per_slice; /* * Iterate through enabled slices and subslices to * count the total enabled EU. */ for (s = 0; s < s_max; s++) { - if (!(s_enable & BIT(s))) + if (!(sseu->slice_mask & BIT(s))) /* skip disabled slice */ continue; @@ -158,7 +158,7 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) */ sseu->has_slice_pg = (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && - sseu->slice_total > 1; + hweight8(sseu->slice_mask) > 1; sseu->has_subslice_pg = IS_BROXTON(dev_priv) && sseu->subslice_total > 1; sseu->has_eu_pg = sseu->eu_per_subslice > 2; @@ -195,10 +195,10 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; const int s_max = 3, ss_max = 3, eu_max = 8; int s, ss; - u32 fuse2, eu_disable[s_max], s_enable, ss_disable; + u32 fuse2, eu_disable[s_max], ss_disable; fuse2 = I915_READ(GEN8_FUSE2); - s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; + sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT; eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK; @@ -209,21 +209,20 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) << (32 - GEN8_EU_DIS1_S2_SHIFT)); - sseu->slice_total = hweight32(s_enable); - /* * The subslice disable field is global, i.e. it applies * to each of the enabled slices. */ sseu->subslice_per_slice = ss_max - hweight32(ss_disable); - sseu->subslice_total = sseu->slice_total * sseu->subslice_per_slice; + sseu->subslice_total = hweight8(sseu->slice_mask) * + sseu->subslice_per_slice; /* * Iterate through enabled slices and subslices to * count the total enabled EU. */ for (s = 0; s < s_max; s++) { - if (!(s_enable & (0x1 << s))) + if (!(sseu->slice_mask & BIT(s))) /* skip disabled slice */ continue; @@ -258,7 +257,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) * BDW supports slice power gating on devices with more than * one slice. */ - sseu->has_slice_pg = (sseu->slice_total > 1); + sseu->has_slice_pg = hweight8(sseu->slice_mask) > 1; sseu->has_subslice_pg = 0; sseu->has_eu_pg = 0; } @@ -375,7 +374,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) info->has_snoop = false; - DRM_DEBUG_DRIVER("slice total: %u\n", info->sseu.slice_total); + DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); DRM_DEBUG_DRIVER("subslice total: %u\n", info->sseu.subslice_total); DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->sseu.subslice_per_slice); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3b076e2bffd4..7209553ab162 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1898,7 +1898,7 @@ make_rpcs(struct drm_i915_private *dev_priv) */ if (INTEL_INFO(dev_priv)->sseu.has_slice_pg) { rpcs |= GEN8_RPCS_S_CNT_ENABLE; - rpcs |= INTEL_INFO(dev_priv)->sseu.slice_total << + rpcs |= hweight8(INTEL_INFO(dev_priv)->sseu.slice_mask) << GEN8_RPCS_S_CNT_SHIFT; rpcs |= GEN8_RPCS_ENABLE; } -- cgit v1.2.1 From 57ec171eae21ee0a2848ade1cb7f8f12a31b0731 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 31 Aug 2016 19:13:05 +0300 Subject: drm/i915: sseu: Convert subslice count fields to subslice mask In an upcoming patch we'll need the actual mask of subslices in addition to their count, so convert the subslice_per_slice field to a mask. Also we can easily calculate subslice_total from the other fields, so instead of storing a cached version of this, add a helper to calculate it. v2: - Use hweight8() on u8 typed vars instead of hweight32(). (Ben) Reviewed-by: Robert Bragg (v1) Reviewed-by: Ben Widawsky (v1) Tested-by: Ben Widawsky (v1) Signed-off-by: Imre Deak --- drivers/gpu/drm/i915/i915_debugfs.c | 37 +++++++---------- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 8 +++- drivers/gpu/drm/i915/intel_device_info.c | 69 +++++++++++++++----------------- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 5 files changed, 55 insertions(+), 63 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0ba28a8ad669..d09c77f141ed 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -5008,7 +5008,7 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, continue; sseu->slice_mask = BIT(0); - sseu->subslice_per_slice++; + sseu->subslice_mask |= BIT(ss); eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) + ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) + ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) + @@ -5017,7 +5017,6 @@ static void cherryview_sseu_device_status(struct drm_i915_private *dev_priv, sseu->eu_per_subslice = max_t(unsigned int, sseu->eu_per_subslice, eu_cnt); } - sseu->subslice_total = sseu->subslice_per_slice; } static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, @@ -5049,8 +5048,6 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, GEN9_PGCTL_SSB_EU311_ACK; for (s = 0; s < s_max; s++) { - unsigned int ss_cnt = 0; - if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0) /* skip disabled slice */ continue; @@ -5058,18 +5055,19 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, sseu->slice_mask |= BIT(s); if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) - ss_cnt = INTEL_INFO(dev_priv)->sseu.subslice_per_slice; + sseu->subslice_mask = + INTEL_INFO(dev_priv)->sseu.subslice_mask; for (ss = 0; ss < ss_max; ss++) { unsigned int eu_cnt; - if (IS_BROXTON(dev_priv) && - !(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss)))) - /* skip disabled subslice */ - continue; + if (IS_BROXTON(dev_priv)) { + if (!(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss)))) + /* skip disabled subslice */ + continue; - if (IS_BROXTON(dev_priv)) - ss_cnt++; + sseu->subslice_mask |= BIT(ss); + } eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] & eu_mask[ss%2]); @@ -5078,11 +5076,6 @@ static void gen9_sseu_device_status(struct drm_i915_private *dev_priv, sseu->eu_per_subslice, eu_cnt); } - - sseu->subslice_total += ss_cnt; - sseu->subslice_per_slice = max_t(unsigned int, - sseu->subslice_per_slice, - ss_cnt); } } @@ -5095,13 +5088,11 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, sseu->slice_mask = slice_info & GEN8_LSLICESTAT_MASK; if (sseu->slice_mask) { - sseu->subslice_per_slice = - INTEL_INFO(dev_priv)->sseu.subslice_per_slice; - sseu->subslice_total = hweight8(sseu->slice_mask) * - sseu->subslice_per_slice; + sseu->subslice_mask = INTEL_INFO(dev_priv)->sseu.subslice_mask; sseu->eu_per_subslice = INTEL_INFO(dev_priv)->sseu.eu_per_subslice; - sseu->eu_total = sseu->eu_per_subslice * sseu->subslice_total; + sseu->eu_total = sseu->eu_per_subslice * + sseu_subslice_total(sseu); /* subtract fused off EU(s) from enabled slice(s) */ for (s = 0; s < hweight8(sseu->slice_mask); s++) { @@ -5122,9 +5113,9 @@ static void i915_print_sseu_info(struct seq_file *m, bool is_available_info, seq_printf(m, " %s Slice Total: %u\n", type, hweight8(sseu->slice_mask)); seq_printf(m, " %s Subslice Total: %u\n", type, - sseu->subslice_total); + sseu_subslice_total(sseu)); seq_printf(m, " %s Subslice Per Slice: %u\n", type, - sseu->subslice_per_slice); + hweight8(sseu->subslice_mask)); seq_printf(m, " %s EU Total: %u\n", type, sseu->eu_total); seq_printf(m, " %s EU Per Subslice: %u\n", type, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5e22105b728f..02c34d6996ea 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -288,7 +288,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = i915_cmd_parser_get_version(dev_priv); break; case I915_PARAM_SUBSLICE_TOTAL: - value = INTEL_INFO(dev_priv)->sseu.subslice_total; + value = sseu_subslice_total(&INTEL_INFO(dev_priv)->sseu); if (!value) return -ENODEV; break; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1ebc5ba69e34..757b1d1b9366 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -673,8 +673,7 @@ struct intel_csr { struct sseu_dev_info { u8 slice_mask; - u8 subslice_total; - u8 subslice_per_slice; + u8 subslice_mask; u8 eu_total; u8 eu_per_subslice; u8 min_eu_in_pool; @@ -685,6 +684,11 @@ struct sseu_dev_info { u8 has_eu_pg:1; }; +static inline unsigned int sseu_subslice_total(const struct sseu_dev_info *sseu) +{ + return hweight8(sseu->slice_mask) * hweight8(sseu->subslice_mask); +} + struct intel_device_info { u32 display_mmio_offset; u16 device_id; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 139d5298cde5..0bdec5c59f48 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -54,26 +54,25 @@ static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) sseu->slice_mask = BIT(0); if (!(fuse & CHV_FGT_DISABLE_SS0)) { - sseu->subslice_per_slice++; + sseu->subslice_mask |= BIT(0); eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK | CHV_FGT_EU_DIS_SS0_R1_MASK); sseu->eu_total += 8 - hweight32(eu_dis); } if (!(fuse & CHV_FGT_DISABLE_SS1)) { - sseu->subslice_per_slice++; + sseu->subslice_mask |= BIT(1); eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK | CHV_FGT_EU_DIS_SS1_R1_MASK); sseu->eu_total += 8 - hweight32(eu_dis); } - sseu->subslice_total = sseu->subslice_per_slice; /* * CHV expected to always have a uniform distribution of EU * across subslices. */ - sseu->eu_per_subslice = sseu->subslice_total ? - sseu->eu_total / sseu->subslice_total : + sseu->eu_per_subslice = sseu_subslice_total(sseu) ? + sseu->eu_total / sseu_subslice_total(sseu) : 0; /* * CHV supports subslice power gating on devices with more than @@ -81,7 +80,7 @@ static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) * more than one EU pair per subslice. */ sseu->has_slice_pg = 0; - sseu->has_subslice_pg = (sseu->subslice_total > 1); + sseu->has_subslice_pg = sseu_subslice_total(sseu) > 1; sseu->has_eu_pg = (sseu->eu_per_subslice > 2); } @@ -91,20 +90,19 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) struct sseu_dev_info *sseu = &info->sseu; int s_max = 3, ss_max = 4, eu_max = 8; int s, ss; - u32 fuse2, ss_disable, eu_disable; + u32 fuse2, eu_disable; u8 eu_mask = 0xff; fuse2 = I915_READ(GEN8_FUSE2); sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; - ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >> GEN9_F2_SS_DIS_SHIFT; /* * The subslice disable field is global, i.e. it applies * to each of the enabled slices. */ - sseu->subslice_per_slice = ss_max - hweight32(ss_disable); - sseu->subslice_total = hweight8(sseu->slice_mask) * - sseu->subslice_per_slice; + sseu->subslice_mask = (1 << ss_max) - 1; + sseu->subslice_mask &= ~((fuse2 & GEN9_F2_SS_DIS_MASK) >> + GEN9_F2_SS_DIS_SHIFT); /* * Iterate through enabled slices and subslices to @@ -119,7 +117,7 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) for (ss = 0; ss < ss_max; ss++) { int eu_per_ss; - if (ss_disable & BIT(ss)) + if (!(sseu->subslice_mask & BIT(ss))) /* skip disabled subslice */ continue; @@ -145,9 +143,9 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) * recovery. BXT is expected to be perfectly uniform in EU * distribution. */ - sseu->eu_per_subslice = sseu->subslice_total ? + sseu->eu_per_subslice = sseu_subslice_total(sseu) ? DIV_ROUND_UP(sseu->eu_total, - sseu->subslice_total) : 0; + sseu_subslice_total(sseu)) : 0; /* * SKL supports slice power gating on devices with more than * one slice, and supports EU power gating on devices with @@ -160,11 +158,11 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && hweight8(sseu->slice_mask) > 1; sseu->has_subslice_pg = - IS_BROXTON(dev_priv) && sseu->subslice_total > 1; + IS_BROXTON(dev_priv) && sseu_subslice_total(sseu) > 1; sseu->has_eu_pg = sseu->eu_per_subslice > 2; if (IS_BROXTON(dev_priv)) { -#define IS_SS_DISABLED(_ss_disable, ss) (_ss_disable & BIT(ss)) +#define IS_SS_DISABLED(ss) (!(sseu->subslice_mask & BIT(ss))) /* * There is a HW issue in 2x6 fused down parts that requires * Pooled EU to be enabled as a WA. The pool configuration @@ -172,16 +170,15 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) * doesn't affect if the device has all 3 subslices enabled. */ /* WaEnablePooledEuFor2x6:bxt */ - info->has_pooled_eu = ((sseu->subslice_per_slice == 3) || - (sseu->subslice_per_slice == 2 && + info->has_pooled_eu = ((hweight8(sseu->subslice_mask) == 3) || + (hweight8(sseu->subslice_mask) == 2 && INTEL_REVID(dev_priv) < BXT_REVID_C0)); sseu->min_eu_in_pool = 0; if (info->has_pooled_eu) { - if (IS_SS_DISABLED(ss_disable, 0) || - IS_SS_DISABLED(ss_disable, 2)) + if (IS_SS_DISABLED(2) || IS_SS_DISABLED(0)) sseu->min_eu_in_pool = 3; - else if (IS_SS_DISABLED(ss_disable, 1)) + else if (IS_SS_DISABLED(1)) sseu->min_eu_in_pool = 6; else sseu->min_eu_in_pool = 9; @@ -195,11 +192,17 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; const int s_max = 3, ss_max = 3, eu_max = 8; int s, ss; - u32 fuse2, eu_disable[s_max], ss_disable; + u32 fuse2, eu_disable[s_max]; fuse2 = I915_READ(GEN8_FUSE2); sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; - ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT; + /* + * The subslice disable field is global, i.e. it applies + * to each of the enabled slices. + */ + sseu->subslice_mask = BIT(ss_max) - 1; + sseu->subslice_mask &= ~((fuse2 & GEN8_F2_SS_DIS_MASK) >> + GEN8_F2_SS_DIS_SHIFT); eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK; eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) | @@ -209,14 +212,6 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) << (32 - GEN8_EU_DIS1_S2_SHIFT)); - /* - * The subslice disable field is global, i.e. it applies - * to each of the enabled slices. - */ - sseu->subslice_per_slice = ss_max - hweight32(ss_disable); - sseu->subslice_total = hweight8(sseu->slice_mask) * - sseu->subslice_per_slice; - /* * Iterate through enabled slices and subslices to * count the total enabled EU. @@ -229,7 +224,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) for (ss = 0; ss < ss_max; ss++) { u32 n_disabled; - if (ss_disable & (0x1 << ss)) + if (!(sseu->subslice_mask & BIT(ss))) /* skip disabled subslice */ continue; @@ -250,8 +245,9 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) * subslices with the exception that any one EU in any one subslice may * be fused off for die recovery. */ - sseu->eu_per_subslice = sseu->subslice_total ? - DIV_ROUND_UP(sseu->eu_total, sseu->subslice_total) : 0; + sseu->eu_per_subslice = sseu_subslice_total(sseu) ? + DIV_ROUND_UP(sseu->eu_total, + sseu_subslice_total(sseu)) : 0; /* * BDW supports slice power gating on devices with more than @@ -375,9 +371,10 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) info->has_snoop = false; DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); - DRM_DEBUG_DRIVER("subslice total: %u\n", info->sseu.subslice_total); + DRM_DEBUG_DRIVER("subslice total: %u\n", + sseu_subslice_total(&info->sseu)); DRM_DEBUG_DRIVER("subslice per slice: %u\n", - info->sseu.subslice_per_slice); + hweight8(info->sseu.subslice_mask)); DRM_DEBUG_DRIVER("EU total: %u\n", info->sseu.eu_total); DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->sseu.eu_per_subslice); DRM_DEBUG_DRIVER("has slice power gating: %s\n", diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7209553ab162..92bfe47ad33c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1905,7 +1905,7 @@ make_rpcs(struct drm_i915_private *dev_priv) if (INTEL_INFO(dev_priv)->sseu.has_subslice_pg) { rpcs |= GEN8_RPCS_SS_CNT_ENABLE; - rpcs |= INTEL_INFO(dev_priv)->sseu.subslice_per_slice << + rpcs |= hweight8(INTEL_INFO(dev_priv)->sseu.subslice_mask) << GEN8_RPCS_SS_CNT_SHIFT; rpcs |= GEN8_RPCS_ENABLE; } -- cgit v1.2.1 From c67ba538753438a303c7522d6b2912863547e27c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 31 Aug 2016 19:13:06 +0300 Subject: drm/i915: sseu: Add debug printf for slice/subslice masks Reviewed-by: Robert Bragg Reviewed-by: Ben Widawsky Tested-by: Ben Widawsky Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1472659987-10417-7-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++++ drivers/gpu/drm/i915/intel_device_info.c | 2 ++ 2 files changed, 6 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d09c77f141ed..413989a62f75 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -5110,10 +5110,14 @@ static void i915_print_sseu_info(struct seq_file *m, bool is_available_info, struct drm_i915_private *dev_priv = node_to_i915(m->private); const char *type = is_available_info ? "Available" : "Enabled"; + seq_printf(m, " %s Slice Mask: %04x\n", type, + sseu->slice_mask); seq_printf(m, " %s Slice Total: %u\n", type, hweight8(sseu->slice_mask)); seq_printf(m, " %s Subslice Total: %u\n", type, sseu_subslice_total(sseu)); + seq_printf(m, " %s Subslice Mask: %04x\n", type, + sseu->subslice_mask); seq_printf(m, " %s Subslice Per Slice: %u\n", type, hweight8(sseu->subslice_mask)); seq_printf(m, " %s EU Total: %u\n", type, diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 0bdec5c59f48..73b6858600ac 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -370,9 +370,11 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) info->has_snoop = false; + DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask); DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); DRM_DEBUG_DRIVER("subslice total: %u\n", sseu_subslice_total(&info->sseu)); + DRM_DEBUG_DRIVER("subslice mask %04x\n", info->sseu.subslice_mask); DRM_DEBUG_DRIVER("subslice per slice: %u\n", hweight8(info->sseu.subslice_mask)); DRM_DEBUG_DRIVER("EU total: %u\n", info->sseu.eu_total); -- cgit v1.2.1 From 795b38b3928d0ad5a6b2a530b30916cc76f4b667 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 31 Aug 2016 19:13:07 +0300 Subject: drm/i915/bdw: sseu: Fix sseu status parsing Currently when checking for fused off EUs we may ignore the EU count in an enabled slice if there is any disabled slice preceding the enabled one (with a lower slice ID). Perhaps this can't happen in reality, but there is no reason to have this assumption built-in, the code is clearer without it. Reviewed-by: Robert Bragg Reviewed-by: Ben Widawsky Tested-by: Ben Widawsky Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1472659987-10417-8-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 413989a62f75..7be8321a32b3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -5095,7 +5095,7 @@ static void broadwell_sseu_device_status(struct drm_i915_private *dev_priv, sseu_subslice_total(sseu); /* subtract fused off EU(s) from enabled slice(s) */ - for (s = 0; s < hweight8(sseu->slice_mask); s++) { + for (s = 0; s < fls(sseu->slice_mask); s++) { u8 subslice_7eu = INTEL_INFO(dev_priv)->sseu.subslice_7eu[s]; -- cgit v1.2.1 From 02c53d99b6eb44c7a78e648d023d0485b71f661e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 3 Sep 2016 07:53:42 +0100 Subject: drm/i915: debugfs/i915_gem_seqno_info does not need rpm nor struct_mutex i915_gem_seqno_info() supplies its own spinlocks to access the waiters, and doesn't need any GGTT or mmio access. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160903065343.25151-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_debugfs.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7be8321a32b3..3590f1fe988e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -714,21 +714,11 @@ static void i915_ring_seqno_info(struct seq_file *m, static int i915_gem_seqno_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; - int ret; - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - intel_runtime_pm_get(dev_priv); for_each_engine(engine, dev_priv) i915_ring_seqno_info(m, engine); - intel_runtime_pm_put(dev_priv); - mutex_unlock(&dev->struct_mutex); - return 0; } -- cgit v1.2.1 From 4bb05040fd685c549e6550f09daffee6cde4c370 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 3 Sep 2016 07:53:43 +0100 Subject: drm/i915: debugfs/i915_gem_interrupt_info does not need struct_mutex i915_gem_interrupt_info() only looks at mmio registers, and the waiters under a spinlock. It doesn't need struct_mutex (but does need the rpm wakelock for mmio access). Maybe useful using get_if_notidle? Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160903065343.25151-2-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/i915_debugfs.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3590f1fe988e..b8e40fde132a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -726,13 +726,9 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) static int i915_interrupt_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; struct intel_engine_cs *engine; - int ret, i, pipe; + int i, pipe; - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; intel_runtime_pm_get(dev_priv); if (IS_CHERRYVIEW(dev_priv)) { @@ -908,7 +904,6 @@ static int i915_interrupt_info(struct seq_file *m, void *data) i915_ring_seqno_info(m, engine); } intel_runtime_pm_put(dev_priv); - mutex_unlock(&dev->struct_mutex); return 0; } -- cgit v1.2.1 From 535b2f5e12d0b04a3f34c70edcbcd43993c27f3a Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Thu, 18 Aug 2016 18:17:23 +0100 Subject: drm/i915/guc: downgrade some DRM_ERROR() messages to DRM_WARN() Where we're going to continue regardless of the problem, rather than fail, then the message should be a WARNing rather than an ERROR. Signed-off-by: Dave Gordon Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_guc_submission.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 32699a744aca..77526d7f41f8 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -114,10 +114,8 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len) if (ret != -ETIMEDOUT) ret = -EIO; - DRM_ERROR("GUC: host2guc action 0x%X failed. ret=%d " - "status=0x%08X response=0x%08X\n", - data[0], ret, status, - I915_READ(SOFT_SCRATCH(15))); + DRM_WARN("Action 0x%X failed; ret=%d status=0x%08X response=0x%08X\n", + data[0], ret, status, I915_READ(SOFT_SCRATCH(15))); dev_priv->guc.action_fail += 1; dev_priv->guc.action_err = ret; @@ -552,8 +550,8 @@ static int guc_ring_doorbell(struct i915_guc_client *gc) if (db_ret.db_status == GUC_DOORBELL_DISABLED) break; - DRM_ERROR("Cookie mismatch. Expected %d, returned %d\n", - db_cmp.cookie, db_ret.cookie); + DRM_WARN("Cookie mismatch. Expected %d, found %d\n", + db_cmp.cookie, db_ret.cookie); /* update the cookie to newly read cookie from GuC */ db_cmp.cookie = db_ret.cookie; @@ -734,8 +732,8 @@ static void guc_init_doorbell_hw(struct intel_guc *guc) /* Restore to original value */ err = guc_update_doorbell_id(guc, client, db_id); if (err) - DRM_ERROR("Failed to restore doorbell to %d, err %d\n", - db_id, err); + DRM_WARN("Failed to restore doorbell to %d, err %d\n", + db_id, err); /* Read back & verify all doorbell registers */ for (i = 0; i < GUC_MAX_DOORBELLS; ++i) @@ -824,8 +822,6 @@ guc_client_alloc(struct drm_i915_private *dev_priv, return client; err: - DRM_ERROR("FAILED to create priority %u GuC client!\n", priority); - guc_client_free(dev_priv, client); return NULL; } @@ -1005,7 +1001,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) GUC_CTX_PRIORITY_KMD_NORMAL, dev_priv->kernel_context); if (!client) { - DRM_ERROR("Failed to create execbuf guc_client\n"); + DRM_ERROR("Failed to create normal GuC client!\n"); return -ENOMEM; } -- cgit v1.2.1 From fc32de9358c0a7b6f7c4639a3a8056b10a9b7669 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Thu, 18 Aug 2016 18:17:24 +0100 Subject: drm/i915/guc: revisit GuC loader message levels Some downgraded from DRM_ERROR() to DRM_WARN() or DRM_NOTE(), a few upgraded from DRM_INFO() to DRM_NOTE() or DRM_WARN(), and one eliminated completely. v2: different permutation of levels :) v3: convert a couple of "this shouldn't happen" messages to WARN() Signed-off-by: Dave Gordon Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_guc_loader.c | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index e67d8de427d0..853928f21596 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -152,12 +152,14 @@ static u32 get_gttype(struct drm_i915_private *dev_priv) static u32 get_core_family(struct drm_i915_private *dev_priv) { - switch (INTEL_INFO(dev_priv)->gen) { + u32 gen = INTEL_GEN(dev_priv); + + switch (gen) { case 9: return GFXCORE_FAMILY_GEN9; default: - DRM_ERROR("GUC: unsupported core family\n"); + WARN(1, "GEN%d does not support GuC operation!\n", gen); return GFXCORE_FAMILY_UNKNOWN; } } @@ -447,7 +449,7 @@ int intel_guc_setup(struct drm_device *dev) goto fail; } else if (*fw_path == '\0') { /* Device has a GuC but we don't know what f/w to load? */ - DRM_INFO("No GuC firmware known for this platform\n"); + WARN(1, "No GuC firmware known for this platform!\n"); err = -ENODEV; goto fail; } @@ -485,10 +487,8 @@ int intel_guc_setup(struct drm_device *dev) * that the state and timing are fairly predictable */ err = i915_reset_guc(dev_priv); - if (err) { - DRM_ERROR("GuC reset failed: %d\n", err); + if (err) goto fail; - } err = guc_ucode_xfer(dev_priv); if (!err) @@ -546,15 +546,15 @@ fail: else if (err == 0) DRM_INFO("GuC firmware load skipped\n"); else if (ret != -EIO) - DRM_INFO("GuC firmware load failed: %d\n", err); + DRM_NOTE("GuC firmware load failed: %d\n", err); else - DRM_ERROR("GuC firmware load failed: %d\n", err); + DRM_WARN("GuC firmware load failed: %d\n", err); if (i915.enable_guc_submission) { if (fw_path == NULL) DRM_INFO("GuC submission without firmware not supported\n"); if (ret == 0) - DRM_INFO("Falling back from GuC submission to execlist mode\n"); + DRM_NOTE("Falling back from GuC submission to execlist mode\n"); else DRM_ERROR("GuC init failed: %d\n", ret); } @@ -586,7 +586,7 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) /* Check the size of the blob before examining buffer contents */ if (fw->size < sizeof(struct guc_css_header)) { - DRM_ERROR("Firmware header is missing\n"); + DRM_NOTE("Firmware header is missing\n"); goto fail; } @@ -598,7 +598,7 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) css->key_size_dw - css->exponent_size_dw) * sizeof(u32); if (guc_fw->header_size != sizeof(struct guc_css_header)) { - DRM_ERROR("CSS header definition mismatch\n"); + DRM_NOTE("CSS header definition mismatch\n"); goto fail; } @@ -608,7 +608,7 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) /* now RSA */ if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) { - DRM_ERROR("RSA key size is bad\n"); + DRM_NOTE("RSA key size is bad\n"); goto fail; } guc_fw->rsa_offset = guc_fw->ucode_offset + guc_fw->ucode_size; @@ -617,14 +617,14 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) /* At least, it should have header, uCode and RSA. Size of all three. */ size = guc_fw->header_size + guc_fw->ucode_size + guc_fw->rsa_size; if (fw->size < size) { - DRM_ERROR("Missing firmware components\n"); + DRM_NOTE("Missing firmware components\n"); goto fail; } /* Header and uCode will be loaded to WOPCM. Size of the two. */ size = guc_fw->header_size + guc_fw->ucode_size; if (size > guc_wopcm_size(to_i915(dev))) { - DRM_ERROR("Firmware is too large to fit in WOPCM\n"); + DRM_NOTE("Firmware is too large to fit in WOPCM\n"); goto fail; } @@ -639,7 +639,7 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) if (guc_fw->guc_fw_major_found != guc_fw->guc_fw_major_wanted || guc_fw->guc_fw_minor_found < guc_fw->guc_fw_minor_wanted) { - DRM_ERROR("GuC firmware version %d.%d, required %d.%d\n", + DRM_NOTE("GuC firmware version %d.%d, required %d.%d\n", guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found, guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted); err = -ENOEXEC; @@ -669,10 +669,10 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw) return; fail: + DRM_WARN("Failed to fetch valid GuC firmware from %s (error %d)\n", + guc_fw->guc_fw_path, err); DRM_DEBUG_DRIVER("GuC fw fetch status FAIL; err %d, fw %p, obj %p\n", err, fw, guc_fw->guc_fw_obj); - DRM_ERROR("Failed to fetch GuC firmware from %s (error %d)\n", - guc_fw->guc_fw_path, err); mutex_lock(&dev->struct_mutex); obj = guc_fw->guc_fw_obj; -- cgit v1.2.1 From 19eb9189c55715b8e15401fb6d862c5766724220 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 6 Sep 2016 08:38:44 +0100 Subject: drm/i915: Don't wait for a spinlock inside error capture If we can't grab the breadcrumb's spinlock, possibly due to a driver deadlock inside the waiters, ignore them. Like hangcheck, error capturing must work no matter how the driver/GPU dies. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160906073844.22561-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gpu_error.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index aed55e4f100f..d45a959b7c53 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -489,7 +489,10 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } } - if (ee->num_waiters) { + if (IS_ERR(ee->waiters)) { + err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n", + dev_priv->engine[i].name); + } else if (ee->num_waiters) { err_printf(m, "%s --- %d waiters\n", dev_priv->engine[i].name, ee->num_waiters); @@ -648,7 +651,8 @@ static void i915_error_state_free(struct kref *error_ref) i915_error_object_free(ee->wa_ctx); kfree(ee->requests); - kfree(ee->waiters); + if (!IS_ERR_OR_NULL(ee->waiters)) + kfree(ee->waiters); } i915_error_object_free(error->semaphore); @@ -933,7 +937,14 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine, ee->num_waiters = 0; ee->waiters = NULL; - spin_lock(&b->lock); + if (RB_EMPTY_ROOT(&b->waiters)) + return; + + if (!spin_trylock(&b->lock)) { + ee->waiters = ERR_PTR(-EDEADLK); + return; + } + count = 0; for (rb = rb_first(&b->waiters); rb != NULL; rb = rb_next(rb)) count++; @@ -947,9 +958,13 @@ static void error_record_engine_waiters(struct intel_engine_cs *engine, if (!waiter) return; - ee->waiters = waiter; + if (!spin_trylock(&b->lock)) { + kfree(waiter); + ee->waiters = ERR_PTR(-EDEADLK); + return; + } - spin_lock(&b->lock); + ee->waiters = waiter; for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { struct intel_wait *w = container_of(rb, typeof(*w), node); -- cgit v1.2.1 From 8ef89995c735f978d5dfcb3ca6bce70d41728c91 Mon Sep 17 00:00:00 2001 From: Ping Gao Date: Tue, 6 Sep 2016 12:04:11 +0800 Subject: drm/i915: enable vGPU detection for all vGPU capability is handled by GVT-g host driver, not needed to put extra HW check for vGPU detection. And we'll actually support vGPU from BDW. Signed-off-by: Ping Gao Signed-off-by: Zhenyu Wang Reviewed-by: Joonas Lahtinen Acked-by: Chris Wilson Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/20160906040412.1274-2-zhenyuw@linux.intel.com --- drivers/gpu/drm/i915/i915_vgpu.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c index 142bac976919..38f805e689d8 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.c +++ b/drivers/gpu/drm/i915/i915_vgpu.c @@ -65,9 +65,6 @@ void i915_check_vgpu(struct drm_i915_private *dev_priv) BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE); - if (!IS_HASWELL(dev_priv)) - return; - magic = __raw_i915_read64(dev_priv, vgtif_reg(magic)); if (magic != VGT_MAGIC) return; -- cgit v1.2.1 From e320d40022128845dfff900422ea9fd69f576c98 Mon Sep 17 00:00:00 2001 From: Zhi Wang Date: Tue, 6 Sep 2016 12:04:12 +0800 Subject: drm/i915: disable 48bit full PPGTT when vGPU is active Disable 48bit full PPGTT on vGPU too for now. Signed-off-by: Zhi Wang Signed-off-by: Zhenyu Wang Reviewed-by: Joonas Lahtinen Acked-by: Chris Wilson Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/20160906040412.1274-3-zhenyuw@linux.intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 570e7311a419..e16c38086abe 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -124,8 +124,11 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, has_full_48bit_ppgtt = IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9; - if (intel_vgpu_active(dev_priv)) - has_full_ppgtt = false; /* emulation is too hard */ + if (intel_vgpu_active(dev_priv)) { + /* emulation is too hard */ + has_full_ppgtt = false; + has_full_48bit_ppgtt = false; + } if (!has_aliasing_ppgtt) return 0; @@ -160,7 +163,7 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, return 0; } - if (INTEL_GEN(dev_priv) >= 8 && i915.enable_execlists) + if (INTEL_GEN(dev_priv) >= 8 && i915.enable_execlists && has_full_ppgtt) return has_full_48bit_ppgtt ? 3 : 2; else return has_aliasing_ppgtt ? 1 : 0; -- cgit v1.2.1 From b18c1bb48eb5911bf99fbc5bf6509d4ae06feb9d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 6 Sep 2016 15:45:38 +0100 Subject: drm/i915: Remove 64b mmio write vfuncs We don't have safe 64-bit mmio writes as they are really split into 2x32-bit writes. This tearing is dangerous as the hardware *will* operate on the intermediate value, requiring great care when assigning. (See, for example, i965_write_fence_reg.) As such we don't currently use them and strongly advise not to us them. Go one step further and remove the 64-bit write vfuncs. v2: Add some more details to the comment about why WRITE64 is absent, and why you need to think twice before using READ64. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160906144538.4204-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 13 +++++++++---- drivers/gpu/drm/i915/intel_uncore.c | 9 --------- 2 files changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 757b1d1b9366..ecfd8e9726b5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -579,8 +579,6 @@ struct intel_uncore_funcs { uint16_t val, bool trace); void (*mmio_writel)(struct drm_i915_private *dev_priv, i915_reg_t r, uint32_t val, bool trace); - void (*mmio_writeq)(struct drm_i915_private *dev_priv, i915_reg_t r, - uint64_t val, bool trace); }; struct intel_uncore { @@ -3758,9 +3756,16 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); * will be implemented using 2 32-bit writes in an arbitrary order with * an arbitrary delay between them. This can cause the hardware to * act upon the intermediate value, possibly leading to corruption and - * machine death. You have been warned. + * machine death. For this reason we do not support I915_WRITE64, or + * dev_priv->uncore.funcs.mmio_writeq. + * + * When reading a 64-bit value as two 32-bit values, the delay may cause + * the two reads to mismatch, e.g. a timestamp overflowing. Also note that + * occasionally a 64-bit register does not actualy support a full readq + * and must be read using two 32-bit reads. + * + * You have been warned. */ -#define I915_WRITE64(reg, val) dev_priv->uncore.funcs.mmio_writeq(dev_priv, (reg), (val), true) #define I915_READ64(reg) dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true) #define I915_READ64_2x32(lower_reg, upper_reg) ({ \ diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index e9f68cd56e32..a9b6c936aadd 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1018,11 +1018,9 @@ gen5_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool __gen5_write(8) __gen5_write(16) __gen5_write(32) -__gen5_write(64) __gen2_write(8) __gen2_write(16) __gen2_write(32) -__gen2_write(64) #undef __gen5_write #undef __gen2_write @@ -1112,23 +1110,18 @@ gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \ __gen9_write(8) __gen9_write(16) __gen9_write(32) -__gen9_write(64) __chv_write(8) __chv_write(16) __chv_write(32) -__chv_write(64) __gen8_write(8) __gen8_write(16) __gen8_write(32) -__gen8_write(64) __hsw_write(8) __hsw_write(16) __hsw_write(32) -__hsw_write(64) __gen6_write(8) __gen6_write(16) __gen6_write(32) -__gen6_write(64) #undef __gen9_write #undef __chv_write @@ -1158,7 +1151,6 @@ static void vgpu_write##x(struct drm_i915_private *dev_priv, \ __vgpu_write(8) __vgpu_write(16) __vgpu_write(32) -__vgpu_write(64) #undef __vgpu_write #undef VGPU_WRITE_FOOTER @@ -1169,7 +1161,6 @@ do { \ dev_priv->uncore.funcs.mmio_writeb = x##_write8; \ dev_priv->uncore.funcs.mmio_writew = x##_write16; \ dev_priv->uncore.funcs.mmio_writel = x##_write32; \ - dev_priv->uncore.funcs.mmio_writeq = x##_write64; \ } while (0) #define ASSIGN_READ_MMIO_VFUNCS(x) \ -- cgit v1.2.1 From ccebc23b57c313229526dc76383ce82f5e0b9001 Mon Sep 17 00:00:00 2001 From: Lyude Date: Mon, 29 Aug 2016 12:31:27 -0400 Subject: drm/i915/skl: Don't try to update plane watermarks if they haven't changed i915 sometimes needs to disable planes in the middle of an atomic commit, and then reenable them later in the same commit. Because of this, we can't make the assumption that the state of the plane actually changed. Since the state of the plane hasn't actually changed, neither have it's watermarks. And if the watermarks hasn't changed then we haven't populated skl_results with anything, which means we'll end up zeroing out a plane's watermarks in the middle of the atomic commit without restoring them later. Simple reproduction recipe: - Get a SKL laptop, launch any kind of X session - Get two extra monitors - Keep hotplugging both displays (so that the display configuration jumps from 1 active pipe to 3 active pipes and back) - Eventually underrun Changes since v1: - Fix incorrect use of "it's" Changes since v2: - Add reproduction recipe Signed-off-by: Lyude Cc: Maarten Lankhorst Fixes: 62e0fb880123 ("drm/i915/skl: Update plane watermarks atomically during plane updates") Signed-off-by: Lyude Testcase: kms_plane Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1472488288-27280-1-git-send-email-cpaul@redhat.com Cc: drm-intel-fixes@lists.freedesktop.org --- drivers/gpu/drm/i915/intel_display.c | 7 ++++++- drivers/gpu/drm/i915/intel_sprite.c | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2c05a4c6018f..2e7923d80f21 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3448,7 +3448,12 @@ static void skylake_disable_primary_plane(struct drm_plane *primary, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - skl_write_plane_wm(intel_crtc, &dev_priv->wm.skl_results, 0); + /* + * We only populate skl_results on watermark updates, and if the + * plane's visiblity isn't actually changing neither is its watermarks. + */ + if (!crtc->primary->state->visible) + skl_write_plane_wm(intel_crtc, &dev_priv->wm.skl_results, 0); I915_WRITE(PLANE_CTL(pipe, 0), 0); I915_WRITE(PLANE_SURF(pipe, 0), 0); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 0df783a66bfb..73a521fdf1bd 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -292,8 +292,13 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) const int pipe = intel_plane->pipe; const int plane = intel_plane->plane + 1; - skl_write_plane_wm(to_intel_crtc(crtc), &dev_priv->wm.skl_results, - plane); + /* + * We only populate skl_results on watermark updates, and if the + * plane's visiblity isn't actually changing neither is its watermarks. + */ + if (!dplane->state->visible) + skl_write_plane_wm(to_intel_crtc(crtc), + &dev_priv->wm.skl_results, plane); I915_WRITE(PLANE_CTL(pipe, plane), 0); -- cgit v1.2.1 From 23f889bdf6ee5cfff012d8b09f6bec920c691696 Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Wed, 17 Aug 2016 15:47:48 +0300 Subject: Revert "drm/i915: Check live status before reading edid" This reverts commit 237ed86c693d8a8e4db476976aeb30df4deac74b. Our current implementation of live status check (repeat 9 times with 10ms delays between each attempt as a workaround for buggy displays) imposes a rather serious penalty, time wise, on intel_hdmi_detect(). Since we we already skip live status checks on platforms before gen 7, and since we seem to have coped quite well before the live status check was introduced for newer platforms too, the previous behaviour is probably preferable, at least unless someone can point to a use-case that the live status check improves (apart from "Bspec says so".) Signed-off-by: David Weinehall Fixes: 237ed86c693d ("drm/i915: Check live status before reading edid") Fixes: f8d03ea0053b ("drm/i915: increase the tries for HDMI hotplug live status checking") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97139 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94014 Acked-by: Chris Wilson Cc: stable@vger.kernel.org # v4.4+ Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/20160817124748.31208-1-david.weinehall@linux.intel.com --- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 -- drivers/gpu/drm/i915/intel_hdmi.c | 43 +++++++++------------------------------ 3 files changed, 11 insertions(+), 36 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e4a25668ccf6..4b14565afb3d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4197,7 +4197,7 @@ static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, * * Return %true if @port is connected, %false otherwise. */ -bool intel_digital_port_connected(struct drm_i915_private *dev_priv, +static bool intel_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { if (HAS_PCH_IBX(dev_priv)) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index debbc1b5b0f9..e1cdbb2e7b8e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1419,8 +1419,6 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); -bool intel_digital_port_connected(struct drm_i915_private *dev_priv, - struct intel_digital_port *port); void intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 1a116a6a1817..c51073f78730 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1439,24 +1439,22 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) } static bool -intel_hdmi_set_edid(struct drm_connector *connector, bool force) +intel_hdmi_set_edid(struct drm_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); - struct edid *edid = NULL; + struct edid *edid; bool connected = false; - if (force) { - intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); + intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - edid = drm_get_edid(connector, - intel_gmbus_get_adapter(dev_priv, - intel_hdmi->ddc_bus)); + edid = drm_get_edid(connector, + intel_gmbus_get_adapter(dev_priv, + intel_hdmi->ddc_bus)); - intel_hdmi_dp_dual_mode_detect(connector, edid != NULL); + intel_hdmi_dp_dual_mode_detect(connector, edid != NULL); - intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); - } + intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); to_intel_connector(connector)->detect_edid = edid; if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { @@ -1482,37 +1480,16 @@ static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { enum drm_connector_status status; - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct drm_i915_private *dev_priv = to_i915(connector->dev); - bool live_status = false; - unsigned int try; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - for (try = 0; !live_status && try < 9; try++) { - if (try) - msleep(10); - live_status = intel_digital_port_connected(dev_priv, - hdmi_to_dig_port(intel_hdmi)); - } - - if (!live_status) { - DRM_DEBUG_KMS("HDMI live status down\n"); - /* - * Live status register is not reliable on all intel platforms. - * So consider live_status only for certain platforms, for - * others, read EDID to determine presence of sink. - */ - if (INTEL_INFO(dev_priv)->gen < 7 || IS_IVYBRIDGE(dev_priv)) - live_status = true; - } - intel_hdmi_unset_edid(connector); - if (intel_hdmi_set_edid(connector, live_status)) { + if (intel_hdmi_set_edid(connector)) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; @@ -1538,7 +1515,7 @@ intel_hdmi_force(struct drm_connector *connector) if (connector->status != connector_status_connected) return; - intel_hdmi_set_edid(connector, true); + intel_hdmi_set_edid(connector); hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; } -- cgit v1.2.1 From dfa104803523a57711d575dfca898c0b3761f5eb Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 1 Sep 2016 15:08:06 -0700 Subject: drm/i915: Don't pass crtc_state to intel_dp_set_link_params() Decouple intel_dp_set_link_params() from struct intel_crtc_state. This will be useful for implementing DP upfront link training. v2: * Rebased on atomic state changes (Manasi) Reviewed-by: Durgadoss R Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Manasi Navare Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_ddi.c | 5 ++++- drivers/gpu/drm/i915/intel_dp.c | 14 +++++++++----- drivers/gpu/drm/i915/intel_dp_mst.c | 6 ++++-- drivers/gpu/drm/i915/intel_drv.h | 3 ++- 4 files changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index ce369c2e96a0..d825b6880bb1 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1639,7 +1639,10 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder, intel_prepare_dp_ddi_buffers(intel_encoder); - intel_dp_set_link_params(intel_dp, crtc->config); + intel_dp_set_link_params(intel_dp, crtc->config->port_clock, + crtc->config->lane_count, + intel_crtc_has_type(crtc->config, + INTEL_OUTPUT_DP_MST)); intel_ddi_init_dp_buf_reg(intel_encoder); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4b14565afb3d..75ac62fa6bf5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1641,11 +1641,12 @@ found: } void intel_dp_set_link_params(struct intel_dp *intel_dp, - const struct intel_crtc_state *pipe_config) + int link_rate, uint8_t lane_count, + bool link_mst) { - intel_dp->link_rate = pipe_config->port_clock; - intel_dp->lane_count = pipe_config->lane_count; - intel_dp->link_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST); + intel_dp->link_rate = link_rate; + intel_dp->lane_count = lane_count; + intel_dp->link_mst = link_mst; } static void intel_dp_prepare(struct intel_encoder *encoder, @@ -1658,7 +1659,10 @@ static void intel_dp_prepare(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - intel_dp_set_link_params(intel_dp, pipe_config); + intel_dp_set_link_params(intel_dp, pipe_config->port_clock, + pipe_config->lane_count, + intel_crtc_has_type(pipe_config, + INTEL_OUTPUT_DP_MST)); /* * There are four kinds of DP registers: diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 29ba4f6bd01f..b228b46e1223 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -153,8 +153,10 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, intel_ddi_clk_select(&intel_dig_port->base, pipe_config); intel_prepare_dp_ddi_buffers(&intel_dig_port->base); - - intel_dp_set_link_params(intel_dp, pipe_config); + intel_dp_set_link_params(intel_dp, + pipe_config->port_clock, + pipe_config->lane_count, + true); intel_ddi_init_dp_buf_reg(&intel_dig_port->base); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e1cdbb2e7b8e..fef4b362d55b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1383,7 +1383,8 @@ bool intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector); void intel_dp_set_link_params(struct intel_dp *intel_dp, - const struct intel_crtc_state *pipe_config); + int link_rate, uint8_t lane_count, + bool link_mst); void intel_dp_start_link_train(struct intel_dp *intel_dp); void intel_dp_stop_link_train(struct intel_dp *intel_dp); void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); -- cgit v1.2.1 From c856052abc769da6d16d0df8807320ccc854c5d9 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 1 Sep 2016 15:08:07 -0700 Subject: drm/i915: Remove ddi_pll_sel from intel_crtc_state The value of ddi_pll_sel is derived from the selection of shared dpll, so just calculate the final value when necessary. v2: Actually remove it from crtc state and delete remaining usages. (CI) Reviewed-by: Durgadoss R Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_ddi.c | 45 ++++++++++++++++++++++++++--------- drivers/gpu/drm/i915/intel_display.c | 43 +++++++-------------------------- drivers/gpu/drm/i915/intel_dp_mst.c | 3 ++- drivers/gpu/drm/i915/intel_dpll_mgr.c | 27 --------------------- drivers/gpu/drm/i915/intel_drv.h | 8 +------ 5 files changed, 45 insertions(+), 81 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index d825b6880bb1..f798760426c6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -546,6 +546,27 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port)); } +static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll) +{ + switch (pll->id) { + case DPLL_ID_WRPLL1: + return PORT_CLK_SEL_WRPLL1; + case DPLL_ID_WRPLL2: + return PORT_CLK_SEL_WRPLL2; + case DPLL_ID_SPLL: + return PORT_CLK_SEL_SPLL; + case DPLL_ID_LCPLL_810: + return PORT_CLK_SEL_LCPLL_810; + case DPLL_ID_LCPLL_1350: + return PORT_CLK_SEL_LCPLL_1350; + case DPLL_ID_LCPLL_2700: + return PORT_CLK_SEL_LCPLL_2700; + default: + MISSING_CASE(pll->id); + return PORT_CLK_SEL_NONE; + } +} + /* Starting with Haswell, different DDI ports can work in FDI mode for * connection to the PCH-located connectors. For this, it is necessary to train * both the DDI port and PCH receiver for the desired DDI buffer settings. @@ -561,7 +582,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; - u32 temp, i, rx_ctl_val; + u32 temp, i, rx_ctl_val, ddi_pll_sel; for_each_encoder_on_crtc(dev, crtc, encoder) { WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG); @@ -592,8 +613,9 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val); /* Configure Port Clock Select */ - I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->config->ddi_pll_sel); - WARN_ON(intel_crtc->config->ddi_pll_sel != PORT_CLK_SEL_SPLL); + ddi_pll_sel = hsw_pll_to_ddi_pll_sel(intel_crtc->config->shared_dpll); + I915_WRITE(PORT_CLK_SEL(PORT_E), ddi_pll_sel); + WARN_ON(ddi_pll_sel != PORT_CLK_SEL_SPLL); /* Start the training iterating through available voltages and emphasis, * testing each value twice. */ @@ -870,7 +892,7 @@ static void skl_ddi_clock_get(struct intel_encoder *encoder, int link_clock = 0; uint32_t dpll_ctl1, dpll; - dpll = pipe_config->ddi_pll_sel; + dpll = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll); dpll_ctl1 = I915_READ(DPLL_CTRL1); @@ -918,7 +940,7 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, int link_clock = 0; u32 val, pll; - val = pipe_config->ddi_pll_sel; + val = hsw_pll_to_ddi_pll_sel(pipe_config->shared_dpll); switch (val & PORT_CLK_SEL_MASK) { case PORT_CLK_SEL_LCPLL_810: link_clock = 81000; @@ -1586,13 +1608,15 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) } void intel_ddi_clk_select(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config) + struct intel_shared_dpll *pll) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = intel_ddi_get_encoder_port(encoder); + if (WARN_ON(!pll)) + return; + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { - uint32_t dpll = pipe_config->ddi_pll_sel; uint32_t val; /* DDI -> PLL mapping */ @@ -1600,14 +1624,13 @@ void intel_ddi_clk_select(struct intel_encoder *encoder, val &= ~(DPLL_CTRL2_DDI_CLK_OFF(port) | DPLL_CTRL2_DDI_CLK_SEL_MASK(port)); - val |= (DPLL_CTRL2_DDI_CLK_SEL(dpll, port) | + val |= (DPLL_CTRL2_DDI_CLK_SEL(pll->id, port) | DPLL_CTRL2_DDI_SEL_OVERRIDE(port)); I915_WRITE(DPLL_CTRL2, val); } else if (INTEL_INFO(dev_priv)->gen < 9) { - WARN_ON(pipe_config->ddi_pll_sel == PORT_CLK_SEL_NONE); - I915_WRITE(PORT_CLK_SEL(port), pipe_config->ddi_pll_sel); + I915_WRITE(PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll)); } } @@ -1632,7 +1655,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder, intel_edp_panel_on(intel_dp); } - intel_ddi_clk_select(intel_encoder, crtc->config); + intel_ddi_clk_select(intel_encoder, crtc->config->shared_dpll); if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2e7923d80f21..76d696b9b22f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10435,15 +10435,12 @@ static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, switch (port) { case PORT_A: - pipe_config->ddi_pll_sel = SKL_DPLL0; id = DPLL_ID_SKL_DPLL0; break; case PORT_B: - pipe_config->ddi_pll_sel = SKL_DPLL1; id = DPLL_ID_SKL_DPLL1; break; case PORT_C: - pipe_config->ddi_pll_sel = SKL_DPLL2; id = DPLL_ID_SKL_DPLL2; break; default: @@ -10462,25 +10459,10 @@ static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, u32 temp; temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); - pipe_config->ddi_pll_sel = temp >> (port * 3 + 1); + id = temp >> (port * 3 + 1); - switch (pipe_config->ddi_pll_sel) { - case SKL_DPLL0: - id = DPLL_ID_SKL_DPLL0; - break; - case SKL_DPLL1: - id = DPLL_ID_SKL_DPLL1; - break; - case SKL_DPLL2: - id = DPLL_ID_SKL_DPLL2; - break; - case SKL_DPLL3: - id = DPLL_ID_SKL_DPLL3; - break; - default: - MISSING_CASE(pipe_config->ddi_pll_sel); + if (WARN_ON(id < SKL_DPLL0 || id > SKL_DPLL3)) return; - } pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); } @@ -10490,10 +10472,9 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, struct intel_crtc_state *pipe_config) { enum intel_dpll_id id; + uint32_t ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); - pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); - - switch (pipe_config->ddi_pll_sel) { + switch (ddi_pll_sel) { case PORT_CLK_SEL_WRPLL1: id = DPLL_ID_WRPLL1; break; @@ -10513,7 +10494,7 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, id = DPLL_ID_LCPLL_2700; break; default: - MISSING_CASE(pipe_config->ddi_pll_sel); + MISSING_CASE(ddi_pll_sel); /* fall through */ case PORT_CLK_SEL_NONE: return; @@ -12797,10 +12778,9 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); if (IS_BROXTON(dev)) { - DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," + DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, " "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n", - pipe_config->ddi_pll_sel, pipe_config->dpll_hw_state.ebb0, pipe_config->dpll_hw_state.ebb4, pipe_config->dpll_hw_state.pll0, @@ -12813,15 +12793,13 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->dpll_hw_state.pll10, pipe_config->dpll_hw_state.pcsdw12); } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { - DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: " + DRM_DEBUG_KMS("dpll_hw_state: " "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n", - pipe_config->ddi_pll_sel, pipe_config->dpll_hw_state.ctrl1, pipe_config->dpll_hw_state.cfgcr1, pipe_config->dpll_hw_state.cfgcr2); } else if (HAS_DDI(dev)) { - DRM_DEBUG_KMS("ddi_pll_sel: 0x%x; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", - pipe_config->ddi_pll_sel, + DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", pipe_config->dpll_hw_state.wrpll, pipe_config->dpll_hw_state.spll); } else { @@ -12930,7 +12908,6 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) struct intel_crtc_scaler_state scaler_state; struct intel_dpll_hw_state dpll_hw_state; struct intel_shared_dpll *shared_dpll; - uint32_t ddi_pll_sel; bool force_thru; /* FIXME: before the switch to atomic started, a new pipe_config was @@ -12942,7 +12919,6 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) scaler_state = crtc_state->scaler_state; shared_dpll = crtc_state->shared_dpll; dpll_hw_state = crtc_state->dpll_hw_state; - ddi_pll_sel = crtc_state->ddi_pll_sel; force_thru = crtc_state->pch_pfit.force_thru; memset(crtc_state, 0, sizeof *crtc_state); @@ -12951,7 +12927,6 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) crtc_state->scaler_state = scaler_state; crtc_state->shared_dpll = shared_dpll; crtc_state->dpll_hw_state = dpll_hw_state; - crtc_state->ddi_pll_sel = ddi_pll_sel; crtc_state->pch_pfit.force_thru = force_thru; } @@ -13374,8 +13349,6 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(double_wide); - PIPE_CONF_CHECK_X(ddi_pll_sel); - PIPE_CONF_CHECK_P(shared_dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index b228b46e1223..54a9d7610d8f 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -150,7 +150,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); if (intel_dp->active_mst_links == 0) { - intel_ddi_clk_select(&intel_dig_port->base, pipe_config); + intel_ddi_clk_select(&intel_dig_port->base, + pipe_config->shared_dpll); intel_prepare_dp_ddi_buffers(&intel_dig_port->base); intel_dp_set_link_params(intel_dp, diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 655a5b382cf9..caf5ad29112a 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -452,26 +452,6 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, return val & SPLL_PLL_ENABLE; } -static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll) -{ - switch (pll->id) { - case DPLL_ID_WRPLL1: - return PORT_CLK_SEL_WRPLL1; - case DPLL_ID_WRPLL2: - return PORT_CLK_SEL_WRPLL2; - case DPLL_ID_SPLL: - return PORT_CLK_SEL_SPLL; - case DPLL_ID_LCPLL_810: - return PORT_CLK_SEL_LCPLL_810; - case DPLL_ID_LCPLL_1350: - return PORT_CLK_SEL_LCPLL_1350; - case DPLL_ID_LCPLL_2700: - return PORT_CLK_SEL_LCPLL_2700; - default: - return PORT_CLK_SEL_NONE; - } -} - #define LC_FREQ 2700 #define LC_FREQ_2K U64_C(LC_FREQ * 2000) @@ -751,8 +731,6 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, if (!pll) return NULL; - crtc_state->ddi_pll_sel = hsw_pll_to_ddi_pll_sel(pll); - intel_reference_shared_dpll(pll, crtc_state); return pll; @@ -1274,8 +1252,6 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, if (!pll) return NULL; - crtc_state->ddi_pll_sel = pll->id; - intel_reference_shared_dpll(pll, crtc_state); return pll; @@ -1628,9 +1604,6 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, intel_reference_shared_dpll(pll, crtc_state); - /* shared DPLL id 0 is DPLL A */ - crtc_state->ddi_pll_sel = pll->id; - return pll; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index fef4b362d55b..c55b7ab2e9ed 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -590,12 +590,6 @@ struct intel_crtc_state { /* Selected dpll when shared or NULL. */ struct intel_shared_dpll *shared_dpll; - /* - * - PORT_CLK_SEL for DDI ports on HSW/BDW. - * - enum skl_dpll on SKL - */ - uint32_t ddi_pll_sel; - /* Actual register state of the dpll, for shared dpll cross-checking. */ struct intel_dpll_hw_state dpll_hw_state; @@ -1136,7 +1130,7 @@ void intel_crt_reset(struct drm_encoder *encoder); /* intel_ddi.c */ void intel_ddi_clk_select(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config); + struct intel_shared_dpll *pll); void intel_ddi_fdi_post_disable(struct intel_encoder *intel_encoder, struct intel_crtc_state *old_crtc_state, struct drm_connector_state *old_conn_state); -- cgit v1.2.1 From ba88d153526f31777ef40b065a772e8dbf97b7c0 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Thu, 1 Sep 2016 15:08:08 -0700 Subject: drm/i915: Split intel_ddi_pre_enable() into DP and HDMI versions Split intel_ddi_pre_enable() into encoder type specific versions that don't depend on crtc_state. The necessary parameters are passed as function arguments. This split will be necessary for implementing DP upfront link training. v3: * Rebased onto latest kernel (Manasi) v2: * Rebased onto kernel v4.7 (Jim) Reviewed-by: Durgadoss R Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Jim Bride Signed-off-by: Manasi Navare Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_ddi.c | 105 ++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 45 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f798760426c6..e4b875e919dd 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1634,60 +1634,75 @@ void intel_ddi_clk_select(struct intel_encoder *encoder, } } -static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state) +static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, + int link_rate, uint32_t lane_count, + struct intel_shared_dpll *pll, + bool link_mst) { - struct drm_encoder *encoder = &intel_encoder->base; - struct drm_i915_private *dev_priv = to_i915(encoder->dev); - struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_ddi_get_encoder_port(intel_encoder); - int type = intel_encoder->type; - - if (type == INTEL_OUTPUT_HDMI) { - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - - intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); - } + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); - if (type == INTEL_OUTPUT_EDP) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + intel_dp_set_link_params(intel_dp, link_rate, lane_count, + link_mst); + if (encoder->type == INTEL_OUTPUT_EDP) intel_edp_panel_on(intel_dp); - } - - intel_ddi_clk_select(intel_encoder, crtc->config->shared_dpll); - - if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - intel_prepare_dp_ddi_buffers(intel_encoder); - - intel_dp_set_link_params(intel_dp, crtc->config->port_clock, - crtc->config->lane_count, - intel_crtc_has_type(crtc->config, - INTEL_OUTPUT_DP_MST)); + intel_ddi_clk_select(encoder, pll); + intel_prepare_dp_ddi_buffers(encoder); + intel_ddi_init_dp_buf_reg(encoder); + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + intel_dp_start_link_train(intel_dp); + if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) + intel_dp_stop_link_train(intel_dp); +} - intel_ddi_init_dp_buf_reg(intel_encoder); +static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, + bool has_hdmi_sink, + struct drm_display_mode *adjusted_mode, + struct intel_shared_dpll *pll) +{ + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_encoder *drm_encoder = &encoder->base; + enum port port = intel_ddi_get_encoder_port(encoder); + int level = intel_ddi_hdmi_level(dev_priv, port); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); - intel_dp_start_link_train(intel_dp); - if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9) - intel_dp_stop_link_train(intel_dp); - } else if (type == INTEL_OUTPUT_HDMI) { - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - int level = intel_ddi_hdmi_level(dev_priv, port); + intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); + intel_ddi_clk_select(encoder, pll); + intel_prepare_hdmi_ddi_buffers(encoder); + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) + skl_ddi_set_iboost(encoder, level); + else if (IS_BROXTON(dev_priv)) + bxt_ddi_vswing_sequence(dev_priv, level, port, + INTEL_OUTPUT_HDMI); - intel_prepare_hdmi_ddi_buffers(intel_encoder); + intel_hdmi->set_infoframes(drm_encoder, + has_hdmi_sink, + adjusted_mode); +} - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) - skl_ddi_set_iboost(intel_encoder, level); - else if (IS_BROXTON(dev_priv)) - bxt_ddi_vswing_sequence(dev_priv, level, port, - INTEL_OUTPUT_HDMI); +static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) +{ + struct drm_encoder *encoder = &intel_encoder->base; + struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); + int type = intel_encoder->type; - intel_hdmi->set_infoframes(encoder, - crtc->config->has_hdmi_sink, - &crtc->config->base.adjusted_mode); + if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { + intel_ddi_pre_enable_dp(intel_encoder, + crtc->config->port_clock, + crtc->config->lane_count, + crtc->config->shared_dpll, + intel_crtc_has_type(crtc->config, + INTEL_OUTPUT_DP_MST)); + } + if (type == INTEL_OUTPUT_HDMI) { + intel_ddi_pre_enable_hdmi(intel_encoder, + crtc->config->has_hdmi_sink, + &crtc->config->base.adjusted_mode, + crtc->config->shared_dpll); } } -- cgit v1.2.1 From a277ca7dc01df9c7b8fe5b1d992d2bcc02e2ec23 Mon Sep 17 00:00:00 2001 From: Durgadoss R Date: Thu, 1 Sep 2016 15:08:09 -0700 Subject: drm/i915: Split bxt_ddi_pll_select() Split out of bxt_ddi_pll_select() the logic that calculates the pll dividers and dpll_hw_state into a new function that doesn't depend on crtc state. This will be used for enabling the port pll when doing upfront link training. v2: * Refactored code so that bxt_clk_div need not be exported (Durga) v1: * Rebased on top of intel_dpll_mgr.c (Durga) * Initial version from Ander on top of intel_ddi.c Reviewed-by: Manasi Navare Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Durgadoss R Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dpll_mgr.c | 168 +++++++++++++++++++++------------- drivers/gpu/drm/i915/intel_dpll_mgr.h | 3 + 2 files changed, 105 insertions(+), 66 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index caf5ad29112a..6fc32cf2b83d 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1460,6 +1460,8 @@ struct bxt_clk_div { uint32_t m2_frac; bool m2_frac_en; uint32_t n; + + int vco; }; /* pre-calculated values for DP linkrates */ @@ -1473,58 +1475,60 @@ static const struct bxt_clk_div bxt_dp_clk_val[] = { {432000, 3, 1, 32, 1677722, 1, 1} }; -static struct intel_shared_dpll * -bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static bool +bxt_ddi_hdmi_pll_dividers(struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state, int clock, + struct bxt_clk_div *clk_div) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_shared_dpll *pll; - enum intel_dpll_id i; - struct intel_digital_port *intel_dig_port; - struct bxt_clk_div clk_div = {0}; - int vco = 0; - uint32_t prop_coef, int_coef, gain_ctl, targ_cnt; - uint32_t lanestagger; - int clock = crtc_state->port_clock; + struct dpll best_clock; - if (encoder->type == INTEL_OUTPUT_HDMI) { - struct dpll best_clock; + /* Calculate HDMI div */ + /* + * FIXME: tie the following calculation into + * i9xx_crtc_compute_clock + */ + if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) { + DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n", + clock, pipe_name(intel_crtc->pipe)); + return false; + } - /* Calculate HDMI div */ - /* - * FIXME: tie the following calculation into - * i9xx_crtc_compute_clock - */ - if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) { - DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n", - clock, pipe_name(crtc->pipe)); - return NULL; - } + clk_div->p1 = best_clock.p1; + clk_div->p2 = best_clock.p2; + WARN_ON(best_clock.m1 != 2); + clk_div->n = best_clock.n; + clk_div->m2_int = best_clock.m2 >> 22; + clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1); + clk_div->m2_frac_en = clk_div->m2_frac != 0; - clk_div.p1 = best_clock.p1; - clk_div.p2 = best_clock.p2; - WARN_ON(best_clock.m1 != 2); - clk_div.n = best_clock.n; - clk_div.m2_int = best_clock.m2 >> 22; - clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1); - clk_div.m2_frac_en = clk_div.m2_frac != 0; + clk_div->vco = best_clock.vco; - vco = best_clock.vco; - } else if (encoder->type == INTEL_OUTPUT_DP || - encoder->type == INTEL_OUTPUT_EDP || - encoder->type == INTEL_OUTPUT_DP_MST) { - int i; - - clk_div = bxt_dp_clk_val[0]; - for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) { - if (bxt_dp_clk_val[i].clock == clock) { - clk_div = bxt_dp_clk_val[i]; - break; - } + return true; +} + +static void bxt_ddi_dp_pll_dividers(int clock, struct bxt_clk_div *clk_div) +{ + int i; + + *clk_div = bxt_dp_clk_val[0]; + for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) { + if (bxt_dp_clk_val[i].clock == clock) { + *clk_div = bxt_dp_clk_val[i]; + break; } - vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2; } + clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2; +} + +static bool bxt_ddi_set_dpll_hw_state(int clock, + struct bxt_clk_div *clk_div, + struct intel_dpll_hw_state *dpll_hw_state) +{ + int vco = clk_div->vco; + uint32_t prop_coef, int_coef, gain_ctl, targ_cnt; + uint32_t lanestagger; + if (vco >= 6200000 && vco <= 6700000) { prop_coef = 4; int_coef = 9; @@ -1543,12 +1547,9 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, targ_cnt = 9; } else { DRM_ERROR("Invalid VCO\n"); - return NULL; + return false; } - memset(&crtc_state->dpll_hw_state, 0, - sizeof(crtc_state->dpll_hw_state)); - if (clock > 270000) lanestagger = 0x18; else if (clock > 135000) @@ -1560,33 +1561,68 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, else lanestagger = 0x02; - crtc_state->dpll_hw_state.ebb0 = - PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2); - crtc_state->dpll_hw_state.pll0 = clk_div.m2_int; - crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n); - crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac; + dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2); + dpll_hw_state->pll0 = clk_div->m2_int; + dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n); + dpll_hw_state->pll2 = clk_div->m2_frac; - if (clk_div.m2_frac_en) - crtc_state->dpll_hw_state.pll3 = - PORT_PLL_M2_FRAC_ENABLE; + if (clk_div->m2_frac_en) + dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE; - crtc_state->dpll_hw_state.pll6 = - prop_coef | PORT_PLL_INT_COEFF(int_coef); - crtc_state->dpll_hw_state.pll6 |= - PORT_PLL_GAIN_CTL(gain_ctl); + dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef); + dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl); - crtc_state->dpll_hw_state.pll8 = targ_cnt; + dpll_hw_state->pll8 = targ_cnt; - crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT; + dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT; - crtc_state->dpll_hw_state.pll10 = + dpll_hw_state->pll10 = PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT) | PORT_PLL_DCO_AMP_OVR_EN_H; - crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE; + dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE; + + dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger; + + return true; +} + +bool bxt_ddi_dp_set_dpll_hw_state(int clock, + struct intel_dpll_hw_state *dpll_hw_state) +{ + struct bxt_clk_div clk_div = {0}; + + bxt_ddi_dp_pll_dividers(clock, &clk_div); + + return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state); +} + +static struct intel_shared_dpll * +bxt_get_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) +{ + struct bxt_clk_div clk_div = {0}; + struct intel_dpll_hw_state dpll_hw_state = {0}; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_digital_port *intel_dig_port; + struct intel_shared_dpll *pll; + int i, clock = crtc_state->port_clock; + + if (encoder->type == INTEL_OUTPUT_HDMI + && !bxt_ddi_hdmi_pll_dividers(crtc, crtc_state, + clock, &clk_div)) + return false; + + if ((encoder->type == INTEL_OUTPUT_DP || + encoder->type == INTEL_OUTPUT_EDP) && + !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state)) + return false; + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); - crtc_state->dpll_hw_state.pcsdw12 = - LANESTAGGER_STRAP_OVRD | lanestagger; + crtc_state->dpll_hw_state = dpll_hw_state; if (encoder->type == INTEL_OUTPUT_DP_MST) { struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index 89c5ada1a315..11a85a53ab40 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -160,5 +160,8 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc); void intel_shared_dpll_commit(struct drm_atomic_state *state); void intel_shared_dpll_init(struct drm_device *dev); +/* BXT dpll related functions */ +bool bxt_ddi_dp_set_dpll_hw_state(int clock, + struct intel_dpll_hw_state *dpll_hw_state); #endif /* _INTEL_DPLL_MGR_H_ */ -- cgit v1.2.1 From 9a4edadaccea5ba9b73abaff8121e68dd0ff70bc Mon Sep 17 00:00:00 2001 From: Jim Bride Date: Thu, 1 Sep 2016 15:08:10 -0700 Subject: drm/i915: Split skl_get_dpll() Split out the DisplayPort and HDMI pll setup code into separate functions and refactor the DP code does not directly depend on crtc state, so that the code can be used for upfront link training. Reviewed-by: Manasi Navare Signed-off-by: Jim Bride Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dpll_mgr.c | 131 +++++++++++++++++++++------------- drivers/gpu/drm/i915/intel_dpll_mgr.h | 4 ++ 2 files changed, 87 insertions(+), 48 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 6fc32cf2b83d..c6d689534140 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1172,75 +1172,110 @@ skip_remaining_dividers: return true; } -static struct intel_shared_dpll * -skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state, + int clock) { - struct intel_shared_dpll *pll; uint32_t ctrl1, cfgcr1, cfgcr2; - int clock = crtc_state->port_clock; + struct skl_wrpll_params wrpll_params = { 0, }; /* * See comment in intel_dpll_hw_state to understand why we always use 0 * as the DPLL id in this function. */ - ctrl1 = DPLL_CTRL1_OVERRIDE(0); - if (encoder->type == INTEL_OUTPUT_HDMI) { - struct skl_wrpll_params wrpll_params = { 0, }; + ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); - ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); + if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params)) + return false; - if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params)) - return NULL; + cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | + DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | + wrpll_params.dco_integer; + + cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | + DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) | + DPLL_CFGCR2_KDIV(wrpll_params.kdiv) | + DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | + wrpll_params.central_freq; + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + crtc_state->dpll_hw_state.ctrl1 = ctrl1; + crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; + crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; + return true; +} + + +bool skl_ddi_dp_set_dpll_hw_state(int clock, + struct intel_dpll_hw_state *dpll_hw_state) +{ + uint32_t ctrl1; + + /* + * See comment in intel_dpll_hw_state to understand why we always use 0 + * as the DPLL id in this function. + */ + ctrl1 = DPLL_CTRL1_OVERRIDE(0); + switch (clock / 2) { + case 81000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); + break; + case 135000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0); + break; + case 270000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); + break; + /* eDP 1.4 rates */ + case 162000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0); + break; + case 108000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0); + break; + case 216000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0); + break; + } - cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | - DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | - wrpll_params.dco_integer; + dpll_hw_state->ctrl1 = ctrl1; + return true; +} - cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | - DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) | - DPLL_CFGCR2_KDIV(wrpll_params.kdiv) | - DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | - wrpll_params.central_freq; +static struct intel_shared_dpll * +skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) +{ + struct intel_shared_dpll *pll; + int clock = crtc_state->port_clock; + bool bret; + struct intel_dpll_hw_state dpll_hw_state; + + memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); + + if (encoder->type == INTEL_OUTPUT_HDMI) { + bret = skl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock); + if (!bret) { + DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n"); + return NULL; + } } else if (encoder->type == INTEL_OUTPUT_DP || encoder->type == INTEL_OUTPUT_DP_MST || encoder->type == INTEL_OUTPUT_EDP) { - switch (crtc_state->port_clock / 2) { - case 81000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); - break; - case 135000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0); - break; - case 270000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); - break; - /* eDP 1.4 rates */ - case 162000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0); - break; - case 108000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0); - break; - case 216000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0); - break; + bret = skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state); + if (!bret) { + DRM_DEBUG_KMS("Could not set DP dpll HW state.\n"); + return NULL; } - - cfgcr1 = cfgcr2 = 0; + crtc_state->dpll_hw_state = dpll_hw_state; } else { return NULL; } - memset(&crtc_state->dpll_hw_state, 0, - sizeof(crtc_state->dpll_hw_state)); - - crtc_state->dpll_hw_state.ctrl1 = ctrl1; - crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; - crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; - if (encoder->type == INTEL_OUTPUT_EDP) pll = intel_find_shared_dpll(crtc, crtc_state, DPLL_ID_SKL_DPLL0, diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index 11a85a53ab40..cb28f8df8701 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -164,4 +164,8 @@ void intel_shared_dpll_init(struct drm_device *dev); bool bxt_ddi_dp_set_dpll_hw_state(int clock, struct intel_dpll_hw_state *dpll_hw_state); +/* SKL dpll related functions */ +bool skl_ddi_dp_set_dpll_hw_state(int clock, + struct intel_dpll_hw_state *dpll_hw_state); + #endif /* _INTEL_DPLL_MGR_H_ */ -- cgit v1.2.1 From 81b9fd8fc68e9e0999efc604c4e5477b8d1982aa Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Thu, 1 Sep 2016 15:08:11 -0700 Subject: drm/i915: Split hsw_get_dpll() Split out the DisplayPort and HDMI pll setup code into separate functions and refactor the DP code that calculates the pll so that it doesn't depend on crtc state. This will be used for acquiring port pll when doing upfront link training. Reviewed-by: Durgadoss R Signed-off-by: Manasi Navare Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dpll_mgr.c | 90 ++++++++++++++++++++++------------- drivers/gpu/drm/i915/intel_dpll_mgr.h | 6 +++ 2 files changed, 63 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index c6d689534140..9a1da98805d6 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -667,11 +667,65 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, *r2_out = best.r2; } +static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(int clock, + struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct intel_shared_dpll *pll; + uint32_t val; + unsigned int p, n2, r2; + + hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); + + val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | + WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | + WRPLL_DIVIDER_POST(p); + + crtc_state->dpll_hw_state.wrpll = val; + + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_WRPLL1, DPLL_ID_WRPLL2); + + if (!pll) + return NULL; + + return pll; +} + +struct intel_shared_dpll *hsw_ddi_dp_get_dpll(struct intel_encoder *encoder, + int clock) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_shared_dpll *pll; + enum intel_dpll_id pll_id; + + switch (clock / 2) { + case 81000: + pll_id = DPLL_ID_LCPLL_810; + break; + case 135000: + pll_id = DPLL_ID_LCPLL_1350; + break; + case 270000: + pll_id = DPLL_ID_LCPLL_2700; + break; + default: + DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock); + return NULL; + } + + pll = intel_get_shared_dpll_by_id(dev_priv, pll_id); + + if (!pll) + return NULL; + + return pll; +} + static struct intel_shared_dpll * hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll; int clock = crtc_state->port_clock; @@ -679,41 +733,12 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, sizeof(crtc_state->dpll_hw_state)); if (encoder->type == INTEL_OUTPUT_HDMI) { - uint32_t val; - unsigned p, n2, r2; - - hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); - - val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | - WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | - WRPLL_DIVIDER_POST(p); - - crtc_state->dpll_hw_state.wrpll = val; - - pll = intel_find_shared_dpll(crtc, crtc_state, - DPLL_ID_WRPLL1, DPLL_ID_WRPLL2); + pll = hsw_ddi_hdmi_get_dpll(clock, crtc, crtc_state); } else if (encoder->type == INTEL_OUTPUT_DP || encoder->type == INTEL_OUTPUT_DP_MST || encoder->type == INTEL_OUTPUT_EDP) { - enum intel_dpll_id pll_id; - - switch (clock / 2) { - case 81000: - pll_id = DPLL_ID_LCPLL_810; - break; - case 135000: - pll_id = DPLL_ID_LCPLL_1350; - break; - case 270000: - pll_id = DPLL_ID_LCPLL_2700; - break; - default: - DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock); - return NULL; - } - - pll = intel_get_shared_dpll_by_id(dev_priv, pll_id); + pll = hsw_ddi_dp_get_dpll(encoder, clock); } else if (encoder->type == INTEL_OUTPUT_ANALOG) { if (WARN_ON(crtc_state->port_clock / 2 != 135000)) @@ -736,7 +761,6 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, return pll; } - static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = { .enable = hsw_ddi_wrpll_enable, .disable = hsw_ddi_wrpll_disable, diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index cb28f8df8701..aed74084f759 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -164,8 +164,14 @@ void intel_shared_dpll_init(struct drm_device *dev); bool bxt_ddi_dp_set_dpll_hw_state(int clock, struct intel_dpll_hw_state *dpll_hw_state); + /* SKL dpll related functions */ bool skl_ddi_dp_set_dpll_hw_state(int clock, struct intel_dpll_hw_state *dpll_hw_state); + +/* HSW dpll related functions */ +struct intel_shared_dpll *hsw_ddi_dp_get_dpll(struct intel_encoder *encoder, + int clock); + #endif /* _INTEL_DPLL_MGR_H_ */ -- cgit v1.2.1 From 6e3b84d831113804fcae3646b99816556915b881 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:36 -0700 Subject: drm/i915: Move HAS_PSR definition to platform struct definition [patch series] Moving all GPU features to the platform struct definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definition Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 5 ++--- drivers/gpu/drm/i915/i915_pci.c | 5 ++++- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ecfd8e9726b5..04e55aa242c3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -654,6 +654,7 @@ struct intel_csr { func(is_kabylake) sep \ func(is_preliminary) sep \ func(has_fbc) sep \ + func(has_psr) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2784,9 +2785,7 @@ struct drm_i915_cmd_table { #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) -#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev) || \ - IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || \ - IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) +#define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr) #define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \ IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \ IS_CHERRYVIEW(dev) || IS_SKYLAKE(dev) || \ diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 2587b1bd41f4..e1caa0b63f3b 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -243,6 +243,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { #define VLV_FEATURES \ .gen = 7, .num_pipes = 2, \ + .has_psr = 1, \ .need_gfx_hws = 1, .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .display_mmio_offset = VLV_DISPLAY_BASE, \ @@ -264,7 +265,8 @@ static const struct intel_device_info intel_valleyview_d_info = { GEN7_FEATURES, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \ .has_ddi = 1, \ - .has_fpga_dbg = 1 + .has_fpga_dbg = 1, \ + .has_psr = 1 static const struct intel_device_info intel_haswell_d_info = { HSW_FEATURES, @@ -312,6 +314,7 @@ static const struct intel_device_info intel_cherryview_info = { .need_gfx_hws = 1, .has_hotplug = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .is_cherryview = 1, + .has_psr = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, -- cgit v1.2.1 From 8d9c20e1d1e3833b5c4dab33d59cb92ea162da6a Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:37 -0700 Subject: drm/i915: Remove .is_mobile field from platform struct As recommended by Ville Syrjala removing .is_mobile field from the platform struct definition for vlv and hsw+ GPUs as there's no need to make the distinction in later hardware anymore. Keep it for older GPUs as it is still needed for ilk-ivb. Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pci.c | 45 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 37 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index e1caa0b63f3b..b5ec8a761b8b 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -250,13 +250,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS -static const struct intel_device_info intel_valleyview_m_info = { - VLV_FEATURES, - .is_valleyview = 1, - .is_mobile = 1, -}; - -static const struct intel_device_info intel_valleyview_d_info = { +static const struct intel_device_info intel_valleyview_info = { VLV_FEATURES, .is_valleyview = 1, }; @@ -268,47 +262,28 @@ static const struct intel_device_info intel_valleyview_d_info = { .has_fpga_dbg = 1, \ .has_psr = 1 -static const struct intel_device_info intel_haswell_d_info = { +static const struct intel_device_info intel_haswell_info = { HSW_FEATURES, .is_haswell = 1, }; -static const struct intel_device_info intel_haswell_m_info = { - HSW_FEATURES, - .is_haswell = 1, - .is_mobile = 1, -}; - #define BDW_FEATURES \ HSW_FEATURES, \ BDW_COLORS -static const struct intel_device_info intel_broadwell_d_info = { +static const struct intel_device_info intel_broadwell_info = { BDW_FEATURES, .gen = 8, .is_broadwell = 1, }; -static const struct intel_device_info intel_broadwell_m_info = { - BDW_FEATURES, - .gen = 8, .is_mobile = 1, - .is_broadwell = 1, -}; - -static const struct intel_device_info intel_broadwell_gt3d_info = { +static const struct intel_device_info intel_broadwell_gt3_info = { BDW_FEATURES, .gen = 8, .is_broadwell = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; -static const struct intel_device_info intel_broadwell_gt3m_info = { - BDW_FEATURES, - .gen = 8, .is_mobile = 1, - .is_broadwell = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, -}; - static const struct intel_device_info intel_cherryview_info = { .gen = 8, .num_pipes = 3, .need_gfx_hws = 1, .has_hotplug = 1, @@ -390,14 +365,10 @@ static const struct pci_device_id pciidlist[] = { INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */ INTEL_IVB_M_IDS(&intel_ivybridge_m_info), INTEL_IVB_D_IDS(&intel_ivybridge_d_info), - INTEL_HSW_D_IDS(&intel_haswell_d_info), - INTEL_HSW_M_IDS(&intel_haswell_m_info), - INTEL_VLV_M_IDS(&intel_valleyview_m_info), - INTEL_VLV_D_IDS(&intel_valleyview_d_info), - INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info), - INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info), - INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info), - INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info), + INTEL_HSW_IDS(&intel_haswell_info), + INTEL_VLV_IDS(&intel_valleyview_info), + INTEL_BDW_GT12_IDS(&intel_broadwell_info), + INTEL_BDW_GT3_IDS(&intel_broadwell_gt3_info), INTEL_CHV_IDS(&intel_cherryview_info), INTEL_SKL_GT1_IDS(&intel_skylake_info), INTEL_SKL_GT2_IDS(&intel_skylake_info), -- cgit v1.2.1 From 07db6be72e2c4e54aca12f3f09b4dc7d33f023f0 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:38 -0700 Subject: drm/i915: Introduce GEN6_FEATURES for device info Introducing a GEN6_FEAUTRES macro to simplify the struct definitions by platforms given that most of the features are common. Inspired by the GEN7_FEATURES macro done by Ben W. and others. Use it for snb. CC: Ben Widawsky Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pci.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index b5ec8a761b8b..bdc207131ab7 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -195,24 +195,22 @@ static const struct intel_device_info intel_ironlake_m_info = { CURSOR_OFFSETS, }; +#define GEN6_FEATURES \ + .gen = 6, .num_pipes = 2, \ + .need_gfx_hws = 1, .has_hotplug = 1, \ + .has_fbc = 1, \ + .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ + .has_llc = 1, \ + GEN_DEFAULT_PIPEOFFSETS, \ + CURSOR_OFFSETS + static const struct intel_device_info intel_sandybridge_d_info = { - .gen = 6, .num_pipes = 2, - .need_gfx_hws = 1, .has_hotplug = 1, - .has_fbc = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING, - .has_llc = 1, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, + GEN6_FEATURES, }; static const struct intel_device_info intel_sandybridge_m_info = { - .gen = 6, .is_mobile = 1, .num_pipes = 2, - .need_gfx_hws = 1, .has_hotplug = 1, - .has_fbc = 1, - .ring_mask = RENDER_RING | BSD_RING | BLT_RING, - .has_llc = 1, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, + GEN6_FEATURES, + .is_mobile = 1, }; #define GEN7_FEATURES \ -- cgit v1.2.1 From 4aa4c23f2be22456070ee02eb50db84c0598c3ed Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:39 -0700 Subject: drm/i915: Move HAS_RUNTIME_PM definition to platform Moving all GPU features to the platform struct definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 6 ++---- drivers/gpu/drm/i915/i915_pci.c | 7 ++++++- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 04e55aa242c3..886ebd71b28d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -655,6 +655,7 @@ struct intel_csr { func(is_preliminary) sep \ func(has_fbc) sep \ func(has_psr) sep \ + func(has_runtime_pm) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2786,10 +2787,7 @@ struct drm_i915_cmd_table { #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr) -#define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \ - IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \ - IS_CHERRYVIEW(dev) || IS_SKYLAKE(dev) || \ - IS_KABYLAKE(dev) || IS_BROXTON(dev)) +#define HAS_RUNTIME_PM(dev) (INTEL_INFO(dev)->has_runtime_pm) #define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_RC6p(dev) (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index bdc207131ab7..d1f5a9a9ee16 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -199,6 +199,7 @@ static const struct intel_device_info intel_ironlake_m_info = { .gen = 6, .num_pipes = 2, \ .need_gfx_hws = 1, .has_hotplug = 1, \ .has_fbc = 1, \ + .has_runtime_pm = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ @@ -242,6 +243,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { #define VLV_FEATURES \ .gen = 7, .num_pipes = 2, \ .has_psr = 1, \ + .has_runtime_pm = 1, \ .need_gfx_hws = 1, .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .display_mmio_offset = VLV_DISPLAY_BASE, \ @@ -258,7 +260,8 @@ static const struct intel_device_info intel_valleyview_info = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \ .has_ddi = 1, \ .has_fpga_dbg = 1, \ - .has_psr = 1 + .has_psr = 1, \ + .has_runtime_pm = 1 static const struct intel_device_info intel_haswell_info = { HSW_FEATURES, @@ -288,6 +291,7 @@ static const struct intel_device_info intel_cherryview_info = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .is_cherryview = 1, .has_psr = 1, + .has_runtime_pm = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, @@ -316,6 +320,7 @@ static const struct intel_device_info intel_broxton_info = { .has_ddi = 1, .has_fpga_dbg = 1, .has_fbc = 1, + .has_runtime_pm = 1, .has_pooled_eu = 0, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, -- cgit v1.2.1 From d4c5636e744738df5c1ee410c50576c48f2d75a0 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:40 -0700 Subject: drm/i915: Remove runtime PM for SNB Remove runtime PM support for SNB as it breaks hotplug support. Feedback from V. Syrjala. Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pci.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index d1f5a9a9ee16..9d788369465b 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -199,7 +199,6 @@ static const struct intel_device_info intel_ironlake_m_info = { .gen = 6, .num_pipes = 2, \ .need_gfx_hws = 1, .has_hotplug = 1, \ .has_fbc = 1, \ - .has_runtime_pm = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ -- cgit v1.2.1 From 2631034677ad74a57f10866e02ae8037fa5724f3 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:41 -0700 Subject: drm/i915: Get rid of HAS_CORE_RING_FREQ No need for HAS_CORE_RING_FREQ as that flag is actually the same as .has_llc. Feedback from V. Syrjala. Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b8e40fde132a..e52e12855850 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1763,7 +1763,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) int gpu_freq, ia_freq; unsigned int max_gpu_freq, min_gpu_freq; - if (!HAS_CORE_RING_FREQ(dev_priv)) { + if (!HAS_LLC(dev_priv)) { seq_puts(m, "unsupported on this chipset\n"); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 886ebd71b28d..0978f1701f1d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2805,10 +2805,6 @@ struct drm_i915_cmd_table { #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \ INTEL_INFO(dev)->gen >= 8) -#define HAS_CORE_RING_FREQ(dev) (INTEL_INFO(dev)->gen >= 6 && \ - !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && \ - !IS_BROXTON(dev)) - #define HAS_POOLED_EU(dev) (INTEL_INFO(dev)->has_pooled_eu) #define INTEL_PCH_DEVICE_ID_MASK 0xff00 -- cgit v1.2.1 From 3bacde19993a7b8f7f2440aeaf112da81f64bb5b Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:42 -0700 Subject: drm/i915 Move HAS_CSR definition to platform definition Moving all GPU features to the platform struct definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_pci.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0978f1701f1d..44e18110a279 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -656,6 +656,7 @@ struct intel_csr { func(has_fbc) sep \ func(has_psr) sep \ func(has_runtime_pm) sep \ + func(has_csr) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2791,7 +2792,7 @@ struct drm_i915_cmd_table { #define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_RC6p(dev) (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) -#define HAS_CSR(dev) (IS_GEN9(dev)) +#define HAS_CSR(dev) (INTEL_INFO(dev)->has_csr) /* * For now, anything with a GuC requires uCode loading, and then supports diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 9d788369465b..21a3bc50faa4 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -301,12 +301,14 @@ static const struct intel_device_info intel_skylake_info = { BDW_FEATURES, .is_skylake = 1, .gen = 9, + .has_csr = 1, }; static const struct intel_device_info intel_skylake_gt3_info = { BDW_FEATURES, .is_skylake = 1, .gen = 9, + .has_csr = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; @@ -321,6 +323,7 @@ static const struct intel_device_info intel_broxton_info = { .has_fbc = 1, .has_runtime_pm = 1, .has_pooled_eu = 0, + .has_csr = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, @@ -330,12 +333,14 @@ static const struct intel_device_info intel_kabylake_info = { BDW_FEATURES, .is_kabylake = 1, .gen = 9, + .has_csr = 1, }; static const struct intel_device_info intel_kabylake_gt3_info = { BDW_FEATURES, .is_kabylake = 1, .gen = 9, + .has_csr = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; -- cgit v1.2.1 From 53233f084d3a756875ad5097440b0faf3348869b Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:43 -0700 Subject: drm/i915: Move HAS_RESOURCE_STREAMER definition to platform definition Moving all GPU features to the platform struct definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_pci.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 44e18110a279..80ca60d5ac16 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -657,6 +657,7 @@ struct intel_csr { func(has_psr) sep \ func(has_runtime_pm) sep \ func(has_csr) sep \ + func(has_resource_streamer) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2803,8 +2804,7 @@ struct drm_i915_cmd_table { #define HAS_GUC_UCODE(dev) (HAS_GUC(dev)) #define HAS_GUC_SCHED(dev) (HAS_GUC(dev)) -#define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \ - INTEL_INFO(dev)->gen >= 8) +#define HAS_RESOURCE_STREAMER(dev) (INTEL_INFO(dev)->has_resource_streamer) #define HAS_POOLED_EU(dev) (INTEL_INFO(dev)->has_pooled_eu) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 21a3bc50faa4..46c48eda23f6 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -260,6 +260,7 @@ static const struct intel_device_info intel_valleyview_info = { .has_ddi = 1, \ .has_fpga_dbg = 1, \ .has_psr = 1, \ + .has_resource_streamer = 1, \ .has_runtime_pm = 1 static const struct intel_device_info intel_haswell_info = { @@ -291,6 +292,7 @@ static const struct intel_device_info intel_cherryview_info = { .is_cherryview = 1, .has_psr = 1, .has_runtime_pm = 1, + .has_resource_streamer = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, @@ -324,6 +326,7 @@ static const struct intel_device_info intel_broxton_info = { .has_runtime_pm = 1, .has_pooled_eu = 0, .has_csr = 1, + .has_resource_streamer = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, -- cgit v1.2.1 From 86f3624bf2750d22a6d7290f625f2d11227edb21 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:44 -0700 Subject: drm/i915: Move HAS_RC6 definition to platform definition Moving all GPU features to the platform struct definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_pci.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 80ca60d5ac16..c16e9cbeabc7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -658,6 +658,7 @@ struct intel_csr { func(has_runtime_pm) sep \ func(has_csr) sep \ func(has_resource_streamer) sep \ + func(has_rc6) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2790,7 +2791,7 @@ struct drm_i915_cmd_table { #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr) #define HAS_RUNTIME_PM(dev) (INTEL_INFO(dev)->has_runtime_pm) -#define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6) +#define HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) #define HAS_RC6p(dev) (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) #define HAS_CSR(dev) (INTEL_INFO(dev)->has_csr) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 46c48eda23f6..42108dcaba17 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -201,6 +201,7 @@ static const struct intel_device_info intel_ironlake_m_info = { .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1, \ + .has_rc6 = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -219,6 +220,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1, \ + .has_rc6 = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS @@ -243,6 +245,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { .gen = 7, .num_pipes = 2, \ .has_psr = 1, \ .has_runtime_pm = 1, \ + .has_rc6 = 1, \ .need_gfx_hws = 1, .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .display_mmio_offset = VLV_DISPLAY_BASE, \ @@ -293,6 +296,7 @@ static const struct intel_device_info intel_cherryview_info = { .has_psr = 1, .has_runtime_pm = 1, .has_resource_streamer = 1, + .has_rc6 = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, @@ -327,6 +331,7 @@ static const struct intel_device_info intel_broxton_info = { .has_pooled_eu = 0, .has_csr = 1, .has_resource_streamer = 1, + .has_rc6 = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, -- cgit v1.2.1 From 33b5bf82a67bff6b494a76dcbc20bcbcf3a835ed Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:45 -0700 Subject: drm/i915: Move HAS_RC6p definition to platform definition Moving all GPU features to the platform struct definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_pci.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c16e9cbeabc7..52ddad6ae3eb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -659,6 +659,7 @@ struct intel_csr { func(has_csr) sep \ func(has_resource_streamer) sep \ func(has_rc6) sep \ + func(has_rc6p) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2792,7 +2793,7 @@ struct drm_i915_cmd_table { #define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr) #define HAS_RUNTIME_PM(dev) (INTEL_INFO(dev)->has_runtime_pm) #define HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) -#define HAS_RC6p(dev) (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) +#define HAS_RC6p(dev) (INTEL_INFO(dev)->has_rc6p) #define HAS_CSR(dev) (INTEL_INFO(dev)->has_csr) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 42108dcaba17..c6a5bd09e6ab 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -202,6 +202,7 @@ static const struct intel_device_info intel_ironlake_m_info = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1, \ .has_rc6 = 1, \ + .has_rc6p = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -221,6 +222,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1, \ .has_rc6 = 1, \ + .has_rc6p = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS @@ -264,6 +266,7 @@ static const struct intel_device_info intel_valleyview_info = { .has_fpga_dbg = 1, \ .has_psr = 1, \ .has_resource_streamer = 1, \ + .has_rc6p = 0 /* RC6p removed-by HSW */, \ .has_runtime_pm = 1 static const struct intel_device_info intel_haswell_info = { -- cgit v1.2.1 From 1d3fe53bbc074dc93fe50152d97e1af364cc4e92 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:46 -0700 Subject: drm/i915: Move HAS_DP_MST definition to platform definition Moving all GPU features to the platform struct definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_pci.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 52ddad6ae3eb..10ff512e4a9b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -660,6 +660,7 @@ struct intel_csr { func(has_resource_streamer) sep \ func(has_rc6) sep \ func(has_rc6p) sep \ + func(has_dp_mst) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2785,8 +2786,7 @@ struct drm_i915_cmd_table { #define HAS_IPS(dev) (IS_HSW_ULT(dev) || IS_BROADWELL(dev)) -#define HAS_DP_MST(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev) || \ - INTEL_INFO(dev)->gen >= 9) +#define HAS_DP_MST(dev) (INTEL_INFO(dev)->has_dp_mst) #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index c6a5bd09e6ab..da2ec6f1f187 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -266,6 +266,7 @@ static const struct intel_device_info intel_valleyview_info = { .has_fpga_dbg = 1, \ .has_psr = 1, \ .has_resource_streamer = 1, \ + .has_dp_mst = 1, \ .has_rc6p = 0 /* RC6p removed-by HSW */, \ .has_runtime_pm = 1 @@ -335,6 +336,7 @@ static const struct intel_device_info intel_broxton_info = { .has_csr = 1, .has_resource_streamer = 1, .has_rc6 = 1, + .has_dp_mst = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, -- cgit v1.2.1 From a13233804686886726aeeb084141d9a759c0b859 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:47 -0700 Subject: drm/i915: Introduce GEN5_FEATURES for device info Introducing a GEN5_FEATURES macro to simplify the struct definitions by platforms given that most of the features are common. Inspired by the GEN7_FEATURES macro done by Ben W. and others. Use it for ilk. CC: Ben Widawsky Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pci.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index da2ec6f1f187..60cfc7824da8 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -178,21 +178,20 @@ static const struct intel_device_info intel_pineview_info = { CURSOR_OFFSETS, }; +#define GEN5_FEATURES \ + .gen = 5, .num_pipes = 2, \ + .need_gfx_hws = 1, .has_hotplug = 1, \ + .ring_mask = RENDER_RING | BSD_RING, \ + GEN_DEFAULT_PIPEOFFSETS, \ + CURSOR_OFFSETS + static const struct intel_device_info intel_ironlake_d_info = { - .gen = 5, .num_pipes = 2, - .need_gfx_hws = 1, .has_hotplug = 1, - .ring_mask = RENDER_RING | BSD_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, + GEN5_FEATURES, }; static const struct intel_device_info intel_ironlake_m_info = { - .gen = 5, .is_mobile = 1, .num_pipes = 2, - .need_gfx_hws = 1, .has_hotplug = 1, - .has_fbc = 1, - .ring_mask = RENDER_RING | BSD_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, + GEN5_FEATURES, + .is_mobile = 1, }; #define GEN6_FEATURES \ -- cgit v1.2.1 From b355f10925fdeb186796eaa4f3e64a7db02c3ccf Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:48 -0700 Subject: drm/i915: Move HAS_GMBUS_IRQ definition to platform definition Moving all GPU features to the platform struct definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_pci.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 10ff512e4a9b..66548d6b9ea0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -661,6 +661,7 @@ struct intel_csr { func(has_rc6) sep \ func(has_rc6p) sep \ func(has_dp_mst) sep \ + func(has_gmbus_irq) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2770,7 +2771,7 @@ struct drm_i915_cmd_table { * interrupt source and so prevents the other device from working properly. */ #define HAS_AUX_IRQ(dev) (INTEL_INFO(dev)->gen >= 5) -#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5) +#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->has_gmbus_irq) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte * rows, which changed the alignment requirements and fence programming. diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 60cfc7824da8..616de269d41d 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -181,6 +181,7 @@ static const struct intel_device_info intel_pineview_info = { #define GEN5_FEATURES \ .gen = 5, .num_pipes = 2, \ .need_gfx_hws = 1, .has_hotplug = 1, \ + .has_gmbus_irq = 1, \ .ring_mask = RENDER_RING | BSD_RING, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -202,6 +203,7 @@ static const struct intel_device_info intel_ironlake_m_info = { .has_llc = 1, \ .has_rc6 = 1, \ .has_rc6p = 1, \ + .has_gmbus_irq = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -222,6 +224,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_llc = 1, \ .has_rc6 = 1, \ .has_rc6p = 1, \ + .has_gmbus_irq = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS @@ -247,6 +250,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { .has_psr = 1, \ .has_runtime_pm = 1, \ .has_rc6 = 1, \ + .has_gmbus_irq = 1, \ .need_gfx_hws = 1, .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .display_mmio_offset = VLV_DISPLAY_BASE, \ @@ -300,6 +304,7 @@ static const struct intel_device_info intel_cherryview_info = { .has_runtime_pm = 1, .has_resource_streamer = 1, .has_rc6 = 1, + .has_gmbus_irq = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, @@ -336,6 +341,7 @@ static const struct intel_device_info intel_broxton_info = { .has_resource_streamer = 1, .has_rc6 = 1, .has_dp_mst = 1, + .has_gmbus_irq = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, -- cgit v1.2.1 From 4d495bea6079b0fcf3a3462cdb87e80ae3664e94 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:49 -0700 Subject: drm/i915: Introduce GEN4_FEATURES for device info Introducing a GEN4_FEATURES macro to simplify the struct definitions by platforms given that most of the features are common. Inspired by the GEN7_FEATURES macro done by Ben W. and others. Use it for i965g, i965gm, g45 and gm45. CC: Ben Widawsky Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pci.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 616de269d41d..66e126683fdd 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -123,23 +123,25 @@ static const struct intel_device_info intel_i945gm_info = { CURSOR_OFFSETS, }; +#define GEN4_FEATURES \ + .gen = 4, .num_pipes = 2, \ + .has_hotplug = 1, \ + .ring_mask = RENDER_RING, \ + GEN_DEFAULT_PIPEOFFSETS, \ + CURSOR_OFFSETS + static const struct intel_device_info intel_i965g_info = { - .gen = 4, .is_broadwater = 1, .num_pipes = 2, - .has_hotplug = 1, + GEN4_FEATURES, + .is_broadwater = 1, .has_overlay = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_i965gm_info = { - .gen = 4, .is_crestline = 1, .num_pipes = 2, - .is_mobile = 1, .has_fbc = 1, .has_hotplug = 1, + GEN4_FEATURES, + .is_crestline = 1, + .is_mobile = 1, .has_fbc = 1, .has_overlay = 1, .supports_tv = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_g33_info = { @@ -152,21 +154,19 @@ static const struct intel_device_info intel_g33_info = { }; static const struct intel_device_info intel_g45_info = { - .gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2, - .has_pipe_cxsr = 1, .has_hotplug = 1, + GEN4_FEATURES, + .is_g4x = 1, .need_gfx_hws = 1, + .has_pipe_cxsr = 1, .ring_mask = RENDER_RING | BSD_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_gm45_info = { - .gen = 4, .is_g4x = 1, .num_pipes = 2, + GEN4_FEATURES, + .is_g4x = 1, .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, - .has_pipe_cxsr = 1, .has_hotplug = 1, + .has_pipe_cxsr = 1, .supports_tv = 1, .ring_mask = RENDER_RING | BSD_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_pineview_info = { -- cgit v1.2.1 From 54d2a6a13ed031db5111bb591252dc48ed1985e1 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:50 -0700 Subject: drm/i915: Introduce GEN3_FEATURES for device info Introducing a GEN3_FEATURES macro to simplify the struct definitions by platforms given that most of the features are common. Inspired by the GEN7_FEATURES macro done by Ben W. and others. Use it for i915g, i915gm, i945g, i945gm, g33 and pnv. CC: Ben Widawsky Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pci.c | 42 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 66e126683fdd..ca776f5d0034 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -88,39 +88,37 @@ static const struct intel_device_info intel_i865g_info = { CURSOR_OFFSETS, }; +#define GEN3_FEATURES \ + .gen = 3, .num_pipes = 2, \ + .ring_mask = RENDER_RING, \ + GEN_DEFAULT_PIPEOFFSETS, \ + CURSOR_OFFSETS + static const struct intel_device_info intel_i915g_info = { - .gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2, + GEN3_FEATURES, + .is_i915g = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_i915gm_info = { - .gen = 3, .is_mobile = 1, .num_pipes = 2, + GEN3_FEATURES, + .is_mobile = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, .has_fbc = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_i945g_info = { - .gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2, + GEN3_FEATURES, + .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_i945gm_info = { - .gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2, + GEN3_FEATURES, + .is_i945gm = 1, .is_mobile = 1, .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, .has_fbc = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; #define GEN4_FEATURES \ @@ -145,12 +143,10 @@ static const struct intel_device_info intel_i965gm_info = { }; static const struct intel_device_info intel_g33_info = { - .gen = 3, .is_g33 = 1, .num_pipes = 2, + GEN3_FEATURES, + .is_g33 = 1, .need_gfx_hws = 1, .has_hotplug = 1, .has_overlay = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_g45_info = { @@ -170,12 +166,10 @@ static const struct intel_device_info intel_gm45_info = { }; static const struct intel_device_info intel_pineview_info = { - .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2, + GEN3_FEATURES, + .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .need_gfx_hws = 1, .has_hotplug = 1, .has_overlay = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; #define GEN5_FEATURES \ -- cgit v1.2.1 From 0eec8dc7f628a8d871de3a6d7e2f467bafcb69c7 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:51 -0700 Subject: drm/i915: Introduce GEN2_FEATURES for device info Introducing a GEN2_FEATURES macro to simplify the struct definitions by platforms given that most of the features are common. Inspired by the GEN7_FEATURES macro done by Ben W. and others. Use it for 830, 845g, i85x, i865g. CC: Ben Widawsky Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pci.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index ca776f5d0034..ca83e6790877 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -54,38 +54,33 @@ #define CHV_COLORS \ .color = { .degamma_lut_size = 65, .gamma_lut_size = 257 } +#define GEN2_FEATURES \ + .gen = 2, .num_pipes = 1, \ + .has_overlay = 1, .overlay_needs_physical = 1, \ + .ring_mask = RENDER_RING, \ + GEN_DEFAULT_PIPEOFFSETS, \ + CURSOR_OFFSETS + static const struct intel_device_info intel_i830_info = { - .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, - .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, + GEN2_FEATURES, + .is_mobile = 1, .cursor_needs_physical = 1, + .num_pipes = 2, /* legal, last one wins */ }; static const struct intel_device_info intel_845g_info = { - .gen = 2, .num_pipes = 1, - .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, + GEN2_FEATURES, }; static const struct intel_device_info intel_i85x_info = { - .gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2, + GEN2_FEATURES, + .is_i85x = 1, .is_mobile = 1, + .num_pipes = 2, /* legal, last one wins */ .cursor_needs_physical = 1, - .has_overlay = 1, .overlay_needs_physical = 1, .has_fbc = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, }; static const struct intel_device_info intel_i865g_info = { - .gen = 2, .num_pipes = 1, - .has_overlay = 1, .overlay_needs_physical = 1, - .ring_mask = RENDER_RING, - GEN_DEFAULT_PIPEOFFSETS, - CURSOR_OFFSETS, + GEN2_FEATURES, }; #define GEN3_FEATURES \ -- cgit v1.2.1 From e1a52536c20a75c56dcb8ceedf2d6b1c2b285e32 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:52 -0700 Subject: drm/i915: Move HAS_HW_CONTEXTS definition to platform Moving all GPU features to the platform definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_pci.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 66548d6b9ea0..e39d2150df0b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -662,6 +662,7 @@ struct intel_csr { func(has_rc6p) sep \ func(has_dp_mst) sep \ func(has_gmbus_irq) sep \ + func(has_hw_contexts) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2746,7 +2747,7 @@ struct drm_i915_cmd_table { HAS_EDRAM(dev)) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) -#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) +#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->has_hw_contexts) #define HAS_LOGICAL_RING_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 8) #define USES_PPGTT(dev) (i915.enable_ppgtt) #define USES_FULL_PPGTT(dev) (i915.enable_ppgtt >= 2) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index ca83e6790877..0b3b28d8af25 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -193,6 +193,7 @@ static const struct intel_device_info intel_ironlake_m_info = { .has_rc6 = 1, \ .has_rc6p = 1, \ .has_gmbus_irq = 1, \ + .has_hw_contexts = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -214,6 +215,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_rc6 = 1, \ .has_rc6p = 1, \ .has_gmbus_irq = 1, \ + .has_hw_contexts = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS @@ -240,6 +242,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { .has_runtime_pm = 1, \ .has_rc6 = 1, \ .has_gmbus_irq = 1, \ + .has_hw_contexts = 1, \ .need_gfx_hws = 1, .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .display_mmio_offset = VLV_DISPLAY_BASE, \ @@ -294,6 +297,7 @@ static const struct intel_device_info intel_cherryview_info = { .has_resource_streamer = 1, .has_rc6 = 1, .has_gmbus_irq = 1, + .has_hw_contexts = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, @@ -331,6 +335,7 @@ static const struct intel_device_info intel_broxton_info = { .has_rc6 = 1, .has_dp_mst = 1, .has_gmbus_irq = 1, + .has_hw_contexts = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, -- cgit v1.2.1 From 4586f1d067c73e1865d6e1af251fabe5334265cd Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:53 -0700 Subject: drm/i915: Move HAS_LOGICAL_RING_CONTEXTS definition to platform Moving all GPU features to the platform definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_pci.c | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e39d2150df0b..431ddf08bc0a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -663,6 +663,7 @@ struct intel_csr { func(has_dp_mst) sep \ func(has_gmbus_irq) sep \ func(has_hw_contexts) sep \ + func(has_logical_ring_contexts) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2748,7 +2749,7 @@ struct drm_i915_cmd_table { #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->has_hw_contexts) -#define HAS_LOGICAL_RING_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 8) +#define HAS_LOGICAL_RING_CONTEXTS(dev) (INTEL_INFO(dev)->has_logical_ring_contexts) #define USES_PPGTT(dev) (i915.enable_ppgtt) #define USES_FULL_PPGTT(dev) (i915.enable_ppgtt >= 2) #define USES_FULL_48BIT_PPGTT(dev) (i915.enable_ppgtt == 3) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 0b3b28d8af25..dc167b0e0b74 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -272,7 +272,8 @@ static const struct intel_device_info intel_haswell_info = { #define BDW_FEATURES \ HSW_FEATURES, \ - BDW_COLORS + BDW_COLORS, \ + .has_logical_ring_contexts = 1 static const struct intel_device_info intel_broadwell_info = { BDW_FEATURES, @@ -298,6 +299,7 @@ static const struct intel_device_info intel_cherryview_info = { .has_rc6 = 1, .has_gmbus_irq = 1, .has_hw_contexts = 1, + .has_logical_ring_contexts = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, @@ -336,6 +338,7 @@ static const struct intel_device_info intel_broxton_info = { .has_dp_mst = 1, .has_gmbus_irq = 1, .has_hw_contexts = 1, + .has_logical_ring_contexts = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, -- cgit v1.2.1 From ca9c4523882bb0ce86b4adb2b5ee4f29d2f0fc5b Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:54 -0700 Subject: drm/i915: Move HAS_L3_DPF definition to platform definition Moving all GPU features to the platform definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_pci.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 431ddf08bc0a..112e378d1937 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -664,6 +664,7 @@ struct intel_csr { func(has_gmbus_irq) sep \ func(has_hw_contexts) sep \ func(has_logical_ring_contexts) sep \ + func(has_l3_dpf) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2841,7 +2842,7 @@ struct drm_i915_cmd_table { IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) /* DPF == dynamic parity feature */ -#define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) +#define HAS_L3_DPF(dev) (INTEL_INFO(dev)->has_l3_dpf) #define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev)) #define GT_FREQUENCY_MULTIPLIER 50 diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index dc167b0e0b74..e192df929dde 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -222,18 +222,21 @@ static const struct intel_device_info intel_sandybridge_m_info = { static const struct intel_device_info intel_ivybridge_d_info = { GEN7_FEATURES, .is_ivybridge = 1, + .has_l3_dpf = 1, }; static const struct intel_device_info intel_ivybridge_m_info = { GEN7_FEATURES, .is_ivybridge = 1, .is_mobile = 1, + .has_l3_dpf = 1, }; static const struct intel_device_info intel_ivybridge_q_info = { GEN7_FEATURES, .is_ivybridge = 1, .num_pipes = 0, /* legal, last one wins */ + .has_l3_dpf = 1, }; #define VLV_FEATURES \ @@ -268,6 +271,7 @@ static const struct intel_device_info intel_valleyview_info = { static const struct intel_device_info intel_haswell_info = { HSW_FEATURES, .is_haswell = 1, + .has_l3_dpf = 1, }; #define BDW_FEATURES \ -- cgit v1.2.1 From 804b87125e3ce49b20d9e8f39a70280e9adc5de1 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:55 -0700 Subject: drm/i915: Move HAS_GMCH_DISPLAY definition to platform Moving all GPU features to the platform definition allows for - standard place when adding new features from new platforms - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_pci.c | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 112e378d1937..fcba6fe3caaf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -665,6 +665,7 @@ struct intel_csr { func(has_hw_contexts) sep \ func(has_logical_ring_contexts) sep \ func(has_l3_dpf) sep \ + func(has_gmch_display) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2838,8 +2839,7 @@ struct drm_i915_cmd_table { #define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP) #define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE) -#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || \ - IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) +#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->has_gmch_display) /* DPF == dynamic parity feature */ #define HAS_L3_DPF(dev) (INTEL_INFO(dev)->has_l3_dpf) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index e192df929dde..0f1eb4a5153d 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -57,6 +57,7 @@ #define GEN2_FEATURES \ .gen = 2, .num_pipes = 1, \ .has_overlay = 1, .overlay_needs_physical = 1, \ + .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -85,6 +86,7 @@ static const struct intel_device_info intel_i865g_info = { #define GEN3_FEATURES \ .gen = 3, .num_pipes = 2, \ + .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -119,6 +121,7 @@ static const struct intel_device_info intel_i945gm_info = { #define GEN4_FEATURES \ .gen = 4, .num_pipes = 2, \ .has_hotplug = 1, \ + .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -246,6 +249,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { .has_rc6 = 1, \ .has_gmbus_irq = 1, \ .has_hw_contexts = 1, \ + .has_gmch_display = 1, \ .need_gfx_hws = 1, .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .display_mmio_offset = VLV_DISPLAY_BASE, \ @@ -304,6 +308,7 @@ static const struct intel_device_info intel_cherryview_info = { .has_gmbus_irq = 1, .has_hw_contexts = 1, .has_logical_ring_contexts = 1, + .has_gmch_display = 1, .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, -- cgit v1.2.1 From 3177659a41cc4362cb740c24a982c2097962eb1b Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:56 -0700 Subject: drm/i915: Make HWS_NEEDS_PHYSICAL the exception Make the .hws_needs_physical the exception by switching the flag on earlier platforms since they are fewer to support. Remove the flag on later GPUs hardware since they all use GTT hws by default. Switch the logic as well in the driver to reflect this change Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- drivers/gpu/drm/i915/i915_pci.c | 27 +++++++++++++++++---------- drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++++++++++---------- 4 files changed, 30 insertions(+), 23 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fcba6fe3caaf..755799e06a21 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -639,7 +639,7 @@ struct intel_csr { func(is_i915g) sep \ func(is_i945gm) sep \ func(is_g33) sep \ - func(need_gfx_hws) sep \ + func(hws_needs_physical) sep \ func(is_g4x) sep \ func(is_pineview) sep \ func(is_broadwater) sep \ @@ -2748,7 +2748,7 @@ struct drm_i915_cmd_table { #define HAS_EDRAM(dev) (!!(__I915__(dev)->edram_cap & EDRAM_ENABLED)) #define HAS_WT(dev) ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \ HAS_EDRAM(dev)) -#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) +#define HWS_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->hws_needs_physical) #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->has_hw_contexts) #define HAS_LOGICAL_RING_CONTEXTS(dev) (INTEL_INFO(dev)->has_logical_ring_contexts) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index d45a959b7c53..334f15df7c8d 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1025,7 +1025,7 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, if (INTEL_GEN(dev_priv) > 2) ee->mode = I915_READ_MODE(engine); - if (I915_NEED_GFX_HWS(dev_priv)) { + if (!HWS_NEEDS_PHYSICAL(dev_priv)) { i915_reg_t mmio; if (IS_GEN7(dev_priv)) { diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 0f1eb4a5153d..05603b151acd 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -58,6 +58,7 @@ .gen = 2, .num_pipes = 1, \ .has_overlay = 1, .overlay_needs_physical = 1, \ .has_gmch_display = 1, \ + .hws_needs_physical = 1, \ .ring_mask = RENDER_RING, \ GEN_DEFAULT_PIPEOFFSETS, \ CURSOR_OFFSETS @@ -95,6 +96,7 @@ static const struct intel_device_info intel_i915g_info = { GEN3_FEATURES, .is_i915g = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, + .hws_needs_physical = 1, }; static const struct intel_device_info intel_i915gm_info = { GEN3_FEATURES, @@ -103,11 +105,13 @@ static const struct intel_device_info intel_i915gm_info = { .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, .has_fbc = 1, + .hws_needs_physical = 1, }; static const struct intel_device_info intel_i945g_info = { GEN3_FEATURES, .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, + .hws_needs_physical = 1, }; static const struct intel_device_info intel_i945gm_info = { GEN3_FEATURES, @@ -116,6 +120,7 @@ static const struct intel_device_info intel_i945gm_info = { .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, .has_fbc = 1, + .hws_needs_physical = 1, }; #define GEN4_FEATURES \ @@ -130,6 +135,7 @@ static const struct intel_device_info intel_i965g_info = { GEN4_FEATURES, .is_broadwater = 1, .has_overlay = 1, + .hws_needs_physical = 1, }; static const struct intel_device_info intel_i965gm_info = { @@ -138,18 +144,19 @@ static const struct intel_device_info intel_i965gm_info = { .is_mobile = 1, .has_fbc = 1, .has_overlay = 1, .supports_tv = 1, + .hws_needs_physical = 1, }; static const struct intel_device_info intel_g33_info = { GEN3_FEATURES, .is_g33 = 1, - .need_gfx_hws = 1, .has_hotplug = 1, + .has_hotplug = 1, .has_overlay = 1, }; static const struct intel_device_info intel_g45_info = { GEN4_FEATURES, - .is_g4x = 1, .need_gfx_hws = 1, + .is_g4x = 1, .has_pipe_cxsr = 1, .ring_mask = RENDER_RING | BSD_RING, }; @@ -157,7 +164,7 @@ static const struct intel_device_info intel_g45_info = { static const struct intel_device_info intel_gm45_info = { GEN4_FEATURES, .is_g4x = 1, - .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, + .is_mobile = 1, .has_fbc = 1, .has_pipe_cxsr = 1, .supports_tv = 1, .ring_mask = RENDER_RING | BSD_RING, @@ -166,13 +173,13 @@ static const struct intel_device_info intel_gm45_info = { static const struct intel_device_info intel_pineview_info = { GEN3_FEATURES, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, - .need_gfx_hws = 1, .has_hotplug = 1, + .has_hotplug = 1, .has_overlay = 1, }; #define GEN5_FEATURES \ .gen = 5, .num_pipes = 2, \ - .need_gfx_hws = 1, .has_hotplug = 1, \ + .has_hotplug = 1, \ .has_gmbus_irq = 1, \ .ring_mask = RENDER_RING | BSD_RING, \ GEN_DEFAULT_PIPEOFFSETS, \ @@ -189,7 +196,7 @@ static const struct intel_device_info intel_ironlake_m_info = { #define GEN6_FEATURES \ .gen = 6, .num_pipes = 2, \ - .need_gfx_hws = 1, .has_hotplug = 1, \ + .has_hotplug = 1, \ .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1, \ @@ -211,7 +218,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { #define GEN7_FEATURES \ .gen = 7, .num_pipes = 3, \ - .need_gfx_hws = 1, .has_hotplug = 1, \ + .has_hotplug = 1, \ .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1, \ @@ -250,7 +257,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { .has_gmbus_irq = 1, \ .has_hw_contexts = 1, \ .has_gmch_display = 1, \ - .need_gfx_hws = 1, .has_hotplug = 1, \ + .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .display_mmio_offset = VLV_DISPLAY_BASE, \ GEN_DEFAULT_PIPEOFFSETS, \ @@ -298,7 +305,7 @@ static const struct intel_device_info intel_broadwell_gt3_info = { static const struct intel_device_info intel_cherryview_info = { .gen = 8, .num_pipes = 3, - .need_gfx_hws = 1, .has_hotplug = 1, + .has_hotplug = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .is_cherryview = 1, .has_psr = 1, @@ -333,7 +340,7 @@ static const struct intel_device_info intel_skylake_gt3_info = { static const struct intel_device_info intel_broxton_info = { .is_broxton = 1, .gen = 9, - .need_gfx_hws = 1, .has_hotplug = 1, + .has_hotplug = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, .num_pipes = 3, .has_ddi = 1, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 4472752812cb..fd8fcc6ec970 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -559,10 +559,10 @@ static int init_ring_common(struct intel_engine_cs *engine) } } - if (I915_NEED_GFX_HWS(dev_priv)) - intel_ring_setup_status_page(engine); - else + if (HWS_NEEDS_PHYSICAL(dev_priv)) ring_setup_phys_status_page(engine); + else + intel_ring_setup_status_page(engine); /* Enforce ordering by reading HEAD register back */ I915_READ_HEAD(engine); @@ -2109,13 +2109,13 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine) goto error; } - if (I915_NEED_GFX_HWS(dev_priv)) { - ret = init_status_page(engine); + if (HWS_NEEDS_PHYSICAL(dev_priv)) { + WARN_ON(engine->id != RCS); + ret = init_phys_status_page(engine); if (ret) goto error; } else { - WARN_ON(engine->id != RCS); - ret = init_phys_status_page(engine); + ret = init_status_page(engine); if (ret) goto error; } @@ -2155,11 +2155,11 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) if (engine->cleanup) engine->cleanup(engine); - if (I915_NEED_GFX_HWS(dev_priv)) { - cleanup_status_page(engine); - } else { + if (HWS_NEEDS_PHYSICAL(dev_priv)) { WARN_ON(engine->id != RCS); cleanup_phys_status_page(engine); + } else { + cleanup_status_page(engine); } intel_engine_cleanup_common(engine); -- cgit v1.2.1 From 3d810fbedec403a8c0ac54fd6a08586ab08831d7 Mon Sep 17 00:00:00 2001 From: Carlos Santa Date: Wed, 17 Aug 2016 12:30:57 -0700 Subject: drm/i915: Move HAS_GUC definition to platform definition Moving all GPU features to the platform definition allows for - standard place when adding new features from new platform - possible to see supported features when dumping struct definitions Signed-off-by: Carlos Santa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_pci.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 755799e06a21..f39bede7664c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -666,6 +666,7 @@ struct intel_csr { func(has_logical_ring_contexts) sep \ func(has_l3_dpf) sep \ func(has_gmch_display) sep \ + func(has_guc) sep \ func(has_pipe_cxsr) sep \ func(has_hotplug) sep \ func(cursor_needs_physical) sep \ @@ -2807,7 +2808,7 @@ struct drm_i915_cmd_table { * command submission once loaded. But these are logically independent * properties, so we have separate macros to test them. */ -#define HAS_GUC(dev) (IS_GEN9(dev)) +#define HAS_GUC(dev) (INTEL_INFO(dev)->has_guc) #define HAS_GUC_UCODE(dev) (HAS_GUC(dev)) #define HAS_GUC_SCHED(dev) (HAS_GUC(dev)) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 05603b151acd..d771870ddd2b 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -327,6 +327,7 @@ static const struct intel_device_info intel_skylake_info = { .is_skylake = 1, .gen = 9, .has_csr = 1, + .has_guc = 1, }; static const struct intel_device_info intel_skylake_gt3_info = { @@ -334,6 +335,7 @@ static const struct intel_device_info intel_skylake_gt3_info = { .is_skylake = 1, .gen = 9, .has_csr = 1, + .has_guc = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; @@ -355,6 +357,7 @@ static const struct intel_device_info intel_broxton_info = { .has_gmbus_irq = 1, .has_hw_contexts = 1, .has_logical_ring_contexts = 1, + .has_guc = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, @@ -365,6 +368,7 @@ static const struct intel_device_info intel_kabylake_info = { .is_kabylake = 1, .gen = 9, .has_csr = 1, + .has_guc = 1, }; static const struct intel_device_info intel_kabylake_gt3_info = { @@ -372,6 +376,7 @@ static const struct intel_device_info intel_kabylake_gt3_info = { .is_kabylake = 1, .gen = 9, .has_csr = 1, + .has_guc = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; -- cgit v1.2.1 From e68a139f6bf38eb9fb8f61de8789870465c2ffaa Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:41 +0100 Subject: drm/i915: Add a sw fence for collecting up dma fences This is really a core kernel struct in disguise until we can finally place it in kernel/. There is an immediate need for a fence collection mechanism that is more flexible than fence-array, in particular being able to easily drive request submission via events (and not just interrupt driven). The same mechanism would be useful for handling nonblocking and asynchronous atomic modesets, parallel execution and more, but for the time being just create a local sw fence for execbuf. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_sw_fence.c | 362 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_sw_fence.h | 65 +++++++ 3 files changed, 428 insertions(+) create mode 100644 drivers/gpu/drm/i915/i915_sw_fence.c create mode 100644 drivers/gpu/drm/i915/i915_sw_fence.h (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index a7da24640e88..a998c2bce70a 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -16,6 +16,7 @@ i915-y := i915_drv.o \ i915_params.o \ i915_pci.o \ i915_suspend.o \ + i915_sw_fence.o \ i915_sysfs.o \ intel_csr.o \ intel_device_info.o \ diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c new file mode 100644 index 000000000000..1e5cbc585ca2 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -0,0 +1,362 @@ +/* + * (C) Copyright 2016 Intel Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#include +#include +#include + +#include "i915_sw_fence.h" + +static DEFINE_SPINLOCK(i915_sw_fence_lock); + +static int __i915_sw_fence_notify(struct i915_sw_fence *fence, + enum i915_sw_fence_notify state) +{ + i915_sw_fence_notify_t fn; + + fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK); + return fn(fence, state); +} + +static void i915_sw_fence_free(struct kref *kref) +{ + struct i915_sw_fence *fence = container_of(kref, typeof(*fence), kref); + + WARN_ON(atomic_read(&fence->pending) > 0); + + if (fence->flags & I915_SW_FENCE_MASK) + __i915_sw_fence_notify(fence, FENCE_FREE); + else + kfree(fence); +} + +static void i915_sw_fence_put(struct i915_sw_fence *fence) +{ + kref_put(&fence->kref, i915_sw_fence_free); +} + +static struct i915_sw_fence *i915_sw_fence_get(struct i915_sw_fence *fence) +{ + kref_get(&fence->kref); + return fence; +} + +static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence, + struct list_head *continuation) +{ + wait_queue_head_t *x = &fence->wait; + wait_queue_t *pos, *next; + unsigned long flags; + + atomic_set_release(&fence->pending, -1); /* 0 -> -1 [done] */ + + /* + * To prevent unbounded recursion as we traverse the graph of + * i915_sw_fences, we move the task_list from this, the next ready + * fence, to the tail of the original fence's task_list + * (and so added to the list to be woken). + */ + + spin_lock_irqsave_nested(&x->lock, flags, 1 + !!continuation); + if (continuation) { + list_for_each_entry_safe(pos, next, &x->task_list, task_list) { + if (pos->func == autoremove_wake_function) + pos->func(pos, TASK_NORMAL, 0, continuation); + else + list_move_tail(&pos->task_list, continuation); + } + } else { + LIST_HEAD(extra); + + do { + list_for_each_entry_safe(pos, next, + &x->task_list, task_list) + pos->func(pos, TASK_NORMAL, 0, &extra); + + if (list_empty(&extra)) + break; + + list_splice_tail_init(&extra, &x->task_list); + } while (1); + } + spin_unlock_irqrestore(&x->lock, flags); +} + +static void __i915_sw_fence_complete(struct i915_sw_fence *fence, + struct list_head *continuation) +{ + if (!atomic_dec_and_test(&fence->pending)) + return; + + if (fence->flags & I915_SW_FENCE_MASK && + __i915_sw_fence_notify(fence, FENCE_COMPLETE) != NOTIFY_DONE) + return; + + __i915_sw_fence_wake_up_all(fence, continuation); +} + +static void i915_sw_fence_complete(struct i915_sw_fence *fence) +{ + if (WARN_ON(i915_sw_fence_done(fence))) + return; + + __i915_sw_fence_complete(fence, NULL); +} + +static void i915_sw_fence_await(struct i915_sw_fence *fence) +{ + WARN_ON(atomic_inc_return(&fence->pending) <= 1); +} + +void i915_sw_fence_init(struct i915_sw_fence *fence, i915_sw_fence_notify_t fn) +{ + BUG_ON((unsigned long)fn & ~I915_SW_FENCE_MASK); + + init_waitqueue_head(&fence->wait); + kref_init(&fence->kref); + atomic_set(&fence->pending, 1); + fence->flags = (unsigned long)fn; +} + +void i915_sw_fence_commit(struct i915_sw_fence *fence) +{ + i915_sw_fence_complete(fence); + i915_sw_fence_put(fence); +} + +static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int flags, void *key) +{ + list_del(&wq->task_list); + __i915_sw_fence_complete(wq->private, key); + i915_sw_fence_put(wq->private); + return 0; +} + +static bool __i915_sw_fence_check_if_after(struct i915_sw_fence *fence, + const struct i915_sw_fence * const signaler) +{ + wait_queue_t *wq; + + if (__test_and_set_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags)) + return false; + + if (fence == signaler) + return true; + + list_for_each_entry(wq, &fence->wait.task_list, task_list) { + if (wq->func != i915_sw_fence_wake) + continue; + + if (__i915_sw_fence_check_if_after(wq->private, signaler)) + return true; + } + + return false; +} + +static void __i915_sw_fence_clear_checked_bit(struct i915_sw_fence *fence) +{ + wait_queue_t *wq; + + if (!__test_and_clear_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags)) + return; + + list_for_each_entry(wq, &fence->wait.task_list, task_list) { + if (wq->func != i915_sw_fence_wake) + continue; + + __i915_sw_fence_clear_checked_bit(wq->private); + } +} + +static bool i915_sw_fence_check_if_after(struct i915_sw_fence *fence, + const struct i915_sw_fence * const signaler) +{ + unsigned long flags; + bool err; + + if (!IS_ENABLED(CONFIG_I915_SW_FENCE_CHECK_DAG)) + return false; + + spin_lock_irqsave(&i915_sw_fence_lock, flags); + err = __i915_sw_fence_check_if_after(fence, signaler); + __i915_sw_fence_clear_checked_bit(fence); + spin_unlock_irqrestore(&i915_sw_fence_lock, flags); + + return err; +} + +int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, + struct i915_sw_fence *signaler, + wait_queue_t *wq) +{ + unsigned long flags; + int pending; + + if (i915_sw_fence_done(signaler)) + return 0; + + /* The dependency graph must be acyclic. */ + if (unlikely(i915_sw_fence_check_if_after(fence, signaler))) + return -EINVAL; + + INIT_LIST_HEAD(&wq->task_list); + wq->flags = 0; + wq->func = i915_sw_fence_wake; + wq->private = i915_sw_fence_get(fence); + + i915_sw_fence_await(fence); + + spin_lock_irqsave(&signaler->wait.lock, flags); + if (likely(!i915_sw_fence_done(signaler))) { + __add_wait_queue_tail(&signaler->wait, wq); + pending = 1; + } else { + i915_sw_fence_wake(wq, 0, 0, NULL); + pending = 0; + } + spin_unlock_irqrestore(&signaler->wait.lock, flags); + + return pending; +} + +struct dma_fence_cb { + struct fence_cb base; + struct i915_sw_fence *fence; + struct fence *dma; + struct timer_list timer; +}; + +static void timer_i915_sw_fence_wake(unsigned long data) +{ + struct dma_fence_cb *cb = (struct dma_fence_cb *)data; + + printk(KERN_WARNING "asynchronous wait on fence %s:%s:%x timed out\n", + cb->dma->ops->get_driver_name(cb->dma), + cb->dma->ops->get_timeline_name(cb->dma), + cb->dma->seqno); + fence_put(cb->dma); + cb->dma = NULL; + + i915_sw_fence_commit(cb->fence); + cb->timer.function = NULL; +} + +static void dma_i915_sw_fence_wake(struct fence *dma, struct fence_cb *data) +{ + struct dma_fence_cb *cb = container_of(data, typeof(*cb), base); + + del_timer_sync(&cb->timer); + if (cb->timer.function) + i915_sw_fence_commit(cb->fence); + fence_put(cb->dma); + + kfree(cb); +} + +int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, + struct fence *dma, + unsigned long timeout, + gfp_t gfp) +{ + struct dma_fence_cb *cb; + int ret; + + if (fence_is_signaled(dma)) + return 0; + + cb = kmalloc(sizeof(*cb), gfp); + if (!cb) { + if (!gfpflags_allow_blocking(gfp)) + return -ENOMEM; + + return fence_wait(dma, false); + } + + cb->fence = i915_sw_fence_get(fence); + i915_sw_fence_await(fence); + + cb->dma = NULL; + __setup_timer(&cb->timer, + timer_i915_sw_fence_wake, (unsigned long)cb, + TIMER_IRQSAFE); + if (timeout) { + cb->dma = fence_get(dma); + mod_timer(&cb->timer, round_jiffies_up(jiffies + timeout)); + } + + ret = fence_add_callback(dma, &cb->base, dma_i915_sw_fence_wake); + if (ret == 0) { + ret = 1; + } else { + dma_i915_sw_fence_wake(dma, &cb->base); + if (ret == -ENOENT) /* fence already signaled */ + ret = 0; + } + + return ret; +} + +int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, + struct reservation_object *resv, + const struct fence_ops *exclude, + bool write, + unsigned long timeout, + gfp_t gfp) +{ + struct fence *excl; + int ret = 0, pending; + + if (write) { + struct fence **shared; + unsigned int count, i; + + ret = reservation_object_get_fences_rcu(resv, + &excl, &count, &shared); + if (ret) + return ret; + + for (i = 0; i < count; i++) { + if (shared[i]->ops == exclude) + continue; + + pending = i915_sw_fence_await_dma_fence(fence, + shared[i], + timeout, + gfp); + if (pending < 0) { + ret = pending; + break; + } + + ret |= pending; + } + + for (i = 0; i < count; i++) + fence_put(shared[i]); + kfree(shared); + } else { + excl = reservation_object_get_excl_rcu(resv); + } + + if (ret >= 0 && excl && excl->ops != exclude) { + pending = i915_sw_fence_await_dma_fence(fence, + excl, + timeout, + gfp); + if (pending < 0) + ret = pending; + else + ret |= pending; + } + + fence_put(excl); + + return ret; +} diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h new file mode 100644 index 000000000000..373141602ca4 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -0,0 +1,65 @@ +/* + * i915_sw_fence.h - library routines for N:M synchronisation points + * + * Copyright (C) 2016 Intel Corporation + * + * This file is released under the GPLv2. + * + */ + +#ifndef _I915_SW_FENCE_H_ +#define _I915_SW_FENCE_H_ + +#include +#include +#include /* for NOTIFY_DONE */ +#include + +struct completion; +struct fence; +struct fence_ops; +struct reservation_object; + +struct i915_sw_fence { + wait_queue_head_t wait; + unsigned long flags; + struct kref kref; + atomic_t pending; +}; + +#define I915_SW_FENCE_CHECKED_BIT 0 /* used internally for DAG checking */ +#define I915_SW_FENCE_PRIVATE_BIT 1 /* available for use by owner */ +#define I915_SW_FENCE_MASK (~3) + +enum i915_sw_fence_notify { + FENCE_COMPLETE, + FENCE_FREE +}; + +typedef int (*i915_sw_fence_notify_t)(struct i915_sw_fence *, + enum i915_sw_fence_notify state); +#define __i915_sw_fence_call __aligned(4) + +void i915_sw_fence_init(struct i915_sw_fence *fence, i915_sw_fence_notify_t fn); +void i915_sw_fence_commit(struct i915_sw_fence *fence); + +int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence, + struct i915_sw_fence *after, + wait_queue_t *wq); +int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, + struct fence *dma, + unsigned long timeout, + gfp_t gfp); +int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, + struct reservation_object *resv, + const struct fence_ops *exclude, + bool write, + unsigned long timeout, + gfp_t gfp); + +static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence) +{ + return atomic_read(&fence->pending) < 0; +} + +#endif /* _I915_SW_FENCE_H_ */ -- cgit v1.2.1 From ba49b2f8237b0241fb86660812c0b235580ac182 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:42 +0100 Subject: drm/i915: Only queue requests during execlists submission Leave the more complicated request dequeueing to the tasklet and instead just kick start the tasklet if we detect we are adding the first request. v2: Play around with list operators until we agree upon something Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 92bfe47ad33c..9bfe304c5256 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -609,35 +609,15 @@ static void intel_lrc_irq_handler(unsigned long data) static void execlists_submit_request(struct drm_i915_gem_request *request) { struct intel_engine_cs *engine = request->engine; - struct drm_i915_gem_request *cursor; - int num_elements = 0; spin_lock_bh(&engine->execlist_lock); - list_for_each_entry(cursor, &engine->execlist_queue, execlist_link) - if (++num_elements > 2) - break; - - if (num_elements > 2) { - struct drm_i915_gem_request *tail_req; - - tail_req = list_last_entry(&engine->execlist_queue, - struct drm_i915_gem_request, - execlist_link); - - if (request->ctx == tail_req->ctx) { - WARN(tail_req->elsp_submitted != 0, - "More than 2 already-submitted reqs queued\n"); - list_del(&tail_req->execlist_link); - i915_gem_request_put(tail_req); - } - } - i915_gem_request_get(request); - list_add_tail(&request->execlist_link, &engine->execlist_queue); request->ctx_hw_id = request->ctx->hw_id; - if (num_elements == 0) - execlists_unqueue(engine); + + if (list_empty(&engine->execlist_queue)) + tasklet_hi_schedule(&engine->irq_tasklet); + list_add_tail(&request->execlist_link, &engine->execlist_queue); spin_unlock_bh(&engine->execlist_lock); } -- cgit v1.2.1 From a52abd2facfe8add456a075c2d9e254db071bf85 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:43 +0100 Subject: drm/i915: Record the position of the workarounds in the tail of the request Rather than blindly assuming we need to advance the tail for resubmitting the request via the ELSP, record the position. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.h | 15 +++++++++------ drivers/gpu/drm/i915/intel_lrc.c | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 91014de8bfbc..2faa3bb4c39b 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -88,20 +88,23 @@ struct drm_i915_gem_request { */ u32 previous_seqno; - /** Position in the ringbuffer of the start of the request */ + /** Position in the ring of the start of the request */ u32 head; /** - * Position in the ringbuffer of the start of the postfix. - * This is required to calculate the maximum available ringbuffer - * space without overwriting the postfix. + * Position in the ring of the start of the postfix. + * This is required to calculate the maximum available ring space + * without overwriting the postfix. */ u32 postfix; - /** Position in the ringbuffer of the end of the whole request */ + /** Position in the ring of the end of the whole request */ u32 tail; - /** Preallocate space in the ringbuffer for the emitting the request */ + /** Position in the ring of the end of any workarounds after the tail */ + u32 wa_tail; + + /** Preallocate space in the ring for the emitting the request */ u32 reserved_space; /** diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 9bfe304c5256..d7fa9b3a55c3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -482,8 +482,7 @@ static void execlists_unqueue(struct intel_engine_cs *engine) * resubmit the request. See gen8_emit_request() for where we * prepare the padding after the end of the request. */ - req0->tail += 8; - req0->tail &= req0->ring->size - 1; + req0->tail = req0->wa_tail; } execlists_elsp_submit_contexts(req0, req1); @@ -711,6 +710,7 @@ intel_logical_ring_advance(struct drm_i915_gem_request *request) intel_ring_emit(ring, MI_NOOP); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); + request->wa_tail = ring->tail; /* We keep the previous context alive until we retire the following * request. This ensures that any the context object is still pinned -- cgit v1.2.1 From 8b38b3a16719ee86f9aa2fd1bc479db7d5b28e48 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:44 +0100 Subject: drm/i915: Compute the ELSP register location once Similar to the issue with reading from the context status buffer, see commit 26720ab97fea ("drm/i915: Move CSB MMIO reads out of the execlists lock"), we frequently write to the ELSP register (4 writes per interrupt) and know we hold the required spinlock and forcewake throughout. We can further reduce the cost of writing these registers beyond the I915_WRITE_FW() by precomputing the address of the ELSP register. We also note that the subsequent read serves no purpose here, and are happy to see it go. v2: Address I915_WRITE mistakes in changelog text data bss dec hex filename 1259784 4581 576 1264941 134d2d drivers/gpu/drm/i915/i915.ko 1259720 4581 576 1264877 134ced drivers/gpu/drm/i915/i915.ko Saves 64 bytes of address recomputation. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d7fa9b3a55c3..a6b9033203e5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -331,10 +331,11 @@ uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx, static void execlists_elsp_write(struct drm_i915_gem_request *rq0, struct drm_i915_gem_request *rq1) { - struct intel_engine_cs *engine = rq0->engine; struct drm_i915_private *dev_priv = rq0->i915; - uint64_t desc[2]; + u32 __iomem *elsp = + dev_priv->regs + i915_mmio_reg_offset(RING_ELSP(engine)); + u64 desc[2]; if (rq1) { desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->engine); @@ -347,15 +348,12 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, rq0->elsp_submitted++; /* You must always write both descriptors in the order below. */ - I915_WRITE_FW(RING_ELSP(engine), upper_32_bits(desc[1])); - I915_WRITE_FW(RING_ELSP(engine), lower_32_bits(desc[1])); + writel(upper_32_bits(desc[1]), elsp); + writel(lower_32_bits(desc[1]), elsp); - I915_WRITE_FW(RING_ELSP(engine), upper_32_bits(desc[0])); + writel(upper_32_bits(desc[0]), elsp); /* The context is automatically loaded after the following */ - I915_WRITE_FW(RING_ELSP(engine), lower_32_bits(desc[0])); - - /* ELSP is a wo register, use another nearby reg for posting */ - POSTING_READ_FW(RING_EXECLIST_STATUS_LO(engine)); + writel(lower_32_bits(desc[0]), elsp); } static void -- cgit v1.2.1 From bbd6c47e114f30dbe26018694059f2491c22271c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:45 +0100 Subject: drm/i915: Reorder submitting the requests to ELSP Just rearrange the code to reduce churn in the next patch. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 76 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index a6b9033203e5..7bb743f79d18 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -328,32 +328,18 @@ uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx, return ctx->engine[engine->id].lrc_desc; } -static void execlists_elsp_write(struct drm_i915_gem_request *rq0, - struct drm_i915_gem_request *rq1) +static inline void +execlists_context_status_change(struct drm_i915_gem_request *rq, + unsigned long status) { - struct intel_engine_cs *engine = rq0->engine; - struct drm_i915_private *dev_priv = rq0->i915; - u32 __iomem *elsp = - dev_priv->regs + i915_mmio_reg_offset(RING_ELSP(engine)); - u64 desc[2]; - - if (rq1) { - desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->engine); - rq1->elsp_submitted++; - } else { - desc[1] = 0; - } - - desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->engine); - rq0->elsp_submitted++; - - /* You must always write both descriptors in the order below. */ - writel(upper_32_bits(desc[1]), elsp); - writel(lower_32_bits(desc[1]), elsp); + /* + * Only used when GVT-g is enabled now. When GVT-g is disabled, + * The compiler should eliminate this function as dead-code. + */ + if (!IS_ENABLED(CONFIG_DRM_I915_GVT)) + return; - writel(upper_32_bits(desc[0]), elsp); - /* The context is automatically loaded after the following */ - writel(lower_32_bits(desc[0]), elsp); + atomic_notifier_call_chain(&rq->ctx->status_notifier, status, rq); } static void @@ -382,6 +368,34 @@ static void execlists_update_context(struct drm_i915_gem_request *rq) execlists_update_context_pdps(ppgtt, reg_state); } +static void execlists_elsp_write(struct drm_i915_gem_request *rq0, + struct drm_i915_gem_request *rq1) +{ + struct intel_engine_cs *engine = rq0->engine; + struct drm_i915_private *dev_priv = rq0->i915; + u32 __iomem *elsp = + dev_priv->regs + i915_mmio_reg_offset(RING_ELSP(engine)); + u64 desc[2]; + + if (rq1) { + desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->engine); + rq1->elsp_submitted++; + } else { + desc[1] = 0; + } + + desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->engine); + rq0->elsp_submitted++; + + /* You must always write both descriptors in the order below. */ + writel(upper_32_bits(desc[1]), elsp); + writel(lower_32_bits(desc[1]), elsp); + + writel(upper_32_bits(desc[0]), elsp); + /* The context is automatically loaded after the following */ + writel(lower_32_bits(desc[0]), elsp); +} + static void execlists_elsp_submit_contexts(struct drm_i915_gem_request *rq0, struct drm_i915_gem_request *rq1) { @@ -402,20 +416,6 @@ static void execlists_elsp_submit_contexts(struct drm_i915_gem_request *rq0, spin_unlock_irq(&dev_priv->uncore.lock); } -static inline void execlists_context_status_change( - struct drm_i915_gem_request *rq, - unsigned long status) -{ - /* - * Only used when GVT-g is enabled now. When GVT-g is disabled, - * The compiler should eliminate this function as dead-code. - */ - if (!IS_ENABLED(CONFIG_DRM_I915_GVT)) - return; - - atomic_notifier_call_chain(&rq->ctx->status_notifier, status, rq); -} - static void execlists_unqueue(struct intel_engine_cs *engine) { struct drm_i915_gem_request *req0 = NULL, *req1 = NULL; -- cgit v1.2.1 From 70c2a24dbfd28eb9b905b369679b32a74361d7ac Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:46 +0100 Subject: drm/i915: Simplify ELSP queue request tracking Emulate HW to track and manage ELSP queue. A set of SW ports are defined and requests are assigned to these ports before submitting them to HW. This helps in cleaning up incomplete requests during reset recovery easier especially after engine reset by decoupling elsp queue management. This will become more clear in the next patch. In the engine reset case we want to resume where we left-off after skipping the incomplete batch which requires checking the elsp queue, removing element and fixing elsp_submitted counts in some cases. Instead of directly manipulating the elsp queue from reset path we can examine these ports, fix up ringbuffer pointers using the incomplete request and restart submissions again after reset. Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Arun Siluvery Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1470414607-32453-3-git-send-email-arun.siluvery@linux.intel.com Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-6-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 13 +- drivers/gpu/drm/i915/i915_gem_request.c | 1 - drivers/gpu/drm/i915/i915_gem_request.h | 21 +- drivers/gpu/drm/i915/intel_lrc.c | 402 +++++++++++++------------------- drivers/gpu/drm/i915/intel_lrc.h | 2 - drivers/gpu/drm/i915/intel_ringbuffer.h | 7 +- 7 files changed, 184 insertions(+), 264 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e52e12855850..1147b99a3120 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2051,7 +2051,7 @@ static int i915_execlists(struct seq_file *m, void *data) status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer); - read_pointer = engine->next_context_status_buffer; + read_pointer = GEN8_CSB_READ_PTR(status_pointer); write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); if (read_pointer > write_pointer) write_pointer += GEN8_CSB_ENTRIES; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2401818171f5..b00fb8548d50 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2575,6 +2575,9 @@ static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine) struct drm_i915_gem_request *request; struct intel_ring *ring; + /* Ensure irq handler finishes, and not run again. */ + tasklet_kill(&engine->irq_tasklet); + /* Mark all pending requests as complete so that any concurrent * (lockless) lookup doesn't try and wait upon the request as we * reset it. @@ -2588,10 +2591,12 @@ static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine) */ if (i915.enable_execlists) { - /* Ensure irq handler finishes or is cancelled. */ - tasklet_kill(&engine->irq_tasklet); - - intel_execlists_cancel_requests(engine); + spin_lock(&engine->execlist_lock); + INIT_LIST_HEAD(&engine->execlist_queue); + i915_gem_request_put(engine->execlist_port[0].request); + i915_gem_request_put(engine->execlist_port[1].request); + memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); + spin_unlock(&engine->execlist_lock); } /* diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 9cc08a1e43c6..ec613fd5e01c 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -402,7 +402,6 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, req->previous_context = NULL; req->file_priv = NULL; req->batch = NULL; - req->elsp_submitted = 0; /* * Reserve space in the ring buffer for all the commands required to diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 2faa3bb4c39b..a231bd318ef0 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -137,27 +137,8 @@ struct drm_i915_gem_request { /** file_priv list entry for this request */ struct list_head client_list; - /** - * The ELSP only accepts two elements at a time, so we queue - * context/tail pairs on a given queue (ring->execlist_queue) until the - * hardware is available. The queue serves a double purpose: we also use - * it to keep track of the up to 2 contexts currently in the hardware - * (usually one in execution and the other queued up by the GPU): We - * only remove elements from the head of the queue when the hardware - * informs us that an element has been completed. - * - * All accesses to the queue are mediated by a spinlock - * (ring->execlist_lock). - */ - - /** Execlist link in the submission queue.*/ + /** Link in the execlist submission queue, guarded by execlist_lock. */ struct list_head execlist_link; - - /** Execlists no. of times this request has been sent to the ELSP */ - int elsp_submitted; - - /** Execlists context hardware id. */ - unsigned int ctx_hw_id; }; extern const struct fence_ops i915_fence_ops; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7bb743f79d18..a33687d294b5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -156,6 +156,11 @@ #define GEN8_CTX_STATUS_COMPLETE (1 << 4) #define GEN8_CTX_STATUS_LITE_RESTORE (1 << 15) +#define GEN8_CTX_STATUS_COMPLETED_MASK \ + (GEN8_CTX_STATUS_ACTIVE_IDLE | \ + GEN8_CTX_STATUS_PREEMPTED | \ + GEN8_CTX_STATUS_ELEMENT_SWITCH) + #define CTX_LRI_HEADER_0 0x01 #define CTX_CONTEXT_CONTROL 0x02 #define CTX_RING_HEAD 0x04 @@ -263,12 +268,10 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; - if (IS_GEN8(dev_priv) || IS_GEN9(dev_priv)) - engine->idle_lite_restore_wa = ~0; - - engine->disable_lite_restore_wa = (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || - IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) && - (engine->id == VCS || engine->id == VCS2); + engine->disable_lite_restore_wa = + (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || + IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) && + (engine->id == VCS || engine->id == VCS2); engine->ctx_desc_template = GEN8_CTX_VALID; if (IS_GEN8(dev_priv)) @@ -351,11 +354,11 @@ execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state) ASSIGN_CTX_PDP(ppgtt, reg_state, 0); } -static void execlists_update_context(struct drm_i915_gem_request *rq) +static u64 execlists_update_context(struct drm_i915_gem_request *rq) { - struct intel_engine_cs *engine = rq->engine; + struct intel_context *ce = &rq->ctx->engine[rq->engine->id]; struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt; - uint32_t *reg_state = rq->ctx->engine[engine->id].lrc_reg_state; + u32 *reg_state = ce->lrc_reg_state; reg_state[CTX_RING_TAIL+1] = intel_ring_offset(rq->ring, rq->tail); @@ -366,26 +369,34 @@ static void execlists_update_context(struct drm_i915_gem_request *rq) */ if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) execlists_update_context_pdps(ppgtt, reg_state); + + return ce->lrc_desc; } -static void execlists_elsp_write(struct drm_i915_gem_request *rq0, - struct drm_i915_gem_request *rq1) +static void execlists_submit_ports(struct intel_engine_cs *engine) { - struct intel_engine_cs *engine = rq0->engine; - struct drm_i915_private *dev_priv = rq0->i915; + struct drm_i915_private *dev_priv = engine->i915; + struct execlist_port *port = engine->execlist_port; u32 __iomem *elsp = dev_priv->regs + i915_mmio_reg_offset(RING_ELSP(engine)); u64 desc[2]; - if (rq1) { - desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->engine); - rq1->elsp_submitted++; + if (!port[0].count) + execlists_context_status_change(port[0].request, + INTEL_CONTEXT_SCHEDULE_IN); + desc[0] = execlists_update_context(port[0].request); + engine->preempt_wa = port[0].count++; /* bdw only? fixed on skl? */ + + if (port[1].request) { + GEM_BUG_ON(port[1].count); + execlists_context_status_change(port[1].request, + INTEL_CONTEXT_SCHEDULE_IN); + desc[1] = execlists_update_context(port[1].request); + port[1].count = 1; } else { desc[1] = 0; } - - desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->engine); - rq0->elsp_submitted++; + GEM_BUG_ON(desc[0] == desc[1]); /* You must always write both descriptors in the order below. */ writel(upper_32_bits(desc[1]), elsp); @@ -396,141 +407,125 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, writel(lower_32_bits(desc[0]), elsp); } -static void execlists_elsp_submit_contexts(struct drm_i915_gem_request *rq0, - struct drm_i915_gem_request *rq1) +static bool ctx_single_port_submission(const struct i915_gem_context *ctx) { - struct drm_i915_private *dev_priv = rq0->i915; - unsigned int fw_domains = rq0->engine->fw_domains; - - execlists_update_context(rq0); - - if (rq1) - execlists_update_context(rq1); + return (IS_ENABLED(CONFIG_DRM_I915_GVT) && + ctx->execlists_force_single_submission); +} - spin_lock_irq(&dev_priv->uncore.lock); - intel_uncore_forcewake_get__locked(dev_priv, fw_domains); +static bool can_merge_ctx(const struct i915_gem_context *prev, + const struct i915_gem_context *next) +{ + if (prev != next) + return false; - execlists_elsp_write(rq0, rq1); + if (ctx_single_port_submission(prev)) + return false; - intel_uncore_forcewake_put__locked(dev_priv, fw_domains); - spin_unlock_irq(&dev_priv->uncore.lock); + return true; } -static void execlists_unqueue(struct intel_engine_cs *engine) +static void execlists_dequeue(struct intel_engine_cs *engine) { - struct drm_i915_gem_request *req0 = NULL, *req1 = NULL; - struct drm_i915_gem_request *cursor, *tmp; + struct drm_i915_gem_request *cursor, *last; + struct execlist_port *port = engine->execlist_port; + bool submit = false; + + last = port->request; + if (last) + /* WaIdleLiteRestore:bdw,skl + * Apply the wa NOOPs to prevent ring:HEAD == req:TAIL + * as we resubmit the request. See gen8_emit_request() + * for where we prepare the padding after the end of the + * request. + */ + last->tail = last->wa_tail; - assert_spin_locked(&engine->execlist_lock); + GEM_BUG_ON(port[1].request); - /* - * If irqs are not active generate a warning as batches that finish - * without the irqs may get lost and a GPU Hang may occur. + /* Hardware submission is through 2 ports. Conceptually each port + * has a (RING_START, RING_HEAD, RING_TAIL) tuple. RING_START is + * static for a context, and unique to each, so we only execute + * requests belonging to a single context from each ring. RING_HEAD + * is maintained by the CS in the context image, it marks the place + * where it got up to last time, and through RING_TAIL we tell the CS + * where we want to execute up to this time. + * + * In this list the requests are in order of execution. Consecutive + * requests from the same context are adjacent in the ringbuffer. We + * can combine these requests into a single RING_TAIL update: + * + * RING_HEAD...req1...req2 + * ^- RING_TAIL + * since to execute req2 the CS must first execute req1. + * + * Our goal then is to point each port to the end of a consecutive + * sequence of requests as being the most optimal (fewest wake ups + * and context switches) submission. */ - WARN_ON(!intel_irqs_enabled(engine->i915)); - - /* Try to read in pairs */ - list_for_each_entry_safe(cursor, tmp, &engine->execlist_queue, - execlist_link) { - if (!req0) { - req0 = cursor; - } else if (req0->ctx == cursor->ctx) { - /* Same ctx: ignore first request, as second request - * will update tail past first request's workload */ - cursor->elsp_submitted = req0->elsp_submitted; - list_del(&req0->execlist_link); - i915_gem_request_put(req0); - req0 = cursor; - } else { - if (IS_ENABLED(CONFIG_DRM_I915_GVT)) { - /* - * req0 (after merged) ctx requires single - * submission, stop picking - */ - if (req0->ctx->execlists_force_single_submission) - break; - /* - * req0 ctx doesn't require single submission, - * but next req ctx requires, stop picking - */ - if (cursor->ctx->execlists_force_single_submission) - break; - } - req1 = cursor; - WARN_ON(req1->elsp_submitted); - break; - } - } - if (unlikely(!req0)) - return; - - execlists_context_status_change(req0, INTEL_CONTEXT_SCHEDULE_IN); - - if (req1) - execlists_context_status_change(req1, - INTEL_CONTEXT_SCHEDULE_IN); - - if (req0->elsp_submitted & engine->idle_lite_restore_wa) { - /* - * WaIdleLiteRestore: make sure we never cause a lite restore - * with HEAD==TAIL. + spin_lock(&engine->execlist_lock); + list_for_each_entry(cursor, &engine->execlist_queue, execlist_link) { + /* Can we combine this request with the current port? It has to + * be the same context/ringbuffer and not have any exceptions + * (e.g. GVT saying never to combine contexts). * - * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL as we - * resubmit the request. See gen8_emit_request() for where we - * prepare the padding after the end of the request. + * If we can combine the requests, we can execute both by + * updating the RING_TAIL to point to the end of the second + * request, and so we never need to tell the hardware about + * the first. */ - req0->tail = req0->wa_tail; + if (last && !can_merge_ctx(cursor->ctx, last->ctx)) { + /* If we are on the second port and cannot combine + * this request with the last, then we are done. + */ + if (port != engine->execlist_port) + break; + + /* If GVT overrides us we only ever submit port[0], + * leaving port[1] empty. Note that we also have + * to be careful that we don't queue the same + * context (even though a different request) to + * the second port. + */ + if (ctx_single_port_submission(cursor->ctx)) + break; + + GEM_BUG_ON(last->ctx == cursor->ctx); + + i915_gem_request_assign(&port->request, last); + port++; + } + last = cursor; + submit = true; + } + if (submit) { + /* Decouple all the requests submitted from the queue */ + engine->execlist_queue.next = &cursor->execlist_link; + cursor->execlist_link.prev = &engine->execlist_queue; + + i915_gem_request_assign(&port->request, last); } + spin_unlock(&engine->execlist_lock); - execlists_elsp_submit_contexts(req0, req1); + if (submit) + execlists_submit_ports(engine); } -static unsigned int -execlists_check_remove_request(struct intel_engine_cs *engine, u32 ctx_id) +static bool execlists_elsp_idle(struct intel_engine_cs *engine) { - struct drm_i915_gem_request *head_req; - - assert_spin_locked(&engine->execlist_lock); - - head_req = list_first_entry_or_null(&engine->execlist_queue, - struct drm_i915_gem_request, - execlist_link); - - if (WARN_ON(!head_req || (head_req->ctx_hw_id != ctx_id))) - return 0; - - WARN(head_req->elsp_submitted == 0, "Never submitted head request\n"); - - if (--head_req->elsp_submitted > 0) - return 0; - - execlists_context_status_change(head_req, INTEL_CONTEXT_SCHEDULE_OUT); - - list_del(&head_req->execlist_link); - i915_gem_request_put(head_req); - - return 1; + return !engine->execlist_port[0].request; } -static u32 -get_context_status(struct intel_engine_cs *engine, unsigned int read_pointer, - u32 *context_id) +static bool execlists_elsp_ready(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = engine->i915; - u32 status; - - read_pointer %= GEN8_CSB_ENTRIES; - - status = I915_READ_FW(RING_CONTEXT_STATUS_BUF_LO(engine, read_pointer)); - - if (status & GEN8_CTX_STATUS_IDLE_ACTIVE) - return 0; + int port; - *context_id = I915_READ_FW(RING_CONTEXT_STATUS_BUF_HI(engine, - read_pointer)); + port = 1; /* wait for a free slot */ + if (engine->disable_lite_restore_wa || engine->preempt_wa) + port = 0; /* wait for GPU to be idle before continuing */ - return status; + return !engine->execlist_port[port].request; } /* @@ -540,67 +535,56 @@ get_context_status(struct intel_engine_cs *engine, unsigned int read_pointer, static void intel_lrc_irq_handler(unsigned long data) { struct intel_engine_cs *engine = (struct intel_engine_cs *)data; + struct execlist_port *port = engine->execlist_port; struct drm_i915_private *dev_priv = engine->i915; - u32 status_pointer; - unsigned int read_pointer, write_pointer; - u32 csb[GEN8_CSB_ENTRIES][2]; - unsigned int csb_read = 0, i; - unsigned int submit_contexts = 0; intel_uncore_forcewake_get(dev_priv, engine->fw_domains); - status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(engine)); - - read_pointer = engine->next_context_status_buffer; - write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); - if (read_pointer > write_pointer) - write_pointer += GEN8_CSB_ENTRIES; - - while (read_pointer < write_pointer) { - if (WARN_ON_ONCE(csb_read == GEN8_CSB_ENTRIES)) - break; - csb[csb_read][0] = get_context_status(engine, ++read_pointer, - &csb[csb_read][1]); - csb_read++; - } - - engine->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES; - - /* Update the read pointer to the old write pointer. Manual ringbuffer - * management ftw */ - I915_WRITE_FW(RING_CONTEXT_STATUS_PTR(engine), - _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, - engine->next_context_status_buffer << 8)); - - intel_uncore_forcewake_put(dev_priv, engine->fw_domains); - - spin_lock(&engine->execlist_lock); + if (!execlists_elsp_idle(engine)) { + u32 __iomem *csb_mmio = + dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)); + u32 __iomem *buf = + dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0)); + unsigned int csb, head, tail; + + csb = readl(csb_mmio); + head = GEN8_CSB_READ_PTR(csb); + tail = GEN8_CSB_WRITE_PTR(csb); + if (tail < head) + tail += GEN8_CSB_ENTRIES; + while (head < tail) { + unsigned int idx = ++head % GEN8_CSB_ENTRIES; + unsigned int status = readl(buf + 2 * idx); + + if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) + continue; + + GEM_BUG_ON(port[0].count == 0); + if (--port[0].count == 0) { + GEM_BUG_ON(status & GEN8_CTX_STATUS_PREEMPTED); + execlists_context_status_change(port[0].request, + INTEL_CONTEXT_SCHEDULE_OUT); + + i915_gem_request_put(port[0].request); + port[0] = port[1]; + memset(&port[1], 0, sizeof(port[1])); + + engine->preempt_wa = false; + } - for (i = 0; i < csb_read; i++) { - if (unlikely(csb[i][0] & GEN8_CTX_STATUS_PREEMPTED)) { - if (csb[i][0] & GEN8_CTX_STATUS_LITE_RESTORE) { - if (execlists_check_remove_request(engine, csb[i][1])) - WARN(1, "Lite Restored request removed from queue\n"); - } else - WARN(1, "Preemption without Lite Restore\n"); + GEM_BUG_ON(port[0].count == 0 && + !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); } - if (csb[i][0] & (GEN8_CTX_STATUS_ACTIVE_IDLE | - GEN8_CTX_STATUS_ELEMENT_SWITCH)) - submit_contexts += - execlists_check_remove_request(engine, csb[i][1]); + writel(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, + GEN8_CSB_WRITE_PTR(csb) << 8), + csb_mmio); } - if (submit_contexts) { - if (!engine->disable_lite_restore_wa || - (csb[i][0] & GEN8_CTX_STATUS_ACTIVE_IDLE)) - execlists_unqueue(engine); - } + if (execlists_elsp_ready(engine)) + execlists_dequeue(engine); - spin_unlock(&engine->execlist_lock); - - if (unlikely(submit_contexts > 2)) - DRM_ERROR("More than two context complete events?\n"); + intel_uncore_forcewake_put(dev_priv, engine->fw_domains); } static void execlists_submit_request(struct drm_i915_gem_request *request) @@ -609,12 +593,9 @@ static void execlists_submit_request(struct drm_i915_gem_request *request) spin_lock_bh(&engine->execlist_lock); - i915_gem_request_get(request); - request->ctx_hw_id = request->ctx->hw_id; - - if (list_empty(&engine->execlist_queue)) - tasklet_hi_schedule(&engine->irq_tasklet); list_add_tail(&request->execlist_link, &engine->execlist_queue); + if (execlists_elsp_idle(engine)) + tasklet_hi_schedule(&engine->irq_tasklet); spin_unlock_bh(&engine->execlist_lock); } @@ -721,23 +702,6 @@ intel_logical_ring_advance(struct drm_i915_gem_request *request) return 0; } -void intel_execlists_cancel_requests(struct intel_engine_cs *engine) -{ - struct drm_i915_gem_request *req, *tmp; - LIST_HEAD(cancel_list); - - WARN_ON(!mutex_is_locked(&engine->i915->drm.struct_mutex)); - - spin_lock_bh(&engine->execlist_lock); - list_replace_init(&engine->execlist_queue, &cancel_list); - spin_unlock_bh(&engine->execlist_lock); - - list_for_each_entry_safe(req, tmp, &cancel_list, execlist_link) { - list_del(&req->execlist_link); - i915_gem_request_put(req); - } -} - static int intel_lr_context_pin(struct i915_gem_context *ctx, struct intel_engine_cs *engine) { @@ -1258,7 +1222,6 @@ static void lrc_init_hws(struct intel_engine_cs *engine) static int gen8_init_common_ring(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; - unsigned int next_context_status_buffer_hw; lrc_init_hws(engine); @@ -1269,32 +1232,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) | _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)); - POSTING_READ(RING_MODE_GEN7(engine)); - - /* - * Instead of resetting the Context Status Buffer (CSB) read pointer to - * zero, we need to read the write pointer from hardware and use its - * value because "this register is power context save restored". - * Effectively, these states have been observed: - * - * | Suspend-to-idle (freeze) | Suspend-to-RAM (mem) | - * BDW | CSB regs not reset | CSB regs reset | - * CHT | CSB regs not reset | CSB regs not reset | - * SKL | ? | ? | - * BXT | ? | ? | - */ - next_context_status_buffer_hw = - GEN8_CSB_WRITE_PTR(I915_READ(RING_CONTEXT_STATUS_PTR(engine))); - /* - * When the CSB registers are reset (also after power-up / gpu reset), - * CSB write pointer is set to all 1's, which is not valid, use '5' in - * this special case, so the first element read is CSB[0]. - */ - if (next_context_status_buffer_hw == GEN8_CSB_PTR_MASK) - next_context_status_buffer_hw = (GEN8_CSB_ENTRIES - 1); - - engine->next_context_status_buffer = next_context_status_buffer_hw; DRM_DEBUG_DRIVER("Execlists enabled for %s\n", engine->name); intel_engine_init_hangcheck(engine); @@ -1680,10 +1618,6 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) } intel_lr_context_unpin(dev_priv->kernel_context, engine); - engine->idle_lite_restore_wa = 0; - engine->disable_lite_restore_wa = false; - engine->ctx_desc_template = 0; - lrc_destroy_wa_ctx_obj(engine); engine->i915 = NULL; } diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index a52cf57dbd40..4d70346500c2 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -97,6 +97,4 @@ int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv, int enable_execlists); void intel_execlists_enable_submission(struct drm_i915_private *dev_priv); -void intel_execlists_cancel_requests(struct intel_engine_cs *engine); - #endif /* _INTEL_LRC_H_ */ diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 84aea549de5d..2181d0a41a96 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -298,11 +298,14 @@ struct intel_engine_cs { /* Execlists */ struct tasklet_struct irq_tasklet; spinlock_t execlist_lock; /* used inside tasklet, use spin_lock_bh */ + struct execlist_port { + struct drm_i915_gem_request *request; + unsigned int count; + } execlist_port[2]; struct list_head execlist_queue; unsigned int fw_domains; - unsigned int next_context_status_buffer; - unsigned int idle_lite_restore_wa; bool disable_lite_restore_wa; + bool preempt_wa; u32 ctx_desc_template; /** -- cgit v1.2.1 From 8af29b0c78ed11a3dd2a544f9df30be988d9de29 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:47 +0100 Subject: drm/i915: Separate out reset flags from the reset counter In preparation for introducing a per-engine reset, we can first separate the mixing of the reset state from the global reset counter. The loss of atomicity in updating the reset state poses a small problem for handling the waiters. For requests, this is solved by advancing the seqno so that a waiter waking up after the reset knows the request is complete. For pending flips, we still rely on the increment of the global reset epoch (as well as the reset-in-progress flag) to signify when the hardware was reset. The advantage, now that we do not inspect the reset state during reset itself i.e. we no longer emit requests during reset, is that we can use the atomic updates of the state flags to ensure that only one reset worker is active. v2: Mika spotted that I transformed the i915_gem_wait_for_error() wakeup into a waiter wakeup. Signed-off-by: Chris Wilson Cc: Arun Siluvery Cc: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1470414607-32453-6-git-send-email-arun.siluvery@linux.intel.com Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-7-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 9 +++ drivers/gpu/drm/i915/i915_drv.c | 16 ++--- drivers/gpu/drm/i915/i915_drv.h | 46 +++++--------- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_request.c | 13 ++-- drivers/gpu/drm/i915/i915_irq.c | 103 ++++++++++++++------------------ drivers/gpu/drm/i915/intel_display.c | 25 +++++--- drivers/gpu/drm/i915/intel_drv.h | 4 +- 8 files changed, 101 insertions(+), 117 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1147b99a3120..24bf923a230f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1287,6 +1287,15 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) enum intel_engine_id id; int j; + if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) + seq_printf(m, "Wedged\n"); + if (test_bit(I915_RESET_IN_PROGRESS, &dev_priv->gpu_error.flags)) + seq_printf(m, "Reset in progress\n"); + if (waitqueue_active(&dev_priv->gpu_error.wait_queue)) + seq_printf(m, "Waiter holding struct mutex\n"); + if (waitqueue_active(&dev_priv->gpu_error.reset_queue)) + seq_printf(m, "struct_mutex blocked for reset\n"); + if (!i915.enable_hangcheck) { seq_printf(m, "Hangcheck disabled\n"); return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 02c34d6996ea..47a676d859db 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1579,7 +1579,7 @@ static int i915_drm_resume(struct drm_device *dev) mutex_lock(&dev->struct_mutex); if (i915_gem_init_hw(dev)) { DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); - atomic_or(I915_WEDGED, &dev_priv->gpu_error.reset_counter); + set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); } mutex_unlock(&dev->struct_mutex); @@ -1741,20 +1741,13 @@ int i915_reset(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; struct i915_gpu_error *error = &dev_priv->gpu_error; - unsigned reset_counter; int ret; mutex_lock(&dev->struct_mutex); /* Clear any previous failed attempts at recovery. Time to try again. */ - atomic_andnot(I915_WEDGED, &error->reset_counter); - - /* Clear the reset-in-progress flag and increment the reset epoch. */ - reset_counter = atomic_inc_return(&error->reset_counter); - if (WARN_ON(__i915_reset_in_progress(reset_counter))) { - ret = -EIO; - goto error; - } + __clear_bit(I915_WEDGED, &error->flags); + error->reset_count++; pr_notice("drm/i915: Resetting chip after gpu hang\n"); @@ -1791,6 +1784,7 @@ int i915_reset(struct drm_i915_private *dev_priv) goto error; } + clear_bit(I915_RESET_IN_PROGRESS, &error->flags); mutex_unlock(&dev->struct_mutex); /* @@ -1805,7 +1799,7 @@ int i915_reset(struct drm_i915_private *dev_priv) return 0; error: - atomic_or(I915_WEDGED, &error->reset_counter); + set_bit(I915_WEDGED, &error->flags); mutex_unlock(&dev->struct_mutex); return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f39bede7664c..dced7e72b625 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1405,9 +1405,10 @@ struct i915_gpu_error { * State variable controlling the reset flow and count * * This is a counter which gets incremented when reset is triggered, - * and again when reset has been handled. So odd values (lowest bit set) - * means that reset is in progress and even values that - * (reset_counter >> 1):th reset was successfully completed. + * + * Before the reset commences, the I915_RESET_IN_PROGRESS bit is set + * meaning that any waiters holding onto the struct_mutex should + * relinquish the lock immediately in order for the reset to start. * * If reset is not completed succesfully, the I915_WEDGE bit is * set meaning that hardware is terminally sour and there is no @@ -1422,10 +1423,11 @@ struct i915_gpu_error { * naturally enforces the correct ordering between the bail-out of the * waiter and the gpu reset work code. */ - atomic_t reset_counter; + unsigned long reset_count; -#define I915_RESET_IN_PROGRESS_FLAG 1 -#define I915_WEDGED (1 << 31) + unsigned long flags; +#define I915_RESET_IN_PROGRESS 0 +#define I915_WEDGED (BITS_PER_LONG - 1) /** * Waitqueue to signal when a hang is detected. Used to for waiters @@ -3241,44 +3243,24 @@ i915_gem_find_active_request(struct intel_engine_cs *engine); void i915_gem_retire_requests(struct drm_i915_private *dev_priv); -static inline u32 i915_reset_counter(struct i915_gpu_error *error) -{ - return atomic_read(&error->reset_counter); -} - -static inline bool __i915_reset_in_progress(u32 reset) -{ - return unlikely(reset & I915_RESET_IN_PROGRESS_FLAG); -} - -static inline bool __i915_reset_in_progress_or_wedged(u32 reset) -{ - return unlikely(reset & (I915_RESET_IN_PROGRESS_FLAG | I915_WEDGED)); -} - -static inline bool __i915_terminally_wedged(u32 reset) -{ - return unlikely(reset & I915_WEDGED); -} - static inline bool i915_reset_in_progress(struct i915_gpu_error *error) { - return __i915_reset_in_progress(i915_reset_counter(error)); + return unlikely(test_bit(I915_RESET_IN_PROGRESS, &error->flags)); } -static inline bool i915_reset_in_progress_or_wedged(struct i915_gpu_error *error) +static inline bool i915_terminally_wedged(struct i915_gpu_error *error) { - return __i915_reset_in_progress_or_wedged(i915_reset_counter(error)); + return unlikely(test_bit(I915_WEDGED, &error->flags)); } -static inline bool i915_terminally_wedged(struct i915_gpu_error *error) +static inline bool i915_reset_in_progress_or_wedged(struct i915_gpu_error *error) { - return __i915_terminally_wedged(i915_reset_counter(error)); + return i915_reset_in_progress(error) | i915_terminally_wedged(error); } static inline u32 i915_reset_count(struct i915_gpu_error *error) { - return ((i915_reset_counter(error) & ~I915_WEDGED) + 1) / 2; + return READ_ONCE(error->reset_count); } void i915_gem_reset(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b00fb8548d50..87a4f3543f0b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4525,7 +4525,7 @@ int i915_gem_init(struct drm_device *dev) * for all other failure, such as an allocation failure, bail. */ DRM_ERROR("Failed to initialize GPU, declaring it wedged\n"); - atomic_or(I915_WEDGED, &dev_priv->gpu_error.reset_counter); + set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); ret = 0; } diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index ec613fd5e01c..24eb4b1b7540 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -233,16 +233,18 @@ void i915_gem_request_retire_upto(struct drm_i915_gem_request *req) } while (tmp != req); } -static int i915_gem_check_wedge(unsigned int reset_counter, bool interruptible) +static int i915_gem_check_wedge(struct drm_i915_private *dev_priv) { - if (__i915_terminally_wedged(reset_counter)) + struct i915_gpu_error *error = &dev_priv->gpu_error; + + if (i915_terminally_wedged(error)) return -EIO; - if (__i915_reset_in_progress(reset_counter)) { + if (i915_reset_in_progress(error)) { /* Non-interruptible callers can't handle -EAGAIN, hence return * -EIO unconditionally for these. */ - if (!interruptible) + if (!dev_priv->mm.interruptible) return -EIO; return -EAGAIN; @@ -331,7 +333,6 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) { struct drm_i915_private *dev_priv = engine->i915; - unsigned int reset_counter = i915_reset_counter(&dev_priv->gpu_error); struct drm_i915_gem_request *req; u32 seqno; int ret; @@ -340,7 +341,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, * EIO if the GPU is already wedged, or EAGAIN to drop the struct_mutex * and restart. */ - ret = i915_gem_check_wedge(reset_counter, dev_priv->mm.interruptible); + ret = i915_gem_check_wedge(dev_priv); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 82358d4e0cc2..ed172d7beecb 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2501,53 +2501,41 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) kobject_uevent_env(kobj, KOBJ_CHANGE, error_event); + DRM_DEBUG_DRIVER("resetting chip\n"); + kobject_uevent_env(kobj, KOBJ_CHANGE, reset_event); + /* - * Note that there's only one work item which does gpu resets, so we - * need not worry about concurrent gpu resets potentially incrementing - * error->reset_counter twice. We only need to take care of another - * racing irq/hangcheck declaring the gpu dead for a second time. A - * quick check for that is good enough: schedule_work ensures the - * correct ordering between hang detection and this work item, and since - * the reset in-progress bit is only ever set by code outside of this - * work we don't need to worry about any other races. + * In most cases it's guaranteed that we get here with an RPM + * reference held, for example because there is a pending GPU + * request that won't finish until the reset is done. This + * isn't the case at least when we get here by doing a + * simulated reset via debugs, so get an RPM reference. */ - if (i915_reset_in_progress(&dev_priv->gpu_error)) { - DRM_DEBUG_DRIVER("resetting chip\n"); - kobject_uevent_env(kobj, KOBJ_CHANGE, reset_event); - - /* - * In most cases it's guaranteed that we get here with an RPM - * reference held, for example because there is a pending GPU - * request that won't finish until the reset is done. This - * isn't the case at least when we get here by doing a - * simulated reset via debugs, so get an RPM reference. - */ - intel_runtime_pm_get(dev_priv); + intel_runtime_pm_get(dev_priv); - intel_prepare_reset(dev_priv); + intel_prepare_reset(dev_priv); - /* - * All state reset _must_ be completed before we update the - * reset counter, for otherwise waiters might miss the reset - * pending state and not properly drop locks, resulting in - * deadlocks with the reset work. - */ - ret = i915_reset(dev_priv); + /* + * All state reset _must_ be completed before we update the + * reset counter, for otherwise waiters might miss the reset + * pending state and not properly drop locks, resulting in + * deadlocks with the reset work. + */ + ret = i915_reset(dev_priv); - intel_finish_reset(dev_priv); + intel_finish_reset(dev_priv); - intel_runtime_pm_put(dev_priv); + intel_runtime_pm_put(dev_priv); - if (ret == 0) - kobject_uevent_env(kobj, - KOBJ_CHANGE, reset_done_event); + if (ret == 0) + kobject_uevent_env(kobj, + KOBJ_CHANGE, reset_done_event); - /* - * Note: The wake_up also serves as a memory barrier so that - * waiters see the update value of the reset counter atomic_t. - */ - wake_up_all(&dev_priv->gpu_error.reset_queue); - } + /* + * Note: The wake_up also serves as a memory barrier so that + * waiters see the updated value of the dev_priv->gpu_error. + */ + wake_up_all(&dev_priv->gpu_error.reset_queue); } static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) @@ -2666,25 +2654,26 @@ void i915_handle_error(struct drm_i915_private *dev_priv, i915_capture_error_state(dev_priv, engine_mask, error_msg); i915_report_and_clear_eir(dev_priv); - if (engine_mask) { - atomic_or(I915_RESET_IN_PROGRESS_FLAG, - &dev_priv->gpu_error.reset_counter); + if (!engine_mask) + return; - /* - * Wakeup waiting processes so that the reset function - * i915_reset_and_wakeup doesn't deadlock trying to grab - * various locks. By bumping the reset counter first, the woken - * processes will see a reset in progress and back off, - * releasing their locks and then wait for the reset completion. - * We must do this for _all_ gpu waiters that might hold locks - * that the reset work needs to acquire. - * - * Note: The wake_up serves as the required memory barrier to - * ensure that the waiters see the updated value of the reset - * counter atomic_t. - */ - i915_error_wake_up(dev_priv); - } + if (test_and_set_bit(I915_RESET_IN_PROGRESS, + &dev_priv->gpu_error.flags)) + return; + + /* + * Wakeup waiting processes so that the reset function + * i915_reset_and_wakeup doesn't deadlock trying to grab + * various locks. By bumping the reset counter first, the woken + * processes will see a reset in progress and back off, + * releasing their locks and then wait for the reset completion. + * We must do this for _all_ gpu waiters that might hold locks + * that the reset work needs to acquire. + * + * Note: The wake_up also provides a memory barrier to ensure that the + * waiters see the updated value of the reset flags. + */ + i915_error_wake_up(dev_priv); i915_reset_and_wakeup(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 76d696b9b22f..7e725054ba58 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3646,15 +3646,26 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) mutex_unlock(&dev->mode_config.mutex); } +static bool abort_flip_on_reset(struct intel_crtc *crtc) +{ + struct i915_gpu_error *error = &to_i915(crtc->base.dev)->gpu_error; + + if (i915_reset_in_progress(error)) + return true; + + if (crtc->reset_count != i915_reset_count(error)) + return true; + + return false; +} + static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - unsigned reset_counter; bool pending; - reset_counter = i915_reset_counter(&to_i915(dev)->gpu_error); - if (intel_crtc->reset_counter != reset_counter) + if (abort_flip_on_reset(intel_crtc)) return false; spin_lock_irq(&dev->event_lock); @@ -11533,10 +11544,8 @@ static bool __pageflip_finished_cs(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - unsigned reset_counter; - reset_counter = i915_reset_counter(&dev_priv->gpu_error); - if (crtc->reset_counter != reset_counter) + if (abort_flip_on_reset(crtc)) return true; /* @@ -12202,8 +12211,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup; - intel_crtc->reset_counter = i915_reset_counter(&dev_priv->gpu_error); - if (__i915_reset_in_progress_or_wedged(intel_crtc->reset_counter)) { + intel_crtc->reset_count = i915_reset_count(&dev_priv->gpu_error); + if (i915_reset_in_progress_or_wedged(&dev_priv->gpu_error)) { ret = -EIO; goto cleanup; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c55b7ab2e9ed..8c089e339c29 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -706,8 +706,8 @@ struct intel_crtc { struct intel_crtc_state *config; - /* reset counter value when the last flip was submitted */ - unsigned int reset_counter; + /* global reset count when the last flip was submitted */ + unsigned int reset_count; /* Access to these should be protected by dev_priv->irq_lock. */ bool cpu_fifo_underrun_disabled; -- cgit v1.2.1 From 2c7487a524147f7a3f588c1394be44149f66da94 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:48 +0100 Subject: drm/i915: Drop local struct_mutex around intel_init_emon[ilk] Access to intel_init_emon() is strictly ordered by gt_powersave, using struct_mutex around it is overkill (and will conflict with the caller holding struct_mutex themselves). Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-8-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_pm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4f833a077089..6af438ffef9a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6773,9 +6773,7 @@ void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv) if (IS_IRONLAKE_M(dev_priv)) { ironlake_enable_drps(dev_priv); - mutex_lock(&dev_priv->drm.struct_mutex); intel_init_emon(dev_priv); - mutex_unlock(&dev_priv->drm.struct_mutex); } else if (INTEL_INFO(dev_priv)->gen >= 6) { /* * PCU communication is slow and this doesn't need to be -- cgit v1.2.1 From ea746f3659232b3104d9534d5a7ebd9934ae1dd6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:49 +0100 Subject: drm/i915: Expand bool interruptible to pass flags to i915_wait_request() We need finer control over wakeup behaviour during i915_wait_request(), so expand the current bool interruptible to a bitmask. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-9-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 16 +++++++++------- drivers/gpu/drm/i915/i915_gem_evict.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/i915_gem_request.c | 9 +++++---- drivers/gpu/drm/i915/i915_gem_request.h | 13 +++++++------ drivers/gpu/drm/i915/i915_gem_shrinker.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_userptr.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- drivers/gpu/drm/i915/intel_ringbuffer.c | 3 ++- drivers/gpu/drm/i915/intel_ringbuffer.h | 4 ++-- 12 files changed, 37 insertions(+), 32 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 24bf923a230f..0e4cbad7a883 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4794,7 +4794,7 @@ i915_drop_caches_set(void *data, u64 val) return ret; if (val & DROP_ACTIVE) { - ret = i915_gem_wait_for_idle(dev_priv, true); + ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); if (ret) goto unlock; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dced7e72b625..20b7743f8ec5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3270,7 +3270,7 @@ int __must_check i915_gem_init_hw(struct drm_device *dev); void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_cleanup_engines(struct drm_device *dev); int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, - bool interruptible); + unsigned int flags); int __must_check i915_gem_suspend(struct drm_device *dev); void i915_gem_resume(struct drm_device *dev); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 87a4f3543f0b..4617250c3000 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -386,7 +386,8 @@ __unsafe_wait_rendering(struct drm_i915_gem_object *obj, int ret; ret = i915_gem_active_wait_unlocked(&active[idx], - true, NULL, rps); + I915_WAIT_INTERRUPTIBLE, + NULL, rps); if (ret) return ret; } @@ -2026,7 +2027,7 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj) * to claim that space for ourselves, we need to take the big * struct_mutex to free the requests+objects and allocate our slot. */ - err = i915_gem_wait_for_idle(dev_priv, true); + err = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); if (err) return err; @@ -2779,7 +2780,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) active = __I915_BO_ACTIVE(obj); for_each_active(active, idx) { s64 *timeout = args->timeout_ns >= 0 ? &args->timeout_ns : NULL; - ret = i915_gem_active_wait_unlocked(&obj->last_read[idx], true, + ret = i915_gem_active_wait_unlocked(&obj->last_read[idx], + I915_WAIT_INTERRUPTIBLE, timeout, rps); if (ret) break; @@ -2982,7 +2984,7 @@ destroy: } int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, - bool interruptible) + unsigned int flags) { struct intel_engine_cs *engine; int ret; @@ -2991,7 +2993,7 @@ int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, if (engine->last_context == NULL) continue; - ret = intel_engine_idle(engine, interruptible); + ret = intel_engine_idle(engine, flags); if (ret) return ret; } @@ -3746,7 +3748,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (target == NULL) return 0; - ret = i915_wait_request(target, true, NULL, NULL); + ret = i915_wait_request(target, I915_WAIT_INTERRUPTIBLE, NULL, NULL); i915_gem_request_put(target); return ret; @@ -4302,7 +4304,7 @@ int i915_gem_suspend(struct drm_device *dev) if (ret) goto err; - ret = i915_gem_wait_for_idle(dev_priv, true); + ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); if (ret) goto err; diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 815d5fbe07ac..103085246975 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -170,7 +170,7 @@ search_again: if (ret) return ret; - ret = i915_gem_wait_for_idle(dev_priv, true); + ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); if (ret) return ret; @@ -275,7 +275,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) return ret; } - ret = i915_gem_wait_for_idle(dev_priv, true); + ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index e16c38086abe..9bcac52b8268 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2683,7 +2683,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) struct i915_ggtt *ggtt = &dev_priv->ggtt; if (unlikely(ggtt->do_idle_maps)) { - if (i915_gem_wait_for_idle(dev_priv, false)) { + if (i915_gem_wait_for_idle(dev_priv, 0)) { DRM_ERROR("Failed to wait for idle; VT'd may hang.\n"); /* Wait a bit, in hopes it avoids the hang */ udelay(10); diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 24eb4b1b7540..f4c15f319d08 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -260,7 +260,7 @@ static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) /* Carefully retire all requests without writing to the rings */ for_each_engine(engine, dev_priv) { - ret = intel_engine_idle(engine, true); + ret = intel_engine_idle(engine, I915_WAIT_INTERRUPTIBLE); if (ret) return ret; } @@ -598,7 +598,7 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, /** * i915_wait_request - wait until execution of request has finished * @req: duh! - * @interruptible: do an interruptible wait (normally yes) + * @flags: how to wait * @timeout: in - how long to wait (NULL forever); out - how much time remaining * @rps: client to charge for RPS boosting * @@ -613,11 +613,12 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, * errno with remaining time filled in timeout argument. */ int i915_wait_request(struct drm_i915_gem_request *req, - bool interruptible, + unsigned int flags, s64 *timeout, struct intel_rps_client *rps) { - int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; + const int state = flags & I915_WAIT_INTERRUPTIBLE ? + TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; DEFINE_WAIT(reset); struct intel_wait wait; unsigned long timeout_remain; diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index a231bd318ef0..479896ef791e 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -218,10 +218,11 @@ struct intel_rps_client; #define IS_RPS_USER(p) (!IS_ERR_OR_NULL(p)) int i915_wait_request(struct drm_i915_gem_request *req, - bool interruptible, + unsigned int flags, s64 *timeout, struct intel_rps_client *rps) __attribute__((nonnull(1))); +#define I915_WAIT_INTERRUPTIBLE BIT(0) static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine); @@ -575,13 +576,13 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) if (!request) return 0; - return i915_wait_request(request, true, NULL, NULL); + return i915_wait_request(request, I915_WAIT_INTERRUPTIBLE, NULL, NULL); } /** * i915_gem_active_wait_unlocked - waits until the request is completed * @active - the active request on which to wait - * @interruptible - whether the wait can be woken by a userspace signal + * @flags - how to wait * @timeout - how long to wait at most * @rps - userspace client to charge for a waitboost * @@ -602,7 +603,7 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) */ static inline int i915_gem_active_wait_unlocked(const struct i915_gem_active *active, - bool interruptible, + unsigned int flags, s64 *timeout, struct intel_rps_client *rps) { @@ -611,7 +612,7 @@ i915_gem_active_wait_unlocked(const struct i915_gem_active *active, request = i915_gem_active_get_unlocked(active); if (request) { - ret = i915_wait_request(request, interruptible, timeout, rps); + ret = i915_wait_request(request, flags, timeout, rps); i915_gem_request_put(request); } @@ -638,7 +639,7 @@ i915_gem_active_retire(struct i915_gem_active *active, if (!request) return 0; - ret = i915_wait_request(request, true, NULL, NULL); + ret = i915_wait_request(request, I915_WAIT_INTERRUPTIBLE, NULL, NULL); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index b80802b35353..35a05f4c51c1 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -323,7 +323,7 @@ i915_gem_shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv, unsigned long timeout = jiffies + msecs_to_jiffies_timeout(timeout_ms); do { - if (i915_gem_wait_for_idle(dev_priv, false) == 0 && + if (i915_gem_wait_for_idle(dev_priv, 0) == 0 && i915_gem_shrinker_lock(&dev_priv->drm, &slu->unlock)) break; @@ -414,7 +414,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr return NOTIFY_DONE; /* Force everything onto the inactive lists */ - ret = i915_gem_wait_for_idle(dev_priv, false); + ret = i915_gem_wait_for_idle(dev_priv, 0); if (ret) goto out; diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index be54825ef3e8..e537930c64b5 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -68,7 +68,7 @@ static void wait_rendering(struct drm_i915_gem_object *obj) for_each_active(active, idx) i915_gem_active_wait_unlocked(&obj->last_read[idx], - false, NULL, NULL); + 0, NULL, NULL); } static void cancel_userptr(struct work_struct *work) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7e725054ba58..b92042f4dc50 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12022,8 +12022,7 @@ static void intel_mmio_flip_work_func(struct work_struct *w) if (work->flip_queued_req) WARN_ON(i915_wait_request(work->flip_queued_req, - false, NULL, - NO_WAITBOOST)); + 0, NULL, NO_WAITBOOST)); /* For framebuffer backed by dmabuf, wait for fence */ resv = i915_gem_object_get_dmabuf_resv(obj); @@ -14071,7 +14070,8 @@ static int intel_atomic_prepare_commit(struct drm_device *dev, continue; ret = i915_wait_request(intel_plane_state->wait_req, - true, NULL, NULL); + I915_WAIT_INTERRUPTIBLE, + NULL, NULL); if (ret) { /* Any hang should be swallowed by the wait */ WARN_ON(ret == -EIO); @@ -14289,7 +14289,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) continue; ret = i915_wait_request(intel_plane_state->wait_req, - true, NULL, NULL); + 0, NULL, NULL); /* EIO should be eaten, and we can't get interrupted in the * worker, and blocking commits have waited already. */ WARN_ON(ret); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index fd8fcc6ec970..a5bf18877068 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2223,7 +2223,8 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes) if (WARN_ON(&target->ring_link == &ring->request_list)) return -ENOSPC; - ret = i915_wait_request(target, true, NULL, NO_WAITBOOST); + ret = i915_wait_request(target, I915_WAIT_INTERRUPTIBLE, + NULL, NO_WAITBOOST); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 2181d0a41a96..18848acf5e74 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -489,11 +489,11 @@ int intel_engine_create_scratch(struct intel_engine_cs *engine, int size); void intel_engine_cleanup_common(struct intel_engine_cs *engine); static inline int intel_engine_idle(struct intel_engine_cs *engine, - bool interruptible) + unsigned int flags) { /* Wait upon the last request to be completed */ return i915_gem_active_wait_unlocked(&engine->last_request, - interruptible, NULL, NULL); + flags, NULL, NULL); } int intel_init_render_ring_buffer(struct intel_engine_cs *engine); -- cgit v1.2.1 From 22dd3bb9190566c7c3b80edb7dea67d1e21d0f91 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:50 +0100 Subject: drm/i915: Mark up all locked waiters In the next patch we want to handle reset directly by a locked waiter in order to avoid issues with returning before the reset is handled. To handle the reset, we must first know whether we hold the struct_mutex. If we do not hold the struct_mtuex we can not perform the reset, but we do not block the reset worker either (and so we can just continue to wait for request completion) - otherwise we must relinquish the mutex. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-10-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +++- drivers/gpu/drm/i915/i915_gem.c | 7 +++++-- drivers/gpu/drm/i915/i915_gem_evict.c | 8 ++++++-- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/i915_gem_request.c | 15 ++++++++++++--- drivers/gpu/drm/i915/i915_gem_request.h | 11 ++++++++--- drivers/gpu/drm/i915/i915_gem_shrinker.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 3 ++- 8 files changed, 38 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0e4cbad7a883..6a270bc0fdb3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4794,7 +4794,9 @@ i915_drop_caches_set(void *data, u64 val) return ret; if (val & DROP_ACTIVE) { - ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); + ret = i915_gem_wait_for_idle(dev_priv, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED); if (ret) goto unlock; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4617250c3000..23069a2d2850 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2802,7 +2802,8 @@ __i915_gem_object_sync(struct drm_i915_gem_request *to, if (!i915.semaphores) { ret = i915_wait_request(from, - from->i915->mm.interruptible, + from->i915->mm.interruptible | + I915_WAIT_LOCKED, NULL, NO_WAITBOOST); if (ret) @@ -4304,7 +4305,9 @@ int i915_gem_suspend(struct drm_device *dev) if (ret) goto err; - ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); + ret = i915_gem_wait_for_idle(dev_priv, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED); if (ret) goto err; diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 103085246975..5b6f81c1dbca 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -170,7 +170,9 @@ search_again: if (ret) return ret; - ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); + ret = i915_gem_wait_for_idle(dev_priv, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED); if (ret) return ret; @@ -275,7 +277,9 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) return ret; } - ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_INTERRUPTIBLE); + ret = i915_gem_wait_for_idle(dev_priv, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9bcac52b8268..f3c6876da521 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2683,7 +2683,7 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) struct i915_ggtt *ggtt = &dev_priv->ggtt; if (unlikely(ggtt->do_idle_maps)) { - if (i915_gem_wait_for_idle(dev_priv, 0)) { + if (i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED)) { DRM_ERROR("Failed to wait for idle; VT'd may hang.\n"); /* Wait a bit, in hopes it avoids the hang */ udelay(10); diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index f4c15f319d08..5f89801e6a16 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -260,7 +260,9 @@ static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) /* Carefully retire all requests without writing to the rings */ for_each_engine(engine, dev_priv) { - ret = intel_engine_idle(engine, I915_WAIT_INTERRUPTIBLE); + ret = intel_engine_idle(engine, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED); if (ret) return ret; } @@ -625,6 +627,10 @@ int i915_wait_request(struct drm_i915_gem_request *req, int ret = 0; might_sleep(); +#if IS_ENABLED(CONFIG_LOCKDEP) + GEM_BUG_ON(!!lockdep_is_held(&req->i915->drm.struct_mutex) != + !!(flags & I915_WAIT_LOCKED)); +#endif if (i915_gem_request_completed(req)) return 0; @@ -667,7 +673,8 @@ int i915_wait_request(struct drm_i915_gem_request *req, goto complete; set_current_state(state); - add_wait_queue(&req->i915->gpu_error.wait_queue, &reset); + if (flags & I915_WAIT_LOCKED) + add_wait_queue(&req->i915->gpu_error.wait_queue, &reset); intel_wait_init(&wait, req->fence.seqno); if (intel_engine_add_wait(req->engine, &wait)) @@ -707,10 +714,12 @@ wakeup: if (i915_spin_request(req, state, 2)) break; } - remove_wait_queue(&req->i915->gpu_error.wait_queue, &reset); intel_engine_remove_wait(req->engine, &wait); + if (flags & I915_WAIT_LOCKED) + remove_wait_queue(&req->i915->gpu_error.wait_queue, &reset); __set_current_state(TASK_RUNNING); + complete: trace_i915_gem_request_wait_end(req); diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 479896ef791e..def35721e9ed 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -222,7 +222,8 @@ int i915_wait_request(struct drm_i915_gem_request *req, s64 *timeout, struct intel_rps_client *rps) __attribute__((nonnull(1))); -#define I915_WAIT_INTERRUPTIBLE BIT(0) +#define I915_WAIT_INTERRUPTIBLE BIT(0) +#define I915_WAIT_LOCKED BIT(1) /* struct_mutex held, handle GPU reset */ static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine); @@ -576,7 +577,9 @@ i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex) if (!request) return 0; - return i915_wait_request(request, I915_WAIT_INTERRUPTIBLE, NULL, NULL); + return i915_wait_request(request, + I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, + NULL, NULL); } /** @@ -639,7 +642,9 @@ i915_gem_active_retire(struct i915_gem_active *active, if (!request) return 0; - ret = i915_wait_request(request, I915_WAIT_INTERRUPTIBLE, NULL, NULL); + ret = i915_wait_request(request, + I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, + NULL, NULL); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 35a05f4c51c1..1c237d02f30b 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -414,7 +414,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr return NOTIFY_DONE; /* Force everything onto the inactive lists */ - ret = i915_gem_wait_for_idle(dev_priv, 0); + ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED); if (ret) goto out; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a5bf18877068..8687a84a7ff3 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2223,7 +2223,8 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes) if (WARN_ON(&target->ring_link == &ring->request_list)) return -ENOSPC; - ret = i915_wait_request(target, I915_WAIT_INTERRUPTIBLE, + ret = i915_wait_request(target, + I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED, NULL, NO_WAITBOOST); if (ret) return ret; -- cgit v1.2.1 From 221fe7994554cc3985fc5d761ed7e44dcae0fa52 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:51 +0100 Subject: drm/i915: Perform a direct reset of the GPU from the waiter If a waiter is holding the struct_mutex, then the reset worker cannot reset the GPU until the waiter returns. We do not want to return -EAGAIN form i915_wait_request as that breaks delicate operations like i915_vma_unbind() which often cannot be restarted easily, and returning -EIO is just as useless (and has in the past proven dangerous). The remaining WARN_ON(i915_wait_request) serve as a valuable reminder that handling errors from an indefinite wait are tricky. We can keep the current semantic that knowing after a reset is complete, so is the request, by performing the reset ourselves if we hold the mutex. uevent emission is still handled by the reset worker, so it may appear slightly out of order with respect to the actual reset (and concurrent use of the device). Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-11-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 11 ++++++----- drivers/gpu/drm/i915/i915_drv.h | 15 +++------------ drivers/gpu/drm/i915/i915_gem_request.c | 29 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_irq.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 3 --- 5 files changed, 40 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 47a676d859db..ff4173e6e298 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1729,6 +1729,8 @@ int i915_resume_switcheroo(struct drm_device *dev) * Reset the chip. Useful if a hang is detected. Returns zero on successful * reset or otherwise an error code. * + * Caller must hold the struct_mutex. + * * Procedure is fairly simple: * - reset the chip using the reset reg * - re-init context state @@ -1743,7 +1745,10 @@ int i915_reset(struct drm_i915_private *dev_priv) struct i915_gpu_error *error = &dev_priv->gpu_error; int ret; - mutex_lock(&dev->struct_mutex); + lockdep_assert_held(&dev->struct_mutex); + + if (!test_and_clear_bit(I915_RESET_IN_PROGRESS, &error->flags)) + return test_bit(I915_WEDGED, &error->flags) ? -EIO : 0; /* Clear any previous failed attempts at recovery. Time to try again. */ __clear_bit(I915_WEDGED, &error->flags); @@ -1784,9 +1789,6 @@ int i915_reset(struct drm_i915_private *dev_priv) goto error; } - clear_bit(I915_RESET_IN_PROGRESS, &error->flags); - mutex_unlock(&dev->struct_mutex); - /* * rps/rc6 re-init is necessary to restore state lost after the * reset and the re-install of gt irqs. Skip for ironlake per @@ -1800,7 +1802,6 @@ int i915_reset(struct drm_i915_private *dev_priv) error: set_bit(I915_WEDGED, &error->flags); - mutex_unlock(&dev->struct_mutex); return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 20b7743f8ec5..15f1977e356a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3863,7 +3863,9 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) schedule_timeout_uninterruptible(remaining_jiffies); } } -static inline bool __i915_request_irq_complete(struct drm_i915_gem_request *req) + +static inline bool +__i915_request_irq_complete(struct drm_i915_gem_request *req) { struct intel_engine_cs *engine = req->engine; @@ -3925,17 +3927,6 @@ static inline bool __i915_request_irq_complete(struct drm_i915_gem_request *req) return true; } - /* We need to check whether any gpu reset happened in between - * the request being submitted and now. If a reset has occurred, - * the seqno will have been advance past ours and our request - * is complete. If we are in the process of handling a reset, - * the request is effectively complete as the rendering will - * be discarded, but we need to return in order to drop the - * struct_mutex. - */ - if (i915_reset_in_progress(&req->i915->gpu_error)) - return true; - return false; } diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 5f89801e6a16..64c370681a81 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -533,6 +533,16 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) engine->submit_request(request); } +static void reset_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) +{ + unsigned long flags; + + spin_lock_irqsave(&q->lock, flags); + if (list_empty(&wait->task_list)) + __add_wait_queue(q, wait); + spin_unlock_irqrestore(&q->lock, flags); +} + static unsigned long local_clock_us(unsigned int *cpu) { unsigned long t; @@ -710,6 +720,25 @@ wakeup: if (__i915_request_irq_complete(req)) break; + /* If the GPU is hung, and we hold the lock, reset the GPU + * and then check for completion. On a full reset, the engine's + * HW seqno will be advanced passed us and we are complete. + * If we do a partial reset, we have to wait for the GPU to + * resume and update the breadcrumb. + * + * If we don't hold the mutex, we can just wait for the worker + * to come along and update the breadcrumb (either directly + * itself, or indirectly by recovering the GPU). + */ + if (flags & I915_WAIT_LOCKED && + i915_reset_in_progress(&req->i915->gpu_error)) { + __set_current_state(TASK_RUNNING); + i915_reset(req->i915); + reset_wait_queue(&req->i915->gpu_error.wait_queue, + &reset); + continue; + } + /* Only spin if we know the GPU is processing this request */ if (i915_spin_request(req, state, 2)) break; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ed172d7beecb..2c7cb5041511 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2521,7 +2521,9 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) * pending state and not properly drop locks, resulting in * deadlocks with the reset work. */ + mutex_lock(&dev_priv->drm.struct_mutex); ret = i915_reset(dev_priv); + mutex_unlock(&dev_priv->drm.struct_mutex); intel_finish_reset(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8687a84a7ff3..d2d85fc869e1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2229,9 +2229,6 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes) if (ret) return ret; - if (i915_reset_in_progress(&target->i915->gpu_error)) - return -EAGAIN; - i915_gem_request_retire_upto(target); intel_ring_update_space(ring); -- cgit v1.2.1 From 780f262a703a683bc56bbb860b25286a6f501d61 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:52 +0100 Subject: drm/i915: Replace wait-on-mutex with wait-on-bit in reset worker Since we have a cooperative mode now with a direct reset, we can avoid the contention on struct_mutex and instead try then sleep on the I915_RESET_IN_PROGRESS bit. If the mutex is held and that bit is cleared, all is fine. Otherwise, we sleep for a bit and try again. In the worst case we sleep for an extra second waiting for the mutex to be released (no one touching the GPU is allowed the struct_mutex whilst the I915_RESET_IN_PROGRESS bit is set). But when we have a direct reset, this allows us to clean up the reset worker faster. v2: Remember to call wake_up_bit() after changing (for the faster wakeup as promised) Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-12-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 14 ++++++++------ drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_irq.c | 31 ++++++++++++++++++------------- 3 files changed, 27 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ff4173e6e298..f2614b2f59f7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1726,8 +1726,8 @@ int i915_resume_switcheroo(struct drm_device *dev) * i915_reset - reset chip after a hang * @dev: drm device to reset * - * Reset the chip. Useful if a hang is detected. Returns zero on successful - * reset or otherwise an error code. + * Reset the chip. Useful if a hang is detected. Marks the device as wedged + * on failure. * * Caller must hold the struct_mutex. * @@ -1739,7 +1739,7 @@ int i915_resume_switcheroo(struct drm_device *dev) * - re-init interrupt state * - re-init display */ -int i915_reset(struct drm_i915_private *dev_priv) +void i915_reset(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; struct i915_gpu_error *error = &dev_priv->gpu_error; @@ -1748,7 +1748,7 @@ int i915_reset(struct drm_i915_private *dev_priv) lockdep_assert_held(&dev->struct_mutex); if (!test_and_clear_bit(I915_RESET_IN_PROGRESS, &error->flags)) - return test_bit(I915_WEDGED, &error->flags) ? -EIO : 0; + return; /* Clear any previous failed attempts at recovery. Time to try again. */ __clear_bit(I915_WEDGED, &error->flags); @@ -1798,11 +1798,13 @@ int i915_reset(struct drm_i915_private *dev_priv) intel_sanitize_gt_powersave(dev_priv); intel_autoenable_gt_powersave(dev_priv); - return 0; +wakeup: + wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS); + return; error: set_bit(I915_WEDGED, &error->flags); - return ret; + goto wakeup; } static int i915_pm_suspend(struct device *kdev) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 15f1977e356a..9a9f07f3574c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2884,7 +2884,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, #endif extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); -extern int i915_reset(struct drm_i915_private *dev_priv); +extern void i915_reset(struct drm_i915_private *dev_priv); extern int intel_guc_reset(struct drm_i915_private *dev_priv); extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine); extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2c7cb5041511..ef2d40278191 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2497,7 +2497,6 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; char *reset_event[] = { I915_RESET_UEVENT "=1", NULL }; char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL }; - int ret; kobject_uevent_env(kobj, KOBJ_CHANGE, error_event); @@ -2512,24 +2511,30 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) * simulated reset via debugs, so get an RPM reference. */ intel_runtime_pm_get(dev_priv); - intel_prepare_reset(dev_priv); - /* - * All state reset _must_ be completed before we update the - * reset counter, for otherwise waiters might miss the reset - * pending state and not properly drop locks, resulting in - * deadlocks with the reset work. - */ - mutex_lock(&dev_priv->drm.struct_mutex); - ret = i915_reset(dev_priv); - mutex_unlock(&dev_priv->drm.struct_mutex); + do { + /* + * All state reset _must_ be completed before we update the + * reset counter, for otherwise waiters might miss the reset + * pending state and not properly drop locks, resulting in + * deadlocks with the reset work. + */ + if (mutex_trylock(&dev_priv->drm.struct_mutex)) { + i915_reset(dev_priv); + mutex_unlock(&dev_priv->drm.struct_mutex); + } - intel_finish_reset(dev_priv); + /* We need to wait for anyone holding the lock to wakeup */ + } while (wait_on_bit_timeout(&dev_priv->gpu_error.flags, + I915_RESET_IN_PROGRESS, + TASK_UNINTERRUPTIBLE, + HZ)); + intel_finish_reset(dev_priv); intel_runtime_pm_put(dev_priv); - if (ret == 0) + if (!test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event); -- cgit v1.2.1 From 821ed7df6e2a1dbae243caebcfe21a0a4329fca0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:53 +0100 Subject: drm/i915: Update reset path to fix incomplete requests Update reset path in preparation for engine reset which requires identification of incomplete requests and associated context and fixing their state so that engine can resume correctly after reset. The request that caused the hang will be skipped and head is reset to the start of breadcrumb. This allows us to resume from where we left-off. Since this request didn't complete normally we also need to cleanup elsp queue manually. This is vital if we employ nonblocking request submission where we may have a web of dependencies upon the hung request and so advancing the seqno manually is no longer trivial. ABI: gem_reset_stats / DRM_IOCTL_I915_GET_RESET_STATS We change the way we count pending batches. Only the active context involved in the reset is marked as either innocent or guilty, and not mark the entire world as pending. By inspection this only affects igt/gem_reset_stats (which assumes implementation details) and not piglit. ARB_robustness gives this guide on how we expect the user of this interface to behave: * Provide a mechanism for an OpenGL application to learn about graphics resets that affect the context. When a graphics reset occurs, the OpenGL context becomes unusable and the application must create a new context to continue operation. Detecting a graphics reset happens through an inexpensive query. And with regards to the actual meaning of the reset values: Certain events can result in a reset of the GL context. Such a reset causes all context state to be lost. Recovery from such events requires recreation of all objects in the affected context. The current status of the graphics reset state is returned by enum GetGraphicsResetStatusARB(); The symbolic constant returned indicates if the GL context has been in a reset state at any point since the last call to GetGraphicsResetStatusARB. NO_ERROR indicates that the GL context has not been in a reset state since the last call. GUILTY_CONTEXT_RESET_ARB indicates that a reset has been detected that is attributable to the current GL context. INNOCENT_CONTEXT_RESET_ARB indicates a reset has been detected that is not attributable to the current GL context. UNKNOWN_CONTEXT_RESET_ARB indicates a detected graphics reset whose cause is unknown. The language here is explicit in that we must mark up the guilty batch, but is loose enough for us to relax the innocent (i.e. pending) accounting as only the active batches are involved with the reset. In the future, we are looking towards single engine resetting (with minimal locking), where it seems inappropriate to mark the entire world as innocent since the reset occurred on a different engine. Reducing the information available means we only have to encounter the pain once, and also reduces the information leaking from one context to another. v2: Legacy ringbuffer submission required a reset following hibernation, or else we restore stale values to the RING_HEAD and walked over stolen garbage. v3: GuC requires replaying the requests after a reset. v4: Restore engine IRQ after reset (so waiters will be woken!) Rearm hangcheck if resetting with a waiter. Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Arun Siluvery Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-13-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 9 +-- drivers/gpu/drm/i915/i915_drv.h | 5 +- drivers/gpu/drm/i915/i915_gem.c | 125 +++++++++++++++++------------ drivers/gpu/drm/i915/i915_gem_context.c | 16 ---- drivers/gpu/drm/i915/i915_guc_submission.c | 8 +- drivers/gpu/drm/i915/intel_engine_cs.c | 15 +++- drivers/gpu/drm/i915/intel_lrc.c | 49 +++++++++-- drivers/gpu/drm/i915/intel_lrc.h | 3 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 47 +++++++---- drivers/gpu/drm/i915/intel_ringbuffer.h | 7 +- 10 files changed, 185 insertions(+), 99 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f2614b2f59f7..7f4e8adec8a8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -559,7 +559,6 @@ static void i915_gem_fini(struct drm_device *dev) } mutex_lock(&dev->struct_mutex); - i915_gem_reset(dev); i915_gem_cleanup_engines(dev); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); @@ -1579,7 +1578,7 @@ static int i915_drm_resume(struct drm_device *dev) mutex_lock(&dev->struct_mutex); if (i915_gem_init_hw(dev)) { DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); - set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); + i915_gem_set_wedged(dev_priv); } mutex_unlock(&dev->struct_mutex); @@ -1755,9 +1754,6 @@ void i915_reset(struct drm_i915_private *dev_priv) error->reset_count++; pr_notice("drm/i915: Resetting chip after gpu hang\n"); - - i915_gem_reset(dev); - ret = intel_gpu_reset(dev_priv, ALL_ENGINES); if (ret) { if (ret != -ENODEV) @@ -1767,6 +1763,7 @@ void i915_reset(struct drm_i915_private *dev_priv) goto error; } + i915_gem_reset(dev_priv); intel_overlay_reset(dev_priv); /* Ok, now get things going again... */ @@ -1803,7 +1800,7 @@ wakeup: return; error: - set_bit(I915_WEDGED, &error->flags); + i915_gem_set_wedged(dev_priv); goto wakeup; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9a9f07f3574c..37978d3f62ce 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2042,6 +2042,7 @@ struct drm_i915_private { /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ struct { + void (*resume)(struct drm_i915_private *); void (*cleanup_engine)(struct intel_engine_cs *engine); /** @@ -3263,7 +3264,8 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error) return READ_ONCE(error->reset_count); } -void i915_gem_reset(struct drm_device *dev); +void i915_gem_reset(struct drm_i915_private *dev_priv); +void i915_gem_set_wedged(struct drm_i915_private *dev_priv); bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force); int __must_check i915_gem_init(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); @@ -3392,7 +3394,6 @@ void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj); int __must_check i915_gem_context_init(struct drm_device *dev); void i915_gem_context_lost(struct drm_i915_private *dev_priv); void i915_gem_context_fini(struct drm_device *dev); -void i915_gem_context_reset(struct drm_device *dev); int i915_gem_context_open(struct drm_device *dev, struct drm_file *file); void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); int i915_switch_context(struct drm_i915_gem_request *req); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 23069a2d2850..674e0eaf39ea 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2555,29 +2555,85 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) return NULL; } -static void i915_gem_reset_engine_status(struct intel_engine_cs *engine) +static void reset_request(struct drm_i915_gem_request *request) +{ + void *vaddr = request->ring->vaddr; + u32 head; + + /* As this request likely depends on state from the lost + * context, clear out all the user operations leaving the + * breadcrumb at the end (so we get the fence notifications). + */ + head = request->head; + if (request->postfix < head) { + memset(vaddr + head, 0, request->ring->size - head); + head = 0; + } + memset(vaddr + head, 0, request->postfix - head); +} + +static void i915_gem_reset_engine(struct intel_engine_cs *engine) { struct drm_i915_gem_request *request; + struct i915_gem_context *incomplete_ctx; bool ring_hung; + /* Ensure irq handler finishes, and not run again. */ + tasklet_kill(&engine->irq_tasklet); + if (engine->irq_seqno_barrier) + engine->irq_seqno_barrier(engine); + request = i915_gem_find_active_request(engine); - if (request == NULL) + if (!request) return; ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG; - i915_set_reset_status(request->ctx, ring_hung); + if (!ring_hung) + return; + + DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n", + engine->name, request->fence.seqno); + + /* Setup the CS to resume from the breadcrumb of the hung request */ + engine->reset_hw(engine, request); + + /* Users of the default context do not rely on logical state + * preserved between batches. They have to emit full state on + * every batch and so it is safe to execute queued requests following + * the hang. + * + * Other contexts preserve state, now corrupt. We want to skip all + * queued requests that reference the corrupt context. + */ + incomplete_ctx = request->ctx; + if (i915_gem_context_is_default(incomplete_ctx)) + return; + list_for_each_entry_continue(request, &engine->request_list, link) - i915_set_reset_status(request->ctx, false); + if (request->ctx == incomplete_ctx) + reset_request(request); } -static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine) +void i915_gem_reset(struct drm_i915_private *dev_priv) { - struct drm_i915_gem_request *request; - struct intel_ring *ring; + struct intel_engine_cs *engine; - /* Ensure irq handler finishes, and not run again. */ - tasklet_kill(&engine->irq_tasklet); + i915_gem_retire_requests(dev_priv); + + for_each_engine(engine, dev_priv) + i915_gem_reset_engine(engine); + + i915_gem_restore_fences(&dev_priv->drm); +} + +static void nop_submit_request(struct drm_i915_gem_request *request) +{ +} + +static void i915_gem_cleanup_engine(struct intel_engine_cs *engine) +{ + engine->submit_request = nop_submit_request; /* Mark all pending requests as complete so that any concurrent * (lockless) lookup doesn't try and wait upon the request as we @@ -2600,54 +2656,22 @@ static void i915_gem_reset_engine_cleanup(struct intel_engine_cs *engine) spin_unlock(&engine->execlist_lock); } - /* - * We must free the requests after all the corresponding objects have - * been moved off active lists. Which is the same order as the normal - * retire_requests function does. This is important if object hold - * implicit references on things like e.g. ppgtt address spaces through - * the request. - */ - request = i915_gem_active_raw(&engine->last_request, - &engine->i915->drm.struct_mutex); - if (request) - i915_gem_request_retire_upto(request); - GEM_BUG_ON(intel_engine_is_active(engine)); - - /* Having flushed all requests from all queues, we know that all - * ringbuffers must now be empty. However, since we do not reclaim - * all space when retiring the request (to prevent HEADs colliding - * with rapid ringbuffer wraparound) the amount of available space - * upon reset is less than when we start. Do one more pass over - * all the ringbuffers to reset last_retired_head. - */ - list_for_each_entry(ring, &engine->buffers, link) { - ring->last_retired_head = ring->tail; - intel_ring_update_space(ring); - } - engine->i915->gt.active_engines &= ~intel_engine_flag(engine); } -void i915_gem_reset(struct drm_device *dev) +void i915_gem_set_wedged(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); struct intel_engine_cs *engine; - /* - * Before we free the objects from the requests, we need to inspect - * them for finding the guilty party. As the requests only borrow - * their reference to the objects, the inspection must be done first. - */ - for_each_engine(engine, dev_priv) - i915_gem_reset_engine_status(engine); + lockdep_assert_held(&dev_priv->drm.struct_mutex); + set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); + i915_gem_context_lost(dev_priv); for_each_engine(engine, dev_priv) - i915_gem_reset_engine_cleanup(engine); + i915_gem_cleanup_engine(engine); mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); - i915_gem_context_reset(dev); - - i915_gem_restore_fences(dev); + i915_gem_retire_requests(dev_priv); } static void @@ -4343,8 +4367,7 @@ void i915_gem_resume(struct drm_device *dev) * guarantee that the context image is complete. So let's just reset * it and start again. */ - if (i915.enable_execlists) - intel_lr_context_reset(dev_priv, dev_priv->kernel_context); + dev_priv->gt.resume(dev_priv); mutex_unlock(&dev->struct_mutex); } @@ -4496,8 +4519,10 @@ int i915_gem_init(struct drm_device *dev) mutex_lock(&dev->struct_mutex); if (!i915.enable_execlists) { + dev_priv->gt.resume = intel_legacy_submission_resume; dev_priv->gt.cleanup_engine = intel_engine_cleanup; } else { + dev_priv->gt.resume = intel_lr_context_resume; dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup; } @@ -4530,7 +4555,7 @@ int i915_gem_init(struct drm_device *dev) * for all other failure, such as an allocation failure, bail. */ DRM_ERROR("Failed to initialize GPU, declaring it wedged\n"); - set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); + i915_gem_set_wedged(dev_priv); ret = 0; } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 35950ee46a1d..df10f4e95736 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -420,22 +420,6 @@ static void i915_gem_context_unpin(struct i915_gem_context *ctx, } } -void i915_gem_context_reset(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - lockdep_assert_held(&dev->struct_mutex); - - if (i915.enable_execlists) { - struct i915_gem_context *ctx; - - list_for_each_entry(ctx, &dev_priv->context_list, link) - intel_lr_context_reset(dev_priv, ctx); - } - - i915_gem_context_lost(dev_priv); -} - int i915_gem_context_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 77526d7f41f8..d5a4e9edccc5 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -994,6 +994,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) struct intel_guc *guc = &dev_priv->guc; struct i915_guc_client *client; struct intel_engine_cs *engine; + struct drm_i915_gem_request *request; /* client for execbuf submission */ client = guc_client_alloc(dev_priv, @@ -1010,9 +1011,14 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) guc_init_doorbell_hw(guc); /* Take over from manual control of ELSP (execlists) */ - for_each_engine(engine, dev_priv) + for_each_engine(engine, dev_priv) { engine->submit_request = i915_guc_submit; + /* Replay the current set of previously submitted requests */ + list_for_each_entry(request, &engine->request_list, link) + i915_guc_submit(request); + } + return 0; } diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 2e96a86105c2..e405f1080296 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -211,6 +211,8 @@ void intel_engine_init_hangcheck(struct intel_engine_cs *engine) { memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); + if (intel_engine_has_waiter(engine)) + i915_queue_hangcheck(engine->i915); } static void intel_engine_init_requests(struct intel_engine_cs *engine) @@ -230,7 +232,6 @@ static void intel_engine_init_requests(struct intel_engine_cs *engine) */ void intel_engine_setup_common(struct intel_engine_cs *engine) { - INIT_LIST_HEAD(&engine->buffers); INIT_LIST_HEAD(&engine->execlist_queue); spin_lock_init(&engine->execlist_lock); @@ -306,6 +307,18 @@ int intel_engine_init_common(struct intel_engine_cs *engine) return 0; } +void intel_engine_reset_irq(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + + spin_lock_irq(&dev_priv->irq_lock); + if (intel_engine_has_waiter(engine)) + engine->irq_enable(engine); + else + engine->irq_disable(engine); + spin_unlock_irq(&dev_priv->irq_lock); +} + /** * intel_engines_cleanup_common - cleans up the engine state created by * the common initiailizers. diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index a33687d294b5..61549a623e2c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1222,11 +1222,16 @@ static void lrc_init_hws(struct intel_engine_cs *engine) static int gen8_init_common_ring(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; + int ret; + + ret = intel_mocs_init_engine(engine); + if (ret) + return ret; lrc_init_hws(engine); - I915_WRITE_IMR(engine, - ~(engine->irq_enable_mask | engine->irq_keep_mask)); + intel_engine_reset_irq(engine); + I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff); I915_WRITE(RING_MODE_GEN7(engine), @@ -1237,7 +1242,10 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) intel_engine_init_hangcheck(engine); - return intel_mocs_init_engine(engine); + if (!execlists_elsp_idle(engine)) + execlists_submit_ports(engine); + + return 0; } static int gen8_init_render_ring(struct intel_engine_cs *engine) @@ -1273,6 +1281,36 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine) return init_workarounds_ring(engine); } +static void reset_common_ring(struct intel_engine_cs *engine, + struct drm_i915_gem_request *request) +{ + struct drm_i915_private *dev_priv = engine->i915; + struct execlist_port *port = engine->execlist_port; + struct intel_context *ce = &request->ctx->engine[engine->id]; + + /* Move the RING_HEAD onto the breadcrumb, past the hanging batch */ + ce->lrc_reg_state[CTX_RING_HEAD+1] = request->postfix; + request->ring->head = request->postfix; + request->ring->last_retired_head = -1; + intel_ring_update_space(request->ring); + + if (i915.enable_guc_submission) + return; + + /* Catch up with any missed context-switch interrupts */ + I915_WRITE(RING_CONTEXT_STATUS_PTR(engine), _MASKED_FIELD(0xffff, 0)); + if (request->ctx != port[0].request->ctx) { + i915_gem_request_put(port[0].request); + port[0] = port[1]; + memset(&port[1], 0, sizeof(port[1])); + } + + /* CS is stopped, and we will resubmit both ports on resume */ + GEM_BUG_ON(request->ctx != port[0].request->ctx); + port[0].count = 0; + port[1].count = 0; +} + static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) { struct i915_hw_ppgtt *ppgtt = req->ctx->ppgtt; @@ -1635,6 +1673,7 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) { /* Default vfuncs which can be overriden by each engine. */ engine->init_hw = gen8_init_common_ring; + engine->reset_hw = reset_common_ring; engine->emit_flush = gen8_emit_flush; engine->emit_request = gen8_emit_request; engine->submit_request = execlists_submit_request; @@ -2087,9 +2126,9 @@ error_deref_obj: return ret; } -void intel_lr_context_reset(struct drm_i915_private *dev_priv, - struct i915_gem_context *ctx) +void intel_lr_context_resume(struct drm_i915_private *dev_priv) { + struct i915_gem_context *ctx = dev_priv->kernel_context; struct intel_engine_cs *engine; for_each_engine(engine, dev_priv) { diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 4d70346500c2..4fed8165f98a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -87,8 +87,7 @@ void intel_lr_context_unpin(struct i915_gem_context *ctx, struct drm_i915_private; -void intel_lr_context_reset(struct drm_i915_private *dev_priv, - struct i915_gem_context *ctx); +void intel_lr_context_resume(struct drm_i915_private *dev_priv); uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx, struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index d2d85fc869e1..7a74750076c5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -564,6 +564,8 @@ static int init_ring_common(struct intel_engine_cs *engine) else intel_ring_setup_status_page(engine); + intel_engine_reset_irq(engine); + /* Enforce ordering by reading HEAD register back */ I915_READ_HEAD(engine); @@ -577,34 +579,33 @@ static int init_ring_common(struct intel_engine_cs *engine) if (I915_READ_HEAD(engine)) DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", engine->name, I915_READ_HEAD(engine)); - I915_WRITE_HEAD(engine, 0); - (void)I915_READ_HEAD(engine); + + intel_ring_update_space(ring); + I915_WRITE_HEAD(engine, ring->head); + I915_WRITE_TAIL(engine, ring->tail); + (void)I915_READ_TAIL(engine); I915_WRITE_CTL(engine, ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); /* If the head is still not zero, the ring is dead */ - if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 && - I915_READ_START(engine) == i915_ggtt_offset(ring->vma) && - (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) { + if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base), + RING_VALID, RING_VALID, + 50)) { DRM_ERROR("%s initialization failed " - "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08x]\n", + "ctl %08x (valid? %d) head %08x [%08x] tail %08x [%08x] start %08x [expected %08x]\n", engine->name, I915_READ_CTL(engine), I915_READ_CTL(engine) & RING_VALID, - I915_READ_HEAD(engine), I915_READ_TAIL(engine), + I915_READ_HEAD(engine), ring->head, + I915_READ_TAIL(engine), ring->tail, I915_READ_START(engine), i915_ggtt_offset(ring->vma)); ret = -EIO; goto out; } - ring->last_retired_head = -1; - ring->head = I915_READ_HEAD(engine); - ring->tail = I915_READ_TAIL(engine) & TAIL_ADDR; - intel_ring_update_space(ring); - intel_engine_init_hangcheck(engine); out: @@ -613,6 +614,15 @@ out: return ret; } +static void reset_ring_common(struct intel_engine_cs *engine, + struct drm_i915_gem_request *request) +{ + struct intel_ring *ring = request->ring; + + ring->head = request->postfix; + ring->last_retired_head = -1; +} + static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) { struct intel_ring *ring = req->ring; @@ -2007,7 +2017,6 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size) } ring->vma = vma; - list_add(&ring->link, &engine->buffers); return ring; } @@ -2015,7 +2024,6 @@ void intel_ring_free(struct intel_ring *ring) { i915_vma_put(ring->vma); - list_del(&ring->link); kfree(ring); } @@ -2169,6 +2177,16 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) engine->i915 = NULL; } +void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *engine; + + for_each_engine(engine, dev_priv) { + engine->buffer->head = engine->buffer->tail; + engine->buffer->last_retired_head = -1; + } +} + int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) { int ret; @@ -2654,6 +2672,7 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, intel_ring_init_semaphores(dev_priv, engine); engine->init_hw = init_ring_common; + engine->reset_hw = reset_ring_common; engine->emit_request = i9xx_emit_request; if (i915.semaphores) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 18848acf5e74..32f527447310 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -87,7 +87,6 @@ struct intel_ring { void *vaddr; struct intel_engine_cs *engine; - struct list_head link; struct list_head request_list; @@ -157,7 +156,6 @@ struct intel_engine_cs { u32 mmio_base; unsigned int irq_shift; struct intel_ring *buffer; - struct list_head buffers; /* Rather than have every client wait upon all user interrupts, * with the herd waking after every interrupt and each doing the @@ -211,6 +209,8 @@ struct intel_engine_cs { void (*irq_disable)(struct intel_engine_cs *engine); int (*init_hw)(struct intel_engine_cs *engine); + void (*reset_hw)(struct intel_engine_cs *engine, + struct drm_i915_gem_request *req); int (*init_context)(struct drm_i915_gem_request *req); @@ -444,6 +444,8 @@ void intel_ring_free(struct intel_ring *ring); void intel_engine_stop(struct intel_engine_cs *engine); void intel_engine_cleanup(struct intel_engine_cs *engine); +void intel_legacy_submission_resume(struct drm_i915_private *dev_priv); + int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request); int __must_check intel_ring_begin(struct drm_i915_gem_request *req, int n); @@ -482,6 +484,7 @@ int __intel_ring_space(int head, int tail, int size); void intel_ring_update_space(struct intel_ring *ring); void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno); +void intel_engine_reset_irq(struct intel_engine_cs *engine); void intel_engine_setup_common(struct intel_engine_cs *engine); int intel_engine_init_common(struct intel_engine_cs *engine); -- cgit v1.2.1 From 5590af3e115a9db11c5d6689ddd0d0053be4f4e0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:54 +0100 Subject: drm/i915: Drive request submission through fence callbacks Drive final request submission from a callback from the fence. This way the request is queued until all dependencies are resolved, at which point it is handed to the backend for queueing to hardware. At this point, no dependencies are set on the request, so the callback is immediate. A side-effect of imposing a heavier-irqsafe spinlock for execlist submission is that we lose the softirq enabling after scheduling the execlists tasklet. To compensate, we manually kickstart the softirq by disabling and enabling the bh around the fence signaling. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Reviewed-by: John Harrison Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-14-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 3 +++ drivers/gpu/drm/i915/i915_gem_request.c | 27 ++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_gem_request.h | 3 +++ drivers/gpu/drm/i915/i915_guc_submission.c | 3 ++- drivers/gpu/drm/i915/intel_breadcrumbs.c | 3 +++ drivers/gpu/drm/i915/intel_lrc.c | 5 +++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 8 ++++++++ 7 files changed, 48 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 674e0eaf39ea..89a5f8d948e7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2549,6 +2549,9 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) if (i915_gem_request_completed(request)) continue; + if (!i915_sw_fence_done(&request->submit)) + break; + return request; } diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 64c370681a81..074fc06ff488 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -318,6 +318,26 @@ static int i915_gem_get_seqno(struct drm_i915_private *dev_priv, u32 *seqno) return 0; } +static int __i915_sw_fence_call +submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) +{ + struct drm_i915_gem_request *request = + container_of(fence, typeof(*request), submit); + + /* Will be called from irq-context when using foreign DMA fences */ + + switch (state) { + case FENCE_COMPLETE: + request->engine->submit_request(request); + break; + + case FENCE_FREE: + break; + } + + return NOTIFY_DONE; +} + /** * i915_gem_request_alloc - allocate a request structure * @@ -396,6 +416,8 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, engine->fence_context, seqno); + i915_sw_fence_init(&req->submit, submit_notify); + INIT_LIST_HEAD(&req->active_list); req->i915 = dev_priv; req->engine = engine; @@ -530,7 +552,10 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) reserved_tail, ret); i915_gem_mark_busy(engine); - engine->submit_request(request); + + local_bh_disable(); + i915_sw_fence_commit(&request->submit); + local_bh_enable(); /* Kick the execlists tasklet if just scheduled */ } static void reset_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index def35721e9ed..e141b1cca16a 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -28,6 +28,7 @@ #include #include "i915_gem.h" +#include "i915_sw_fence.h" struct intel_wait { struct rb_node node; @@ -82,6 +83,8 @@ struct drm_i915_gem_request { struct intel_ring *ring; struct intel_signal_node signaling; + struct i915_sw_fence submit; + /** GEM sequence number associated with the previous request, * when the HWS breadcrumb is equal to this the GPU is processing * this request. diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index d5a4e9edccc5..0eb6b71935cf 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -1016,7 +1016,8 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) /* Replay the current set of previously submitted requests */ list_for_each_entry(request, &engine->request_list, link) - i915_guc_submit(request); + if (i915_sw_fence_done(&request->submit)) + i915_guc_submit(request); } return 0; diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 2491e4c1eaf0..9bad14d22c95 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -462,7 +462,10 @@ static int intel_breadcrumbs_signaler(void *arg) */ intel_engine_remove_wait(engine, &request->signaling.wait); + + local_bh_disable(); fence_signal(&request->fence); + local_bh_enable(); /* kick start the tasklets */ /* Find the next oldest signal. Note that as we have * not been holding the lock, another client may diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 61549a623e2c..16d7cdd11082 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -590,14 +590,15 @@ static void intel_lrc_irq_handler(unsigned long data) static void execlists_submit_request(struct drm_i915_gem_request *request) { struct intel_engine_cs *engine = request->engine; + unsigned long flags; - spin_lock_bh(&engine->execlist_lock); + spin_lock_irqsave(&engine->execlist_lock, flags); list_add_tail(&request->execlist_link, &engine->execlist_queue); if (execlists_elsp_idle(engine)) tasklet_hi_schedule(&engine->irq_tasklet); - spin_unlock_bh(&engine->execlist_lock); + spin_unlock_irqrestore(&engine->execlist_lock, flags); } int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 32f527447310..7f64d611159b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -226,7 +226,15 @@ struct intel_engine_cs { #define I915_DISPATCH_PINNED BIT(1) #define I915_DISPATCH_RS BIT(2) int (*emit_request)(struct drm_i915_gem_request *req); + + /* Pass the request to the hardware queue (e.g. directly into + * the legacy ringbuffer or to the end of an execlist). + * + * This is called from an atomic context with irqs disabled; must + * be irq safe. + */ void (*submit_request)(struct drm_i915_gem_request *req); + /* Some chipsets are not quite as coherent as advertised and need * an expensive kick to force a true read of the up-to-date seqno. * However, the up-to-date seqno is not always required and the last -- cgit v1.2.1 From 0f25dff6e960c44c5e7d306ff3a3fdad5367a90e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:55 +0100 Subject: drm/i915: Reorder i915_add_request to separate the phases better Let's avoid mixing sealing the hardware commands for the request and adding the request to the software tracking. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-15-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 074fc06ff488..a149310c82ce 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -494,6 +494,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) u32 reserved_tail; int ret; + trace_i915_gem_request_add(request); + /* * To ensure that this call will not fail, space for its emissions * should already have been reserved in the ring buffer. Let the ring @@ -517,20 +519,6 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) WARN(ret, "engine->emit_flush() failed: %d!\n", ret); } - trace_i915_gem_request_add(request); - - /* Seal the request and mark it as pending execution. Note that - * we may inspect this state, without holding any locks, during - * hangcheck. Hence we apply the barrier to ensure that we do not - * see a more recent value in the hws than we are tracking. - */ - request->emitted_jiffies = jiffies; - request->previous_seqno = engine->last_submitted_seqno; - engine->last_submitted_seqno = request->fence.seqno; - i915_gem_active_set(&engine->last_request, request); - list_add_tail(&request->link, &engine->request_list); - list_add_tail(&request->ring_link, &ring->request_list); - /* Record the position of the start of the breadcrumb so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the @@ -551,6 +539,18 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) "for adding the request (%d bytes)\n", reserved_tail, ret); + /* Seal the request and mark it as pending execution. Note that + * we may inspect this state, without holding any locks, during + * hangcheck. Hence we apply the barrier to ensure that we do not + * see a more recent value in the hws than we are tracking. + */ + request->emitted_jiffies = jiffies; + request->previous_seqno = engine->last_submitted_seqno; + engine->last_submitted_seqno = request->fence.seqno; + i915_gem_active_set(&engine->last_request, request); + list_add_tail(&request->link, &engine->request_list); + list_add_tail(&request->ring_link, &ring->request_list); + i915_gem_mark_busy(engine); local_bh_disable(); -- cgit v1.2.1 From a2bc4695bbf24877d75b34da5d11fcb38393eee9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:56 +0100 Subject: drm/i915: Prepare object synchronisation for asynchronicity We are about to specialize object synchronisation to enable nonblocking execbuf submission. First we make a copy of the current object synchronisation for execbuffer. The general i915_gem_object_sync() will be removed following the removal of CS flips in the near future. Signed-off-by: Chris Wilson Reviewed-by: John Harrison Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-16-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 2 - drivers/gpu/drm/i915/i915_gem.c | 91 ------------------------------ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +- drivers/gpu/drm/i915/i915_gem_request.c | 87 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem_request.h | 5 ++ drivers/gpu/drm/i915/intel_display.c | 2 +- 6 files changed, 95 insertions(+), 95 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 37978d3f62ce..1e2dda88a483 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3221,8 +3221,6 @@ i915_gem_obj_finish_shmem_access(struct drm_i915_gem_object *obj) } int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); -int i915_gem_object_sync(struct drm_i915_gem_object *obj, - struct drm_i915_gem_request *to); void i915_vma_move_to_active(struct i915_vma *vma, struct drm_i915_gem_request *req, unsigned int flags); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 89a5f8d948e7..4b5364d477f1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2818,97 +2818,6 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) return ret; } -static int -__i915_gem_object_sync(struct drm_i915_gem_request *to, - struct drm_i915_gem_request *from) -{ - int ret; - - if (to->engine == from->engine) - return 0; - - if (!i915.semaphores) { - ret = i915_wait_request(from, - from->i915->mm.interruptible | - I915_WAIT_LOCKED, - NULL, - NO_WAITBOOST); - if (ret) - return ret; - } else { - int idx = intel_engine_sync_index(from->engine, to->engine); - if (from->fence.seqno <= from->engine->semaphore.sync_seqno[idx]) - return 0; - - trace_i915_gem_ring_sync_to(to, from); - ret = to->engine->semaphore.sync_to(to, from); - if (ret) - return ret; - - from->engine->semaphore.sync_seqno[idx] = from->fence.seqno; - } - - return 0; -} - -/** - * i915_gem_object_sync - sync an object to a ring. - * - * @obj: object which may be in use on another ring. - * @to: request we are wishing to use - * - * This code is meant to abstract object synchronization with the GPU. - * Conceptually we serialise writes between engines inside the GPU. - * We only allow one engine to write into a buffer at any time, but - * multiple readers. To ensure each has a coherent view of memory, we must: - * - * - If there is an outstanding write request to the object, the new - * request must wait for it to complete (either CPU or in hw, requests - * on the same ring will be naturally ordered). - * - * - If we are a write request (pending_write_domain is set), the new - * request must wait for outstanding read requests to complete. - * - * Returns 0 if successful, else propagates up the lower layer error. - */ -int -i915_gem_object_sync(struct drm_i915_gem_object *obj, - struct drm_i915_gem_request *to) -{ - struct i915_gem_active *active; - unsigned long active_mask; - int idx; - - lockdep_assert_held(&obj->base.dev->struct_mutex); - - active_mask = i915_gem_object_get_active(obj); - if (!active_mask) - return 0; - - if (obj->base.pending_write_domain) { - active = obj->last_read; - } else { - active_mask = 1; - active = &obj->last_write; - } - - for_each_active(active_mask, idx) { - struct drm_i915_gem_request *request; - int ret; - - request = i915_gem_active_peek(&active[idx], - &obj->base.dev->struct_mutex); - if (!request) - continue; - - ret = __i915_gem_object_sync(to, request); - if (ret) - return ret; - } - - return 0; -} - static void __i915_vma_iounmap(struct i915_vma *vma) { GEM_BUG_ON(i915_vma_is_pinned(vma)); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 9432d4ce9ffb..ccaf15ba4e32 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1133,7 +1133,8 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, struct drm_i915_gem_object *obj = vma->obj; if (obj->flags & other_rings) { - ret = i915_gem_object_sync(obj, req); + ret = i915_gem_request_await_object + (req, obj, obj->base.pending_write_domain); if (ret) return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index a149310c82ce..017cadf54d80 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -460,6 +460,93 @@ err: return ERR_PTR(ret); } +static int +i915_gem_request_await_request(struct drm_i915_gem_request *to, + struct drm_i915_gem_request *from) +{ + int idx, ret; + + GEM_BUG_ON(to == from); + + if (to->engine == from->engine) + return 0; + + idx = intel_engine_sync_index(from->engine, to->engine); + if (from->fence.seqno <= from->engine->semaphore.sync_seqno[idx]) + return 0; + + trace_i915_gem_ring_sync_to(to, from); + if (!i915.semaphores) { + ret = i915_wait_request(from, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED, + NULL, NO_WAITBOOST); + if (ret) + return ret; + } else { + ret = to->engine->semaphore.sync_to(to, from); + if (ret) + return ret; + } + + from->engine->semaphore.sync_seqno[idx] = from->fence.seqno; + return 0; +} + +/** + * i915_gem_request_await_object - set this request to (async) wait upon a bo + * + * @to: request we are wishing to use + * @obj: object which may be in use on another ring. + * + * This code is meant to abstract object synchronization with the GPU. + * Conceptually we serialise writes between engines inside the GPU. + * We only allow one engine to write into a buffer at any time, but + * multiple readers. To ensure each has a coherent view of memory, we must: + * + * - If there is an outstanding write request to the object, the new + * request must wait for it to complete (either CPU or in hw, requests + * on the same ring will be naturally ordered). + * + * - If we are a write request (pending_write_domain is set), the new + * request must wait for outstanding read requests to complete. + * + * Returns 0 if successful, else propagates up the lower layer error. + */ +int +i915_gem_request_await_object(struct drm_i915_gem_request *to, + struct drm_i915_gem_object *obj, + bool write) +{ + struct i915_gem_active *active; + unsigned long active_mask; + int idx; + + if (write) { + active_mask = i915_gem_object_get_active(obj); + active = obj->last_read; + } else { + active_mask = 1; + active = &obj->last_write; + } + + for_each_active(active_mask, idx) { + struct drm_i915_gem_request *request; + int ret; + + request = i915_gem_active_peek(&active[idx], + &obj->base.dev->struct_mutex); + if (!request) + continue; + + ret = i915_gem_request_await_request(to, request); + if (ret) + return ret; + } + + return 0; +} + static void i915_gem_mark_busy(const struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index e141b1cca16a..883df3bdb381 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -209,6 +209,11 @@ static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst, *pdst = src; } +int +i915_gem_request_await_object(struct drm_i915_gem_request *to, + struct drm_i915_gem_object *obj, + bool write); + void __i915_add_request(struct drm_i915_gem_request *req, bool flush_caches); #define i915_add_request(req) \ __i915_add_request(req, true) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b92042f4dc50..69b80d078f06 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12273,7 +12273,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, goto cleanup_unpin; } - ret = i915_gem_object_sync(obj, request); + ret = i915_gem_request_await_object(request, obj, false); if (ret) goto cleanup_request; -- cgit v1.2.1 From dadd481bfe559f09bc3c42e9d552149c1cb84e6a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:57 +0100 Subject: drm/i915/guc: Prepare for nonblocking execbuf submission Currently the presumption is that the request construction and its submission to the GuC are all under the same holding of struct_mutex. We wish to relax this to separate the request construction and the later submission to the GuC. This requires us to reserve some space in the GuC command queue for the future submission. For flexibility to handle out-of-order request submission we do not preallocate the next slot in the GuC command queue during request construction, just ensuring that there is enough space later. Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-17-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_guc_submission.c | 35 ++++++++++++++++++++---------- drivers/gpu/drm/i915/intel_guc.h | 2 ++ 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 0eb6b71935cf..279a4d060288 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -432,20 +432,23 @@ int i915_guc_wq_check_space(struct drm_i915_gem_request *request) { const size_t wqi_size = sizeof(struct guc_wq_item); struct i915_guc_client *gc = request->i915->guc.execbuf_client; - struct guc_process_desc *desc; + struct guc_process_desc *desc = gc->client_base + gc->proc_desc_offset; u32 freespace; + int ret; - GEM_BUG_ON(gc == NULL); - - desc = gc->client_base + gc->proc_desc_offset; - + spin_lock(&gc->wq_lock); freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size); - if (likely(freespace >= wqi_size)) - return 0; - - gc->no_wq_space += 1; + freespace -= gc->wq_rsvd; + if (likely(freespace >= wqi_size)) { + gc->wq_rsvd += wqi_size; + ret = 0; + } else { + gc->no_wq_space++; + ret = -EAGAIN; + } + spin_unlock(&gc->wq_lock); - return -EAGAIN; + return ret; } static void guc_add_workqueue_item(struct i915_guc_client *gc, @@ -480,12 +483,14 @@ static void guc_add_workqueue_item(struct i915_guc_client *gc, * workqueue buffer dw by dw. */ BUILD_BUG_ON(wqi_size != 16); + GEM_BUG_ON(gc->wq_rsvd < wqi_size); /* postincrement WQ tail for next time */ wq_off = gc->wq_tail; + GEM_BUG_ON(wq_off & (wqi_size - 1)); gc->wq_tail += wqi_size; gc->wq_tail &= gc->wq_size - 1; - GEM_BUG_ON(wq_off & (wqi_size - 1)); + gc->wq_rsvd -= wqi_size; /* WQ starts from the page after doorbell / process_desc */ wq_page = (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT; @@ -589,6 +594,7 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq) struct i915_guc_client *client = guc->execbuf_client; int b_ret; + spin_lock(&client->wq_lock); guc_add_workqueue_item(client, rq); b_ret = guc_ring_doorbell(client); @@ -599,6 +605,7 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq) guc->submissions[engine_id] += 1; guc->last_seqno[engine_id] = rq->fence.seqno; + spin_unlock(&client->wq_lock); } /* @@ -789,6 +796,8 @@ guc_client_alloc(struct drm_i915_private *dev_priv, /* We'll keep just the first (doorbell/proc) page permanently kmap'd. */ client->vma = vma; client->client_base = kmap(i915_vma_first_page(vma)); + + spin_lock_init(&client->wq_lock); client->wq_offset = GUC_DB_SIZE; client->wq_size = GUC_WQ_SIZE; @@ -1015,9 +1024,11 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) engine->submit_request = i915_guc_submit; /* Replay the current set of previously submitted requests */ - list_for_each_entry(request, &engine->request_list, link) + list_for_each_entry(request, &engine->request_list, link) { + client->wq_rsvd += sizeof(struct guc_wq_item); if (i915_sw_fence_done(&request->submit)) i915_guc_submit(request); + } } return 0; diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index c97326269588..467845967e0b 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -78,9 +78,11 @@ struct i915_guc_client { uint16_t doorbell_id; uint16_t padding[3]; /* Maintain alignment */ + spinlock_t wq_lock; uint32_t wq_offset; uint32_t wq_size; uint32_t wq_tail; + uint32_t wq_rsvd; uint32_t no_wq_space; uint32_t b_fail; int retcode; -- cgit v1.2.1 From 80b5bdbdcbce6efd1083269616dc9efea3c63363 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:58 +0100 Subject: drm/i915: Ignore valid but unknown semaphores If we find a ring waiting on a semaphore for another assigned but not yet emitted request, treat it as valid and waiting. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-18-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_irq.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ef2d40278191..b76d45d91a84 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2831,10 +2831,10 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, } } - DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n", - engine->id, ipehr, offset); + DRM_DEBUG_DRIVER("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n", + engine->id, ipehr, offset); - return NULL; + return ERR_PTR(-ENODEV); } static struct intel_engine_cs * @@ -2922,6 +2922,9 @@ static int semaphore_passed(struct intel_engine_cs *engine) if (signaller == NULL) return -1; + if (IS_ERR(signaller)) + return 0; + /* Prevent pathological recursion due to driver bugs */ if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES) return -1; -- cgit v1.2.1 From 32c2b4bda62839c527b47bc843aebcdd535c9519 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:11:59 +0100 Subject: drm/i915: Avoid incrementing hangcheck whilst waiting for external fence If we are waiting upon an external fence, from the pov of hangcheck the engine is stuck on the last submitted seqno. Currently we give a small increment to the hangcheck score in order to catch a stuck waiter / driver. Now that we both have an independent wait hangcheck and may be stuck waiting on an external fence, resetting the GPU has little effect on that external fence. As we cannot advance by resetting, skip incrementing the hangcheck score. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-19-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_irq.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b76d45d91a84..8462817a7dae 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3099,10 +3099,6 @@ static void i915_hangcheck_elapsed(struct work_struct *work) if (engine->hangcheck.seqno == seqno) { if (i915_seqno_passed(seqno, submit)) { engine->hangcheck.action = HANGCHECK_IDLE; - if (busy) { - /* Safeguard against driver failure */ - engine->hangcheck.score += BUSY; - } } else { /* We always increment the hangcheck score * if the engine is busy and still processing -- cgit v1.2.1 From 0a046a0e93d2971d42f975b7ac409af0d4d9e7b4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:12:00 +0100 Subject: drm/i915: Nonblocking request submission Now that we have fences in place to drive request submission, we can employ those to queue requests after their dependencies as opposed to stalling in the middle of an execbuf ioctl. (However, we still choose to spin before enabling the IRQ as that is faster - though contentious.) v2: Do the fence ordering first, where we can still fail. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-20-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 21 +++++++++++++++------ drivers/gpu/drm/i915/i915_gem_request.h | 1 + 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 017cadf54d80..40978bc12ceb 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -477,12 +477,13 @@ i915_gem_request_await_request(struct drm_i915_gem_request *to, trace_i915_gem_ring_sync_to(to, from); if (!i915.semaphores) { - ret = i915_wait_request(from, - I915_WAIT_INTERRUPTIBLE | - I915_WAIT_LOCKED, - NULL, NO_WAITBOOST); - if (ret) - return ret; + if (!i915_spin_request(from, TASK_INTERRUPTIBLE, 2)) { + ret = i915_sw_fence_await_dma_fence(&to->submit, + &from->fence, 0, + GFP_KERNEL); + if (ret < 0) + return ret; + } } else { ret = to->engine->semaphore.sync_to(to, from); if (ret) @@ -577,6 +578,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) { struct intel_engine_cs *engine = request->engine; struct intel_ring *ring = request->ring; + struct drm_i915_gem_request *prev; u32 request_start; u32 reserved_tail; int ret; @@ -631,6 +633,13 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) * hangcheck. Hence we apply the barrier to ensure that we do not * see a more recent value in the hws than we are tracking. */ + + prev = i915_gem_active_raw(&engine->last_request, + &request->i915->drm.struct_mutex); + if (prev) + i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, + &request->submitq); + request->emitted_jiffies = jiffies; request->previous_seqno = engine->last_submitted_seqno; engine->last_submitted_seqno = request->fence.seqno; diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 883df3bdb381..974bd7bcc801 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -84,6 +84,7 @@ struct drm_i915_gem_request { struct intel_signal_node signaling; struct i915_sw_fence submit; + wait_queue_t submitq; /** GEM sequence number associated with the previous request, * when the HWS breadcrumb is equal to this the GPU is processing -- cgit v1.2.1 From 851ba2d6977d6ada31366ae0b791a69132f2c8a7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 14:12:01 +0100 Subject: drm/i915: Serialise execbuf operation after a dma-buf reservation object Now that we can wait upon fences before emitting the request, it becomes trivial to wait upon any implicit fence provided by the dma-buf reservation object. To protect against failure, we force any asynchronous waits on a foreign fence to timeout after 10s - so that a stall in another driver does not permanently cripple ourselves. Still unpleasant though! Testcase: igt/prime_vgem/fence-wait Signed-off-by: Chris Wilson Reviewed-by: John Harrison Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160909131201.16673-21-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index ccaf15ba4e32..33c85227643d 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1131,6 +1131,7 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, list_for_each_entry(vma, vmas, exec_list) { struct drm_i915_gem_object *obj = vma->obj; + struct reservation_object *resv; if (obj->flags & other_rings) { ret = i915_gem_request_await_object @@ -1139,6 +1140,16 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, return ret; } + resv = i915_gem_object_get_dmabuf_resv(obj); + if (resv) { + ret = i915_sw_fence_await_reservation + (&req->submit, resv, &i915_fence_ops, + obj->base.pending_write_domain, 10*HZ, + GFP_KERNEL | __GFP_NOWARN); + if (ret < 0) + return ret; + } + if (obj->base.write_domain & I915_GEM_DOMAIN_CPU) i915_gem_clflush_object(obj, false); } -- cgit v1.2.1 From 7aab2d534e35177cb08aed4075aa200b368ad496 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 20:02:18 +0100 Subject: drm/i915: Shrink objects prior to hibernation In an attempt to keep the hibernation image as same as possible, let's try and discard any unwanted pages and our own page arrays. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160909190218.16831-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4b5364d477f1..c8bd02277b7d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4589,6 +4589,11 @@ void i915_gem_load_cleanup(struct drm_device *dev) int i915_gem_freeze_late(struct drm_i915_private *dev_priv) { struct drm_i915_gem_object *obj; + struct list_head *phases[] = { + &dev_priv->mm.unbound_list, + &dev_priv->mm.bound_list, + NULL + }, **p; /* Called just before we write the hibernation image. * @@ -4599,16 +4604,18 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) * * To make sure the hibernation image contains the latest state, * we update that state just before writing out the image. + * + * To try and reduce the hibernation image, we manually shrink + * the objects as well. */ - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) { - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - } + i915_gem_shrink_all(dev_priv); - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + for (p = phases; *p; p++) { + list_for_each_entry(obj, *p, global_list) { + obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->base.write_domain = I915_GEM_DOMAIN_CPU; + } } return 0; -- cgit v1.2.1 From fbb30a5c463ff882980ce62d2ac27a0672efafb8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Sep 2016 21:19:57 +0100 Subject: drm/i915: Flush to GTT domain all GGTT bound objects after hibernation Recently I have been applying an optimisation to avoid stalling and clflushing GGTT objects based on their current binding. That is we only set-to-gtt-domain upon first bind. However, on hibernation the objects remain bound, but they are in the CPU domain. Currently (since commit 975f7ff42edf ("drm/i915: Lazily migrate the objects after hibernation")) we only flush scanout objects as all other objects are expected to be flushed prior to use. That breaks down in the face of the runtime optimisation above - and we need to flush all GGTT pinned objects (essentially ringbuffers). To reduce the burden of extra clflushes, we only flush those objects we cannot discard from the GGTT. Everything pinned to the scanout, or current contexts or ringbuffers will be flushed and rebound. Other objects, such as inactive contexts, will be left unbound and in the CPU domain until first use after resuming. Fixes: 7abc98fadfdd ("drm/i915: Only change the context object's domain...") Fixes: 57e885318119 ("drm/i915: Use VMA for ringbuffer tracking") References: https://bugs.freedesktop.org/show_bug.cgi?id=94722 Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Mika Kuoppala Cc: David Weinehall Reviewed-by: Matthew Auld Link: http://patchwork.freedesktop.org/patch/msgid/20160909201957.2499-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index f3c6876da521..61ab65b01cc4 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3237,8 +3237,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct i915_ggtt *ggtt = &dev_priv->ggtt; - struct drm_i915_gem_object *obj; - struct i915_vma *vma; + struct drm_i915_gem_object *obj, *on; i915_check_and_clear_faults(dev_priv); @@ -3246,20 +3245,32 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total, true); - /* Cache flush objects bound into GGTT and rebind them. */ - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { + ggtt->base.closed = true; /* skip rewriting PTE on VMA unbind */ + + /* clflush objects bound into the GGTT and rebind them. */ + list_for_each_entry_safe(obj, on, + &dev_priv->mm.bound_list, global_list) { + bool ggtt_bound = false; + struct i915_vma *vma; + list_for_each_entry(vma, &obj->vma_list, obj_link) { if (vma->vm != &ggtt->base) continue; + if (!i915_vma_unbind(vma)) + continue; + WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE)); + ggtt_bound = true; } - if (obj->pin_display) + if (ggtt_bound) WARN_ON(i915_gem_object_set_to_gtt_domain(obj, false)); } + ggtt->base.closed = false; + if (INTEL_INFO(dev)->gen >= 8) { if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) chv_setup_private_ppat(dev_priv); -- cgit v1.2.1 From f169660ed4e57a03e6f6ed07fe192dbcb7687a0d Mon Sep 17 00:00:00 2001 From: Jim Bride Date: Wed, 7 Sep 2016 15:47:34 -0700 Subject: drm/i915/dp: Add a standalone function to obtain shared dpll for HSW/BDW/SKL/BXT Add the PLL selection code for HSW/BDW/BXT/SKL into a stand-alone function in order to allow for the implementation of a platform neutral upfront link training function. v4: * Removed dereferencing NULL pointer in case of failure (Dhinakaran Pandiyan) v3: * Add Hooks for all DDI platforms into this standalone function v2: * Change the macro to use dev_priv instead of dev (David Weinehall) Reviewed-by: Durgadoss R Signed-off-by: Manasi Navare Signed-off-by: Jim Bride Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_ddi.c | 39 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dpll_mgr.c | 38 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dpll_mgr.h | 2 ++ drivers/gpu/drm/i915/intel_drv.h | 3 ++- 4 files changed, 81 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index e4b875e919dd..25e7973663f7 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2393,6 +2393,45 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port *intel_dig_port) return connector; } +struct intel_shared_dpll * +intel_ddi_get_link_dpll(struct intel_dp *intel_dp, int clock) +{ + struct intel_connector *connector = intel_dp->attached_connector; + struct intel_encoder *encoder = connector->encoder; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct intel_shared_dpll *pll = NULL; + struct intel_shared_dpll_config tmp_pll_config; + enum intel_dpll_id dpll_id; + + if (IS_BROXTON(dev_priv)) { + dpll_id = (enum intel_dpll_id)dig_port->port; + /* + * Select the required PLL. This works for platforms where + * there is no shared DPLL. + */ + pll = &dev_priv->shared_dplls[dpll_id]; + if (WARN_ON(pll->active_mask)) { + + DRM_ERROR("Shared DPLL in use. active_mask:%x\n", + pll->active_mask); + return NULL; + } + tmp_pll_config = pll->config; + if (!bxt_ddi_dp_set_dpll_hw_state(clock, + &pll->config.hw_state)) { + DRM_ERROR("Could not setup DPLL\n"); + pll->config = tmp_pll_config; + return NULL; + } + } else if (IS_SKYLAKE(dev_priv)) { + pll = skl_find_link_pll(dev_priv, clock); + } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { + pll = hsw_ddi_dp_get_dpll(encoder, clock); + } + return pll; +} + void intel_ddi_init(struct drm_device *dev, enum port port) { struct drm_i915_private *dev_priv = to_i915(dev); diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 9a1da98805d6..4b067accd5cd 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -23,6 +23,44 @@ #include "intel_drv.h" +struct intel_shared_dpll * +skl_find_link_pll(struct drm_i915_private *dev_priv, int clock) +{ + struct intel_shared_dpll *pll = NULL; + struct intel_dpll_hw_state dpll_hw_state; + enum intel_dpll_id i; + bool found = false; + + if (!skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state)) + return pll; + + for (i = DPLL_ID_SKL_DPLL1; i <= DPLL_ID_SKL_DPLL3; i++) { + pll = &dev_priv->shared_dplls[i]; + + /* Only want to check enabled timings first */ + if (pll->config.crtc_mask == 0) + continue; + + if (memcmp(&dpll_hw_state, &pll->config.hw_state, + sizeof(pll->config.hw_state)) == 0) { + found = true; + break; + } + } + + /* Ok no matching timings, maybe there's a free one? */ + for (i = DPLL_ID_SKL_DPLL1; + ((found == false) && (i <= DPLL_ID_SKL_DPLL3)); i++) { + pll = &dev_priv->shared_dplls[i]; + if (pll->config.crtc_mask == 0) { + pll->config.hw_state = dpll_hw_state; + break; + } + } + + return pll; +} + struct intel_shared_dpll * intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, enum intel_dpll_id id) diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index aed74084f759..f4385353bc11 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -168,6 +168,8 @@ bool bxt_ddi_dp_set_dpll_hw_state(int clock, /* SKL dpll related functions */ bool skl_ddi_dp_set_dpll_hw_state(int clock, struct intel_dpll_hw_state *dpll_hw_state); +struct intel_shared_dpll *skl_find_link_pll(struct drm_i915_private *dev_priv, + int clock); /* HSW dpll related functions */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8c089e339c29..1bcf8ead2264 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1159,7 +1159,8 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state); uint32_t ddi_signal_levels(struct intel_dp *intel_dp); - +struct intel_shared_dpll *intel_ddi_get_link_dpll(struct intel_dp *intel_dp, + int clock); unsigned int intel_fb_align_height(struct drm_device *dev, unsigned int height, uint32_t pixel_format, -- cgit v1.2.1 From 7bfaddf057f3ae774fa355cb7d87324ca67add94 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Wed, 7 Sep 2016 11:28:00 -0700 Subject: drm/i915/dp: Move max. vswing check to it's own function Wrap the max. vswing check in a separate function. This makes the clock recovery phase of DP link training cleaner v3: Fixed the paranthesis warning (Mika Kahola) v2: Fixed the Compiler warning (Mika Kahola) Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Manasi Navare Reviewed-by: Mika Kahola Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dp_link_training.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index 0deebed71a26..b9880cf0ae6c 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -112,6 +112,18 @@ intel_dp_update_link_train(struct intel_dp *intel_dp) return ret == intel_dp->lane_count; } +static bool intel_dp_link_max_vswing_reached(struct intel_dp *intel_dp) +{ + int lane; + + for (lane = 0; lane < intel_dp->lane_count; lane++) + if ((intel_dp->train_set[lane] & + DP_TRAIN_MAX_SWING_REACHED) == 0) + return false; + + return true; +} + /* Enable corresponding port and start training pattern 1 */ static void intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) @@ -170,10 +182,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) } /* Check to see if we've tried the max voltage */ - for (i = 0; i < intel_dp->lane_count; i++) - if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) - break; - if (i == intel_dp->lane_count) { + if (intel_dp_link_max_vswing_reached(intel_dp)) { ++loop_tries; if (loop_tries == 5) { DRM_ERROR("too many full retries, give up\n"); -- cgit v1.2.1 From 13b1996e842aa4164c4d838908bc6dd76c3bd2b2 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Wed, 7 Sep 2016 11:28:01 -0700 Subject: drm/dp/i915: Make clock recovery in the link training compliant with DP Spec 1.2 This function cleans up clock recovery loop in link training compliant tp Dp Spec 1.2. It tries the clock recovery 5 times for the same voltage or until max voltage swing is reached and removes the additional non compliant retries. This function now returns a boolean values based on if clock recovery passed or failed. v3: * Better Debug prints in case of failures (Mika Kahola) v2: * Rebased on top of new revision of vswing patch (Manasi Navare) Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Manasi Navare Reviewed-by: Mika Kahola Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dp_link_training.c | 60 +++++++++++++-------------- 1 file changed, 28 insertions(+), 32 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index b9880cf0ae6c..80b932664743 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -125,12 +125,11 @@ static bool intel_dp_link_max_vswing_reached(struct intel_dp *intel_dp) } /* Enable corresponding port and start training pattern 1 */ -static void +static bool intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) { - int i; uint8_t voltage; - int voltage_tries, loop_tries; + int voltage_tries, max_vswing_tries; uint8_t link_config[2]; uint8_t link_bw, rate_select; @@ -146,6 +145,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2); + if (intel_dp->num_sink_rates) drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET, &rate_select, 1); @@ -161,58 +161,54 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE)) { DRM_ERROR("failed to enable link training\n"); - return; + return false; } - voltage = 0xff; - voltage_tries = 0; - loop_tries = 0; + voltage_tries = 1; + max_vswing_tries = 0; for (;;) { uint8_t link_status[DP_LINK_STATUS_SIZE]; drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd); + if (!intel_dp_get_link_status(intel_dp, link_status)) { DRM_ERROR("failed to get link status\n"); - break; + return false; } if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { DRM_DEBUG_KMS("clock recovery OK\n"); - break; + return true; } - /* Check to see if we've tried the max voltage */ - if (intel_dp_link_max_vswing_reached(intel_dp)) { - ++loop_tries; - if (loop_tries == 5) { - DRM_ERROR("too many full retries, give up\n"); - intel_dp_dump_link_status(link_status); - break; - } - intel_dp_reset_link_train(intel_dp, - DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); - voltage_tries = 0; - continue; + if (voltage_tries == 5) { + DRM_DEBUG_KMS("Same voltage tried 5 times\n"); + return false; + } + + if (max_vswing_tries == 1) { + DRM_DEBUG_KMS("Max Voltage Swing reached\n"); + return false; } - /* Check to see if we've tried the same voltage 5 times */ - if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { - ++voltage_tries; - if (voltage_tries == 5) { - DRM_ERROR("too many voltage retries, give up\n"); - break; - } - } else - voltage_tries = 0; voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Update training set as requested by target */ intel_get_adjust_train(intel_dp, link_status); if (!intel_dp_update_link_train(intel_dp)) { DRM_ERROR("failed to update link training\n"); - break; + return false; } + + if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == + voltage) + ++voltage_tries; + else + voltage_tries = 1; + + if (intel_dp_link_max_vswing_reached(intel_dp)) + ++max_vswing_tries; + } } -- cgit v1.2.1 From c92bd2fa33038d18858beca3cc65d53c99ce95f6 Mon Sep 17 00:00:00 2001 From: "Navare, Manasi D" Date: Thu, 1 Sep 2016 15:08:15 -0700 Subject: drm/i915: Make DP link training channel equalization DP 1.2 Spec compliant Fix the number of tries in channel euqalization link training sequence according to DP 1.2 Spec. It returns a boolean depending on channel equalization pass or failure. Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Manasi Navare Reviewed-by: Mika Kahola Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dp_link_training.c | 57 ++++++++++----------------- drivers/gpu/drm/i915/intel_drv.h | 1 + 2 files changed, 22 insertions(+), 36 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index 80b932664743..c438b02184cb 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -244,12 +244,12 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) return training_pattern; } -static void +static bool intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) { - bool channel_eq = false; - int tries, cr_tries; + int tries; u32 training_pattern; + uint8_t link_status[DP_LINK_STATUS_SIZE]; training_pattern = intel_dp_training_pattern(intel_dp); @@ -258,20 +258,11 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) training_pattern | DP_LINK_SCRAMBLING_DISABLE)) { DRM_ERROR("failed to start channel equalization\n"); - return; + return false; } - tries = 0; - cr_tries = 0; - channel_eq = false; - for (;;) { - uint8_t link_status[DP_LINK_STATUS_SIZE]; - - if (cr_tries > 5) { - DRM_ERROR("failed to train DP, aborting\n"); - intel_dp_dump_link_status(link_status); - break; - } + intel_dp->channel_eq_status = false; + for (tries = 0; tries < 5; tries++) { drm_dp_link_train_channel_eq_delay(intel_dp->dpcd); if (!intel_dp_get_link_status(intel_dp, link_status)) { @@ -282,44 +273,38 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) /* Make sure clock is still ok */ if (!drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { - intel_dp_link_training_clock_recovery(intel_dp); - intel_dp_set_link_train(intel_dp, - training_pattern | - DP_LINK_SCRAMBLING_DISABLE); - cr_tries++; - continue; + intel_dp_dump_link_status(link_status); + DRM_DEBUG_KMS("Clock recovery check failed, cannot " + "continue channel equalization\n"); + break; } if (drm_dp_channel_eq_ok(link_status, intel_dp->lane_count)) { - channel_eq = true; + intel_dp->channel_eq_status = true; + DRM_DEBUG_KMS("Channel EQ done. DP Training " + "successful\n"); break; } - /* Try 5 times, then try clock recovery if that fails */ - if (tries > 5) { - intel_dp_link_training_clock_recovery(intel_dp); - intel_dp_set_link_train(intel_dp, - training_pattern | - DP_LINK_SCRAMBLING_DISABLE); - tries = 0; - cr_tries++; - continue; - } - /* Update training set as requested by target */ intel_get_adjust_train(intel_dp, link_status); if (!intel_dp_update_link_train(intel_dp)) { DRM_ERROR("failed to update link training\n"); break; } - ++tries; + } + + /* Try 5 times, else fail and try at lower BW */ + if (tries == 5) { + intel_dp_dump_link_status(link_status); + DRM_DEBUG_KMS("Channel equalization failed 5 times\n"); } intel_dp_set_idle_link_train(intel_dp); - if (channel_eq) - DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); + return intel_dp->channel_eq_status; + } void intel_dp_stop_link_train(struct intel_dp *intel_dp) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1bcf8ead2264..7700e3254b26 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -878,6 +878,7 @@ struct intel_dp { bool link_mst; bool has_audio; bool detect_done; + bool channel_eq_status; enum hdmi_force_audio force_audio; bool limited_color_range; bool color_range_auto; -- cgit v1.2.1 From 82daabae9e85a9b54698ce2480429ddf8fe2f098 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 9 Sep 2016 21:02:53 +0100 Subject: drm/i915: remove writeq ifdeffery drm already provides fallback versions of readq and writeq. Signed-off-by: Matthew Auld Reviewed-by: Joonas Lahtinen Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1473451373-9852-1-git-send-email-matthew.auld@intel.com --- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 61ab65b01cc4..0bb4232f66bc 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2304,12 +2304,7 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) { -#ifdef writeq writeq(pte, addr); -#else - iowrite32((u32)pte, addr); - iowrite32(pte >> 32, addr + 4); -#endif } static void gen8_ggtt_insert_page(struct i915_address_space *vm, -- cgit v1.2.1 From 2686ebfdf7f9af6bec5b173b629aff7370b21f17 Mon Sep 17 00:00:00 2001 From: "Navare, Manasi D" Date: Mon, 12 Sep 2016 18:04:23 -0700 Subject: drm/i915: Add support for Kabylake to function obtaining shared PLL This adds support for KBL in the new function added in commit ID: commit that returns a shared pll in case of DDI platforms. Signed-off-by: Manasi Navare Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1473728663-14355-1-git-send-email-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 25e7973663f7..15d47c87def6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2424,7 +2424,7 @@ intel_ddi_get_link_dpll(struct intel_dp *intel_dp, int clock) pll->config = tmp_pll_config; return NULL; } - } else if (IS_SKYLAKE(dev_priv)) { + } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { pll = skl_find_link_pll(dev_priv, clock); } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { pll = hsw_ddi_dp_get_dpll(encoder, clock); -- cgit v1.2.1 From 40918e0bb81be02f507a941f8b2741f0dc1771b0 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 7 Sep 2016 17:42:31 -0700 Subject: Revert "drm/i915/psr: Make idle_frames sensible again" This reverts commit 1c80c25fb622973dd135878e98d172be20859049 Author: Daniel Vetter Date: Wed May 18 18:47:12 2016 +0200 drm/i915/psr: Make idle_frames sensible again There are panels that needs 4 idle frames before entering PSR, but VBT is unproperly set. Also lately it was identified that idle frame count calculated at HW can be off by 1, what makes the minimum of 2, at least. Without the current vbt+1 we are with the risk of having HW calculating 0 idle frames and entering PSR when it shouldn't. Regardless the lack of link training. [Jani: there is some disagreement on the explanation, but the commit regresses so revert it is.] References: http://marc.info/?i=20160904191153.GA2328@light.dominikbrodowski.net Cc: Dominik Brodowski Cc: Jani Nikula Cc: Daniel Vetter Signed-off-by: Rodrigo Vivi Fixes: 1c80c25fb622 ("drm/i915/psr: Make idle_frames sensible again") Cc: drm-intel-fixes@lists.freedesktop.org # v4.8-rc1+ Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473295351-8766-1-git-send-email-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_psr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 59a21c9d2e43..108ba1e5d658 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -255,14 +255,14 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = to_i915(dev); uint32_t max_sleep_time = 0x1f; - /* Lately it was identified that depending on panel idle frame count - * calculated at HW can be off by 1. So let's use what came - * from VBT + 1. - * There are also other cases where panel demands at least 4 - * but VBT is not being set. To cover these 2 cases lets use - * at least 5 when VBT isn't set to be on the safest side. + /* + * Let's respect VBT in case VBT asks a higher idle_frame value. + * Let's use 6 as the minimum to cover all known cases including + * the off-by-one issue that HW has in some cases. Also there are + * cases where sink should be able to train + * with the 5 or 6 idle patterns. */ - uint32_t idle_frames = dev_priv->vbt.psr.idle_frames + 1; + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); uint32_t val = EDP_PSR_ENABLE; val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT; -- cgit v1.2.1 From c8ebfad7a063fe665417fa0eeb0da7cfe987d8ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 13 Sep 2016 12:22:19 +0300 Subject: drm/i915: Ignore OpRegion panel type except on select machines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out commit a05628195a0d ("drm/i915: Get panel_type from OpRegion panel details") has regressed quite a few machines. So it looks like we can't use the panel type from OpRegion on all systems, and yet we absolutely must use it on some specific systems. Despite trying, I was unable to find any automagic way to determine if the OpRegion panel type is respectable or not. The only glimmer of hope I had was bit 8 in the SCIC response, but that turned out to not work either (it was always 0 on both types of systems). So, to fix the regressions without breaking the machine we know to need the OpRegion panel type, let's just add a quirk for this. Only specific machines known to require the OpRegion panel type will therefore use it. Everyone else will fall bck to the VBT panel type. The only known machine so far is a "Conrac GmbH IX45GM2". The PCI subsystem ID on this machine is just a generic 8086:2a42, so of no use. Instead we'll go with a DMI match. I suspect we can now also revert commit aeddda06c1a7 ("drm/i915: Ignore panel type from OpRegion on SKL") but let's leave that to a separate patch. v2: Do the DMI match in the opregion code directly, as dev_priv->quirks gets populated too late Cc: Rob Kramer Cc: Martin van Es Cc: Andrea Arcangeli Cc: Dave Airlie Cc: Marco Krüger Cc: Sean Greenslade Cc: Trudy Tective Cc: Robin Müller Cc: Alexander Kobel Cc: Alexey Shumitsky Cc: Emil Andersen Lauridsen Cc: oceans112@gmail.com Cc: James Hogan Cc: James Bottomley Cc: stable@vger.kernel.org References: https://lists.freedesktop.org/archives/intel-gfx/2016-August/105545.html References: https://lists.freedesktop.org/archives/dri-devel/2016-August/116888.html References: https://lists.freedesktop.org/archives/intel-gfx/2016-June/098826.html Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94825 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97060 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97443 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97363 Fixes: a05628195a0d ("drm/i915: Get panel_type from OpRegion panel details") Tested-by: Marco Krüger Tested-by: Alexey Shumitsky Tested-by: Sean Greenslade Tested-by: Emil Andersen Lauridsen Tested-by: Robin Müller Tested-by: oceans112@gmail.com Tested-by: Rob Kramer Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1473758539-21565-1-git-send-email-ville.syrjala@linux.intel.com References: http://patchwork.freedesktop.org/patch/msgid/1473602239-15855-1-git-send-email-adrienverge@gmail.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/intel_opregion.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index adca262d591a..7acbbbf97833 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -1047,6 +1047,23 @@ err_out: return err; } +static int intel_use_opregion_panel_type_callback(const struct dmi_system_id *id) +{ + DRM_INFO("Using panel type from OpRegion on %s\n", id->ident); + return 1; +} + +static const struct dmi_system_id intel_use_opregion_panel_type[] = { + { + .callback = intel_use_opregion_panel_type_callback, + .ident = "Conrac GmbH IX45GM2", + .matches = {DMI_MATCH(DMI_SYS_VENDOR, "Conrac GmbH"), + DMI_MATCH(DMI_PRODUCT_NAME, "IX45GM2"), + }, + }, + { } +}; + int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv) { @@ -1072,6 +1089,16 @@ intel_opregion_get_panel_type(struct drm_i915_private *dev_priv) return -ENODEV; } + /* + * So far we know that some machined must use it, others must not use it. + * There doesn't seem to be any way to determine which way to go, except + * via a quirk list :( + */ + if (!dmi_check_system(intel_use_opregion_panel_type)) { + DRM_DEBUG_KMS("Ignoring OpRegion panel type (%d)\n", ret - 1); + return -ENODEV; + } + /* * FIXME On Dell XPS 13 9350 the OpRegion panel type (0) gives us * low vswing for eDP, whereas the VBT panel type (2) gives us normal -- cgit v1.2.1 From b0876afdff45a4714e11f18ebbfb81762b417eac Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Wed, 14 Sep 2016 13:10:33 +0100 Subject: drm/i915: Only expand COND once in wait_for() Commentary from Chris Wilson's original version: > I was looking at some wait_for() timeouts on a slow system, with lots of > debug enabled (KASAN, lockdep, mmio_debug). Thinking that we were > mishandling the timeout, I tried to ensure that we loop at least once > after first testing COND. However, the double test of COND either side > of the timeout check makes that unlikely. But we can do an equivalent > loop, that keeps the COND check after testing for timeout (required so > that we are not preempted between testing COND and then testing for a > timeout) without expanding COND twice. > > The advantage of only expanding COND once is a dramatic reduction in > code size: > > text data bss dec hex > 1308733 5184 1152 1315069 1410fd before > 1305341 5184 1152 1311677 1403bd after but it turned out that due to a missing iniitialiser, gcc had "gone wild trimming undefined code" :( This version acheives a rather more modest (but still worthwhile) gain of ~550 bytes. Signed-off-by: Dave Gordon Original-idea-by: Chris Wilson Cc: Chris Wilson Cc: Zanoni, Paulo R Link: http://patchwork.freedesktop.org/patch/msgid/1473855033-26980-1-git-send-email-david.s.gordon@intel.com Reviewed-by: Paulo Zanoni Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_drv.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7700e3254b26..810c89eb6863 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -52,11 +52,15 @@ */ #define _wait_for(COND, US, W) ({ \ unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1; \ - int ret__ = 0; \ - while (!(COND)) { \ - if (time_after(jiffies, timeout__)) { \ - if (!(COND)) \ - ret__ = -ETIMEDOUT; \ + int ret__; \ + for (;;) { \ + bool expired__ = time_after(jiffies, timeout__); \ + if (COND) { \ + ret__ = 0; \ + break; \ + } \ + if (expired__) { \ + ret__ = -ETIMEDOUT; \ break; \ } \ if ((W) && drm_can_sleep()) { \ -- cgit v1.2.1 From b20e3cfe4b7dc62869a1f7e25d910a039c9aeb15 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Mon, 12 Sep 2016 21:19:35 +0100 Subject: drm/i915: clarify PMINTRMSK/pm_intr_keep usage No functional changes; just renaming a bit, tweaking a datatype, prettifying layout, and adding comments, in particular in the GuC setup code that touches this data. Signed-off-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1473711577-11454-2-git-send-email-david.s.gordon@intel.com Reviewed-by: Tvrtko Ursulin Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_irq.c | 4 ++-- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_guc_loader.c | 27 +++++++++++++++++++++------ 4 files changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1e2dda88a483..d01a50e8e57c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1184,6 +1184,7 @@ struct intel_gen6_power_mgmt { bool interrupts_enabled; u32 pm_iir; + /* PM interrupt bits that should never be masked */ u32 pm_intr_keep; /* Frequencies are stored in potentially platform dependent multiples. diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8462817a7dae..c128fdbd24e4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -371,7 +371,7 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) spin_lock_irq(&dev_priv->irq_lock); dev_priv->rps.interrupts_enabled = false; - I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0)); + I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0u)); __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) & @@ -4500,7 +4500,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev_priv->rps.pm_intr_keep |= GEN6_PM_RP_UP_EI_EXPIRED; if (INTEL_INFO(dev_priv)->gen >= 8) - dev_priv->rps.pm_intr_keep |= GEN8_PMINTR_REDIRECT_TO_NON_DISP; + dev_priv->rps.pm_intr_keep |= GEN8_PMINTR_REDIRECT_TO_GUC; INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work, i915_hangcheck_elapsed); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a29d707f0932..70d96162def6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7067,7 +7067,7 @@ enum { #define VLV_RCEDATA _MMIO(0xA0BC) #define GEN6_RC6pp_THRESHOLD _MMIO(0xA0C0) #define GEN6_PMINTRMSK _MMIO(0xA168) -#define GEN8_PMINTR_REDIRECT_TO_NON_DISP (1<<31) +#define GEN8_PMINTR_REDIRECT_TO_GUC (1<<31) #define GEN8_MISC_CTRL0 _MMIO(0xA180) #define VLV_PWRDWNUPCTL _MMIO(0xA294) #define GEN9_MEDIA_PG_IDLE_HYSTERESIS _MMIO(0xA0C4) diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 853928f21596..00217481f1fa 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -134,13 +134,28 @@ static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv) I915_WRITE(GUC_WD_VECS_IER, ~irqs); /* - * If GuC has routed PM interrupts to itself, don't keep it. - * and keep other interrupts those are unmasked by GuC. - */ + * 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_intr_keep' 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_intr_keep so that it's left enabled for the GuC. + * + * OTOH the REDIRECT_TO_GUC bit is initially SET in pm_intr_keep + * (so interrupts go to the DISPLAY unit at first); but here we + * need to CLEAR that bit, which will result in the register bit + * being left SET! + */ tmp = I915_READ(GEN6_PMINTRMSK); - if (tmp & GEN8_PMINTR_REDIRECT_TO_NON_DISP) { - dev_priv->rps.pm_intr_keep |= ~(tmp & ~GEN8_PMINTR_REDIRECT_TO_NON_DISP); - dev_priv->rps.pm_intr_keep &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP; + if (tmp & GEN8_PMINTR_REDIRECT_TO_GUC) { + dev_priv->rps.pm_intr_keep |= ~tmp; + dev_priv->rps.pm_intr_keep &= ~GEN8_PMINTR_REDIRECT_TO_GUC; } } -- cgit v1.2.1 From 0c5664e41728b6d0b39de37a17940ee5cd8a1a64 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Mon, 12 Sep 2016 21:19:36 +0100 Subject: drm/i915/guc: general tidying up (loader) Renaming to more consistent scheme, delete unused definitions Signed-off-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1473711577-11454-3-git-send-email-david.s.gordon@intel.com Reviewed-by: Tvrtko Ursulin Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_guc_reg.h | 3 --- drivers/gpu/drm/i915/intel_guc_loader.c | 27 ++++++++++++++++----------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index cf5a65be4fe0..a47e1e4aec03 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ b/drivers/gpu/drm/i915/i915_guc_reg.h @@ -103,9 +103,6 @@ #define HOST2GUC_INTERRUPT _MMIO(0xc4c8) #define HOST2GUC_TRIGGER (1<<0) -#define DRBMISC1 0x1984 -#define DOORBELL_ENABLE (1<<0) - #define GEN8_DRBREGL(x) _MMIO(0x1000 + (x) * 8) #define GEN8_DRB_VALID (1<<0) #define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4) diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 00217481f1fa..6fd39efb7894 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -97,7 +97,7 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) } }; -static void direct_interrupts_to_host(struct drm_i915_private *dev_priv) +static void guc_interrupts_release(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; int irqs; @@ -114,7 +114,7 @@ static void direct_interrupts_to_host(struct drm_i915_private *dev_priv) I915_WRITE(GUC_WD_VECS_IER, 0); } -static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv) +static void guc_interrupts_capture(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; int irqs; @@ -179,7 +179,12 @@ static u32 get_core_family(struct drm_i915_private *dev_priv) } } -static void set_guc_init_params(struct drm_i915_private *dev_priv) +/* + * Initialise the GuC parameter block before starting the firmware + * transfer. These parameters are read by the firmware on startup + * and cannot be changed thereafter. + */ +static void guc_params_init(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; u32 params[GUC_CTL_MAX_DWORDS]; @@ -392,11 +397,11 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE | I915_READ(GEN7_MISCCPCTL))); - /* allows for 5us before GT can go to RC6 */ + /* allows for 5us (in 10ns units) before GT can go to RC6 */ I915_WRITE(GUC_ARAT_C6DIS, 0x1FF); } - set_guc_init_params(dev_priv); + guc_params_init(dev_priv); ret = guc_ucode_xfer_dma(dev_priv, vma); @@ -411,7 +416,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) return ret; } -static int i915_reset_guc(struct drm_i915_private *dev_priv) +static int guc_hw_reset(struct drm_i915_private *dev_priv) { int ret; u32 guc_status; @@ -478,7 +483,7 @@ int intel_guc_setup(struct drm_device *dev) goto fail; } - direct_interrupts_to_host(dev_priv); + guc_interrupts_release(dev_priv); guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING; @@ -501,7 +506,7 @@ int intel_guc_setup(struct drm_device *dev) * Always reset the GuC just before (re)loading, so * that the state and timing are fairly predictable */ - err = i915_reset_guc(dev_priv); + err = guc_hw_reset(dev_priv); if (err) goto fail; @@ -526,7 +531,7 @@ int intel_guc_setup(struct drm_device *dev) err = i915_guc_submission_enable(dev_priv); if (err) goto fail; - direct_interrupts_to_guc(dev_priv); + guc_interrupts_capture(dev_priv); } return 0; @@ -535,7 +540,7 @@ fail: if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING) guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL; - direct_interrupts_to_host(dev_priv); + guc_interrupts_release(dev_priv); i915_guc_submission_disable(dev_priv); i915_guc_submission_fini(dev_priv); @@ -768,7 +773,7 @@ void intel_guc_fini(struct drm_device *dev) struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; mutex_lock(&dev->struct_mutex); - direct_interrupts_to_host(dev_priv); + guc_interrupts_release(dev_priv); i915_guc_submission_disable(dev_priv); i915_guc_submission_fini(dev_priv); -- cgit v1.2.1 From 7a9347f947757f6c5ea432b299a8ba33ef7b78c7 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Mon, 12 Sep 2016 21:19:37 +0100 Subject: drm/i915/guc: general tidying up (submission) Renaming to more consistent scheme, and updating comments, mostly about i915_guc_wq_reserve(), aka i915_guc_wq_check_space(). Signed-off-by: Dave Gordon Link: http://patchwork.freedesktop.org/patch/msgid/1473711577-11454-4-git-send-email-david.s.gordon@intel.com Reviewed-by: Tvrtko Ursulin Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_guc_submission.c | 63 +++++++++++++++--------------- drivers/gpu/drm/i915/intel_guc.h | 2 +- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 3 files changed, 34 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 279a4d060288..43358e18d34c 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -59,7 +59,7 @@ * WQ_TYPE_INORDER is needed to support legacy submission via GuC, which * represents in-order queue. The kernel driver packs ring tail pointer and an * ELSP context descriptor dword into Work Item. - * See guc_add_workqueue_item() + * See guc_wq_item_append() * */ @@ -288,7 +288,7 @@ static uint32_t select_doorbell_cacheline(struct intel_guc *guc) /* * Initialise the process descriptor shared with the GuC firmware. */ -static void guc_init_proc_desc(struct intel_guc *guc, +static void guc_proc_desc_init(struct intel_guc *guc, struct i915_guc_client *client) { struct guc_process_desc *desc; @@ -320,7 +320,7 @@ static void guc_init_proc_desc(struct intel_guc *guc, * write queue, etc). */ -static void guc_init_ctx_desc(struct intel_guc *guc, +static void guc_ctx_desc_init(struct intel_guc *guc, struct i915_guc_client *client) { struct drm_i915_private *dev_priv = guc_to_i915(guc); @@ -399,7 +399,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, sizeof(desc) * client->ctx_index); } -static void guc_fini_ctx_desc(struct intel_guc *guc, +static void guc_ctx_desc_fini(struct intel_guc *guc, struct i915_guc_client *client) { struct guc_context_desc desc; @@ -413,7 +413,7 @@ static void guc_fini_ctx_desc(struct intel_guc *guc, } /** - * i915_guc_wq_check_space() - check that the GuC can accept a request + * i915_guc_wq_reserve() - reserve space in the GuC's workqueue * @request: request associated with the commands * * Return: 0 if space is available @@ -421,14 +421,14 @@ static void guc_fini_ctx_desc(struct intel_guc *guc, * * This function must be called (and must return 0) before a request * is submitted to the GuC via i915_guc_submit() below. Once a result - * of 0 has been returned, it remains valid until (but only until) - * the next call to submit(). + * of 0 has been returned, it must be balanced by a corresponding + * call to submit(). * - * This precheck allows the caller to determine in advance that space + * Reservation allows the caller to determine in advance that space * will be available for the next submission before committing resources * to it, and helps avoid late failures with complicated recovery paths. */ -int i915_guc_wq_check_space(struct drm_i915_gem_request *request) +int i915_guc_wq_reserve(struct drm_i915_gem_request *request) { const size_t wqi_size = sizeof(struct guc_wq_item); struct i915_guc_client *gc = request->i915->guc.execbuf_client; @@ -451,8 +451,9 @@ int i915_guc_wq_check_space(struct drm_i915_gem_request *request) return ret; } -static void guc_add_workqueue_item(struct i915_guc_client *gc, - struct drm_i915_gem_request *rq) +/* Construct a Work Item and append it to the GuC's Work Queue */ +static void guc_wq_item_append(struct i915_guc_client *gc, + struct drm_i915_gem_request *rq) { /* wqi_len is in DWords, and does not include the one-word header */ const size_t wqi_size = sizeof(struct guc_wq_item); @@ -465,7 +466,7 @@ static void guc_add_workqueue_item(struct i915_guc_client *gc, desc = gc->client_base + gc->proc_desc_offset; - /* Free space is guaranteed, see i915_guc_wq_check_space() above */ + /* Free space is guaranteed, see i915_guc_wq_reserve() above */ freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size); GEM_BUG_ON(freespace < wqi_size); @@ -575,14 +576,13 @@ static int guc_ring_doorbell(struct i915_guc_client *gc) * Return: 0 on success, otherwise an errno. * (Note: nonzero really shouldn't happen!) * - * The caller must have already called i915_guc_wq_check_space() above - * with a result of 0 (success) since the last request submission. This - * guarantees that there is space in the work queue for the new request, - * so enqueuing the item cannot fail. + * The caller must have already called i915_guc_wq_reserve() above with + * a result of 0 (success), guaranteeing that there is space in the work + * queue for the new request, so enqueuing the item cannot fail. * * Bad Things Will Happen if the caller violates this protocol e.g. calls - * submit() when check() says there's no space, or calls submit() multiple - * times with no intervening check(). + * submit() when _reserve() says there's no space, or calls _submit() + * a different number of times from (successful) calls to _reserve(). * * The only error here arises if the doorbell hardware isn't functioning * as expected, which really shouln't happen. @@ -595,7 +595,7 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq) int b_ret; spin_lock(&client->wq_lock); - guc_add_workqueue_item(client, rq); + guc_wq_item_append(client, rq); b_ret = guc_ring_doorbell(client); client->submissions[engine_id] += 1; @@ -686,7 +686,7 @@ guc_client_free(struct drm_i915_private *dev_priv, i915_vma_unpin_and_release(&client->vma); if (client->ctx_index != GUC_INVALID_CTX_ID) { - guc_fini_ctx_desc(guc, client); + guc_ctx_desc_fini(guc, client); ida_simple_remove(&guc->ctx_ids, client->ctx_index); } @@ -818,8 +818,8 @@ guc_client_alloc(struct drm_i915_private *dev_priv, else client->proc_desc_offset = (GUC_DB_SIZE / 2); - guc_init_proc_desc(guc, client); - guc_init_ctx_desc(guc, client); + guc_proc_desc_init(guc, client); + guc_ctx_desc_init(guc, client); if (guc_init_doorbell(guc, client, db_id)) goto err; @@ -835,7 +835,7 @@ err: return NULL; } -static void guc_create_log(struct intel_guc *guc) +static void guc_log_create(struct intel_guc *guc) { struct i915_vma *vma; unsigned long offset; @@ -875,7 +875,7 @@ static void guc_create_log(struct intel_guc *guc) guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags; } -static void init_guc_policies(struct guc_policies *policies) +static void guc_policies_init(struct guc_policies *policies) { struct guc_policy *policy; u32 p, i; @@ -897,7 +897,7 @@ static void init_guc_policies(struct guc_policies *policies) policies->is_valid = 1; } -static void guc_create_ads(struct intel_guc *guc) +static void guc_addon_create(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); struct i915_vma *vma; @@ -940,7 +940,7 @@ static void guc_create_ads(struct intel_guc *guc) /* GuC scheduling policies */ policies = (void *)ads + sizeof(struct guc_ads); - init_guc_policies(policies); + guc_policies_init(policies); ads->scheduler_policies = i915_ggtt_offset(vma) + sizeof(struct guc_ads); @@ -971,9 +971,11 @@ static void guc_create_ads(struct intel_guc *guc) */ int i915_guc_submission_init(struct drm_i915_private *dev_priv) { + const size_t ctxsize = sizeof(struct guc_context_desc); + const size_t poolsize = GUC_MAX_GPU_CONTEXTS * ctxsize; + const size_t gemsize = round_up(poolsize, PAGE_SIZE); struct intel_guc *guc = &dev_priv->guc; struct i915_vma *vma; - u32 size; /* Wipe bitmap & delete client in case of reinitialisation */ bitmap_clear(guc->doorbell_bitmap, 0, GUC_MAX_DOORBELLS); @@ -985,15 +987,14 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv) if (guc->ctx_pool_vma) return 0; /* already allocated */ - size = PAGE_ALIGN(GUC_MAX_GPU_CONTEXTS*sizeof(struct guc_context_desc)); - vma = guc_allocate_vma(guc, size); + vma = guc_allocate_vma(guc, gemsize); if (IS_ERR(vma)) return PTR_ERR(vma); guc->ctx_pool_vma = vma; ida_init(&guc->ctx_ids); - guc_create_log(guc); - guc_create_ads(guc); + guc_log_create(guc); + guc_addon_create(guc); return 0; } diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 467845967e0b..b1ba86958811 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -159,7 +159,7 @@ extern int intel_guc_resume(struct drm_device *dev); /* i915_guc_submission.c */ int i915_guc_submission_init(struct drm_i915_private *dev_priv); int i915_guc_submission_enable(struct drm_i915_private *dev_priv); -int i915_guc_wq_check_space(struct drm_i915_gem_request *rq); +int i915_guc_wq_reserve(struct drm_i915_gem_request *rq); void i915_guc_submission_disable(struct drm_i915_private *dev_priv); void i915_guc_submission_fini(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 16d7cdd11082..251143361f31 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -627,7 +627,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request * going any further, as the i915_add_request() call * later on mustn't fail ... */ - ret = i915_guc_wq_check_space(request); + ret = i915_guc_wq_reserve(request); if (ret) return ret; } -- cgit v1.2.1 From 6f3fff602e8179c74249a66046cf88767e1923b2 Mon Sep 17 00:00:00 2001 From: Deepak M Date: Thu, 15 Sep 2016 15:01:10 +0530 Subject: drm/i915: Add ddb size field to device info structure Adding the ddb size into the devide info will avoid platform checks while computing wm. v2: Added comment and WARN_ON if ddb size is zero.(Jani) v3: Added WARN_ON at the right place.(Jani) Suggested-by: Ander Conselvan de Oliveira Signed-off-by: Deepak M Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473931870-7724-1-git-send-email-m.deepak@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_pci.c | 5 +++++ drivers/gpu/drm/i915/intel_pm.c | 13 ++----------- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d01a50e8e57c..a4bf10407cba 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -710,6 +710,7 @@ struct intel_device_info { u8 ring_mask; /* Rings supported by the HW */ u8 num_rings; DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON); + u16 ddb_size; /* in blocks */ /* Register offsets for the various display pipes and transcoders */ int pipe_offsets[I915_MAX_TRANSCODERS]; int trans_offsets[I915_MAX_TRANSCODERS]; diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index d771870ddd2b..687c768833b3 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -328,6 +328,7 @@ static const struct intel_device_info intel_skylake_info = { .gen = 9, .has_csr = 1, .has_guc = 1, + .ddb_size = 896, }; static const struct intel_device_info intel_skylake_gt3_info = { @@ -336,6 +337,7 @@ static const struct intel_device_info intel_skylake_gt3_info = { .gen = 9, .has_csr = 1, .has_guc = 1, + .ddb_size = 896, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; @@ -358,6 +360,7 @@ static const struct intel_device_info intel_broxton_info = { .has_hw_contexts = 1, .has_logical_ring_contexts = 1, .has_guc = 1, + .ddb_size = 512, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, BDW_COLORS, @@ -369,6 +372,7 @@ static const struct intel_device_info intel_kabylake_info = { .gen = 9, .has_csr = 1, .has_guc = 1, + .ddb_size = 896, }; static const struct intel_device_info intel_kabylake_gt3_info = { @@ -377,6 +381,7 @@ static const struct intel_device_info intel_kabylake_gt3_info = { .gen = 9, .has_csr = 1, .has_guc = 1, + .ddb_size = 896, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6af438ffef9a..2df06b703e3d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2853,13 +2853,6 @@ bool ilk_disable_lp_wm(struct drm_device *dev) return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL); } -/* - * On gen9, we need to allocate Display Data Buffer (DDB) portions to the - * different active planes. - */ - -#define SKL_DDB_SIZE 896 /* in blocks */ -#define BXT_DDB_SIZE 512 #define SKL_SAGV_BLOCK_TIME 30 /* µs */ /* @@ -3057,10 +3050,8 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, else *num_active = hweight32(dev_priv->active_crtcs); - if (IS_BROXTON(dev)) - ddb_size = BXT_DDB_SIZE; - else - ddb_size = SKL_DDB_SIZE; + ddb_size = INTEL_INFO(dev_priv)->ddb_size; + WARN_ON(ddb_size == 0); ddb_size -= 4; /* 4 blocks for bypass path allocation */ -- cgit v1.2.1 From 1c29bd3d6011bed4cbae215571f6f4c25ab10012 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:49 +0300 Subject: drm: Helper to read max clock rate Helper routine to read out maximum supported pixel rate for DisplayPort legay VGA converter or TMDS clock rate for other digital legacy converters. The helper returns clock rate in kHz. v2: Return early if detailed port cap info is not available. Replace if-else ladder with switch-case (Ville) Reviewed-by: Jim Bride Signed-off-by: Mika Kahola Acked-by: Dave Airlie Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-4-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 5d20255f3db3..f171fbf8b1b9 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -438,6 +438,39 @@ int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link) } EXPORT_SYMBOL(drm_dp_link_configure); +/** + * drm_dp_downstream_max_clock() - extract branch device max + * pixel rate for legacy VGA + * converter or max TMDS clock + * rate for others + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + * Returns max clock in kHz on success or 0 if max clock not defined + */ +int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) +{ + int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; + bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DETAILED_CAP_INFO_AVAILABLE; + + if (!detailed_cap_info) + return 0; + + switch (type) { + case DP_DS_PORT_TYPE_VGA: + return port_cap[1] * 8 * 1000; + case DP_DS_PORT_TYPE_DVI: + case DP_DS_PORT_TYPE_HDMI: + case DP_DS_PORT_TYPE_DP_DUALMODE: + return port_cap[1] * 2500; + default: + return 0; + } +} +EXPORT_SYMBOL(drm_dp_downstream_max_clock); + /* * I2C-over-AUX implementation */ -- cgit v1.2.1 From 7529d6af1cd16b0ecd286a1bf6ceee5328ab9809 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:50 +0300 Subject: drm: Helper to read max bits per component Helper routine to read out maximum supported bits per component for DisplayPort legay converters. v2: Return early if detailed port cap info is not available. Replace if-else ladder with switch-case (Ville) Reviewed-by: Jim Bride Signed-off-by: Mika Kahola Acked-by: Dave Airlie Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-5-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index f171fbf8b1b9..57c61d126a56 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -471,6 +471,48 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], } EXPORT_SYMBOL(drm_dp_downstream_max_clock); +/** + * drm_dp_downstream_max_bpc() - extract branch device max + * bits per component + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + * Returns max bpc on success or 0 if max bpc not defined + */ +int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) +{ + int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; + bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DETAILED_CAP_INFO_AVAILABLE; + int bpc; + + if (!detailed_cap_info) + return 0; + + switch (type) { + case DP_DS_PORT_TYPE_VGA: + case DP_DS_PORT_TYPE_DVI: + case DP_DS_PORT_TYPE_HDMI: + case DP_DS_PORT_TYPE_DP_DUALMODE: + bpc = port_cap[2] & DP_DS_MAX_BPC_MASK; + + switch (bpc) { + case DP_DS_8BPC: + return 8; + case DP_DS_10BPC: + return 10; + case DP_DS_12BPC: + return 12; + case DP_DS_16BPC: + return 16; + } + default: + return 0; + } +} +EXPORT_SYMBOL(drm_dp_downstream_max_bpc); + /* * I2C-over-AUX implementation */ -- cgit v1.2.1 From 266d783baaf5f34a5bea3b56489f091451a89767 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:51 +0300 Subject: drm: Read DP branch device id Read DisplayPort branch device id string. Reviewed-by: Jim Bride Signed-off-by: Mika Kahola Acked-by: Dave Airlie Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-6-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 57c61d126a56..7b3a638725d9 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -513,6 +513,18 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], } EXPORT_SYMBOL(drm_dp_downstream_max_bpc); +/** + * drm_dp_downstream_id() - identify branch device + * @aux: DisplayPort AUX channel + * + * Returns branch device id on success or NULL on failure + */ +int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]) +{ + return drm_dp_dpcd_read(aux, DP_BRANCH_ID, id, 6); +} +EXPORT_SYMBOL(drm_dp_downstream_id); + /* * I2C-over-AUX implementation */ -- cgit v1.2.1 From b633958587ddd47fd9fe3d0d34d51f769b51d77b Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:52 +0300 Subject: drm/i915: Cleanup DisplayPort AUX channel initialization Let's remove reference to "struct intel_connector *connector" in intel_dp_aux_init() function as it is no longer required. Reviewed-by: Jim Bride Signed-off-by: Mika Kahola Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-7-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 75ac62fa6bf5..c69ad13aab42 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1243,7 +1243,7 @@ intel_dp_aux_fini(struct intel_dp *intel_dp) } static void -intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) +intel_dp_aux_init(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; @@ -5624,7 +5624,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, connector->interlace_allowed = true; connector->doublescan_allowed = 0; - intel_dp_aux_init(intel_dp, intel_connector); + intel_dp_aux_init(intel_dp); INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work); -- cgit v1.2.1 From 0e390a33a668f97ea3ffa7c6ceb4266e1b39450a Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:53 +0300 Subject: drm/i915: Read DP branch device HW revision HW revision is mandatory field for DisplayPort branch devices. This is defined in DPCD register field 0x509. v2: move drm_dp_ds_revision structure to be part of drm_dp_link structure (Daniel) v3: remove dependency to drm_dp_helper but instead parse DPCD and print HW revision info to dmesg (Ville) Reviewed-by: Jim Bride Signed-off-by: Mika Kahola Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-8-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c69ad13aab42..bb0417c52154 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1419,6 +1419,25 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) DRM_DEBUG_KMS("common rates: %s\n", str); } +static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) +{ + uint8_t rev; + int len; + + if ((drm_debug & DRM_UT_KMS) == 0) + return; + + if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_PRESENT)) + return; + + len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_HW_REV, &rev, 1); + if (len < 0) + return; + + DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf); +} + static int rate_to_index(int find, const int *rates) { int i = 0; @@ -4312,6 +4331,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp_probe_oui(intel_dp); + intel_dp_print_hw_revision(intel_dp); + intel_dp_configure_mst(intel_dp); if (intel_dp->is_mst) { -- cgit v1.2.1 From 1a2724fa94b6308dee87f7851be7ec84a409a538 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:54 +0300 Subject: drm/i915: Read DP branch device SW revision SW revision is mandatory field for DisplayPort branch devices. This is defined in DPCD register fields 0x50A and 0x50B. v2: move drm_dp_ds_revision structure to be part of drm_dp_link structure (Daniel) v3: remove dependency to drm_dp_helper but instead parse DPCD and print SW revision info to dmesg (Ville) v4: commit message fix (Jim Bride) Signed-off-by: Mika Kahola Reviewed-by: Jim Bride Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-9-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bb0417c52154..7428c729ed4e 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1438,6 +1438,25 @@ static void intel_dp_print_hw_revision(struct intel_dp *intel_dp) DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf); } +static void intel_dp_print_sw_revision(struct intel_dp *intel_dp) +{ + uint8_t rev[2]; + int len; + + if ((drm_debug & DRM_UT_KMS) == 0) + return; + + if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_PRESENT)) + return; + + len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV, &rev, 2); + if (len < 0) + return; + + DRM_DEBUG_KMS("sink sw revision: %d.%d\n", rev[0], rev[1]); +} + static int rate_to_index(int find, const int *rates) { int i = 0; @@ -4332,6 +4351,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp_probe_oui(intel_dp); intel_dp_print_hw_revision(intel_dp); + intel_dp_print_sw_revision(intel_dp); intel_dp_configure_mst(intel_dp); -- cgit v1.2.1 From 70ec064516cc45525f7072f9e57ff780e987f0cd Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:55 +0300 Subject: drm/i915: Check pixel rate for DP to VGA dongle Filter out a mode that exceeds the max pixel rate setting for DP to VGA dongle. This is defined in DPCD register 0x81 if detailed cap info i.e. info field is 4 bytes long and it is available for DP downstream port. The register defines the pixel rate divided by 8 in MP/s. v2: DPCD read outs and computation moved to drm (Ville, Daniel) v3: Sink pixel rate computation moved to drm_dp_max_sink_dotclock() function (Daniel) v4: Use of drm_dp_helper.c routines to compute max pixel clock (Ville) v5: Use of intel_dp->downstream_ports to read out port capabilities. Code restructuring (Ville) v6: Move DP branch device check to drm_dp_helper.c (Daniel) v7: Cleanup as suggested by Ville Reviewed-by: Jim Bride Signed-off-by: Mika Kahola Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-10-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7428c729ed4e..8f17c882929b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -190,6 +190,29 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return (max_link_clock * max_lanes * 8) / 10; } +static int +intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &intel_dig_port->base; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + int max_dotclk = dev_priv->max_dotclk_freq; + int ds_max_dotclk; + + int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK; + + if (type != DP_DS_PORT_TYPE_VGA) + return max_dotclk; + + ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd, + intel_dp->downstream_ports); + + if (ds_max_dotclk != 0) + max_dotclk = min(max_dotclk, ds_max_dotclk); + + return max_dotclk; +} + static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) @@ -199,7 +222,9 @@ intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; int target_clock = mode->clock; int max_rate, mode_rate, max_lanes, max_link_clock; - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + int max_dotclk; + + max_dotclk = intel_dp_downstream_max_dotclock(intel_dp); if (is_edp(intel_dp) && fixed_mode) { if (mode->hdisplay > fixed_mode->hdisplay) -- cgit v1.2.1 From f9bb705e65f64710971e50624db5ef1857d9db39 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:56 +0300 Subject: drm/i915: Update bits per component for display info DisplayPort branch device may define max supported bits per component. Update display info based on this value if bpc is defined. v2: cleanup to match the drm_dp_helper.c patches introduced earlier in this series v3: Fill bpc for connector's display info in separate drm_dp_helper function (Daniel) v4: remove updating bpc for display info as it may be overridden when parsing EDID. Instead, check bpc for DP branch device during compute_config v5: Indentation fixes (Jim Bride) Signed-off-by: Mika Kahola Reviewed-by: Jim Bride Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-11-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8f17c882929b..69cee9b0a08d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1524,6 +1524,20 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, } } +int intel_dp_compute_bpp(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config) +{ + int bpp, bpc; + + bpp = pipe_config->pipe_bpp; + bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, intel_dp->downstream_ports); + + if (bpc > 0) + bpp = min(bpp, 3*bpc); + + return bpp; +} + bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -1590,7 +1604,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, /* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */ - bpp = pipe_config->pipe_bpp; + bpp = intel_dp_compute_bpp(intel_dp, pipe_config); if (is_edp(intel_dp)) { /* Get bpp from vbt only for panels that dont have bpp in edid */ -- cgit v1.2.1 From 80209e5f2c42c491ec5f4a63705b4377b407587c Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 9 Sep 2016 14:10:57 +0300 Subject: drm: Add DP branch device info on debugfs Read DisplayPort branch device info from through debugfs interface. v2: use drm_dp_helper routines to collect data v3: cleanup to match the drm_dp_helper.c patches introduced earlier in this series v4: move DP branch device info to function 'intel_dp_branch_device_info()' v5: initial step to move debugging info from intel_dp. to drm_dp_helper.c (Daniel) v6: read hw and sw revision without using specific drm_dp_helper routines v7: indentation fixes (Jim Bride) Signed-off-by: Mika Kahola Reviewed-by: Jim Bride Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473419458-17080-12-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 85 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_debugfs.c | 3 ++ 2 files changed, 88 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 7b3a638725d9..e26936309e07 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -525,6 +525,91 @@ int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]) } EXPORT_SYMBOL(drm_dp_downstream_id); +/** + * drm_dp_downstream_debug() - debug DP branch devices + * @m: pointer for debugfs file + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * @aux: DisplayPort AUX channel + * + */ +void drm_dp_downstream_debug(struct seq_file *m, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], struct drm_dp_aux *aux) +{ + bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DETAILED_CAP_INFO_AVAILABLE; + int clk; + int bpc; + char id[6]; + int len; + uint8_t rev[2]; + int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; + bool branch_device = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_PRESENT; + + seq_printf(m, "\tDP branch device present: %s\n", + branch_device ? "yes" : "no"); + + if (!branch_device) + return; + + switch (type) { + case DP_DS_PORT_TYPE_DP: + seq_puts(m, "\t\tType: DisplayPort\n"); + break; + case DP_DS_PORT_TYPE_VGA: + seq_puts(m, "\t\tType: VGA\n"); + break; + case DP_DS_PORT_TYPE_DVI: + seq_puts(m, "\t\tType: DVI\n"); + break; + case DP_DS_PORT_TYPE_HDMI: + seq_puts(m, "\t\tType: HDMI\n"); + break; + case DP_DS_PORT_TYPE_NON_EDID: + seq_puts(m, "\t\tType: others without EDID support\n"); + break; + case DP_DS_PORT_TYPE_DP_DUALMODE: + seq_puts(m, "\t\tType: DP++\n"); + break; + case DP_DS_PORT_TYPE_WIRELESS: + seq_puts(m, "\t\tType: Wireless\n"); + break; + default: + seq_puts(m, "\t\tType: N/A\n"); + } + + drm_dp_downstream_id(aux, id); + seq_printf(m, "\t\tID: %s\n", id); + + len = drm_dp_dpcd_read(aux, DP_BRANCH_HW_REV, &rev[0], 1); + if (len > 0) + seq_printf(m, "\t\tHW: %d.%d\n", + (rev[0] & 0xf0) >> 4, rev[0] & 0xf); + + len = drm_dp_dpcd_read(aux, DP_BRANCH_SW_REV, &rev, 2); + if (len > 0) + seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]); + + if (detailed_cap_info) { + clk = drm_dp_downstream_max_clock(dpcd, port_cap); + + if (clk > 0) { + if (type == DP_DS_PORT_TYPE_VGA) + seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk); + else + seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk); + } + + bpc = drm_dp_downstream_max_bpc(dpcd, port_cap); + + if (bpc > 0) + seq_printf(m, "\t\tMax bpc: %d\n", bpc); + } +} +EXPORT_SYMBOL(drm_dp_downstream_debug); + /* * I2C-over-AUX implementation */ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6a270bc0fdb3..a6d174ac6652 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2860,6 +2860,9 @@ static void intel_dp_info(struct seq_file *m, seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio)); if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) intel_panel_info(m, &intel_connector->panel); + + drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports, + &intel_dp->aux); } static void intel_hdmi_info(struct seq_file *m, -- cgit v1.2.1 From f580bea97df4c0297ce64473b42645ed4612900d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 15 Sep 2016 16:28:52 +0300 Subject: drm/i915: make intel_dp_compute_bpp static Fix sparse warning: drivers/gpu/drm/i915/intel_dp.c:1527:5: warning: symbol 'intel_dp_compute_bpp' was not declared. Should it be static? Fixes: f9bb705e65f6 ("drm/i915: Update bits per component for display info") Cc: Mika Kahola Cc: Jim Bride Reviewed-by: Jim Bride Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473946137-1931-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 69cee9b0a08d..acd0c51f74d5 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1524,8 +1524,8 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, } } -int intel_dp_compute_bpp(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config) +static int intel_dp_compute_bpp(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config) { int bpp, bpc; -- cgit v1.2.1 From bcbfcc37cdd4fd7564a6657d5d6bd4719079900b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 15 Sep 2016 16:28:53 +0300 Subject: drm/i915: do not use 'false' as a NULL pointer Fixes sparse warning: drivers/gpu/drm/i915/intel_dpll_mgr.c:1712:24: warning: Using plain integer as NULL pointer Fixes: a277ca7dc01d ("drm/i915: Split bxt_ddi_pll_select()") Cc: Manasi Navare Cc: Ander Conselvan de Oliveira Cc: Durgadoss R Cc: Rodrigo Vivi Reviewed-by: Dhinakaran Pandiyan Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473946137-1931-2-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dpll_mgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 4b067accd5cd..c26d18a574b6 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1709,12 +1709,12 @@ bxt_get_dpll(struct intel_crtc *crtc, if (encoder->type == INTEL_OUTPUT_HDMI && !bxt_ddi_hdmi_pll_dividers(crtc, crtc_state, clock, &clk_div)) - return false; + return NULL; if ((encoder->type == INTEL_OUTPUT_DP || encoder->type == INTEL_OUTPUT_EDP) && !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state)) - return false; + return NULL; memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); -- cgit v1.2.1 From 911f4869eb334cb397c9c40c4b8893fcd93880ed Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 15 Sep 2016 16:28:55 +0300 Subject: drm/i915: use NULL for NULL pointers Fix sparse warning: drivers/gpu/drm/i915/i915_cmd_parser.c:987:72: warning: Using plain integer as NULL pointer Fixes: 52a42cec4b70 ("drm/i915/cmdparser: Accelerate copies from WC memory") Cc: Chris Wilson Reviewed-by: Dhinakaran Pandiyan Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1473946137-1931-4-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_cmd_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 3c72b3b103e7..70980f82a15b 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -984,7 +984,7 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, src = ERR_PTR(-ENODEV); if (src_needs_clflush && - i915_memcpy_from_wc((void *)(uintptr_t)batch_start_offset, 0, 0)) { + i915_memcpy_from_wc((void *)(uintptr_t)batch_start_offset, NULL, 0)) { src = i915_gem_object_pin_map(src_obj, I915_MAP_WC); if (!IS_ERR(src)) { i915_memcpy_from_wc(dst, -- cgit v1.2.1 From 3442d9eee459bb565c37a15eed57572b511e9c64 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Fri, 16 Sep 2016 13:39:15 +0300 Subject: drm: Fix DisplayPort branch device ID kernel-doc Fix missing parameter description for DisplayPort branch device ID. This fixes warning of "No description found for parameter 'id[6]'" when creating documentation by 'make htmldocs'. Reported-by: kbuild test robot References: https://lists.freedesktop.org/archives/intel-gfx/2016-September/106645.html Fixes: 266d783baaf5 ("drm: Read DP branch device id") Signed-off-by: Mika Kahola Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1474022355-29990-1-git-send-email-mika.kahola@intel.com --- drivers/gpu/drm/drm_dp_helper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index e26936309e07..559db96c2f8c 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -516,6 +516,7 @@ EXPORT_SYMBOL(drm_dp_downstream_max_bpc); /** * drm_dp_downstream_id() - identify branch device * @aux: DisplayPort AUX channel + * @id: DisplayPort branch device id * * Returns branch device id on success or NULL on failure */ -- cgit v1.2.1 From 6e05f3d3b9298a56d6f1acb474a75cf14a17c31e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 19 Sep 2016 09:26:08 +0200 Subject: drm/i915: Update DRIVER_DATE to 20160919 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a4bf10407cba..4dd307ed4336 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -70,7 +70,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20160902" +#define DRIVER_DATE "20160919" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v1.2.1