From f7d3c970f43a599c7545bfa821761cdb1bef8e23 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:24 +0300 Subject: drm/i915/dsi: don't debug log "missing" sequences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not interesting. They are not "missing", they are just not part of the VBT sequences for the panel. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/54909b29802398d23f1d26f6589671e69688f904.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index cd154ce6b6c1..a537c71cdcc6 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -385,11 +385,8 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) return; data = dev_priv->vbt.dsi.sequence[seq_id]; - if (!data) { - DRM_DEBUG_KMS("MIPI sequence %d - %s not available\n", - seq_id, sequence_name(seq_id)); + if (!data) return; - } WARN_ON(*data != seq_id); -- cgit v1.2.3 From 0b9407c39864b878543c61b719e9ba5a7bfeb0c6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:25 +0300 Subject: drm/i915/dsi: add debug logging to element execution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just simple breadcrumbs for now. While at it, rename the i2c skip function. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/d11c40a99f5ef2419ede87a2ac1858e4c60768b8.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index a537c71cdcc6..89f77a142521 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -126,6 +126,8 @@ static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, u16 len; enum port port; + DRM_DEBUG_KMS("\n"); + flags = *data++; type = *data++; @@ -199,6 +201,8 @@ static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data) { u32 delay = *((const u32 *) data); + DRM_DEBUG_KMS("\n"); + usleep_range(delay, delay + 10); data += 4; @@ -307,6 +311,8 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) u8 gpio_source, gpio_index; bool value; + DRM_DEBUG_KMS("\n"); + if (dev_priv->vbt.dsi.seq_version >= 3) data++; @@ -331,8 +337,10 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) return data; } -static const u8 *mipi_exec_i2c_skip(struct intel_dsi *intel_dsi, const u8 *data) +static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data) { + DRM_DEBUG_KMS("Skipping I2C element execution\n"); + return data + *(data + 6) + 7; } @@ -342,7 +350,7 @@ static const fn_mipi_elem_exec exec_elem[] = { [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet, [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, - [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c_skip, + [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c, }; /* -- cgit v1.2.3 From 044aad65ee02abe2c51e06052df03a5c3f573f78 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:26 +0300 Subject: drm/i915/dsi: add skip functions for spi and pmic elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In sequence block v3 these are gracefully skipped anyway, but add the functions so we can have some debug breadcrumbs. v2: the pmic block is 15 bytes (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/d102ef1f21e6ea9a17655ef31593e68343336a48.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 89f77a142521..29156995a265 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -344,6 +344,20 @@ static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data) return data + *(data + 6) + 7; } +static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data) +{ + DRM_DEBUG_KMS("Skipping SPI element execution\n"); + + return data + *(data + 5) + 6; +} + +static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data) +{ + DRM_DEBUG_KMS("Skipping PMIC element execution\n"); + + return data + 15; +} + typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, const u8 *data); static const fn_mipi_elem_exec exec_elem[] = { @@ -351,6 +365,8 @@ static const fn_mipi_elem_exec exec_elem[] = { [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c, + [MIPI_SEQ_ELEM_SPI] = mipi_exec_spi, + [MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic, }; /* -- cgit v1.2.3 From b1cb1bd29189a017bf2aab879ba7fe22b62c3abe Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:27 +0300 Subject: drm/i915/dsi: update reset and power sequences in panel prepare/unprepare hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the documentation alone, it's anyone's guess when exactly we should be running these sequences. Add power on/off sequences where they feel logical and update assert/deassert reset. The drm panel hooks don't currently offer us more granularity anyway. v2: update assert/deassert reset as well (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1543320494df953fa073e136248238eaa1eed059.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 29156995a265..2c5d14eb7851 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -459,6 +459,8 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) static int vbt_panel_prepare(struct drm_panel *panel) { generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET); + generic_exec_sequence(panel, MIPI_SEQ_POWER_ON); + generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET); generic_exec_sequence(panel, MIPI_SEQ_INIT_OTP); return 0; @@ -466,7 +468,8 @@ static int vbt_panel_prepare(struct drm_panel *panel) static int vbt_panel_unprepare(struct drm_panel *panel) { - generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET); + generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET); + generic_exec_sequence(panel, MIPI_SEQ_POWER_OFF); return 0; } -- cgit v1.2.3 From 416062d017e20e5493f4e764658b104287ce6c4c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:28 +0300 Subject: drm/i915/dsi: run backlight on/off sequences in panel enable/disable hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the documentation alone, it's anyone's guess when exactly we should be running these sequences. Add them where it feels logical. The drm panel hooks don't currently offer us more granularity anyway. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/267c4a2bde2076af18e9b8335c0bef2e26ea3112.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 2c5d14eb7851..24953f9f7e1d 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -477,12 +477,14 @@ static int vbt_panel_unprepare(struct drm_panel *panel) static int vbt_panel_enable(struct drm_panel *panel) { generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_ON); + generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_ON); return 0; } static int vbt_panel_disable(struct drm_panel *panel) { + generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_OFF); generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_OFF); return 0; -- cgit v1.2.3 From 4b4f497e13f0195dd305d0b1dea06291e1e6f521 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:29 +0300 Subject: drm/i915/bios: log about presence of DSI sequences we do not run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Leave behind some debugging clues in case some panels don't work properly. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/b36302b24676af511f4bbf702be21cc7e8f987c2.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_bios.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index c6e69e4cfa83..83667e8cdd6b 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -996,6 +996,10 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, goto err; } + /* Log about presence of sequences we won't run. */ + if (seq_id == MIPI_SEQ_TEAR_ON || seq_id == MIPI_SEQ_TEAR_OFF) + DRM_DEBUG_KMS("Unsupported sequence %u\n", seq_id); + dev_priv->vbt.dsi.sequence[seq_id] = data + index; if (sequence->version >= 3) -- cgit v1.2.3 From 8e4f768c434e3c197a1b6d59c8e6d0807b10c4cd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 15:02:30 +0300 Subject: drm/i915/dsi: double check element parsing against size if present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be a little paranoid in case the specs change or something. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/27050d48d0ff3d58e79fcacc41ced4c071b01424.1474286487.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 24953f9f7e1d..9f279a3d0f74 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -441,7 +441,15 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) operation_size = *data++; if (mipi_elem_exec) { + const u8 *next = data + operation_size; + data = mipi_elem_exec(intel_dsi, data); + + /* Consistency check if we have size. */ + if (operation_size && data != next) { + DRM_ERROR("Inconsistent operation size\n"); + return; + } } else if (operation_size) { /* We have size, skip. */ DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n", -- cgit v1.2.3 From 32b421e79e6b546da1d469f1229403ac9142d695 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 19 Sep 2016 13:35:25 +0300 Subject: drm/i915/backlight: setup and cache pwm alternate increment value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will also be needed later on when setting up the alternate increment in backlight enable. Cc: Shawn Lee Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/9984b20bc59aee90b83caf59ce91f3fb122c9627.1474281249.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 810c89eb6863..1b451e759976 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -263,6 +263,7 @@ struct intel_panel { bool enabled; bool combination_mode; /* gen 2/4 only */ bool active_low_pwm; + bool alternate_pwm_increment; /* lpt+ */ /* PWM chip */ bool util_pin_active_low; /* bxt+ */ diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index c10e9b0405e8..8bc43205d6a0 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1242,10 +1242,10 @@ static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_panel *panel = &connector->panel; u32 mul; - if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY) + if (panel->backlight.alternate_pwm_increment) mul = 128; else mul = 16; @@ -1261,9 +1261,10 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_panel *panel = &connector->panel; u32 mul, clock; - if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY) + if (panel->backlight.alternate_pwm_increment) mul = 16; else mul = 128; @@ -1414,6 +1415,13 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; u32 pch_ctl1, pch_ctl2, val; + bool alt; + + if (HAS_PCH_LPT(dev_priv)) + alt = I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; + else + alt = I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; + panel->backlight.alternate_pwm_increment = alt; pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; -- cgit v1.2.3 From e29aff05f239f8dd24e9ee7816fd96726e20105a Mon Sep 17 00:00:00 2001 From: Shawn Lee Date: Mon, 19 Sep 2016 13:35:26 +0300 Subject: drm/i915/backlight: setup backlight pwm alternate increment on backlight enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backlight enable is supposed to do a full setup of the backlight. We were missing the PWM alternate increment bit in the south chicken registers on lpt+ pch. This potentially caused a PWM frequency change when the chicken register value was lost e.g. on suspend. v2 by Jani, rebase on the patch caching alt increment Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97486 References: https://bugs.freedesktop.org/show_bug.cgi?id=67454 Cc: Cooper Chiou Cc: Wei Shun Chen Cc: Gary C Wang Cc: stable@vger.kernel.org # v4.4+ 32b421e79e6b drm/i915/backlight: setup and cache... Cc: stable@vger.kernel.org # v4.4+ Reviewed-by: Ville Syrjälä Signed-off-by: Shawn Lee Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/8265f5935bd31c039ddfc82819d26c2ca1ae9cba.1474281249.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_panel.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 8bc43205d6a0..be4b4d546fd9 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -841,7 +841,7 @@ static void lpt_enable_backlight(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_panel *panel = &connector->panel; - u32 pch_ctl1, pch_ctl2; + u32 pch_ctl1, pch_ctl2, schicken; pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { @@ -850,6 +850,22 @@ static void lpt_enable_backlight(struct intel_connector *connector) I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); } + if (HAS_PCH_LPT(dev_priv)) { + schicken = I915_READ(SOUTH_CHICKEN2); + if (panel->backlight.alternate_pwm_increment) + schicken |= LPT_PWM_GRANULARITY; + else + schicken &= ~LPT_PWM_GRANULARITY; + I915_WRITE(SOUTH_CHICKEN2, schicken); + } else { + schicken = I915_READ(SOUTH_CHICKEN1); + if (panel->backlight.alternate_pwm_increment) + schicken |= SPT_PWM_GRANULARITY; + else + schicken &= ~SPT_PWM_GRANULARITY; + I915_WRITE(SOUTH_CHICKEN1, schicken); + } + pch_ctl2 = panel->backlight.max << 16; I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); -- cgit v1.2.3 From 51f592050a523fc5882f9b8b4e9259422e41e848 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 14 Sep 2016 13:04:13 +0300 Subject: drm/i915: Unlock PPS registers after GPU reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reapply the PPS register unlock workaround after GPU reset on platforms where the reset clobbers the display HW state. This at least gets rid of the related WARN during LVDS encoder enabling on PNV. Fixes: ed6143b8f75 ("drm/i915/lvds: Restore initial HW state during encoder enabling") Reported-by: Ville Syrjälä Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1473847453-4771-1-git-send-email-imre.deak@intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 69b80d078f06..18fdbb7f6c28 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3627,6 +3627,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) intel_runtime_pm_disable_interrupts(dev_priv); intel_runtime_pm_enable_interrupts(dev_priv); + intel_pps_unlock_regs_wa(dev_priv); intel_modeset_init_hw(dev); spin_lock_irq(&dev_priv->irq_lock); -- cgit v1.2.3 From d636951ec01bcb2b7dee02f75ff4815714785a53 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 20 Sep 2016 16:54:32 +0300 Subject: drm/i915: Cleanup instdone collection Consolidate the instdone logic so we can get a bit fancier. This patch also removes the duplicated print of INSTDONE[0]. v2: (Imre) - Rebased on top of hangcheck INSTDONE changes. - Move all INSTDONE registers into a single struct, store it within the engine error struct during error capturing. Signed-off-by: Ben Widawsky Signed-off-by: Imre Deak Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1474379673-28326-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 41 +++++++++++----- drivers/gpu/drm/i915/i915_drv.h | 8 ++-- drivers/gpu/drm/i915/i915_gpu_error.c | 84 +++++++++++++++++++++++---------- drivers/gpu/drm/i915/i915_irq.c | 69 ++++++++++++++++++--------- drivers/gpu/drm/i915/i915_reg.h | 1 - drivers/gpu/drm/i915/intel_ringbuffer.h | 10 +++- 6 files changed, 151 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a6d174ac6652..ba155c038d0e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1277,15 +1277,36 @@ out: return ret; } +static void i915_instdone_info(struct drm_i915_private *dev_priv, + struct seq_file *m, + struct intel_instdone *instdone) +{ + seq_printf(m, "\t\tINSTDONE: 0x%08x\n", + instdone->instdone); + + if (INTEL_GEN(dev_priv) <= 3) + return; + + seq_printf(m, "\t\tSC_INSTDONE: 0x%08x\n", + instdone->slice_common); + + if (INTEL_GEN(dev_priv) <= 6) + return; + + seq_printf(m, "\t\tSAMPLER_INSTDONE: 0x%08x\n", + instdone->sampler); + seq_printf(m, "\t\tROW_INSTDONE: 0x%08x\n", + instdone->row); +} + static int i915_hangcheck_info(struct seq_file *m, void *unused) { 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]; - u32 instdone[I915_NUM_INSTDONE_REG]; + struct intel_instdone instdone; enum intel_engine_id id; - int j; if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) seq_printf(m, "Wedged\n"); @@ -1308,7 +1329,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seqno[id] = intel_engine_get_seqno(engine); } - i915_get_extra_instdone(dev_priv, instdone); + i915_get_engine_instdone(dev_priv, RCS, &instdone); intel_runtime_pm_put(dev_priv); @@ -1336,18 +1357,14 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seq_printf(m, "\taction = %d\n", engine->hangcheck.action); if (engine->id == RCS) { - seq_puts(m, "\tinstdone read ="); - - for (j = 0; j < I915_NUM_INSTDONE_REG; j++) - seq_printf(m, " 0x%08x", instdone[j]); + seq_puts(m, "\tinstdone read =\n"); - seq_puts(m, "\n\tinstdone accu ="); + i915_instdone_info(dev_priv, m, &instdone); - for (j = 0; j < I915_NUM_INSTDONE_REG; j++) - seq_printf(m, " 0x%08x", - engine->hangcheck.instdone[j]); + seq_puts(m, "\tinstdone accu =\n"); - seq_puts(m, "\n"); + i915_instdone_info(dev_priv, m, + &engine->hangcheck.instdone); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4dd307ed4336..356899543d4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -759,7 +759,7 @@ struct drm_i915_error_state { u32 gam_ecochk; u32 gab_ctl; u32 gfx_mode; - u32 extra_instdone[I915_NUM_INSTDONE_REG]; + u64 fence[I915_MAX_NUM_FENCES]; struct intel_overlay_error_state *overlay; struct intel_display_error_state *display; @@ -791,7 +791,6 @@ struct drm_i915_error_state { u32 hws; u32 ipeir; u32 ipehr; - u32 instdone; u32 bbstate; u32 instpm; u32 instps; @@ -802,6 +801,7 @@ struct drm_i915_error_state { u64 faddr; u32 rc_psmi; /* sleep state */ u32 semaphore_mboxes[I915_NUM_ENGINES - 1]; + struct intel_instdone instdone; struct drm_i915_error_object { int page_count; @@ -3542,7 +3542,9 @@ void i915_error_state_get(struct drm_device *dev, void i915_error_state_put(struct i915_error_state_file_priv *error_priv); void i915_destroy_error_state(struct drm_device *dev); -void i915_get_extra_instdone(struct drm_i915_private *dev_priv, uint32_t *instdone); +void i915_get_engine_instdone(struct drm_i915_private *dev_priv, + enum intel_engine_id engine_id, + struct intel_instdone *instdone); const char *i915_cache_level_str(struct drm_i915_private *i915, int type); /* i915_cmd_parser.c */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 334f15df7c8d..6a2775aad354 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -228,6 +228,27 @@ static const char *hangcheck_action_to_str(enum intel_engine_hangcheck_action a) return "unknown"; } +static void error_print_instdone(struct drm_i915_error_state_buf *m, + struct drm_i915_error_engine *ee) +{ + err_printf(m, " INSTDONE: 0x%08x\n", + ee->instdone.instdone); + + if (ee->engine_id != RCS || INTEL_GEN(m->i915) <= 3) + return; + + err_printf(m, " SC_INSTDONE: 0x%08x\n", + ee->instdone.slice_common); + + if (INTEL_GEN(m->i915) <= 6) + return; + + err_printf(m, " SAMPLER_INSTDONE: 0x%08x\n", + ee->instdone.sampler); + err_printf(m, " ROW_INSTDONE: 0x%08x\n", + ee->instdone.row); +} + static void error_print_engine(struct drm_i915_error_state_buf *m, struct drm_i915_error_engine *ee) { @@ -242,7 +263,9 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, (u32)(ee->acthd>>32), (u32)ee->acthd); err_printf(m, " IPEIR: 0x%08x\n", ee->ipeir); err_printf(m, " IPEHR: 0x%08x\n", ee->ipehr); - err_printf(m, " INSTDONE: 0x%08x\n", ee->instdone); + + error_print_instdone(m, ee); + if (ee->batchbuffer) { u64 start = ee->batchbuffer->gtt_offset; u64 end = start + ee->batchbuffer->gtt_size; @@ -402,10 +425,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, for (i = 0; i < dev_priv->num_fence_regs; i++) err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); - for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++) - err_printf(m, " INSTDONE_%d: 0x%08x\n", i, - error->extra_instdone[i]); - if (INTEL_INFO(dev)->gen >= 6) { err_printf(m, "ERROR: 0x%08x\n", error->error); @@ -855,7 +874,8 @@ static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv, if (engine_id) *engine_id = i; - return error->engine[i].ipehr ^ error->engine[i].instdone; + return error->engine[i].ipehr ^ + error->engine[i].instdone.instdone; } } @@ -998,7 +1018,6 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base)); ee->ipeir = I915_READ(RING_IPEIR(engine->mmio_base)); ee->ipehr = I915_READ(RING_IPEHR(engine->mmio_base)); - ee->instdone = I915_READ(RING_INSTDONE(engine->mmio_base)); ee->instps = I915_READ(RING_INSTPS(engine->mmio_base)); ee->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); if (INTEL_GEN(dev_priv) >= 8) { @@ -1010,9 +1029,10 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, ee->faddr = I915_READ(DMA_FADD_I8XX); ee->ipeir = I915_READ(IPEIR); ee->ipehr = I915_READ(IPEHR); - ee->instdone = I915_READ(GEN2_INSTDONE); } + i915_get_engine_instdone(dev_priv, engine->id, &ee->instdone); + ee->waiting = intel_engine_has_waiter(engine); ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); ee->acthd = intel_engine_get_active_head(engine); @@ -1372,8 +1392,6 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, } error->eir = I915_READ(EIR); error->pgtbl_er = I915_READ(PGTBL_ER); - - i915_get_extra_instdone(dev_priv, error->extra_instdone); } static void i915_error_capture_msg(struct drm_i915_private *dev_priv, @@ -1532,20 +1550,38 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type) } /* NB: please notice the memset */ -void i915_get_extra_instdone(struct drm_i915_private *dev_priv, - uint32_t *instdone) +void i915_get_engine_instdone(struct drm_i915_private *dev_priv, + enum intel_engine_id engine_id, + struct intel_instdone *instdone) { - memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG); - - if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv)) - instdone[0] = I915_READ(GEN2_INSTDONE); - else if (IS_GEN4(dev_priv) || IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) { - instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE)); - instdone[1] = I915_READ(GEN4_INSTDONE1); - } else if (INTEL_GEN(dev_priv) >= 7) { - instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE)); - instdone[1] = I915_READ(GEN7_SC_INSTDONE); - instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); - instdone[3] = I915_READ(GEN7_ROW_INSTDONE); + u32 mmio_base = dev_priv->engine[engine_id].mmio_base; + + memset(instdone, 0, sizeof(*instdone)); + + switch (INTEL_GEN(dev_priv)) { + default: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine_id != RCS) + break; + + instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); + instdone->sampler = I915_READ(GEN7_SAMPLER_INSTDONE); + instdone->row = I915_READ(GEN7_ROW_INSTDONE); + + break; + case 6: + case 5: + case 4: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine_id == RCS) + /* HACK: Using the wrong struct member */ + instdone->slice_common = I915_READ(GEN4_INSTDONE1); + break; + case 3: + case 2: + instdone->instdone = I915_READ(GEN2_INSTDONE); + break; } } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c128fdbd24e4..371647c4c53c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2545,18 +2545,36 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) wake_up_all(&dev_priv->gpu_error.reset_queue); } +static inline void +i915_err_print_instdone(struct drm_i915_private *dev_priv, + struct intel_instdone *instdone) +{ + pr_err(" INSTDONE: 0x%08x\n", instdone->instdone); + + if (INTEL_GEN(dev_priv) <= 3) + return; + + pr_err(" SC_INSTDONE: 0x%08x\n", instdone->slice_common); + + if (INTEL_GEN(dev_priv) <= 6) + return; + + pr_err(" SAMPLER_INSTDONE: 0x%08x\n", instdone->sampler); + pr_err(" ROW_INSTDONE: 0x%08x\n", instdone->row); +} + static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) { - uint32_t instdone[I915_NUM_INSTDONE_REG]; + struct intel_instdone instdone; u32 eir = I915_READ(EIR); - int pipe, i; + int pipe; if (!eir) return; pr_err("render error detected, EIR: 0x%08x\n", eir); - i915_get_extra_instdone(dev_priv, instdone); + i915_get_engine_instdone(dev_priv, RCS, &instdone); if (IS_G4X(dev_priv)) { if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) { @@ -2564,8 +2582,7 @@ static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965)); pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965)); - for (i = 0; i < ARRAY_SIZE(instdone); i++) - pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]); + i915_err_print_instdone(dev_priv, &instdone); pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS)); pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965)); I915_WRITE(IPEIR_I965, ipeir); @@ -2600,8 +2617,7 @@ static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) if (eir & I915_ERROR_INSTRUCTION) { pr_err("instruction error\n"); pr_err(" INSTPM: 0x%08x\n", I915_READ(INSTPM)); - for (i = 0; i < ARRAY_SIZE(instdone); i++) - pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]); + i915_err_print_instdone(dev_priv, &instdone); if (INTEL_GEN(dev_priv) < 4) { u32 ipeir = I915_READ(IPEIR); @@ -2948,31 +2964,42 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) engine->hangcheck.deadlock = 0; } +static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone) +{ + u32 tmp = current_instdone | *old_instdone; + bool unchanged; + + unchanged = tmp == *old_instdone; + *old_instdone |= tmp; + + return unchanged; +} + static bool subunits_stuck(struct intel_engine_cs *engine) { - u32 instdone[I915_NUM_INSTDONE_REG]; + struct drm_i915_private *dev_priv = engine->i915; + struct intel_instdone instdone; + struct intel_instdone *accu_instdone = &engine->hangcheck.instdone; bool stuck; - int i; if (engine->id != RCS) return true; - i915_get_extra_instdone(engine->i915, instdone); + i915_get_engine_instdone(dev_priv, RCS, &instdone); /* There might be unstable subunit states even when * actual head is not moving. Filter out the unstable ones by * accumulating the undone -> done transitions and only * consider those as progress. */ - stuck = true; - for (i = 0; i < I915_NUM_INSTDONE_REG; i++) { - const u32 tmp = instdone[i] | engine->hangcheck.instdone[i]; - - if (tmp != engine->hangcheck.instdone[i]) - stuck = false; - - engine->hangcheck.instdone[i] |= tmp; - } + stuck = instdone_unchanged(instdone.instdone, + &accu_instdone->instdone); + stuck &= instdone_unchanged(instdone.slice_common, + &accu_instdone->slice_common); + stuck &= instdone_unchanged(instdone.sampler, + &accu_instdone->sampler); + stuck &= instdone_unchanged(instdone.row, + &accu_instdone->row); return stuck; } @@ -2983,7 +3010,7 @@ head_stuck(struct intel_engine_cs *engine, u64 acthd) if (acthd != engine->hangcheck.acthd) { /* Clear subunit states on head movement */ - memset(engine->hangcheck.instdone, 0, + memset(&engine->hangcheck.instdone, 0, sizeof(engine->hangcheck.instdone)); return HANGCHECK_ACTIVE; @@ -3153,7 +3180,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) /* Clear head and subunit states on seqno movement */ acthd = 0; - memset(engine->hangcheck.instdone, 0, + memset(&engine->hangcheck.instdone, 0, sizeof(engine->hangcheck.instdone)); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 70d96162def6..41331455a111 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1708,7 +1708,6 @@ enum skl_disp_power_wells { #define GEN7_SC_INSTDONE _MMIO(0x7100) #define GEN7_SAMPLER_INSTDONE _MMIO(0xe160) #define GEN7_ROW_INSTDONE _MMIO(0xe164) -#define I915_NUM_INSTDONE_REG 4 #define RING_IPEIR(base) _MMIO((base)+0x64) #define RING_IPEHR(base) _MMIO((base)+0x68) /* diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 7f64d611159b..4ff47023e68d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -73,13 +73,21 @@ enum intel_engine_hangcheck_action { #define HANGCHECK_SCORE_RING_HUNG 31 +struct intel_instdone { + u32 instdone; + /* The following exist only in the RCS engine */ + u32 slice_common; + u32 sampler; + u32 row; +}; + struct intel_engine_hangcheck { u64 acthd; u32 seqno; int score; enum intel_engine_hangcheck_action action; int deadlock; - u32 instdone[I915_NUM_INSTDONE_REG]; + struct intel_instdone instdone; }; struct intel_ring { -- cgit v1.2.3 From f9e613728090e7fe4e755bf56df17cbc277bac3f Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 20 Sep 2016 16:54:33 +0300 Subject: drm/i915: Try to print INSTDONE bits for all slice/subslice v2: (Imre) - Access only subslices that are known to exist. - Reset explicitly the MCR selector to slice/sub-slice ID 0 after the readout. - Use the subslice INSTDONE bits for the hangcheck/subunits-stuck detection too. - Take the uncore lock for the MCR-select/subslice-readout sequence. Signed-off-by: Ben Widawsky Signed-off-by: Imre Deak Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1474379673-28326-2-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 14 ++++-- drivers/gpu/drm/i915/i915_gpu_error.c | 76 ++++++++++++++++++++++++++++++--- drivers/gpu/drm/i915/i915_irq.c | 25 ++++++++--- drivers/gpu/drm/i915/i915_reg.h | 5 +++ drivers/gpu/drm/i915/intel_ringbuffer.h | 23 +++++++++- 5 files changed, 125 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ba155c038d0e..d3f83c5ab70b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1281,6 +1281,9 @@ static void i915_instdone_info(struct drm_i915_private *dev_priv, struct seq_file *m, struct intel_instdone *instdone) { + int slice; + int subslice; + seq_printf(m, "\t\tINSTDONE: 0x%08x\n", instdone->instdone); @@ -1293,10 +1296,13 @@ static void i915_instdone_info(struct drm_i915_private *dev_priv, if (INTEL_GEN(dev_priv) <= 6) return; - seq_printf(m, "\t\tSAMPLER_INSTDONE: 0x%08x\n", - instdone->sampler); - seq_printf(m, "\t\tROW_INSTDONE: 0x%08x\n", - instdone->row); + for_each_instdone_slice_subslice(dev_priv, slice, subslice) + seq_printf(m, "\t\tSAMPLER_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, instdone->sampler[slice][subslice]); + + for_each_instdone_slice_subslice(dev_priv, slice, subslice) + seq_printf(m, "\t\tROW_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, instdone->row[slice][subslice]); } static int i915_hangcheck_info(struct seq_file *m, void *unused) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 6a2775aad354..2bbab226a46c 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -231,6 +231,9 @@ static const char *hangcheck_action_to_str(enum intel_engine_hangcheck_action a) static void error_print_instdone(struct drm_i915_error_state_buf *m, struct drm_i915_error_engine *ee) { + int slice; + int subslice; + err_printf(m, " INSTDONE: 0x%08x\n", ee->instdone.instdone); @@ -243,10 +246,15 @@ static void error_print_instdone(struct drm_i915_error_state_buf *m, if (INTEL_GEN(m->i915) <= 6) return; - err_printf(m, " SAMPLER_INSTDONE: 0x%08x\n", - ee->instdone.sampler); - err_printf(m, " ROW_INSTDONE: 0x%08x\n", - ee->instdone.row); + for_each_instdone_slice_subslice(m->i915, slice, subslice) + err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, + ee->instdone.sampler[slice][subslice]); + + for_each_instdone_slice_subslice(m->i915, slice, subslice) + err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, + ee->instdone.row[slice][subslice]); } static void error_print_engine(struct drm_i915_error_state_buf *m, @@ -1549,12 +1557,52 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type) } } +static inline uint32_t +read_subslice_reg(struct drm_i915_private *dev_priv, int slice, + int subslice, i915_reg_t reg) +{ + uint32_t mcr; + uint32_t ret; + enum forcewake_domains fw_domains; + + fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, + FW_REG_READ); + fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, + GEN8_MCR_SELECTOR, + FW_REG_READ | FW_REG_WRITE); + + spin_lock_irq(&dev_priv->uncore.lock); + intel_uncore_forcewake_get__locked(dev_priv, fw_domains); + + mcr = I915_READ_FW(GEN8_MCR_SELECTOR); + /* + * The HW expects the slice and sublice selectors to be reset to 0 + * after reading out the registers. + */ + WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); + mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); + mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); + I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); + + ret = I915_READ_FW(reg); + + mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); + I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); + + intel_uncore_forcewake_put__locked(dev_priv, fw_domains); + spin_unlock_irq(&dev_priv->uncore.lock); + + return ret; +} + /* NB: please notice the memset */ void i915_get_engine_instdone(struct drm_i915_private *dev_priv, enum intel_engine_id engine_id, struct intel_instdone *instdone) { u32 mmio_base = dev_priv->engine[engine_id].mmio_base; + int slice; + int subslice; memset(instdone, 0, sizeof(*instdone)); @@ -1566,8 +1614,24 @@ void i915_get_engine_instdone(struct drm_i915_private *dev_priv, break; instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); - instdone->sampler = I915_READ(GEN7_SAMPLER_INSTDONE); - instdone->row = I915_READ(GEN7_ROW_INSTDONE); + for_each_instdone_slice_subslice(dev_priv, slice, subslice) { + instdone->sampler[slice][subslice] = + read_subslice_reg(dev_priv, slice, subslice, + GEN7_SAMPLER_INSTDONE); + instdone->row[slice][subslice] = + read_subslice_reg(dev_priv, slice, subslice, + GEN7_ROW_INSTDONE); + } + break; + case 7: + instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); + + if (engine_id != RCS) + break; + + instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); + instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); + instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); break; case 6: diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 371647c4c53c..a5c02f6ea6a0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2549,6 +2549,9 @@ static inline void i915_err_print_instdone(struct drm_i915_private *dev_priv, struct intel_instdone *instdone) { + int slice; + int subslice; + pr_err(" INSTDONE: 0x%08x\n", instdone->instdone); if (INTEL_GEN(dev_priv) <= 3) @@ -2559,8 +2562,13 @@ i915_err_print_instdone(struct drm_i915_private *dev_priv, if (INTEL_GEN(dev_priv) <= 6) return; - pr_err(" SAMPLER_INSTDONE: 0x%08x\n", instdone->sampler); - pr_err(" ROW_INSTDONE: 0x%08x\n", instdone->row); + for_each_instdone_slice_subslice(dev_priv, slice, subslice) + pr_err(" SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, instdone->sampler[slice][subslice]); + + for_each_instdone_slice_subslice(dev_priv, slice, subslice) + pr_err(" ROW_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, instdone->row[slice][subslice]); } static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) @@ -2981,6 +2989,8 @@ static bool subunits_stuck(struct intel_engine_cs *engine) struct intel_instdone instdone; struct intel_instdone *accu_instdone = &engine->hangcheck.instdone; bool stuck; + int slice; + int subslice; if (engine->id != RCS) return true; @@ -2996,10 +3006,13 @@ static bool subunits_stuck(struct intel_engine_cs *engine) &accu_instdone->instdone); stuck &= instdone_unchanged(instdone.slice_common, &accu_instdone->slice_common); - stuck &= instdone_unchanged(instdone.sampler, - &accu_instdone->sampler); - stuck &= instdone_unchanged(instdone.row, - &accu_instdone->row); + + for_each_instdone_slice_subslice(dev_priv, slice, subslice) { + stuck &= instdone_unchanged(instdone.sampler[slice][subslice], + &accu_instdone->sampler[slice][subslice]); + stuck &= instdone_unchanged(instdone.row[slice][subslice], + &accu_instdone->row[slice][subslice]); + } return stuck; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 41331455a111..8d44cee710f0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1708,6 +1708,11 @@ enum skl_disp_power_wells { #define GEN7_SC_INSTDONE _MMIO(0x7100) #define GEN7_SAMPLER_INSTDONE _MMIO(0xe160) #define GEN7_ROW_INSTDONE _MMIO(0xe164) +#define GEN8_MCR_SELECTOR _MMIO(0xfdc) +#define GEN8_MCR_SLICE(slice) (((slice) & 3) << 26) +#define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3) +#define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24) +#define GEN8_MCR_SUBSLICE_MASK GEN8_MCR_SUBSLICE(3) #define RING_IPEIR(base) _MMIO((base)+0x64) #define RING_IPEHR(base) _MMIO((base)+0x68) /* diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 4ff47023e68d..66553bdb0a47 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -73,12 +73,31 @@ enum intel_engine_hangcheck_action { #define HANGCHECK_SCORE_RING_HUNG 31 +#define I915_MAX_SLICES 3 +#define I915_MAX_SUBSLICES 3 + +#define instdone_slice_mask(dev_priv__) \ + (INTEL_GEN(dev_priv__) == 7 ? \ + 1 : INTEL_INFO(dev_priv__)->sseu.slice_mask) + +#define instdone_subslice_mask(dev_priv__) \ + (INTEL_GEN(dev_priv__) == 7 ? \ + 1 : INTEL_INFO(dev_priv__)->sseu.subslice_mask) + +#define for_each_instdone_slice_subslice(dev_priv__, slice__, subslice__) \ + for ((slice__) = 0, (subslice__) = 0; \ + (slice__) < I915_MAX_SLICES; \ + (subslice__) = ((subslice__) + 1) < I915_MAX_SUBSLICES ? (subslice__) + 1 : 0, \ + (slice__) += ((subslice__) == 0)) \ + for_each_if((BIT(slice__) & instdone_slice_mask(dev_priv__)) && \ + (BIT(subslice__) & instdone_subslice_mask(dev_priv__))) + struct intel_instdone { u32 instdone; /* The following exist only in the RCS engine */ u32 slice_common; - u32 sampler; - u32 row; + u32 sampler[I915_MAX_SLICES][I915_MAX_SUBSLICES]; + u32 row[I915_MAX_SLICES][I915_MAX_SUBSLICES]; }; struct intel_engine_hangcheck { -- cgit v1.2.3 From 6277c8d07b8f1b667f672628f88b18e831e67517 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 20 Sep 2016 14:58:19 +0300 Subject: drm/i915: Queue page flip work via a low latency, unbound workqueue While user space has control over the scheduling priority of its page flipping thread, the corresponding work the driver schedules for MMIO flips always runs from the generic system workqueue which has some scheduling overhead due it being CPU bound. This would hinder an application that wants more stringent guarantees over flip timing (to avoid missing a flip at the next frame count). Fix this by scheduling the work from the unbound system workqueue which provides for minimal scheduling latency. v2: - Use an unbound workqueue instead of a high-prio one. (Tvrtko, Chris) v3: - Use the system unbound wq instead of a dedicated one. (Maarten) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97775 Testcase: igt/kms_cursor_legacy CC: Chris Wilson CC: Maarten Lankhorst CC: Tvrtko Ursulin Signed-off-by: Imre Deak Reviewed-by: Tvrtko Ursulin (v1) Reviewed-by: Chris Wilson Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1474372699-22841-1-git-send-email-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 18fdbb7f6c28..f7b2f8f609e7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12266,7 +12266,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->flip_queued_req = i915_gem_active_get(&obj->last_write, &obj->base.dev->struct_mutex); - schedule_work(&work->mmio_work); + queue_work(system_unbound_wq, &work->mmio_work); } else { request = i915_gem_request_alloc(engine, engine->last_context); if (IS_ERR(request)) { -- cgit v1.2.3 From f2a91d1a6f5960c08f1ca60bd076f4dc020c50c6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Sep 2016 14:51:06 +0100 Subject: drm/i915: Restore current RPS state after reset Following commit 821ed7df6e2a ("drm/i915: Update reset path to fix incomplete requests") we no longer mark the context as lost on reset as we keep the requests (and contexts) alive. However, RPS remains reset and we need to restore the current state to match the in-flight requests. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97824 Fixes: 821ed7df6e2a ("drm/i915: Update reset path to fix incomplete requests") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Cc: Arun Siluvery Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/20160921135108.29574-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 9 --------- drivers/gpu/drm/i915/i915_gem.c | 7 +++++++ drivers/gpu/drm/i915/i915_irq.c | 6 ++++++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7f4e8adec8a8..8ae5853ea3c6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1786,15 +1786,6 @@ void i915_reset(struct drm_i915_private *dev_priv) goto error; } - /* - * rps/rc6 re-init is necessary to restore state lost after the - * reset and the re-install of gt irqs. Skip for ironlake per - * 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); - wakeup: wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS); return; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c8bd02277b7d..aeb46658ab3c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2628,6 +2628,13 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) i915_gem_reset_engine(engine); i915_gem_restore_fences(&dev_priv->drm); + + if (dev_priv->gt.awake) { + intel_sanitize_gt_powersave(dev_priv); + intel_enable_gt_powersave(dev_priv); + if (INTEL_GEN(dev_priv) >= 6) + gen6_rps_busy(dev_priv); + } } static void nop_submit_request(struct drm_i915_gem_request *request) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a5c02f6ea6a0..f8c0beaadf30 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -350,6 +350,9 @@ void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) { + if (READ_ONCE(dev_priv->rps.interrupts_enabled)) + return; + spin_lock_irq(&dev_priv->irq_lock); WARN_ON_ONCE(dev_priv->rps.pm_iir); WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); @@ -368,6 +371,9 @@ u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask) void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) { + if (!READ_ONCE(dev_priv->rps.interrupts_enabled)) + return; + spin_lock_irq(&dev_priv->irq_lock); dev_priv->rps.interrupts_enabled = false; -- cgit v1.2.3 From 6a800eabba34945c2986d70114b41d564bad52a8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Sep 2016 14:51:07 +0100 Subject: drm/i915: Only shrink the unbound objects during freeze At the point of creating the hibernation image, the runtime power manage core is disabled - and using the rpm functions triggers a warn. i915_gem_shrink_all() tries to unbind objects, which requires device access and so tries to how an rpm reference triggering a warning: [ 44.235420] ------------[ cut here ]------------ [ 44.235424] WARNING: CPU: 2 PID: 2199 at drivers/gpu/drm/i915/intel_runtime_pm.c:2688 intel_runtime_pm_get_if_in_use+0xe6/0xf0 [ 44.235426] WARN_ON_ONCE(ret < 0) [ 44.235445] Modules linked in: ctr ccm arc4 rt2800usb rt2x00usb rt2800lib rt2x00lib crc_ccitt mac80211 cmac cfg80211 btusb rfcomm bnep btrtl btbcm btintel bluetooth dcdbas x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_realtek crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec_generic aesni_intel snd_hda_codec_hdmi aes_x86_64 lrw gf128mul snd_hda_intel glue_helper ablk_helper cryptd snd_hda_codec hid_multitouch joydev snd_hda_core binfmt_misc i2c_hid serio_raw snd_pcm acpi_pad snd_timer snd i2c_designware_platform 8250_dw nls_iso8859_1 i2c_designware_core lpc_ich mfd_core soundcore usbhid hid psmouse ahci libahci [ 44.235447] CPU: 2 PID: 2199 Comm: kworker/u8:8 Not tainted 4.8.0-rc5+ #130 [ 44.235447] Hardware name: Dell Inc. XPS 13 9343/0310JH, BIOS A07 11/11/2015 [ 44.235450] Workqueue: events_unbound async_run_entry_fn [ 44.235453] 0000000000000000 ffff8801b2f7fb98 ffffffff81306c2f ffff8801b2f7fbe8 [ 44.235454] 0000000000000000 ffff8801b2f7fbd8 ffffffff81056c01 00000a801f50ecc0 [ 44.235456] ffff88020ce50000 ffff88020ce59b60 ffffffff81a60b5c ffffffff81414840 [ 44.235456] Call Trace: [ 44.235459] [] dump_stack+0x4d/0x6e [ 44.235461] [] __warn+0xd1/0xf0 [ 44.235464] [] ? i915_pm_suspend_late+0x30/0x30 [ 44.235465] [] warn_slowpath_fmt+0x4f/0x60 [ 44.235468] [] ? pm_runtime_get_if_in_use+0x6e/0xa0 [ 44.235469] [] intel_runtime_pm_get_if_in_use+0xe6/0xf0 [ 44.235471] [] i915_gem_shrink+0x306/0x360 [ 44.235473] [] ? pci_platform_power_transition+0x24/0x90 [ 44.235475] [] ? i915_pm_suspend_late+0x30/0x30 [ 44.235476] [] i915_gem_shrink_all+0x1b/0x30 [ 44.235478] [] i915_gem_freeze_late+0x33/0x90 [ 44.235479] [] i915_pm_freeze_late+0x37/0x40 [ 44.235481] [] dpm_run_callback+0x4e/0x130 [ 44.235483] [] __device_suspend_late+0xdb/0x1f0 [ 44.235484] [] async_suspend_late+0x1f/0xa0 [ 44.235486] [] async_run_entry_fn+0x37/0x150 [ 44.235488] [] process_one_work+0x148/0x3f0 [ 44.235490] [] worker_thread+0x12b/0x490 [ 44.235491] [] ? process_one_work+0x3f0/0x3f0 [ 44.235492] [] kthread+0xc9/0xe0 [ 44.235495] [] ret_from_fork+0x1f/0x40 [ 44.235496] [] ? kthread_park+0x60/0x60 [ 44.235497] ---[ end trace e438706b97c7f132 ]--- Alternatively, to actually shrink everything we have to do so slightly earlier in the hibernation process. To keep lockdep silent, we need to take struct_mutex for the shrinker even though we know that we are the only user during the freeze. Fixes: 7aab2d534e35 ("drm/i915: Shrink objects prior to hibernation") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160921135108.29574-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 12 +++++++++++- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8ae5853ea3c6..bfb2efd8d4d4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1863,7 +1863,17 @@ static int i915_pm_resume(struct device *kdev) /* freeze: before creating the hibernation_image */ static int i915_pm_freeze(struct device *kdev) { - return i915_pm_suspend(kdev); + int ret; + + ret = i915_pm_suspend(kdev); + if (ret) + return ret; + + ret = i915_gem_freeze(kdev_to_i915(kdev)); + if (ret) + return ret; + + return 0; } static int i915_pm_freeze_late(struct device *kdev) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 356899543d4b..008c74bfabad 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3076,6 +3076,7 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data, void i915_gem_load_init(struct drm_device *dev); void i915_gem_load_cleanup(struct drm_device *dev); void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); +int i915_gem_freeze(struct drm_i915_private *dev_priv); int i915_gem_freeze_late(struct drm_i915_private *dev_priv); void *i915_gem_object_alloc(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index aeb46658ab3c..1418c1c522cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4593,6 +4593,19 @@ void i915_gem_load_cleanup(struct drm_device *dev) rcu_barrier(); } +int i915_gem_freeze(struct drm_i915_private *dev_priv) +{ + intel_runtime_pm_get(dev_priv); + + mutex_lock(&dev_priv->drm.struct_mutex); + i915_gem_shrink_all(dev_priv); + mutex_unlock(&dev_priv->drm.struct_mutex); + + intel_runtime_pm_put(dev_priv); + + return 0; +} + int i915_gem_freeze_late(struct drm_i915_private *dev_priv) { struct drm_i915_gem_object *obj; @@ -4616,7 +4629,8 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) * the objects as well. */ - i915_gem_shrink_all(dev_priv); + mutex_lock(&dev_priv->drm.struct_mutex); + i915_gem_shrink(dev_priv, -1UL, I915_SHRINK_UNBOUND); for (p = phases; *p; p++) { list_for_each_entry(obj, *p, global_list) { @@ -4624,6 +4638,7 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) obj->base.write_domain = I915_GEM_DOMAIN_CPU; } } + mutex_unlock(&dev_priv->drm.struct_mutex); return 0; } -- cgit v1.2.3 From bafb2f7d4755bf1571bd5e9a03b97f3fc4fe69ae Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Sep 2016 14:51:08 +0100 Subject: drm/i915/execlists: Reset RING registers upon resume There is a disparity in the context image saved to disk and our own bookkeeping - that is we presume the RING_HEAD and RING_TAIL match our stored ce->ring->tail value. However, as we emit WA_TAIL_DWORDS into the ring but may not tell the GPU about them, the GPU may be lagging behind our bookkeeping. Upon hibernation we do not save stolen pages, presuming that their contents are volatile. This means that although we start writing into the ring at tail, the GPU starts executing from its HEAD and there may be some garbage in between and so the GPU promptly hangs upon resume. Testcase: igt/gem_exec_suspend/basic-S4 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96526 Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160921135108.29574-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 50 +++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 251143361f31..39417b77bff2 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2129,30 +2129,42 @@ error_deref_obj: 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; + struct i915_gem_context *ctx; + + /* Because we emit WA_TAIL_DWORDS there may be a disparity + * between our bookkeeping in ce->ring->head and ce->ring->tail and + * that stored in context. As we only write new commands from + * ce->ring->tail onwards, everything before that is junk. If the GPU + * starts reading from its RING_HEAD from the context, it may try to + * execute that junk and die. + * + * So to avoid that we reset the context images upon resume. For + * simplicity, we just zero everything out. + */ + list_for_each_entry(ctx, &dev_priv->context_list, link) { + for_each_engine(engine, dev_priv) { + struct intel_context *ce = &ctx->engine[engine->id]; + u32 *reg; - for_each_engine(engine, dev_priv) { - struct intel_context *ce = &ctx->engine[engine->id]; - void *vaddr; - uint32_t *reg_state; - - if (!ce->state) - continue; - - vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB); - if (WARN_ON(IS_ERR(vaddr))) - continue; + if (!ce->state) + continue; - reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; + reg = i915_gem_object_pin_map(ce->state->obj, + I915_MAP_WB); + if (WARN_ON(IS_ERR(reg))) + continue; - reg_state[CTX_RING_HEAD+1] = 0; - reg_state[CTX_RING_TAIL+1] = 0; + reg += LRC_STATE_PN * PAGE_SIZE / sizeof(*reg); + reg[CTX_RING_HEAD+1] = 0; + reg[CTX_RING_TAIL+1] = 0; - ce->state->obj->dirty = true; - i915_gem_object_unpin_map(ce->state->obj); + ce->state->obj->dirty = true; + i915_gem_object_unpin_map(ce->state->obj); - ce->ring->head = 0; - ce->ring->tail = 0; + ce->ring->head = ce->ring->tail = 0; + ce->ring->last_retired_head = -1; + intel_ring_update_space(ce->ring); + } } } -- cgit v1.2.3 From 5748be60ea66a7f299fc28bf1ebe3f63a5a266e8 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 19 Sep 2016 18:24:37 -0700 Subject: drm/i915: Standardize port type for DVO encoders Changing the return type from 'char' to 'enum port' in intel_dvo_port_name() makes it easier to later move the port information to intel_encoder. In addition, the port type conforms to what we have elsewhere. Removing the last conditional that handles invalid port because dvo_reg is intialized to valid values for all DVO devices at definition. v2: Changed return type, for real (Jani) Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Lyude Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1474334681-22690-2-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_dvo.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 2e452c505e7e..648975588cc2 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -412,16 +412,14 @@ intel_dvo_get_current_mode(struct drm_connector *connector) return mode; } -static char intel_dvo_port_name(i915_reg_t dvo_reg) +static enum port intel_dvo_port(i915_reg_t dvo_reg) { if (i915_mmio_reg_equal(dvo_reg, DVOA)) - return 'A'; + return PORT_A; else if (i915_mmio_reg_equal(dvo_reg, DVOB)) - return 'B'; - else if (i915_mmio_reg_equal(dvo_reg, DVOC)) - return 'C'; + return PORT_B; else - return '?'; + return PORT_C; } void intel_dvo_init(struct drm_device *dev) @@ -464,6 +462,7 @@ void intel_dvo_init(struct drm_device *dev) bool dvoinit; enum pipe pipe; uint32_t dpll[I915_MAX_PIPES]; + enum port port; /* Allow the I2C driver info to specify the GPIO to be used in * special cases, but otherwise default to what's defined @@ -511,9 +510,10 @@ void intel_dvo_init(struct drm_device *dev) if (!dvoinit) continue; + port = intel_dvo_port(dvo->dvo_reg); drm_encoder_init(dev, &intel_encoder->base, &intel_dvo_enc_funcs, encoder_type, - "DVO %c", intel_dvo_port_name(dvo->dvo_reg)); + "DVO %c", port_name(port)); intel_encoder->type = INTEL_OUTPUT_DVO; intel_encoder->crtc_mask = (1 << 0) | (1 << 1); -- cgit v1.2.3 From 03cdc1d4f79573a59392986fb4b50c55d47cff71 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Mon, 19 Sep 2016 18:24:38 -0700 Subject: drm/i915: Store port enum in intel_encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Storing the port enum in intel_encoder makes it convenient to know the port attached to an encoder. Moving the port information up from intel_digital_port to intel_encoder avoids unecessary intel_digital_port access and handles MST encoders cleanly without requiring conditional checks for them (thanks danvet). v2: Renamed the port enum member from 'attached_port' to 'port' (danvet) Fixed missing initialization of port in intel_sdvo.c (danvet) v3: Fixed missing initialization of port in intel_crt.c (Ville) v4: Storing port for DVO encoders too. Signed-off-by: Dhinakaran Pandiyan Cc: Daniel Vetter Cc: Ville Syrjälä Acked-by: Daniel Vetter Reviewed-by: Lyude Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1474334681-22690-3-git-send-email-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_crt.c | 2 ++ drivers/gpu/drm/i915/intel_ddi.c | 1 + drivers/gpu/drm/i915/intel_dp.c | 1 + drivers/gpu/drm/i915/intel_dp_mst.c | 1 + drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_dsi.c | 1 + drivers/gpu/drm/i915/intel_dvo.c | 2 ++ drivers/gpu/drm/i915/intel_hdmi.c | 1 + drivers/gpu/drm/i915/intel_lvds.c | 3 ++- drivers/gpu/drm/i915/intel_sdvo.c | 1 + drivers/gpu/drm/i915/intel_tv.c | 2 ++ 12 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 008c74bfabad..46462b181f5e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -185,6 +185,7 @@ enum plane { #define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites[(p)] + (s) + 'A') enum port { + PORT_NONE = -1, PORT_A = 0, PORT_B, PORT_C, diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index dfbcf16b41df..88ebbdde185a 1