From 6c34bd4532a3f39952952ddc102737595729afc4 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 18 Oct 2021 17:34:17 +0300 Subject: [PATCH 01/14] drm/i915/dp: Ensure sink rate values are always valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atm, there are no sink rate values set for DP (vs. eDP) sinks until the DPCD capabilities are successfully read from the sink. During this time intel_dp->num_common_rates is 0 which can lead to a intel_dp->common_rates[-1] (*) access, which is an undefined behaviour, in the following cases: - In intel_dp_sync_state(), if the encoder is enabled without a sink connected to the encoder's connector (BIOS enabled a monitor, but the user unplugged the monitor until the driver loaded). - In intel_dp_sync_state() if the encoder is enabled with a sink connected, but for some reason the DPCD read has failed. - In intel_dp_compute_link_config() if modesetting a connector without a sink connected on it. - In intel_dp_compute_link_config() if modesetting a connector with a a sink connected on it, but before probing the connector first. To avoid the (*) access in all the above cases, make sure that the sink rate table - and hence the common rate table - is always valid, by setting a default minimum sink rate when registering the connector before anything could use it. I also considered setting all the DP link rates by default, so that modesetting with higher resolution modes also succeeds in the last two cases above. However in case a sink is not connected that would stop working after the first modeset, due to the LT fallback logic. So this would need more work, beyond the scope of this fix. As I mentioned in the previous patch, I don't think the issue this patch fixes is user visible, however it is an undefined behaviour by definition and triggers a BUG() in CONFIG_UBSAN builds, hence CC:stable. v2: Clear the default sink rates, before initializing these for eDP. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4297 References: https://gitlab.freedesktop.org/drm/intel/-/issues/4298 Suggested-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211018143417.1452632-1-imre.deak@intel.com (cherry picked from commit 3f61ef9777c0ab0f03f4af0ed6fd3e5250537a8d) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9d8132dd4cc5..9c898693f6c6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -120,6 +120,12 @@ bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state) return crtc_state->port_clock >= 1000000; } +static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp) +{ + intel_dp->sink_rates[0] = 162000; + intel_dp->num_sink_rates = 1; +} + /* update sink rates from dpcd */ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) { @@ -2553,6 +2559,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) */ intel_psr_init_dpcd(intel_dp); + /* Clear the default sink rates */ + intel_dp->num_sink_rates = 0; + /* Read the eDP 1.4+ supported link rates. */ if (intel_dp->edp_dpcd[0] >= DP_EDP_14) { __le16 sink_rates[DP_MAX_SUPPORTED_RATES]; @@ -5000,6 +5009,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, } intel_dp_set_source_rates(intel_dp); + intel_dp_set_default_sink_rates(intel_dp); + intel_dp_set_common_rates(intel_dp); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp); From cc99bc62ff6902688ee7bd3a7b25eefc620fbb6a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 18 Oct 2021 12:41:51 +0300 Subject: [PATCH 02/14] drm/i915/dp: Ensure max link params are always valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Atm until the DPCD for a connector is read the max link rate and lane count params are invalid. If the connector is modeset, in intel_dp_compute_config(), intel_dp_common_len_rate_limit(max_link_rate) will return 0, leading to a intel_dp->common_rates[-1] access. Fix the above by making sure the max link params are always valid. The above access leads to an undefined behaviour by definition, though not causing a user visible problem to my best knowledge, see the previous patch why. Nevertheless it is an undefined behaviour and it triggers a BUG() in CONFIG_UBSAN builds, hence CC:stable. Cc: Ville Syrjälä Cc: Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211018094154.1407705-4-imre.deak@intel.com (cherry picked from commit 9ad87de4735620ffc555592e8c5f580478fa3ed0) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dp.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9c898693f6c6..0ddc24a37895 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1864,6 +1864,12 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, intel_dp->lane_count = lane_count; } +static void intel_dp_reset_max_link_params(struct intel_dp *intel_dp) +{ + intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); + intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); +} + /* Enable backlight PWM and backlight PP control. */ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) @@ -2020,8 +2026,7 @@ void intel_dp_sync_state(struct intel_encoder *encoder, if (intel_dp->dpcd[DP_DPCD_REV] == 0) intel_dp_get_dpcd(intel_dp); - intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); - intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); + intel_dp_reset_max_link_params(intel_dp); } bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, @@ -2597,6 +2602,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) intel_dp_set_sink_rates(intel_dp); intel_dp_set_common_rates(intel_dp); + intel_dp_reset_max_link_params(intel_dp); /* Read the eDP DSC DPCD registers */ if (DISPLAY_VER(dev_priv) >= 10) @@ -4338,12 +4344,7 @@ intel_dp_detect(struct drm_connector *connector, * supports link training fallback params. */ if (intel_dp->reset_link_params || intel_dp->is_mst) { - /* Initial max link lane count */ - intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); - - /* Initial max link rate */ - intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); - + intel_dp_reset_max_link_params(intel_dp); intel_dp->reset_link_params = false; } @@ -5011,6 +5012,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, intel_dp_set_source_rates(intel_dp); intel_dp_set_default_sink_rates(intel_dp); intel_dp_set_common_rates(intel_dp); + intel_dp_reset_max_link_params(intel_dp); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp); From c4d6da21b2c6627d968d7c1410925ff4a8c199c4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 19 Oct 2021 14:43:34 +0300 Subject: [PATCH 03/14] Revert "drm/i915/bios: gracefully disable dual eDP for now" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 05734ca2a8f76c9eb3890b3c9dfc3467f03105c1. It's not graceful, instead it leads to boot time warning splats in the case it is supposed to handle gracefully. Apparently the BIOS/GOP enabling the port we end up skipping leads to state readout problems. Back to the drawing board. References: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_21255/bat-adlp-4/boot0.txt Fixes: 05734ca2a8f7 ("drm/i915/bios: gracefully disable dual eDP for now") Cc: José Roberto de Souza Cc: Uma Shankar Cc: Ville Syrjälä Cc: Swati Sharma Reviewed-by: José Roberto de Souza Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211019114334.24643-1-jani.nikula@intel.com (cherry picked from commit 171c555c2c2664a250cd35680c34c31a6d233dc7) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_bios.c | 47 ----------------------- 1 file changed, 47 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index b99907c656bb..f9776ca85de3 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1930,50 +1930,6 @@ static int _intel_bios_max_tmds_clock(const struct intel_bios_encoder_data *devd } } -static enum port get_edp_port(struct drm_i915_private *i915) -{ - const struct intel_bios_encoder_data *devdata; - enum port port; - - for_each_port(port) { - devdata = i915->vbt.ports[port]; - - if (devdata && intel_bios_encoder_supports_edp(devdata)) - return port; - } - - return PORT_NONE; -} - -/* - * FIXME: The power sequencer and backlight code currently do not support more - * than one set registers, at least not on anything other than VLV/CHV. It will - * clobber the registers. As a temporary workaround, gracefully prevent more - * than one eDP from being registered. - */ -static void sanitize_dual_edp(struct intel_bios_encoder_data *devdata, - enum port port) -{ - struct drm_i915_private *i915 = devdata->i915; - struct child_device_config *child = &devdata->child; - enum port p; - - /* CHV might not clobber PPS registers. */ - if (IS_CHERRYVIEW(i915)) - return; - - p = get_edp_port(i915); - if (p == PORT_NONE) - return; - - drm_dbg_kms(&i915->drm, "both ports %c and %c configured as eDP, " - "disabling port %c eDP\n", port_name(p), port_name(port), - port_name(port)); - - child->device_type &= ~DEVICE_TYPE_DISPLAYPORT_OUTPUT; - child->device_type &= ~DEVICE_TYPE_INTERNAL_CONNECTOR; -} - static bool is_port_valid(struct drm_i915_private *i915, enum port port) { /* @@ -2031,9 +1987,6 @@ static void parse_ddi_port(struct drm_i915_private *i915, supports_typec_usb, supports_tbt, devdata->dsc != NULL); - if (is_edp) - sanitize_dual_edp(devdata, port); - if (is_dvi) sanitize_ddc_pin(devdata, port); From 8a30b871b6f3804a72c523a2b086b72f1bf6146d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 21 Oct 2021 16:34:08 +0300 Subject: [PATCH 04/14] drm/i915/cdclk: put the cdclk vtables in const data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the const that was accidentally left out from the vtables. Fixes: 6b4cd9cba620 ("drm/i915: constify the cdclk vtable") Cc: Dave Airlie Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211021133408.32166-1-jani.nikula@intel.com (cherry picked from commit 877d074939a5f82b099da2db3bcccc6c418b9c39) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_cdclk.c | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 9e466d829019..868dd43a7542 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2885,7 +2885,7 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv) return freq; } -static struct intel_cdclk_funcs tgl_cdclk_funcs = { +static const struct intel_cdclk_funcs tgl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, @@ -2893,7 +2893,7 @@ static struct intel_cdclk_funcs tgl_cdclk_funcs = { .calc_voltage_level = tgl_calc_voltage_level, }; -static struct intel_cdclk_funcs ehl_cdclk_funcs = { +static const struct intel_cdclk_funcs ehl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, @@ -2901,7 +2901,7 @@ static struct intel_cdclk_funcs ehl_cdclk_funcs = { .calc_voltage_level = ehl_calc_voltage_level, }; -static struct intel_cdclk_funcs icl_cdclk_funcs = { +static const struct intel_cdclk_funcs icl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, @@ -2909,7 +2909,7 @@ static struct intel_cdclk_funcs icl_cdclk_funcs = { .calc_voltage_level = icl_calc_voltage_level, }; -static struct intel_cdclk_funcs bxt_cdclk_funcs = { +static const struct intel_cdclk_funcs bxt_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, @@ -2917,54 +2917,54 @@ static struct intel_cdclk_funcs bxt_cdclk_funcs = { .calc_voltage_level = bxt_calc_voltage_level, }; -static struct intel_cdclk_funcs skl_cdclk_funcs = { +static const struct intel_cdclk_funcs skl_cdclk_funcs = { .get_cdclk = skl_get_cdclk, .set_cdclk = skl_set_cdclk, .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, .modeset_calc_cdclk = skl_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs bdw_cdclk_funcs = { +static const struct intel_cdclk_funcs bdw_cdclk_funcs = { .get_cdclk = bdw_get_cdclk, .set_cdclk = bdw_set_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = bdw_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs chv_cdclk_funcs = { +static const struct intel_cdclk_funcs chv_cdclk_funcs = { .get_cdclk = vlv_get_cdclk, .set_cdclk = chv_set_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = vlv_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs vlv_cdclk_funcs = { +static const struct intel_cdclk_funcs vlv_cdclk_funcs = { .get_cdclk = vlv_get_cdclk, .set_cdclk = vlv_set_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = vlv_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs hsw_cdclk_funcs = { +static const struct intel_cdclk_funcs hsw_cdclk_funcs = { .get_cdclk = hsw_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; /* SNB, IVB, 965G, 945G */ -static struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = { +static const struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = { .get_cdclk = fixed_400mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs ilk_cdclk_funcs = { +static const struct intel_cdclk_funcs ilk_cdclk_funcs = { .get_cdclk = fixed_450mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs gm45_cdclk_funcs = { +static const struct intel_cdclk_funcs gm45_cdclk_funcs = { .get_cdclk = gm45_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, @@ -2972,7 +2972,7 @@ static struct intel_cdclk_funcs gm45_cdclk_funcs = { /* G45 uses G33 */ -static struct intel_cdclk_funcs i965gm_cdclk_funcs = { +static const struct intel_cdclk_funcs i965gm_cdclk_funcs = { .get_cdclk = i965gm_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, @@ -2980,19 +2980,19 @@ static struct intel_cdclk_funcs i965gm_cdclk_funcs = { /* i965G uses fixed 400 */ -static struct intel_cdclk_funcs pnv_cdclk_funcs = { +static const struct intel_cdclk_funcs pnv_cdclk_funcs = { .get_cdclk = pnv_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs g33_cdclk_funcs = { +static const struct intel_cdclk_funcs g33_cdclk_funcs = { .get_cdclk = g33_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i945gm_cdclk_funcs = { +static const struct intel_cdclk_funcs i945gm_cdclk_funcs = { .get_cdclk = i945gm_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, @@ -3000,37 +3000,37 @@ static struct intel_cdclk_funcs i945gm_cdclk_funcs = { /* i945G uses fixed 400 */ -static struct intel_cdclk_funcs i915gm_cdclk_funcs = { +static const struct intel_cdclk_funcs i915gm_cdclk_funcs = { .get_cdclk = i915gm_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i915g_cdclk_funcs = { +static const struct intel_cdclk_funcs i915g_cdclk_funcs = { .get_cdclk = fixed_333mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i865g_cdclk_funcs = { +static const struct intel_cdclk_funcs i865g_cdclk_funcs = { .get_cdclk = fixed_266mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i85x_cdclk_funcs = { +static const struct intel_cdclk_funcs i85x_cdclk_funcs = { .get_cdclk = i85x_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i845g_cdclk_funcs = { +static const struct intel_cdclk_funcs i845g_cdclk_funcs = { .get_cdclk = fixed_200mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; -static struct intel_cdclk_funcs i830_cdclk_funcs = { +static const struct intel_cdclk_funcs i830_cdclk_funcs = { .get_cdclk = fixed_133mhz_get_cdclk, .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, From 9ca8bb7a1d201d62773a90bbab267f81f2ea427d Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 20 Oct 2021 12:21:47 -0700 Subject: [PATCH 05/14] drm/i915/guc: Fix recursive lock in GuC submission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use __release_guc_id (lock held) rather than release_guc_id (acquires lock), add lockdep annotations. 213.280129] i915: Running i915_perf_live_selftests/live_noa_gpr [ 213.283459] ============================================ [ 213.283462] WARNING: possible recursive locking detected {{[ 213.283466] 5.15.0-rc6+ #18 Tainted: G U W }} [ 213.283470] -------------------------------------------- [ 213.283472] kworker/u24:0/8 is trying to acquire lock: [ 213.283475] ffff8ffc4f6cc1e8 (&guc->submission_state.lock){....}-{2:2}, at: destroyed_worker_func+0x2df/0x350 [i915] {{[ 213.283618] }} {{ but task is already holding lock:}} [ 213.283621] ffff8ffc4f6cc1e8 (&guc->submission_state.lock){....}-{2:2}, at: destroyed_worker_func+0x4f/0x350 [i915] {{[ 213.283720] }} {{ other info that might help us debug this:}} [ 213.283724] Possible unsafe locking scenario:[ 213.283727] CPU0 [ 213.283728] ---- [ 213.283730] lock(&guc->submission_state.lock); [ 213.283734] lock(&guc->submission_state.lock); {{[ 213.283737] }} {{ *** DEADLOCK ***}}[ 213.283740] May be due to missing lock nesting notation[ 213.283744] 3 locks held by kworker/u24:0/8: [ 213.283747] #0: ffff8ffb80059d38 ((wq_completion)events_unbound){..}-{0:0}, at: process_one_work+0x1f3/0x550 [ 213.283757] #1: ffffb509000e3e78 ((work_completion)(&guc->submission_state.destroyed_worker)){..}-{0:0}, at: process_one_work+0x1f3/0x550 [ 213.283766] #2: ffff8ffc4f6cc1e8 (&guc->submission_state.lock){....}-{2:2}, at: destroyed_worker_func+0x4f/0x350 [i915] {{[ 213.283860] }} {{ stack backtrace:}} [ 213.283863] CPU: 8 PID: 8 Comm: kworker/u24:0 Tainted: G U W 5.15.0-rc6+ #18 [ 213.283868] Hardware name: ASUS System Product Name/PRIME B560M-A AC, BIOS 0403 01/26/2021 [ 213.283873] Workqueue: events_unbound destroyed_worker_func [i915] [ 213.283957] Call Trace: [ 213.283960] dump_stack_lvl+0x57/0x72 [ 213.283966] __lock_acquire.cold+0x191/0x2d3 [ 213.283972] lock_acquire+0xb5/0x2b0 [ 213.283978] ? destroyed_worker_func+0x2df/0x350 [i915] [ 213.284059] ? destroyed_worker_func+0x2d7/0x350 [i915] [ 213.284139] ? lock_release+0xb9/0x280 [ 213.284143] _raw_spin_lock_irqsave+0x48/0x60 [ 213.284148] ? destroyed_worker_func+0x2df/0x350 [i915] [ 213.284226] destroyed_worker_func+0x2df/0x350 [i915] [ 213.284310] process_one_work+0x270/0x550 [ 213.284315] worker_thread+0x52/0x3b0 [ 213.284319] ? process_one_work+0x550/0x550 [ 213.284322] kthread+0x135/0x160 [ 213.284326] ? set_kthread_struct+0x40/0x40 [ 213.284331] ret_from_fork+0x1f/0x30 and a bit later in the trace: {{ 227.499864] do_raw_spin_lock+0x94/0xa0}} [ 227.499868] _raw_spin_lock_irqsave+0x50/0x60 [ 227.499871] ? guc_flush_destroyed_contexts+0x4f/0xf0 [i915] [ 227.499995] guc_flush_destroyed_contexts+0x4f/0xf0 [i915] [ 227.500104] intel_guc_submission_reset_prepare+0x99/0x4b0 [i915] [ 227.500209] ? mark_held_locks+0x49/0x70 [ 227.500212] intel_uc_reset_prepare+0x46/0x50 [i915] [ 227.500320] reset_prepare+0x78/0x90 [i915] [ 227.500412] __intel_gt_set_wedged.part.0+0x13/0xe0 [i915] [ 227.500485] intel_gt_set_wedged.part.0+0x54/0x100 [i915] [ 227.500556] intel_gt_set_wedged_on_fini+0x1a/0x30 [i915] [ 227.500622] intel_gt_driver_unregister+0x1e/0x60 [i915] [ 227.500694] i915_driver_remove+0x4a/0xf0 [i915] [ 227.500767] i915_pci_probe+0x84/0x170 [i915] [ 227.500838] local_pci_probe+0x42/0x80 [ 227.500842] pci_device_probe+0xd9/0x190 [ 227.500844] really_probe+0x1f2/0x3f0 [ 227.500847] __driver_probe_device+0xfe/0x180 [ 227.500848] driver_probe_device+0x1e/0x90 [ 227.500850] __driver_attach+0xc4/0x1d0 [ 227.500851] ? __device_attach_driver+0xe0/0xe0 [ 227.500853] ? __device_attach_driver+0xe0/0xe0 [ 227.500854] bus_for_each_dev+0x64/0x90 [ 227.500856] bus_add_driver+0x12e/0x1f0 [ 227.500857] driver_register+0x8f/0xe0 [ 227.500859] i915_init+0x1d/0x8f [i915] [ 227.500934] ? 0xffffffffc144a000 [ 227.500936] do_one_initcall+0x58/0x2d0 [ 227.500938] ? rcu_read_lock_sched_held+0x3f/0x80 [ 227.500940] ? kmem_cache_alloc_trace+0x238/0x2d0 [ 227.500944] do_init_module+0x5c/0x270 [ 227.500946] __do_sys_finit_module+0x95/0xe0 [ 227.500949] do_syscall_64+0x38/0x90 [ 227.500951] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 227.500953] RIP: 0033:0x7ffa59d2ae0d [ 227.500954] Code: c8 0c 00 0f 05 eb a9 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 3b 80 0c 00 f7 d8 64 89 01 48 [ 227.500955] RSP: 002b:00007fff320bbf48 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 227.500956] RAX: ffffffffffffffda RBX: 00000000022ea710 RCX: 00007ffa59d2ae0d [ 227.500957] RDX: 0000000000000000 RSI: 00000000022e1d90 RDI: 0000000000000004 [ 227.500958] RBP: 0000000000000020 R08: 00007ffa59df3a60 R09: 0000000000000070 [ 227.500958] R10: 00000000022e1d90 R11: 0000000000000246 R12: 00000000022e1d90 [ 227.500959] R13: 00000000022e58e0 R14: 0000000000000043 R15: 00000000022e42c0 v2: (CI build) - Fix build error Fixes: 1a52faed31311 ("drm/i915/guc: Take GT PM ref when deregistering context") Signed-off-by: Matthew Brost Cc: stable@vger.kernel.org Reviewed-by: Thomas Hellström Signed-off-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20211020192147.8048-1-matthew.brost@intel.com (cherry picked from commit 12a9917e9e84fef4efa73c09b32870df0b1ed795) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index d7710debcd47..38b47e73e35d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2373,6 +2373,7 @@ static inline void guc_lrc_desc_unpin(struct intel_context *ce) unsigned long flags; bool disabled; + lockdep_assert_held(&guc->submission_state.lock); GEM_BUG_ON(!intel_gt_pm_is_awake(gt)); GEM_BUG_ON(!lrc_desc_registered(guc, ce->guc_id.id)); GEM_BUG_ON(ce != __get_context(guc, ce->guc_id.id)); @@ -2388,7 +2389,7 @@ static inline void guc_lrc_desc_unpin(struct intel_context *ce) } spin_unlock_irqrestore(&ce->guc_state.lock, flags); if (unlikely(disabled)) { - release_guc_id(guc, ce); + __release_guc_id(guc, ce); __guc_context_destroy(ce); return; } From 02295cf3897aa04072d4d25c7ae642eb86e2d63f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 26 Oct 2021 12:34:07 +0300 Subject: [PATCH 06/14] drm/i915/dp: fix integer overflow in 128b/132b data rate calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intermediate value 1000000 * 10 * 9671 overflows 32 bits, so force promotion to a bigger type. From the logs: [drm:intel_dp_compute_config [i915]] DP link rate required 3657063 available -580783288 v2: Use mul_u32_u32() (Ville) Fixes: 48efd014f0ea ("drm/i915/dp: add max data rate calculation for UHBR rates") Cc: Manasi Navare Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20211026093407.11381-1-jani.nikula@intel.com (cherry picked from commit bf0d608b55d9b7f426031dfd9f08d9df36c94728) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0ddc24a37895..2a3521c6aae6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -287,7 +287,7 @@ intel_dp_max_data_rate(int max_link_rate, int max_lanes) */ int max_link_rate_kbps = max_link_rate * 10; - max_link_rate_kbps = DIV_ROUND_CLOSEST_ULL(max_link_rate_kbps * 9671, 10000); + max_link_rate_kbps = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(max_link_rate_kbps, 9671), 10000); max_link_rate = max_link_rate_kbps / 8; } From ab0f0c79d1a6c5832d8464804e773103e3e12fea Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 27 Oct 2021 12:32:55 +0300 Subject: [PATCH 07/14] drm/i915: Revert 'guc_id' from i915_request tracepoint Avoid adding backend specific data to the tracepoints outside of the LOW_LEVEL_TRACEPOINTS kernel config protection. These bits of information are bound to change depending on the selected submission method per platform and are not necessarily possible to maintain in the future. Fixes: dbf9da8d55ef ("drm/i915/guc: Add trace point for GuC submit") Signed-off-by: Joonas Lahtinen Cc: John Harrison Cc: Matthew Brost Cc: Daniele Ceraolo Spurio Cc: Chris Wilson Cc: Matt Roper Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20211027093255.66489-1-joonas.lahtinen@linux.intel.com (cherry picked from commit 64512a66b67e6546e2db15192b3603cd6d58b75c) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_trace.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 9795f456cccf..8104981a6604 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -794,7 +794,6 @@ DECLARE_EVENT_CLASS(i915_request, TP_STRUCT__entry( __field(u32, dev) __field(u64, ctx) - __field(u32, guc_id) __field(u16, class) __field(u16, instance) __field(u32, seqno) @@ -805,16 +804,14 @@ DECLARE_EVENT_CLASS(i915_request, __entry->dev = rq->engine->i915->drm.primary->index; __entry->class = rq->engine->uabi_class; __entry->instance = rq->engine->uabi_instance; - __entry->guc_id = rq->context->guc_id.id; __entry->ctx = rq->fence.context; __entry->seqno = rq->fence.seqno; __entry->tail = rq->tail; ), - TP_printk("dev=%u, engine=%u:%u, guc_id=%u, ctx=%llu, seqno=%u, tail=%u", + TP_printk("dev=%u, engine=%u:%u, ctx=%llu, seqno=%u, tail=%u", __entry->dev, __entry->class, __entry->instance, - __entry->guc_id, __entry->ctx, __entry->seqno, - __entry->tail) + __entry->ctx, __entry->seqno, __entry->tail) ); DEFINE_EVENT(i915_request, i915_request_add, From 5740211ea442dbfd143093f8eea39faba186042f Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 21 Oct 2021 13:53:31 +0100 Subject: [PATCH 08/14] drm/i915/dmabuf: fix broken build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wbinvd_on_all_cpus() is only defined on x86 it seems, plus we need to include asm/smp.h here. Reported-by: kernel test robot Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Ashutosh Dixit Link: https://patchwork.freedesktop.org/patch/msgid/20211021125332.2455288-1-matthew.auld@intel.com (cherry picked from commit 777226dac058d119286b4081953cb5aa2cb7394b) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index 1adcd8e02d29..a45d0ec2c5b6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -12,6 +12,13 @@ #include "i915_gem_object.h" #include "i915_scatterlist.h" +#if defined(CONFIG_X86) +#include +#else +#define wbinvd_on_all_cpus() \ + pr_warn(DRIVER_NAME ": Missing cache flush in %s\n", __func__) +#endif + I915_SELFTEST_DECLARE(static bool force_different_devices;) static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf) From af6c83ae25a556376ff08291200716232b5a6efc Mon Sep 17 00:00:00 2001 From: Zhi A Wang Date: Thu, 26 Aug 2021 14:38:34 +0000 Subject: [PATCH 09/14] drm/i915/gvt: fix the usage of ww lock in gvt scheduler. As the APIs related to ww lock in i915 was changed recently, the usage of ww lock in GVT-g scheduler needs to be changed accrodingly. We noticed a deadlock when GVT-g scheduler submits the workload to i915. After some investigation, it seems the way of how to use ww lock APIs has been changed. Releasing a ww now requires a explicit i915_gem_ww_ctx_fini(). Fixes: 67f1120381df ("drm/i915/gvt: Introduce per object locking in GVT scheduler.") Cc: Zhenyu Wang Signed-off-by: Zhi A Wang Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20210826143834.25410-1-zhi.a.wang@intel.com Acked-by: Zhenyu Wang (cherry picked from commit d168cd797982db9db617113644c87b8f5f3cf27e) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/scheduler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 0d18e13e3468..6c804102528b 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -576,7 +576,7 @@ retry: /* No one is going to touch shadow bb from now on. */ i915_gem_object_flush_map(bb->obj); - i915_gem_object_unlock(bb->obj); + i915_gem_ww_ctx_fini(&ww); } } return 0; @@ -630,7 +630,7 @@ retry: return ret; } - i915_gem_object_unlock(wa_ctx->indirect_ctx.obj); + i915_gem_ww_ctx_fini(&ww); /* FIXME: we are not tracking our pinned VMA leaving it * up to the core to fix up the stray pin_count upon From 99bac3063e8e0f437b04897a399b9394919d1a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 30 Sep 2021 22:09:42 +0300 Subject: [PATCH 10/14] drm/i915: Extend the async flip VT-d w/a to skl/bxt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like skl/bxt/derivatives also need the plane stride stretch w/a when using async flips and VT-d is enabled, or else we get corruption on screen. To my surprise this was even documented in bspec, but only as a note on the CHICHKEN_PIPESL register description rather than on the w/a list. So very much the same thing as on HSW/BDW, except the bits moved yet again. Cc: stable@vger.kernel.org Cc: Karthik B S Fixes: 55ea1cb178ef ("drm/i915: Enable async flips in i915") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20210930190943.17547-1-ville.syrjala@linux.intel.com Reviewed-by: Matt Roper (cherry picked from commit d08df3b0bdb25546e86dc9a6c4e3ec0c43832299) Signed-off-by: Jani Nikula (cherry picked from commit b2d73debfdc16b742e64948dc4461876af3f8c10) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_pm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f90fe39cf8ca..ecbb3d141632 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -77,6 +77,8 @@ struct intel_wm_config { static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) { + enum pipe pipe; + if (HAS_LLC(dev_priv)) { /* * WaCompressedResourceDisplayNewHashMode:skl,kbl @@ -90,6 +92,16 @@ static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) SKL_DE_COMPRESSED_HASH_MODE); } + for_each_pipe(dev_priv, pipe) { + /* + * "Plane N strech max must be programmed to 11b (x1) + * when Async flips are enabled on that plane." + */ + if (!IS_GEMINILAKE(dev_priv) && intel_vtd_active()) + intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe), + SKL_PLANE1_STRETCH_MAX_MASK, SKL_PLANE1_STRETCH_MAX_X1); + } + /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */ intel_uncore_write(&dev_priv->uncore, CHICKEN_PAR1_1, intel_uncore_read(&dev_priv->uncore, CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP); From 1977e8eb40ed53f0cac7db1a78295726f4ac0b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 25 Oct 2021 17:21:47 +0300 Subject: [PATCH 11/14] drm/i915: Fix type1 DVI DP dual mode adapter heuristic for modern platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like we never updated intel_bios_is_port_dp_dual_mode() when the VBT port mapping became erratic on modern platforms. This is causing us to look up the wrong child device and thus throwing the heuristic off (ie. we might end looking at a child device for a genuine DP++ port when we were supposed to look at one for a native HDMI port). Fix it up by not using the outdated port_mapping[] in intel_bios_is_port_dp_dual_mode() and rely on intel_bios_encoder_data_lookup() instead. Cc: stable@vger.kernel.org Tested-by: Randy Dunlap Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4138 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211025142147.23897-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula (cherry picked from commit 32c2bc89c7420fad2959ee23ef5b6be8b05d2bde) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_bios.c | 87 +++++++++++++++++------ 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index f9776ca85de3..2b1423a43437 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1707,6 +1707,39 @@ static void sanitize_aux_ch(struct intel_bios_encoder_data *devdata, child->aux_channel = 0; } +static u8 dvo_port_type(u8 dvo_port) +{ + switch (dvo_port) { + case DVO_PORT_HDMIA: + case DVO_PORT_HDMIB: + case DVO_PORT_HDMIC: + case DVO_PORT_HDMID: + case DVO_PORT_HDMIE: + case DVO_PORT_HDMIF: + case DVO_PORT_HDMIG: + case DVO_PORT_HDMIH: + case DVO_PORT_HDMII: + return DVO_PORT_HDMIA; + case DVO_PORT_DPA: + case DVO_PORT_DPB: + case DVO_PORT_DPC: + case DVO_PORT_DPD: + case DVO_PORT_DPE: + case DVO_PORT_DPF: + case DVO_PORT_DPG: + case DVO_PORT_DPH: + case DVO_PORT_DPI: + return DVO_PORT_DPA; + case DVO_PORT_MIPIA: + case DVO_PORT_MIPIB: + case DVO_PORT_MIPIC: + case DVO_PORT_MIPID: + return DVO_PORT_MIPIA; + default: + return dvo_port; + } +} + static enum port __dvo_port_to_port(int n_ports, int n_dvo, const int port_mapping[][3], u8 dvo_port) { @@ -2623,8 +2656,25 @@ bool intel_bios_is_port_edp(struct drm_i915_private *i915, enum port port) return false; } -static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, - enum port port) +static bool child_dev_is_dp_dual_mode(const struct child_device_config *child) +{ + if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) != + (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS)) + return false; + + if (dvo_port_type(child->dvo_port) == DVO_PORT_DPA) + return true; + + /* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */ + if (dvo_port_type(child->dvo_port) == DVO_PORT_HDMIA && + child->aux_channel != 0) + return true; + + return false; +} + +bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *i915, + enum port port) { static const struct { u16 dp, hdmi; @@ -2639,32 +2689,23 @@ static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, }; + const struct intel_bios_encoder_data *devdata; + + if (HAS_DDI(i915)) { + const struct intel_bios_encoder_data *devdata; + + devdata = intel_bios_encoder_data_lookup(i915, port); + + return devdata && child_dev_is_dp_dual_mode(&devdata->child); + } if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) return false; - if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) != - (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS)) - return false; - - if (child->dvo_port == port_mapping[port].dp) - return true; - - /* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */ - if (child->dvo_port == port_mapping[port].hdmi && - child->aux_channel != 0) - return true; - - return false; -} - -bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *i915, - enum port port) -{ - const struct intel_bios_encoder_data *devdata; - list_for_each_entry(devdata, &i915->vbt.display_devices, node) { - if (child_dev_is_dp_dual_mode(&devdata->child, port)) + if ((devdata->child.dvo_port == port_mapping[port].dp || + devdata->child.dvo_port == port_mapping[port].hdmi) && + child_dev_is_dp_dual_mode(&devdata->child)) return true; } From cecbc0c7eba7983965cac94f88d2db00b913253b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 29 Oct 2021 22:18:02 +0300 Subject: [PATCH 12/14] drm/i915/hdmi: Turn DP++ TMDS output buffers back on in encoder->shutdown() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like our VBIOS/GOP generally fail to turn the DP dual mode adater TMDS output buffers back on after a reboot. This leads to a black screen after reboot if we turned the TMDS output buffers off prior to reboot. And if i915 decides to do a fastboot the black screen will persist even after i915 takes over. Apparently this has been a problem ever since commit b2ccb822d376 ("drm/i915: Enable/disable TMDS output buffers in DP++ adaptor as needed") if one rebooted while the display was turned off. And things became worse with commit fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") since now we always turn the display off before a reboot. This was reported on a RKL, but I confirmed the same behaviour on my SNB as well. So looks pretty universal. Let's fix this by explicitly turning the TMDS output buffers back on in the encoder->shutdown() hook. Note that this gets called after irqs have been disabled, so the i2c communication with the DP dual mode adapter has to be performed via polling (which the gmbus code is perfectly happy to do for us). We also need a bit of care in handling DDI encoders which may or may not be set up for HDMI output. Specifically ddc_pin will not be populated for a DP only DDI encoder, in which case we don't want to call intel_gmbus_get_adapter(). We can handle that by simply doing the dual mode adapter type check before calling intel_gmbus_get_adapter(). Cc: # v5.11+ Fixes: fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4371 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20211029191802.18448-2-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy (cherry picked from commit 49c55f7b035b87371a6d3c53d9af9f92ddc962db) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/g4x_hdmi.c | 1 + drivers/gpu/drm/i915/display/intel_ddi.c | 1 + drivers/gpu/drm/i915/display/intel_hdmi.c | 16 ++++++++++++++-- drivers/gpu/drm/i915/display/intel_hdmi.h | 1 + 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 88c427f3c346..f5b4dd5b4275 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -584,6 +584,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, else intel_encoder->enable = g4x_enable_hdmi; } + intel_encoder->shutdown = intel_hdmi_encoder_shutdown; intel_encoder->type = INTEL_OUTPUT_HDMI; intel_encoder->power_domain = intel_port_to_power_domain(port); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1dcfe31e6c6f..cfb567df71b3 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4361,6 +4361,7 @@ static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder) enum phy phy = intel_port_to_phy(i915, encoder->port); intel_dp_encoder_shutdown(encoder); + intel_hdmi_encoder_shutdown(encoder); if (!intel_phy_is_tc(i915, phy)) return; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index d2e61f6c6e08..371736bdc01f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1246,12 +1246,13 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) { struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); - struct i2c_adapter *adapter = - intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); + struct i2c_adapter *adapter; if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI) return; + adapter = intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); + drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n", enable ? "Enabling" : "Disabling"); @@ -2258,6 +2259,17 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, return 0; } +void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder) +{ + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + + /* + * Give a hand to buggy BIOSen which forget to turn + * the TMDS output buffers back on after a reboot. + */ + intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); +} + static void intel_hdmi_unset_edid(struct drm_connector *connector) { diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index b43a180d007e..2bf440eb400a 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -28,6 +28,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, int intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state); +void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder); bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, struct drm_connector *connector, bool high_tmds_clock_ratio, From 90ab96f3872eae816f4e07deaa77322a91237960 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:50:59 +0300 Subject: [PATCH 13/14] drm/i915/fb: Fix rounding error in subsampled plane size calculation For NV12 FBs with odd main surface tile-row height the CCS surface height was incorrectly calculated 1 less than the actual value. Fix this by rounding up the result of divison. For consistency do the same for the CCS surface width calculation. Fixes: b3e57bccd68a ("drm/i915/tgl: Gen-12 render decompression") Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-2-imre.deak@intel.com (cherry picked from commit 2ee5ef9c934ad26376c9282171e731e6c0339815) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index fa1f375e696b..cb511b2b7069 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -378,8 +378,8 @@ static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_pl intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane); intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane); - *w = main_width / main_hsub / hsub; - *h = main_height / main_vsub / vsub; + *w = DIV_ROUND_UP(main_width, main_hsub * hsub); + *h = DIV_ROUND_UP(main_height, main_vsub * vsub); } static u32 intel_adjust_tile_offset(int *x, int *y, From ade4a1fc5741a36b559dfbd4557dc3da1a4394af Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 27 Oct 2021 01:51:00 +0300 Subject: [PATCH 14/14] drm/i915/adlp/fb: Prevent the mapping of redundant trailing padding NULL pages So far the remapped view size in GTT/DPT was padded to the next aligned offset unnecessarily after the last color plane with an unaligned size. Remove the unnecessary padding. Cc: Juha-Pekka Heikkila Fixes: 3d1adc3d64cf ("drm/i915/adlp: Add support for remapping CCS FBs") Signed-off-by: Imre Deak Reviewed-by: Juha-Pekka Heikkila Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-3-imre.deak@intel.com (cherry picked from commit 6b6636e17649d75b4d0cc55d3dff9e44511a442a) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display.c | 9 ++++++++- drivers/gpu/drm/i915/gt/intel_ggtt.c | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ff598b6cd953..ec403e46a328 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -848,9 +848,16 @@ unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info int i; for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) { + unsigned int plane_size; + + plane_size = rem_info->plane[i].dst_stride * rem_info->plane[i].height; + if (plane_size == 0) + continue; + if (rem_info->plane_alignment) size = ALIGN(size, rem_info->plane_alignment); - size += rem_info->plane[i].dst_stride * rem_info->plane[i].height; + + size += plane_size; } return size; diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index f17383e76eb7..57c97554393b 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -1396,6 +1396,9 @@ remap_pages(struct drm_i915_gem_object *obj, { unsigned int row; + if (!width || !height) + return sg; + if (alignment_pad) { st->nents++;