]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jul 2023 15:07:04 +0000 (17:07 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jul 2023 15:07:04 +0000 (17:07 +0200)
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

queue-6.1/drm-i915-fix-typec-mode-initialization-during-system-resume.patch [new file with mode: 0644]
queue-6.1/drm-i915-tc-fix-system-resume-mst-mode-restore-for-dp-alt-sinks.patch [new file with mode: 0644]
queue-6.1/drm-i915-tc-fix-tc-port-link-ref-init-for-dp-mst-during-hw-readout.patch [new file with mode: 0644]
queue-6.1/series

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 (file)
index 0000000..1574e9d
--- /dev/null
@@ -0,0 +1,182 @@
+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);
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 (file)
index 0000000..a1ca9c3
--- /dev/null
@@ -0,0 +1,143 @@
+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);
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 (file)
index 0000000..796b883
--- /dev/null
@@ -0,0 +1,95 @@
+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);
+       /*
index ae25d8f18ee8da46203e6ee436732848dacaabed..1200d2e115792a7a8c0d10ee744efc71803e15b8 100644 (file)
@@ -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