--- /dev/null
+From a82796a2e332d108b2d3aff38509caad370f69b5 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@intel.com>
+Date: Thu, 22 Sep 2022 20:21:48 +0300
+Subject: drm/i915: Fix TypeC mode initialization during system resume
+
+From: Imre Deak <imre.deak@intel.com>
+
+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 <imre.deak@intel.com>
+Reviewed-by: Mika Kahola <mika.kahola@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220922172148.2913088-1-imre.deak@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
--- /dev/null
+From 06f66261a1567d66b9d35c87393b6edfbea4c8f8 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@intel.com>
+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 <imre.deak@intel.com>
+
+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 <imre.deak@intel.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230316131724.359612-5-imre.deak@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+
--- /dev/null
+From 67165722c27cc46de112a4e10b450170c8980a6f Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@intel.com>
+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 <imre.deak@intel.com>
+
+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 <imre.deak@intel.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Reviewed-by: Mika Kahola <mika.kahola@intel.com>
+Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230316131724.359612-3-imre.deak@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+
+ /*
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