From 6b7adc3b60ab7a82cee214737411f8e187e25f34 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 16 Jul 2023 17:07:04 +0200 Subject: [PATCH] 6.1-stable patches added patches: drm-i915-fix-typec-mode-initialization-during-system-resume.patch drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch drm-i915-tc-fix-tc-port-link-ref-init-for-dp-mst-during-hw-readout.patch --- ...-initialization-during-system-resume.patch | 182 ++++++++++++++++++ ...me-mst-mode-restore-for-dp-alt-sinks.patch | 143 ++++++++++++++ ...ef-init-for-dp-mst-during-hw-readout.patch | 95 +++++++++ queue-6.1/series | 3 + 4 files changed, 423 insertions(+) create mode 100644 queue-6.1/drm-i915-fix-typec-mode-initialization-during-system-resume.patch create mode 100644 queue-6.1/drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch create mode 100644 queue-6.1/drm-i915-tc-fix-tc-port-link-ref-init-for-dp-mst-during-hw-readout.patch diff --git a/queue-6.1/drm-i915-fix-typec-mode-initialization-during-system-resume.patch b/queue-6.1/drm-i915-fix-typec-mode-initialization-during-system-resume.patch new file mode 100644 index 00000000000..1574e9dc108 --- /dev/null +++ b/queue-6.1/drm-i915-fix-typec-mode-initialization-during-system-resume.patch @@ -0,0 +1,182 @@ +From a82796a2e332d108b2d3aff38509caad370f69b5 Mon Sep 17 00:00:00 2001 +From: Imre Deak +Date: Thu, 22 Sep 2022 20:21:48 +0300 +Subject: drm/i915: Fix TypeC mode initialization during system resume + +From: Imre Deak + +commit a82796a2e332d108b2d3aff38509caad370f69b5 upstream. + +During system resume DP MST requires AUX to be working already before +the HW state readout of the given encoder. Since AUX requires the +encoder/PHY TypeC mode to be initialized, which atm only happens during +HW state readout, these AUX transfers can change the TypeC mode +incorrectly (disconnecting the PHY for an enabled encoder) and trigger +the state check WARNs in intel_tc_port_sanitize(). + +Fix this by initializing the TypeC mode earlier both during driver +loading and system resume and making sure that the mode can't change +until the encoder's state is read out. While at it add the missing +DocBook comments and rename +intel_tc_port_sanitize()->intel_tc_port_sanitize_mode() for consistency. + +Signed-off-by: Imre Deak +Reviewed-by: Mika Kahola +Link: https://patchwork.freedesktop.org/patch/msgid/20220922172148.2913088-1-imre.deak@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_ddi.c | 8 +++ + drivers/gpu/drm/i915/display/intel_tc.c | 66 +++++++++++++++++++++++-------- + drivers/gpu/drm/i915/display/intel_tc.h | 3 - + 3 files changed, 60 insertions(+), 17 deletions(-) + +--- a/drivers/gpu/drm/i915/display/intel_ddi.c ++++ b/drivers/gpu/drm/i915/display/intel_ddi.c +@@ -3579,7 +3579,7 @@ static void intel_ddi_sync_state(struct + enum phy phy = intel_port_to_phy(i915, encoder->port); + + if (intel_phy_is_tc(i915, phy)) +- intel_tc_port_sanitize(enc_to_dig_port(encoder)); ++ intel_tc_port_sanitize_mode(enc_to_dig_port(encoder)); + + if (crtc_state && intel_crtc_has_dp_encoder(crtc_state)) + intel_dp_sync_state(encoder, crtc_state); +@@ -3789,11 +3789,17 @@ static void intel_ddi_encoder_destroy(st + + static void intel_ddi_encoder_reset(struct drm_encoder *encoder) + { ++ struct drm_i915_private *i915 = to_i915(encoder->dev); + struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder)); ++ struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); ++ enum phy phy = intel_port_to_phy(i915, dig_port->base.port); + + intel_dp->reset_link_params = true; + + intel_pps_encoder_reset(intel_dp); ++ ++ if (intel_phy_is_tc(i915, phy)) ++ intel_tc_port_init_mode(dig_port); + } + + static const struct drm_encoder_funcs intel_ddi_funcs = { +--- a/drivers/gpu/drm/i915/display/intel_tc.c ++++ b/drivers/gpu/drm/i915/display/intel_tc.c +@@ -687,18 +687,58 @@ static void + intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port, + int refcount) + { ++ dig_port->tc_link_refcount = refcount; ++} ++ ++/** ++ * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode ++ * @dig_port: digital port ++ * ++ * Read out the HW state and initialize the TypeC mode of @dig_port. The mode ++ * will be locked until intel_tc_port_sanitize_mode() is called. ++ */ ++void intel_tc_port_init_mode(struct intel_digital_port *dig_port) ++{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ++ intel_wakeref_t tc_cold_wref; ++ enum intel_display_power_domain domain; + ++ mutex_lock(&dig_port->tc_lock); ++ ++ drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_DISCONNECTED); ++ drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref); + drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount); +- dig_port->tc_link_refcount = refcount; ++ ++ tc_cold_wref = tc_cold_block(dig_port, &domain); ++ ++ dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); ++ /* Prevent changing dig_port->tc_mode until intel_tc_port_sanitize_mode() is called. */ ++ intel_tc_port_link_init_refcount(dig_port, 1); ++ dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); ++ ++ tc_cold_unblock(dig_port, domain, tc_cold_wref); ++ ++ drm_dbg_kms(&i915->drm, "Port %s: init mode (%s)\n", ++ dig_port->tc_port_name, ++ tc_port_mode_name(dig_port->tc_mode)); ++ ++ mutex_unlock(&dig_port->tc_lock); + } + +-void intel_tc_port_sanitize(struct intel_digital_port *dig_port) ++/** ++ * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode ++ * @dig_port: digital port ++ * ++ * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver ++ * loading and system resume: ++ * If the encoder is enabled keep the TypeC mode/PHY connected state locked until ++ * the encoder is disabled. ++ * If the encoder is disabled make sure the PHY is disconnected. ++ */ ++void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port) + { + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_encoder *encoder = &dig_port->base; +- intel_wakeref_t tc_cold_wref; +- enum intel_display_power_domain domain; + int active_links = 0; + + mutex_lock(&dig_port->tc_lock); +@@ -708,21 +748,14 @@ void intel_tc_port_sanitize(struct intel + else if (encoder->base.crtc) + active_links = to_intel_crtc(encoder->base.crtc)->active; + +- drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_DISCONNECTED); +- drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref); ++ drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount != 1); ++ intel_tc_port_link_init_refcount(dig_port, active_links); + +- tc_cold_wref = tc_cold_block(dig_port, &domain); +- +- dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); + if (active_links) { + if (!icl_tc_phy_is_connected(dig_port)) + drm_dbg_kms(&i915->drm, + "Port %s: PHY disconnected with %d active link(s)\n", + dig_port->tc_port_name, active_links); +- intel_tc_port_link_init_refcount(dig_port, active_links); +- +- dig_port->tc_lock_wakeref = tc_cold_block(dig_port, +- &dig_port->tc_lock_power_domain); + } else { + /* + * TBT-alt is the default mode in any case the PHY ownership is not +@@ -736,9 +769,10 @@ void intel_tc_port_sanitize(struct intel + dig_port->tc_port_name, + tc_port_mode_name(dig_port->tc_mode)); + icl_tc_phy_disconnect(dig_port); +- } + +- tc_cold_unblock(dig_port, domain, tc_cold_wref); ++ tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain, ++ fetch_and_zero(&dig_port->tc_lock_wakeref)); ++ } + + drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n", + dig_port->tc_port_name, +@@ -923,4 +957,6 @@ void intel_tc_port_init(struct intel_dig + dig_port->tc_mode = TC_PORT_DISCONNECTED; + dig_port->tc_link_refcount = 0; + tc_port_load_fia_params(i915, dig_port); ++ ++ intel_tc_port_init_mode(dig_port); + } +--- a/drivers/gpu/drm/i915/display/intel_tc.h ++++ b/drivers/gpu/drm/i915/display/intel_tc.h +@@ -24,7 +24,8 @@ int intel_tc_port_fia_max_lane_count(str + void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, + int required_lanes); + +-void intel_tc_port_sanitize(struct intel_digital_port *dig_port); ++void intel_tc_port_init_mode(struct intel_digital_port *dig_port); ++void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port); + void intel_tc_port_lock(struct intel_digital_port *dig_port); + void intel_tc_port_unlock(struct intel_digital_port *dig_port); + void intel_tc_port_flush_work(struct intel_digital_port *dig_port); diff --git a/queue-6.1/drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch b/queue-6.1/drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch new file mode 100644 index 00000000000..a1ca9c315a9 --- /dev/null +++ b/queue-6.1/drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch @@ -0,0 +1,143 @@ +From 06f66261a1567d66b9d35c87393b6edfbea4c8f8 Mon Sep 17 00:00:00 2001 +From: Imre Deak +Date: Thu, 16 Mar 2023 15:17:14 +0200 +Subject: drm/i915/tc: Fix system resume MST mode restore for DP-alt sinks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Imre Deak + +commit 06f66261a1567d66b9d35c87393b6edfbea4c8f8 upstream. + +At least restoring the MST topology during system resume needs to use +AUX before the display HW readout->sanitization sequence is complete, +but on TC ports the PHY may be in the wrong mode for this, resulting in +the AUX transfers to fail. + +The initial TC port mode is kept fixed as BIOS left it for the above HW +readout sequence (to prevent changing the mode on an enabled port). If +the port is disabled this initial mode is TBT - as in any case the PHY +ownership is not held - even if a DP-alt sink is connected. Thus, the +AUX transfers during this time will use TBT mode instead of the expected +DP-alt mode and so time out. + +Fix the above by connecting the PHY during port initialization if the +port is disabled, which will switch to the expected mode (DP-alt in the +above case). + +As the encoder/pipe HW state isn't read-out yet at this point, check if +the port is enabled based on the DDI_BUF enabled flag. Save the read-out +initial mode, so intel_tc_port_sanitize_mode() can check this wrt. the +read-out encoder HW state. + +Signed-off-by: Imre Deak +Reviewed-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20230316131724.359612-5-imre.deak@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_tc.c | 49 +++++++++++++++++++-- + 2 files changed, 47 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/display/intel_display_types.h ++++ b/drivers/gpu/drm/i915/display/intel_display_types.h +@@ -1763,6 +1763,7 @@ struct intel_digital_port { + bool tc_legacy_port:1; + char tc_port_name[8]; + enum tc_port_mode tc_mode; ++ enum tc_port_mode tc_init_mode; + enum phy_fia tc_phy_fia; + u8 tc_phy_fia_idx; + +--- a/drivers/gpu/drm/i915/display/intel_tc.c ++++ b/drivers/gpu/drm/i915/display/intel_tc.c +@@ -5,6 +5,7 @@ + + #include "i915_drv.h" + #include "i915_reg.h" ++#include "intel_de.h" + #include "intel_display.h" + #include "intel_display_power_map.h" + #include "intel_display_types.h" +@@ -116,6 +117,24 @@ assert_tc_cold_blocked(struct intel_digi + drm_WARN_ON(&i915->drm, !enabled); + } + ++static enum intel_display_power_domain ++tc_port_power_domain(struct intel_digital_port *dig_port) ++{ ++ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ++ enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); ++ ++ return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1; ++} ++ ++static void ++assert_tc_port_power_enabled(struct intel_digital_port *dig_port) ++{ ++ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ++ ++ drm_WARN_ON(&i915->drm, ++ !intel_display_power_is_enabled(i915, tc_port_power_domain(dig_port))); ++} ++ + u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port) + { + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); +@@ -693,6 +712,16 @@ static void __intel_tc_port_put_link(str + dig_port->tc_link_refcount--; + } + ++static bool tc_port_is_enabled(struct intel_digital_port *dig_port) ++{ ++ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ++ ++ assert_tc_port_power_enabled(dig_port); ++ ++ return intel_de_read(i915, DDI_BUF_CTL(dig_port->base.port)) & ++ DDI_BUF_CTL_ENABLE; ++} ++ + /** + * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode + * @dig_port: digital port +@@ -715,9 +744,23 @@ void intel_tc_port_init_mode(struct inte + tc_cold_wref = tc_cold_block(dig_port, &domain); + + dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); ++ /* ++ * Save the initial mode for the state check in ++ * intel_tc_port_sanitize_mode(). ++ */ ++ dig_port->tc_init_mode = dig_port->tc_mode; ++ dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); ++ ++ /* ++ * The PHY needs to be connected for AUX to work during HW readout and ++ * MST topology resume, but the PHY mode can only be changed if the ++ * port is disabled. ++ */ ++ if (!tc_port_is_enabled(dig_port)) ++ intel_tc_port_update_mode(dig_port, 1, false); ++ + /* Prevent changing dig_port->tc_mode until intel_tc_port_sanitize_mode() is called. */ + __intel_tc_port_get_link(dig_port); +- dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); + + tc_cold_unblock(dig_port, domain, tc_cold_wref); + +@@ -764,11 +807,11 @@ void intel_tc_port_sanitize_mode(struct + * we'll just switch to disconnected mode from it here without + * a note. + */ +- if (dig_port->tc_mode != TC_PORT_TBT_ALT) ++ if (dig_port->tc_init_mode != TC_PORT_TBT_ALT) + drm_dbg_kms(&i915->drm, + "Port %s: PHY left in %s mode on disabled port, disconnecting it\n", + dig_port->tc_port_name, +- tc_port_mode_name(dig_port->tc_mode)); ++ tc_port_mode_name(dig_port->tc_init_mode)); + icl_tc_phy_disconnect(dig_port); + __intel_tc_port_put_link(dig_port); + diff --git a/queue-6.1/drm-i915-tc-fix-tc-port-link-ref-init-for-dp-mst-during-hw-readout.patch b/queue-6.1/drm-i915-tc-fix-tc-port-link-ref-init-for-dp-mst-during-hw-readout.patch new file mode 100644 index 00000000000..796b8833c78 --- /dev/null +++ b/queue-6.1/drm-i915-tc-fix-tc-port-link-ref-init-for-dp-mst-during-hw-readout.patch @@ -0,0 +1,95 @@ +From 67165722c27cc46de112a4e10b450170c8980a6f Mon Sep 17 00:00:00 2001 +From: Imre Deak +Date: Thu, 16 Mar 2023 15:17:12 +0200 +Subject: drm/i915/tc: Fix TC port link ref init for DP MST during HW readout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Imre Deak + +commit 67165722c27cc46de112a4e10b450170c8980a6f upstream. + +An enabled TC MST port holds one TC port link reference, regardless of +the number of enabled streams on it, but the TC port HW readout takes +one reference for each active MST stream. + +Fix the HW readout, taking only one reference for MST ports. + +This didn't cause an actual problem, since the encoder HW readout doesn't +yet support reading out the MST HW state. + +Signed-off-by: Imre Deak +Reviewed-by: Ville Syrjälä +Reviewed-by: Mika Kahola +Reviewed-by: Andrzej Hajda +Link: https://patchwork.freedesktop.org/patch/msgid/20230316131724.359612-3-imre.deak@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_tc.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/i915/display/intel_tc.c ++++ b/drivers/gpu/drm/i915/display/intel_tc.c +@@ -683,11 +683,14 @@ static void intel_tc_port_update_mode(st + tc_cold_unblock(dig_port, domain, wref); + } + +-static void +-intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port, +- int refcount) ++static void __intel_tc_port_get_link(struct intel_digital_port *dig_port) + { +- dig_port->tc_link_refcount = refcount; ++ dig_port->tc_link_refcount++; ++} ++ ++static void __intel_tc_port_put_link(struct intel_digital_port *dig_port) ++{ ++ dig_port->tc_link_refcount--; + } + + /** +@@ -713,7 +716,7 @@ void intel_tc_port_init_mode(struct inte + + dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); + /* Prevent changing dig_port->tc_mode until intel_tc_port_sanitize_mode() is called. */ +- intel_tc_port_link_init_refcount(dig_port, 1); ++ __intel_tc_port_get_link(dig_port); + dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); + + tc_cold_unblock(dig_port, domain, tc_cold_wref); +@@ -749,8 +752,6 @@ void intel_tc_port_sanitize_mode(struct + active_links = to_intel_crtc(encoder->base.crtc)->active; + + drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount != 1); +- intel_tc_port_link_init_refcount(dig_port, active_links); +- + if (active_links) { + if (!icl_tc_phy_is_connected(dig_port)) + drm_dbg_kms(&i915->drm, +@@ -769,6 +770,7 @@ void intel_tc_port_sanitize_mode(struct + dig_port->tc_port_name, + tc_port_mode_name(dig_port->tc_mode)); + icl_tc_phy_disconnect(dig_port); ++ __intel_tc_port_put_link(dig_port); + + tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain, + fetch_and_zero(&dig_port->tc_lock_wakeref)); +@@ -880,14 +882,14 @@ void intel_tc_port_get_link(struct intel + int required_lanes) + { + __intel_tc_port_lock(dig_port, required_lanes); +- dig_port->tc_link_refcount++; ++ __intel_tc_port_get_link(dig_port); + intel_tc_port_unlock(dig_port); + } + + void intel_tc_port_put_link(struct intel_digital_port *dig_port) + { + intel_tc_port_lock(dig_port); +- --dig_port->tc_link_refcount; ++ __intel_tc_port_put_link(dig_port); + intel_tc_port_unlock(dig_port); + + /* diff --git a/queue-6.1/series b/queue-6.1/series index ae25d8f18ee..1200d2e1157 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -588,3 +588,6 @@ xfs-check-that-per-cpu-inodegc-workers-actually-run-on-that-cpu.patch xfs-disable-reaping-in-fscounters-scrub.patch xfs-fix-xfs_inodegc_stop-racing-with-mod_delayed_work.patch mm-mmap-fix-extra-maple-tree-write.patch +drm-i915-fix-typec-mode-initialization-during-system-resume.patch +drm-i915-tc-fix-tc-port-link-ref-init-for-dp-mst-during-hw-readout.patch +drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch -- 2.47.3