]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 25 Jul 2023 10:26:29 +0000 (12:26 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 25 Jul 2023 10:26:29 +0000 (12:26 +0200)
added patches:
drm-amd-display-add-polling-method-to-handle-mst-reply-packet.patch
drm-amd-display-clean-up-errors-warnings-in-amdgpu_dm.c.patch
drm-amd-display-fix-linux-dp-link-lost-handled-only-one-time.patch
drm-amd-display-fix-some-coding-style-issues.patch
drm-amd-display-force-connector-state-when-bpc-changes-during-compliance.patch
drm-amd-display-use-max_dsc_bpp-in-amdgpu_dm.patch
drm-dp_mst-clear-msg_rdy-flag-before-sending-new-message.patch

queue-6.1/drm-amd-display-add-polling-method-to-handle-mst-reply-packet.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-clean-up-errors-warnings-in-amdgpu_dm.c.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-fix-linux-dp-link-lost-handled-only-one-time.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-fix-some-coding-style-issues.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-force-connector-state-when-bpc-changes-during-compliance.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-use-max_dsc_bpp-in-amdgpu_dm.patch [new file with mode: 0644]
queue-6.1/drm-dp_mst-clear-msg_rdy-flag-before-sending-new-message.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/drm-amd-display-add-polling-method-to-handle-mst-reply-packet.patch b/queue-6.1/drm-amd-display-add-polling-method-to-handle-mst-reply-packet.patch
new file mode 100644 (file)
index 0000000..a907dcc
--- /dev/null
@@ -0,0 +1,365 @@
+From stable-owner@vger.kernel.org Tue Jul 25 00:26:58 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Mon, 24 Jul 2023 17:26:38 -0500
+Subject: drm/amd/display: Add polling method to handle MST reply packet
+To: <stable@vger.kernel.org>
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230724222638.1477-8-mario.limonciello@amd.com>
+
+From: Wayne Lin <wayne.lin@amd.com>
+
+commit 4f6d9e38c4d244ad106eb9ebd8c0e1215e866f35 upstream.
+
+[Why]
+Specific TBT4 dock doesn't send out short HPD to notify source
+that IRQ event DOWN_REP_MSG_RDY is set. Which violates the spec
+and cause source can't send out streams to mst sinks.
+
+[How]
+To cover this misbehavior, add an additional polling method to detect
+DOWN_REP_MSG_RDY is set. HPD driven handling method is still kept.
+Just hook up our handler to drm mgr->cbs->poll_hpd_irq().
+
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Jerry Zuo <jerry.zuo@amd.com>
+Acked-by: Alan Liu <haoping.liu@amd.com>
+Signed-off-by: Wayne Lin <wayne.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c           |  117 +++---------
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h           |    7 
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c |  110 +++++++++++
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h |   11 +
+ 4 files changed, 159 insertions(+), 86 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -1325,6 +1325,15 @@ static void dm_handle_hpd_rx_offload_wor
+       if (amdgpu_in_reset(adev))
+               goto skip;
++      if (offload_work->data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
++              offload_work->data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
++              dm_handle_mst_sideband_msg_ready_event(&aconnector->mst_mgr, DOWN_OR_UP_MSG_RDY_EVENT);
++              spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
++              offload_work->offload_wq->is_handling_mst_msg_rdy_event = false;
++              spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
++              goto skip;
++      }
++
+       mutex_lock(&adev->dm.dc_lock);
+       if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
+               dc_link_dp_handle_automated_test(dc_link);
+@@ -3229,87 +3238,6 @@ static void handle_hpd_irq(void *param)
+ }
+-static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
+-{
+-      u8 esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
+-      u8 dret;
+-      bool new_irq_handled = false;
+-      int dpcd_addr;
+-      int dpcd_bytes_to_read;
+-
+-      const int max_process_count = 30;
+-      int process_count = 0;
+-
+-      const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
+-
+-      if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
+-              dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
+-              /* DPCD 0x200 - 0x201 for downstream IRQ */
+-              dpcd_addr = DP_SINK_COUNT;
+-      } else {
+-              dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
+-              /* DPCD 0x2002 - 0x2005 for downstream IRQ */
+-              dpcd_addr = DP_SINK_COUNT_ESI;
+-      }
+-
+-      dret = drm_dp_dpcd_read(
+-              &aconnector->dm_dp_aux.aux,
+-              dpcd_addr,
+-              esi,
+-              dpcd_bytes_to_read);
+-
+-      while (dret == dpcd_bytes_to_read &&
+-              process_count < max_process_count) {
+-              u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
+-              u8 retry;
+-
+-              dret = 0;
+-
+-              process_count++;
+-
+-              DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+-              /* handle HPD short pulse irq */
+-              if (aconnector->mst_mgr.mst_state)
+-                      drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
+-                                                      esi,
+-                                                      ack,
+-                                                      &new_irq_handled);
+-
+-              if (new_irq_handled) {
+-                      /* ACK at DPCD to notify down stream */
+-                      for (retry = 0; retry < 3; retry++) {
+-                              ssize_t wret;
+-
+-                              wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
+-                                                        dpcd_addr + 1,
+-                                                        ack[1]);
+-                              if (wret == 1)
+-                                      break;
+-                      }
+-
+-                      if (retry == 3) {
+-                              DRM_ERROR("Failed to ack MST event.\n");
+-                              return;
+-                      }
+-
+-                      drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
+-                      /* check if there is new irq to be handled */
+-                      dret = drm_dp_dpcd_read(
+-                              &aconnector->dm_dp_aux.aux,
+-                              dpcd_addr,
+-                              esi,
+-                              dpcd_bytes_to_read);
+-
+-                      new_irq_handled = false;
+-              } else {
+-                      break;
+-              }
+-      }
+-
+-      if (process_count == max_process_count)
+-              DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
+-}
+-
+ static void schedule_hpd_rx_offload_work(struct hpd_rx_irq_offload_work_queue *offload_wq,
+                                                       union hpd_irq_data hpd_irq_data)
+ {
+@@ -3371,7 +3299,23 @@ static void handle_hpd_rx_irq(void *para
+       if (dc_link_dp_allow_hpd_rx_irq(dc_link)) {
+               if (hpd_irq_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
+                       hpd_irq_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
+-                      dm_handle_mst_sideband_msg(aconnector);
++                      bool skip = false;
++
++                      /*
++                       * DOWN_REP_MSG_RDY is also handled by polling method
++                       * mgr->cbs->poll_hpd_irq()
++                       */
++                      spin_lock(&offload_wq->offload_lock);
++                      skip = offload_wq->is_handling_mst_msg_rdy_event;
++
++                      if (!skip)
++                              offload_wq->is_handling_mst_msg_rdy_event = true;
++
++                      spin_unlock(&offload_wq->offload_lock);
++
++                      if (!skip)
++                              schedule_hpd_rx_offload_work(offload_wq, hpd_irq_data);
++
+                       goto out;
+               }
+@@ -3482,11 +3426,11 @@ static void register_hpd_handlers(struct
+                       amdgpu_dm_irq_register_interrupt(adev, &int_params,
+                                       handle_hpd_rx_irq,
+                                       (void *) aconnector);
+-
+-                      if (adev->dm.hpd_rx_offload_wq)
+-                              adev->dm.hpd_rx_offload_wq[dc_link->link_index].aconnector =
+-                                      aconnector;
+               }
++
++              if (adev->dm.hpd_rx_offload_wq)
++                      adev->dm.hpd_rx_offload_wq[connector->index].aconnector =
++                              aconnector;
+       }
+ }
+@@ -7082,6 +7026,7 @@ void amdgpu_dm_connector_init_helper(str
+       aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */
+       aconnector->audio_inst = -1;
+       mutex_init(&aconnector->hpd_lock);
++      mutex_init(&aconnector->handle_mst_msg_ready);
+       /*
+        * configure support HPD hot plug connector_>polled default value is 0
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+@@ -194,6 +194,11 @@ struct hpd_rx_irq_offload_work_queue {
+        */
+       bool is_handling_link_loss;
+       /**
++       * @is_handling_mst_msg_rdy_event: Used to prevent inserting mst message
++       * ready event when we're already handling mst message ready event
++       */
++      bool is_handling_mst_msg_rdy_event;
++      /**
+        * @aconnector: The aconnector that this work queue is attached to
+        */
+       struct amdgpu_dm_connector *aconnector;
+@@ -614,6 +619,8 @@ struct amdgpu_dm_connector {
+       struct drm_dp_mst_port *port;
+       struct amdgpu_dm_connector *mst_port;
+       struct drm_dp_aux *dsc_aux;
++      struct mutex handle_mst_msg_ready;
++
+       /* TODO see if we can merge with ddc_bus or make a dm_connector */
+       struct amdgpu_i2c_adapter *i2c;
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -590,8 +590,118 @@ dm_dp_add_mst_connector(struct drm_dp_ms
+       return connector;
+ }
++void dm_handle_mst_sideband_msg_ready_event(
++      struct drm_dp_mst_topology_mgr *mgr,
++      enum mst_msg_ready_type msg_rdy_type)
++{
++      uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
++      uint8_t dret;
++      bool new_irq_handled = false;
++      int dpcd_addr;
++      uint8_t dpcd_bytes_to_read;
++      const uint8_t max_process_count = 30;
++      uint8_t process_count = 0;
++      u8 retry;
++      struct amdgpu_dm_connector *aconnector =
++                      container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
++
++
++      const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
++
++      if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
++              dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
++              /* DPCD 0x200 - 0x201 for downstream IRQ */
++              dpcd_addr = DP_SINK_COUNT;
++      } else {
++              dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
++              /* DPCD 0x2002 - 0x2005 for downstream IRQ */
++              dpcd_addr = DP_SINK_COUNT_ESI;
++      }
++
++      mutex_lock(&aconnector->handle_mst_msg_ready);
++
++      while (process_count < max_process_count) {
++              u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
++
++              process_count++;
++
++              dret = drm_dp_dpcd_read(
++                      &aconnector->dm_dp_aux.aux,
++                      dpcd_addr,
++                      esi,
++                      dpcd_bytes_to_read);
++
++              if (dret != dpcd_bytes_to_read) {
++                      DRM_DEBUG_KMS("DPCD read and acked number is not as expected!");
++                      break;
++              }
++
++              DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
++
++              switch (msg_rdy_type) {
++              case DOWN_REP_MSG_RDY_EVENT:
++                      /* Only handle DOWN_REP_MSG_RDY case*/
++                      esi[1] &= DP_DOWN_REP_MSG_RDY;
++                      break;
++              case UP_REQ_MSG_RDY_EVENT:
++                      /* Only handle UP_REQ_MSG_RDY case*/
++                      esi[1] &= DP_UP_REQ_MSG_RDY;
++                      break;
++              default:
++                      /* Handle both cases*/
++                      esi[1] &= (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY);
++                      break;
++              }
++
++              if (!esi[1])
++                      break;
++
++              /* handle MST irq */
++              if (aconnector->mst_mgr.mst_state)
++                      drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
++                                               esi,
++                                               ack,
++                                               &new_irq_handled);
++
++              if (new_irq_handled) {
++                      /* ACK at DPCD to notify down stream */
++                      for (retry = 0; retry < 3; retry++) {
++                              ssize_t wret;
++
++                              wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
++                                                        dpcd_addr + 1,
++                                                        ack[1]);
++                              if (wret == 1)
++                                      break;
++                      }
++
++                      if (retry == 3) {
++                              DRM_ERROR("Failed to ack MST event.\n");
++                              return;
++                      }
++
++                      drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
++
++                      new_irq_handled = false;
++              } else {
++                      break;
++              }
++      }
++
++      mutex_unlock(&aconnector->handle_mst_msg_ready);
++
++      if (process_count == max_process_count)
++              DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
++}
++
++static void dm_handle_mst_down_rep_msg_ready(struct drm_dp_mst_topology_mgr *mgr)
++{
++      dm_handle_mst_sideband_msg_ready_event(mgr, DOWN_REP_MSG_RDY_EVENT);
++}
++
+ static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
+       .add_connector = dm_dp_add_mst_connector,
++      .poll_hpd_irq = dm_handle_mst_down_rep_msg_ready,
+ };
+ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+@@ -49,6 +49,13 @@
+ #define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B    1031
+ #define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B 1000
++enum mst_msg_ready_type {
++      NONE_MSG_RDY_EVENT = 0,
++      DOWN_REP_MSG_RDY_EVENT = 1,
++      UP_REQ_MSG_RDY_EVENT = 2,
++      DOWN_OR_UP_MSG_RDY_EVENT = 3
++};
++
+ struct amdgpu_display_manager;
+ struct amdgpu_dm_connector;
+@@ -61,6 +68,10 @@ void amdgpu_dm_initialize_dp_connector(s
+ void
+ dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);
++void dm_handle_mst_sideband_msg_ready_event(
++      struct drm_dp_mst_topology_mgr *mgr,
++      enum mst_msg_ready_type msg_rdy_type);
++
+ struct dsc_mst_fairness_vars {
+       int pbn;
+       bool dsc_enabled;
diff --git a/queue-6.1/drm-amd-display-clean-up-errors-warnings-in-amdgpu_dm.c.patch b/queue-6.1/drm-amd-display-clean-up-errors-warnings-in-amdgpu_dm.c.patch
new file mode 100644 (file)
index 0000000..501e988
--- /dev/null
@@ -0,0 +1,517 @@
+From stable-owner@vger.kernel.org Tue Jul 25 00:26:56 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Mon, 24 Jul 2023 17:26:36 -0500
+Subject: drm/amd/display: Clean up errors & warnings in amdgpu_dm.c
+To: <stable@vger.kernel.org>
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230724222638.1477-6-mario.limonciello@amd.com>
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+commit 87279fdf5ee0ad1360765ef70389d1c4d0f81bb6 upstream.
+
+Fix the following errors & warnings reported by checkpatch:
+
+ERROR: space required before the open brace '{'
+ERROR: space required before the open parenthesis '('
+ERROR: that open brace { should be on the previous line
+ERROR: space prohibited before that ',' (ctx:WxW)
+ERROR: else should follow close brace '}'
+ERROR: open brace '{' following function definitions go on the next line
+ERROR: code indent should use tabs where possible
+
+WARNING: braces {} are not necessary for single statement blocks
+WARNING: void function return statements are not generally useful
+WARNING: Block comments use * on subsequent lines
+WARNING: Block comments use a trailing */ on a separate line
+
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[ Modified for missing
+  c5a31f178e35 ("drm/amd/display: move dp irq handler functions from dc_link_dp to link_dp_irq_handler")
+  which landed in 6.3]
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  133 ++++++++++------------
+ 1 file changed, 65 insertions(+), 68 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -408,12 +408,12 @@ static void dm_pflip_high_irq(void *inte
+       spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
+-      if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
+-              DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n",
+-                                               amdgpu_crtc->pflip_status,
+-                                               AMDGPU_FLIP_SUBMITTED,
+-                                               amdgpu_crtc->crtc_id,
+-                                               amdgpu_crtc);
++      if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
++              DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
++                           amdgpu_crtc->pflip_status,
++                           AMDGPU_FLIP_SUBMITTED,
++                           amdgpu_crtc->crtc_id,
++                           amdgpu_crtc);
+               spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
+               return;
+       }
+@@ -861,7 +861,7 @@ static int dm_set_powergating_state(void
+ }
+ /* Prototypes of private functions */
+-static int dm_early_init(void* handle);
++static int dm_early_init(void *handle);
+ /* Allocate memory for FBC compressed data  */
+ static void amdgpu_dm_fbc_init(struct drm_connector *connector)
+@@ -1260,7 +1260,7 @@ static void mmhub_read_system_context(st
+       pa_config->system_aperture.start_addr = (uint64_t)logical_addr_low << 18;
+       pa_config->system_aperture.end_addr = (uint64_t)logical_addr_high << 18;
+-      pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24 ;
++      pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24;
+       pa_config->system_aperture.agp_bot = (uint64_t)agp_bot << 24;
+       pa_config->system_aperture.agp_top = (uint64_t)agp_top << 24;
+@@ -1343,8 +1343,7 @@ static void dm_handle_hpd_rx_offload_wor
+               DP_TEST_RESPONSE,
+               &test_response.raw,
+               sizeof(test_response));
+-      }
+-      else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
++      } else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
+                       hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) &&
+                       dc_link_dp_allow_hpd_rx_irq(dc_link)) {
+               dc_link_dp_handle_link_loss(dc_link);
+@@ -1519,7 +1518,7 @@ static int amdgpu_dm_init(struct amdgpu_
+       mutex_init(&adev->dm.audio_lock);
+       spin_lock_init(&adev->dm.vblank_lock);
+-      if(amdgpu_dm_irq_init(adev)) {
++      if (amdgpu_dm_irq_init(adev)) {
+               DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
+               goto error;
+       }
+@@ -1654,9 +1653,8 @@ static int amdgpu_dm_init(struct amdgpu_
+       if (amdgpu_dc_debug_mask & DC_DISABLE_STUTTER)
+               adev->dm.dc->debug.disable_stutter = true;
+-      if (amdgpu_dc_debug_mask & DC_DISABLE_DSC) {
++      if (amdgpu_dc_debug_mask & DC_DISABLE_DSC)
+               adev->dm.dc->debug.disable_dsc = true;
+-      }
+       if (amdgpu_dc_debug_mask & DC_DISABLE_CLOCK_GATING)
+               adev->dm.dc->debug.disable_clock_gate = true;
+@@ -1877,8 +1875,6 @@ static void amdgpu_dm_fini(struct amdgpu
+       mutex_destroy(&adev->dm.audio_lock);
+       mutex_destroy(&adev->dm.dc_lock);
+       mutex_destroy(&adev->dm.dpia_aux_lock);
+-
+-      return;
+ }
+ static int load_dmcu_fw(struct amdgpu_device *adev)
+@@ -1887,7 +1883,7 @@ static int load_dmcu_fw(struct amdgpu_de
+       int r;
+       const struct dmcu_firmware_header_v1_0 *hdr;
+-      switch(adev->asic_type) {
++      switch (adev->asic_type) {
+ #if defined(CONFIG_DRM_AMD_DC_SI)
+       case CHIP_TAHITI:
+       case CHIP_PITCAIRN:
+@@ -2679,7 +2675,7 @@ static void dm_gpureset_commit_state(str
+               struct dc_scaling_info scaling_infos[MAX_SURFACES];
+               struct dc_flip_addrs flip_addrs[MAX_SURFACES];
+               struct dc_stream_update stream_update;
+-      } * bundle;
++      } *bundle;
+       int k, m;
+       bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
+@@ -2709,8 +2705,6 @@ static void dm_gpureset_commit_state(str
+ cleanup:
+       kfree(bundle);
+-
+-      return;
+ }
+ static int dm_resume(void *handle)
+@@ -2924,8 +2918,7 @@ static const struct amd_ip_funcs amdgpu_
+       .set_powergating_state = dm_set_powergating_state,
+ };
+-const struct amdgpu_ip_block_version dm_ip_block =
+-{
++const struct amdgpu_ip_block_version dm_ip_block = {
+       .type = AMD_IP_BLOCK_TYPE_DCE,
+       .major = 1,
+       .minor = 0,
+@@ -2982,9 +2975,12 @@ static void update_connector_ext_caps(st
+       caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
+       caps->aux_support = false;
+-      if (caps->ext_caps->bits.oled == 1 /*||
+-          caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
+-          caps->ext_caps->bits.hdr_aux_backlight_control == 1*/)
++      if (caps->ext_caps->bits.oled == 1
++          /*
++           * ||
++           * caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
++           * caps->ext_caps->bits.hdr_aux_backlight_control == 1
++           */)
+               caps->aux_support = true;
+       if (amdgpu_backlight == 0)
+@@ -3248,6 +3244,7 @@ static void dm_handle_mst_sideband_msg(s
+               process_count < max_process_count) {
+               u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
+               u8 retry;
++
+               dret = 0;
+               process_count++;
+@@ -3449,7 +3446,7 @@ static void register_hpd_handlers(struct
+               aconnector = to_amdgpu_dm_connector(connector);
+               dc_link = aconnector->dc_link;
+-              if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
++              if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
+                       int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
+                       int_params.irq_source = dc_link->irq_source_hpd;
+@@ -3458,7 +3455,7 @@ static void register_hpd_handlers(struct
+                                       (void *) aconnector);
+               }
+-              if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
++              if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
+                       /* Also register for DP short pulse (hpd_rx). */
+                       int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
+@@ -3484,7 +3481,7 @@ static int dce60_register_irq_handlers(s
+       struct dc_interrupt_params int_params = {0};
+       int r;
+       int i;
+-      unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
++      unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+       int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+       int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+@@ -3498,11 +3495,12 @@ static int dce60_register_irq_handlers(s
+        *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
+        *    coming from DC hardware.
+        *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
+-       *    for acknowledging and handling. */
++       *    for acknowledging and handling.
++       */
+       /* Use VBLANK interrupt */
+       for (i = 0; i < adev->mode_info.num_crtc; i++) {
+-              r = amdgpu_irq_add_id(adev, client_id, i+1 , &adev->crtc_irq);
++              r = amdgpu_irq_add_id(adev, client_id, i + 1, &adev->crtc_irq);
+               if (r) {
+                       DRM_ERROR("Failed to add crtc irq id!\n");
+                       return r;
+@@ -3510,7 +3508,7 @@ static int dce60_register_irq_handlers(s
+               int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+               int_params.irq_source =
+-                      dc_interrupt_to_irq_source(dc, i+1 , 0);
++                      dc_interrupt_to_irq_source(dc, i + 1, 0);
+               c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
+@@ -3566,7 +3564,7 @@ static int dce110_register_irq_handlers(
+       struct dc_interrupt_params int_params = {0};
+       int r;
+       int i;
+-      unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
++      unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+       if (adev->family >= AMDGPU_FAMILY_AI)
+               client_id = SOC15_IH_CLIENTID_DCE;
+@@ -3583,7 +3581,8 @@ static int dce110_register_irq_handlers(
+        *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
+        *    coming from DC hardware.
+        *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
+-       *    for acknowledging and handling. */
++       *    for acknowledging and handling.
++       */
+       /* Use VBLANK interrupt */
+       for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) {
+@@ -4032,7 +4031,7 @@ static void amdgpu_dm_update_backlight_c
+ }
+ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
+-                              unsigned *min, unsigned *max)
++                              unsigned int *min, unsigned int *max)
+ {
+       if (!caps)
+               return 0;
+@@ -4052,7 +4051,7 @@ static int get_brightness_range(const st
+ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
+                                       uint32_t brightness)
+ {
+-      unsigned min, max;
++      unsigned int min, max;
+       if (!get_brightness_range(caps, &min, &max))
+               return brightness;
+@@ -4065,7 +4064,7 @@ static u32 convert_brightness_from_user(
+ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
+                                     uint32_t brightness)
+ {
+-      unsigned min, max;
++      unsigned int min, max;
+       if (!get_brightness_range(caps, &min, &max))
+               return brightness;
+@@ -4546,7 +4545,6 @@ fail:
+ static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
+ {
+       drm_atomic_private_obj_fini(&dm->atomic_obj);
+-      return;
+ }
+ /******************************************************************************
+@@ -5272,6 +5270,7 @@ static bool adjust_colour_depth_from_dis
+ {
+       enum dc_color_depth depth = timing_out->display_color_depth;
+       int normalized_clk;
++
+       do {
+               normalized_clk = timing_out->pix_clk_100hz / 10;
+               /* YCbCr 4:2:0 requires additional adjustment of 1/2 */
+@@ -5487,6 +5486,7 @@ create_fake_sink(struct amdgpu_dm_connec
+ {
+       struct dc_sink_init_data sink_init_data = { 0 };
+       struct dc_sink *sink = NULL;
++
+       sink_init_data.link = aconnector->dc_link;
+       sink_init_data.sink_signal = aconnector->dc_link->connector_signal;
+@@ -5610,7 +5610,7 @@ get_highest_refresh_rate_mode(struct amd
+               return &aconnector->freesync_vid_base;
+       /* Find the preferred mode */
+-      list_for_each_entry (m, list_head, head) {
++      list_for_each_entry(m, list_head, head) {
+               if (m->type & DRM_MODE_TYPE_PREFERRED) {
+                       m_pref = m;
+                       break;
+@@ -5634,7 +5634,7 @@ get_highest_refresh_rate_mode(struct amd
+        * For some monitors, preferred mode is not the mode with highest
+        * supported refresh rate.
+        */
+-      list_for_each_entry (m, list_head, head) {
++      list_for_each_entry(m, list_head, head) {
+               current_refresh  = drm_mode_vrefresh(m);
+               if (m->hdisplay == m_pref->hdisplay &&
+@@ -5905,7 +5905,7 @@ create_stream_for_sink(struct amdgpu_dm_
+                * This may not be an error, the use case is when we have no
+                * usermode calls to reset and set mode upon hotplug. In this
+                * case, we call set mode ourselves to restore the previous mode
+-               * and the modelist may not be filled in in time.
++               * and the modelist may not be filled in time.
+                */
+               DRM_DEBUG_DRIVER("No preferred mode found\n");
+       } else {
+@@ -5929,9 +5929,9 @@ create_stream_for_sink(struct amdgpu_dm_
+               drm_mode_set_crtcinfo(&mode, 0);
+       /*
+-      * If scaling is enabled and refresh rate didn't change
+-      * we copy the vic and polarities of the old timings
+-      */
++       * If scaling is enabled and refresh rate didn't change
++       * we copy the vic and polarities of the old timings
++       */
+       if (!scale || mode_refresh != preferred_refresh)
+               fill_stream_properties_from_drm_display_mode(
+                       stream, &mode, &aconnector->base, con_state, NULL,
+@@ -6593,6 +6593,7 @@ static int dm_encoder_helper_atomic_chec
+       if (!state->duplicated) {
+               int max_bpc = conn_state->max_requested_bpc;
++
+               is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
+                         aconnector->force_yuv420_output;
+               color_depth = convert_color_depth_from_display_info(connector,
+@@ -6913,7 +6914,7 @@ static bool is_duplicate_mode(struct amd
+ {
+       struct drm_display_mode *m;
+-      list_for_each_entry (m, &aconnector->base.probed_modes, head) {
++      list_for_each_entry(m, &aconnector->base.probed_modes, head) {
+               if (drm_mode_equal(m, mode))
+                       return true;
+       }
+@@ -7216,7 +7217,6 @@ static int amdgpu_dm_connector_init(stru
+       link->priv = aconnector;
+-      DRM_DEBUG_DRIVER("%s()\n", __func__);
+       i2c = create_i2c(link->ddc, link->link_index, &res);
+       if (!i2c) {
+@@ -7861,8 +7861,7 @@ static void amdgpu_dm_commit_planes(stru
+                        * DRI3/Present extension with defined target_msc.
+                        */
+                       last_flip_vblank = amdgpu_get_vblank_counter_kms(pcrtc);
+-              }
+-              else {
++              } else {
+                       /* For variable refresh rate mode only:
+                        * Get vblank of last completed flip to avoid > 1 vrr
+                        * flips per video frame by use of throttling, but allow
+@@ -8189,8 +8188,8 @@ static void amdgpu_dm_atomic_commit_tail
+               dc_resource_state_copy_construct_current(dm->dc, dc_state);
+       }
+-      for_each_oldnew_crtc_in_state (state, crtc, old_crtc_state,
+-                                     new_crtc_state, i) {
++      for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
++                                    new_crtc_state, i) {
+               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+               dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+@@ -8213,9 +8212,7 @@ static void amdgpu_dm_atomic_commit_tail
+               dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+               drm_dbg_state(state->dev,
+-                      "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
+-                      "planes_changed:%d, mode_changed:%d,active_changed:%d,"
+-                      "connectors_changed:%d\n",
++                      "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
+                       acrtc->crtc_id,
+                       new_crtc_state->enable,
+                       new_crtc_state->active,
+@@ -8700,8 +8697,8 @@ static int do_aquire_global_lock(struct
+                                       &commit->flip_done, 10*HZ);
+               if (ret == 0)
+-                      DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done "
+-                                "timed out\n", crtc->base.id, crtc->name);
++                      DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done timed out\n",
++                                crtc->base.id, crtc->name);
+               drm_crtc_commit_put(commit);
+       }
+@@ -8786,7 +8783,8 @@ is_timing_unchanged_for_freesync(struct
+       return false;
+ }
+-static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) {
++static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
++{
+       u64 num, den, res;
+       struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
+@@ -8909,9 +8907,7 @@ static int dm_update_crtc_state(struct a
+               goto skip_modeset;
+       drm_dbg_state(state->dev,
+-              "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
+-              "planes_changed:%d, mode_changed:%d,active_changed:%d,"
+-              "connectors_changed:%d\n",
++              "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
+               acrtc->crtc_id,
+               new_crtc_state->enable,
+               new_crtc_state->active,
+@@ -8940,8 +8936,7 @@ static int dm_update_crtc_state(struct a
+                                                    old_crtc_state)) {
+                       new_crtc_state->mode_changed = false;
+                       DRM_DEBUG_DRIVER(
+-                              "Mode change not required for front porch change, "
+-                              "setting mode_changed to %d",
++                              "Mode change not required for front porch change, setting mode_changed to %d",
+                               new_crtc_state->mode_changed);
+                       set_freesync_fixed_config(dm_new_crtc_state);
+@@ -8953,9 +8948,8 @@ static int dm_update_crtc_state(struct a
+                       struct drm_display_mode *high_mode;
+                       high_mode = get_highest_refresh_rate_mode(aconnector, false);
+-                      if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
++                      if (!drm_mode_equal(&new_crtc_state->mode, high_mode))
+                               set_freesync_fixed_config(dm_new_crtc_state);
+-                      }
+               }
+               ret = dm_atomic_get_state(state, &dm_state);
+@@ -9123,6 +9117,7 @@ static bool should_reset_plane(struct dr
+        */
+       for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) {
+               struct amdgpu_framebuffer *old_afb, *new_afb;
++
+               if (other->type == DRM_PLANE_TYPE_CURSOR)
+                       continue;
+@@ -9221,11 +9216,12 @@ static int dm_check_cursor_fb(struct amd
+       }
+       /* Core DRM takes care of checking FB modifiers, so we only need to
+-       * check tiling flags when the FB doesn't have a modifier. */
++       * check tiling flags when the FB doesn't have a modifier.
++       */
+       if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) {
+               if (adev->family < AMDGPU_FAMILY_AI) {
+                       linear = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_2D_TILED_THIN1 &&
+-                               AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
++                               AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
+                                AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0;
+               } else {
+                       linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
+@@ -9438,12 +9434,12 @@ static int dm_check_crtc_cursor(struct d
+       /* On DCE and DCN there is no dedicated hardware cursor plane. We get a
+        * cursor per pipe but it's going to inherit the scaling and
+        * positioning from the underlying pipe. Check the cursor plane's
+-       * blending properties match the underlying planes'. */
++       * blending properties match the underlying planes'.
++       */
+       new_cursor_state = drm_atomic_get_new_plane_state(state, cursor);
+-      if (!new_cursor_state || !new_cursor_state->fb) {
++      if (!new_cursor_state || !new_cursor_state->fb)
+               return 0;
+-      }
+       dm_get_oriented_plane_size(new_cursor_state, &cursor_src_w, &cursor_src_h);
+       cursor_scale_w = new_cursor_state->crtc_w * 1000 / cursor_src_w;
+@@ -9489,6 +9485,7 @@ static int add_affected_mst_dsc_crtcs(st
+       struct drm_connector_state *conn_state, *old_conn_state;
+       struct amdgpu_dm_connector *aconnector = NULL;
+       int i;
++
+       for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
+               if (!conn_state->crtc)
+                       conn_state = old_conn_state;
+@@ -9931,7 +9928,7 @@ static int amdgpu_dm_atomic_check(struct
+       }
+       /* Store the overall update type for use later in atomic check. */
+-      for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) {
++      for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+               struct dm_crtc_state *dm_new_crtc_state =
+                       to_dm_crtc_state(new_crtc_state);
+@@ -9953,7 +9950,7 @@ fail:
+       else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS)
+               DRM_DEBUG_DRIVER("Atomic check stopped due to signal.\n");
+       else
+-              DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
++              DRM_DEBUG_DRIVER("Atomic check failed with err: %d\n", ret);
+       trace_amdgpu_dm_atomic_check_finish(state, ret);
diff --git a/queue-6.1/drm-amd-display-fix-linux-dp-link-lost-handled-only-one-time.patch b/queue-6.1/drm-amd-display-fix-linux-dp-link-lost-handled-only-one-time.patch
new file mode 100644 (file)
index 0000000..0564fb1
--- /dev/null
@@ -0,0 +1,111 @@
+From stable-owner@vger.kernel.org Tue Jul 25 00:26:54 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Mon, 24 Jul 2023 17:26:37 -0500
+Subject: drm/amd/display: fix linux dp link lost handled only one time
+To: <stable@vger.kernel.org>
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230724222638.1477-7-mario.limonciello@amd.com>
+
+From: Hersen Wu <hersenxs.wu@amd.com>
+
+commit e322843e5e33e72ff218d661f3d15ff9c9f2f1b5 upstream.
+
+[Why]
+linux amdgpu defer handle link lost irq. dm add handle
+request to irq work queue for the first irq of link lost.
+if link training fails for link lost handle, link will not
+be enabled anymore.
+
+[How]
+allow adding handle request of link lost to work queue
+before running dp link training for link lost.
+
+Signed-off-by: Hersen Wu <hersenxs.wu@amd.com>
+Acked-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[ Modified due to not having
+  c5a31f178e352 ("drm/amd/display: move dp irq handler functions from dc_link_dp to link_dp_irq_handler")
+  until kernel 6.3-rc1.]
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   24 +++++++++++++++++++---
+ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c  |    2 -
+ drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h   |    4 +++
+ 3 files changed, 26 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -1346,10 +1346,28 @@ static void dm_handle_hpd_rx_offload_wor
+       } else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
+                       hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) &&
+                       dc_link_dp_allow_hpd_rx_irq(dc_link)) {
+-              dc_link_dp_handle_link_loss(dc_link);
++              /* offload_work->data is from handle_hpd_rx_irq->
++               * schedule_hpd_rx_offload_work.this is defer handle
++               * for hpd short pulse. upon here, link status may be
++               * changed, need get latest link status from dpcd
++               * registers. if link status is good, skip run link
++               * training again.
++               */
++              union hpd_irq_data irq_data;
++
++              memset(&irq_data, 0, sizeof(irq_data));
++
++              /* before dc_link_dp_handle_link_loss, allow new link lost handle
++               * request be added to work queue if link lost at end of dc_link_
++               * dp_handle_link_loss
++               */
+               spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
+               offload_work->offload_wq->is_handling_link_loss = false;
+               spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
++
++              if ((read_hpd_rx_irq_data(dc_link, &irq_data) == DC_OK) &&
++                      hpd_rx_irq_check_link_loss_status(dc_link, &irq_data))
++                      dc_link_dp_handle_link_loss(dc_link);
+       }
+       mutex_unlock(&adev->dm.dc_lock);
+@@ -3324,7 +3342,7 @@ static void handle_hpd_rx_irq(void *para
+       union hpd_irq_data hpd_irq_data;
+       bool link_loss = false;
+       bool has_left_work = false;
+-      int idx = aconnector->base.index;
++      int idx = dc_link->link_index;
+       struct hpd_rx_irq_offload_work_queue *offload_wq = &adev->dm.hpd_rx_offload_wq[idx];
+       memset(&hpd_irq_data, 0, sizeof(hpd_irq_data));
+@@ -3466,7 +3484,7 @@ static void register_hpd_handlers(struct
+                                       (void *) aconnector);
+                       if (adev->dm.hpd_rx_offload_wq)
+-                              adev->dm.hpd_rx_offload_wq[connector->index].aconnector =
++                              adev->dm.hpd_rx_offload_wq[dc_link->link_index].aconnector =
+                                       aconnector;
+               }
+       }
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+@@ -3115,7 +3115,7 @@ struct dc_link_settings dp_get_max_link_
+       return max_link_cap;
+ }
+-static enum dc_status read_hpd_rx_irq_data(
++enum dc_status read_hpd_rx_irq_data(
+       struct dc_link *link,
+       union hpd_irq_data *irq_data)
+ {
+--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
+@@ -82,6 +82,10 @@ bool perform_link_training_with_retries(
+       enum signal_type signal,
+       bool do_fallback);
++enum dc_status read_hpd_rx_irq_data(
++      struct dc_link *link,
++      union hpd_irq_data *irq_data);
++
+ bool hpd_rx_irq_check_link_loss_status(
+       struct dc_link *link,
+       union hpd_irq_data *hpd_irq_dpcd_data);
diff --git a/queue-6.1/drm-amd-display-fix-some-coding-style-issues.patch b/queue-6.1/drm-amd-display-fix-some-coding-style-issues.patch
new file mode 100644 (file)
index 0000000..71bbd09
--- /dev/null
@@ -0,0 +1,359 @@
+From stable-owner@vger.kernel.org Tue Jul 25 00:26:52 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Mon, 24 Jul 2023 17:26:33 -0500
+Subject: drm/amd/display: fix some coding style issues
+To: <stable@vger.kernel.org>
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230724222638.1477-3-mario.limonciello@amd.com>
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+commit ae67558be712237109100fd14f12378adcf24356 upstream.
+
+Fix the following checkpatch checks in amdgpu_dm.c
+
+CHECK: Prefer kernel type 'u8' over 'uint8_t'
+CHECK: Prefer kernel type 'u32' over 'uint32_t'
+CHECK: Prefer kernel type 'u64' over 'uint64_t'
+CHECK: Prefer kernel type 's32' over 'int32_t'
+
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[ PSR-SU support was introduced in kernel 6.2 with commits like
+  30ebe41582d1 ("drm/amd/display: add FB_DAMAGE_CLIPS support")
+  but PSR-SU isn't enabled in 6.1.y, so this block needs to be skipped
+  when backporting. ]
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   90 +++++++++++-----------
+ 1 file changed, 45 insertions(+), 45 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -211,7 +211,7 @@ static void amdgpu_dm_destroy_drm_device
+ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
+                                   struct amdgpu_dm_connector *amdgpu_dm_connector,
+-                                  uint32_t link_index,
++                                  u32 link_index,
+                                   struct amdgpu_encoder *amdgpu_encoder);
+ static int amdgpu_dm_encoder_init(struct drm_device *dev,
+                                 struct amdgpu_encoder *aencoder,
+@@ -263,7 +263,7 @@ static u32 dm_vblank_get_counter(struct
+ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
+                                 u32 *vbl, u32 *position)
+ {
+-      uint32_t v_blank_start, v_blank_end, h_position, v_position;
++      u32 v_blank_start, v_blank_end, h_position, v_position;
+       if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
+               return -EINVAL;
+@@ -391,7 +391,7 @@ static void dm_pflip_high_irq(void *inte
+       struct amdgpu_device *adev = irq_params->adev;
+       unsigned long flags;
+       struct drm_pending_vblank_event *e;
+-      uint32_t vpos, hpos, v_blank_start, v_blank_end;
++      u32 vpos, hpos, v_blank_start, v_blank_end;
+       bool vrr_active;
+       amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP);
+@@ -678,7 +678,7 @@ static void dmub_hpd_callback(struct amd
+       struct drm_connector *connector;
+       struct drm_connector_list_iter iter;
+       struct dc_link *link;
+-      uint8_t link_index = 0;
++      u8 link_index = 0;
+       struct drm_device *dev;
+       if (adev == NULL)
+@@ -779,7 +779,7 @@ static void dm_dmub_outbox1_low_irq(void
+       struct amdgpu_device *adev = irq_params->adev;
+       struct amdgpu_display_manager *dm = &adev->dm;
+       struct dmcub_trace_buf_entry entry = { 0 };
+-      uint32_t count = 0;
++      u32 count = 0;
+       struct dmub_hpd_work *dmub_hpd_wrk;
+       struct dc_link *plink = NULL;
+@@ -1045,7 +1045,7 @@ static int dm_dmub_hw_init(struct amdgpu
+       struct dmub_srv_hw_params hw_params;
+       enum dmub_status status;
+       const unsigned char *fw_inst_const, *fw_bss_data;
+-      uint32_t i, fw_inst_const_size, fw_bss_data_size;
++      u32 i, fw_inst_const_size, fw_bss_data_size;
+       bool has_hw_support;
+       if (!dmub_srv)
+@@ -1206,10 +1206,10 @@ static void dm_dmub_hw_resume(struct amd
+ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
+ {
+-      uint64_t pt_base;
+-      uint32_t logical_addr_low;
+-      uint32_t logical_addr_high;
+-      uint32_t agp_base, agp_bot, agp_top;
++      u64 pt_base;
++      u32 logical_addr_low;
++      u32 logical_addr_high;
++      u32 agp_base, agp_bot, agp_top;
+       PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base;
+       memset(pa_config, 0, sizeof(*pa_config));
+@@ -2536,7 +2536,7 @@ struct amdgpu_dm_connector *
+ amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
+                                            struct drm_crtc *crtc)
+ {
+-      uint32_t i;
++      u32 i;
+       struct drm_connector_state *new_con_state;
+       struct drm_connector *connector;
+       struct drm_crtc *crtc_from_state;
+@@ -3172,8 +3172,8 @@ static void handle_hpd_irq(void *param)
+ static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
+ {
+-      uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
+-      uint8_t dret;
++      u8 esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
++      u8 dret;
+       bool new_irq_handled = false;
+       int dpcd_addr;
+       int dpcd_bytes_to_read;
+@@ -3201,7 +3201,7 @@ static void dm_handle_mst_sideband_msg(s
+       while (dret == dpcd_bytes_to_read &&
+               process_count < max_process_count) {
+-              uint8_t retry;
++              u8 retry;
+               dret = 0;
+               process_count++;
+@@ -3220,7 +3220,7 @@ static void dm_handle_mst_sideband_msg(s
+                               dpcd_bytes_to_read - 1;
+                       for (retry = 0; retry < 3; retry++) {
+-                              uint8_t wret;
++                              u8 wret;
+                               wret = drm_dp_dpcd_write(
+                                       &aconnector->dm_dp_aux.aux,
+@@ -4236,12 +4236,12 @@ static void amdgpu_set_panel_orientation
+ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+ {
+       struct amdgpu_display_manager *dm = &adev->dm;
+-      int32_t i;
++      s32 i;
+       struct amdgpu_dm_connector *aconnector = NULL;
+       struct amdgpu_encoder *aencoder = NULL;
+       struct amdgpu_mode_info *mode_info = &adev->mode_info;
+-      uint32_t link_cnt;
+-      int32_t primary_planes;
++      u32 link_cnt;
++      s32 primary_planes;
+       enum dc_connection_type new_connection_type = dc_connection_none;
+       const struct dc_plane_cap *plane;
+       bool psr_feature_enabled = false;
+@@ -4768,7 +4768,7 @@ fill_plane_color_attributes(const struct
+ static int
+ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
+                           const struct drm_plane_state *plane_state,
+-                          const uint64_t tiling_flags,
++                          const u64 tiling_flags,
+                           struct dc_plane_info *plane_info,
+                           struct dc_plane_address *address,
+                           bool tmz_surface,
+@@ -4977,7 +4977,7 @@ static void fill_dc_dirty_rects(struct d
+       uint32_t num_clips;
+       bool bb_changed;
+       bool fb_changed;
+-      uint32_t i = 0;
++      u32 i = 0;
+       flip_addrs->dirty_rect_count = 0;
+@@ -5111,7 +5111,7 @@ static enum dc_color_depth
+ convert_color_depth_from_display_info(const struct drm_connector *connector,
+                                     bool is_y420, int requested_bpc)
+ {
+-      uint8_t bpc;
++      u8 bpc;
+       if (is_y420) {
+               bpc = 8;
+@@ -5655,8 +5655,8 @@ static void apply_dsc_policy_for_edp(str
+                                   uint32_t max_dsc_target_bpp_limit_override)
+ {
+       const struct dc_link_settings *verified_link_cap = NULL;
+-      uint32_t link_bw_in_kbps;
+-      uint32_t edp_min_bpp_x16, edp_max_bpp_x16;
++      u32 link_bw_in_kbps;
++      u32 edp_min_bpp_x16, edp_max_bpp_x16;
+       struct dc *dc = sink->ctx->dc;
+       struct dc_dsc_bw_range bw_range = {0};
+       struct dc_dsc_config dsc_cfg = {0};
+@@ -5713,11 +5713,11 @@ static void apply_dsc_policy_for_stream(
+                                       struct dsc_dec_dpcd_caps *dsc_caps)
+ {
+       struct drm_connector *drm_connector = &aconnector->base;
+-      uint32_t link_bandwidth_kbps;
++      u32 link_bandwidth_kbps;
+       struct dc *dc = sink->ctx->dc;
+-      uint32_t max_supported_bw_in_kbps, timing_bw_in_kbps;
+-      uint32_t dsc_max_supported_bw_in_kbps;
+-      uint32_t max_dsc_target_bpp_limit_override =
++      u32 max_supported_bw_in_kbps, timing_bw_in_kbps;
++      u32 dsc_max_supported_bw_in_kbps;
++      u32 max_dsc_target_bpp_limit_override =
+               drm_connector->display_info.max_dsc_bpp;
+       link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
+@@ -6871,7 +6871,7 @@ static uint add_fs_modes(struct amdgpu_d
+       const struct drm_display_mode *m;
+       struct drm_display_mode *new_mode;
+       uint i;
+-      uint32_t new_modes_count = 0;
++      u32 new_modes_count = 0;
+       /* Standard FPS values
+        *
+@@ -6885,7 +6885,7 @@ static uint add_fs_modes(struct amdgpu_d
+        * 60           - Commonly used
+        * 48,72,96,120 - Multiples of 24
+        */
+-      static const uint32_t common_rates[] = {
++      static const u32 common_rates[] = {
+               23976, 24000, 25000, 29970, 30000,
+               48000, 50000, 60000, 72000, 96000, 120000
+       };
+@@ -6901,8 +6901,8 @@ static uint add_fs_modes(struct amdgpu_d
+               return 0;
+       for (i = 0; i < ARRAY_SIZE(common_rates); i++) {
+-              uint64_t target_vtotal, target_vtotal_diff;
+-              uint64_t num, den;
++              u64 target_vtotal, target_vtotal_diff;
++              u64 num, den;
+               if (drm_mode_vrefresh(m) * 1000 < common_rates[i])
+                       continue;
+@@ -7150,7 +7150,7 @@ create_i2c(struct ddc_service *ddc_servi
+  */
+ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
+                                   struct amdgpu_dm_connector *aconnector,
+-                                  uint32_t link_index,
++                                  u32 link_index,
+                                   struct amdgpu_encoder *aencoder)
+ {
+       int res = 0;
+@@ -7641,8 +7641,8 @@ static void amdgpu_dm_commit_planes(stru
+                                   struct drm_crtc *pcrtc,
+                                   bool wait_for_vblank)
+ {
+-      uint32_t i;
+-      uint64_t timestamp_ns;
++      u32 i;
++      u64 timestamp_ns;
+       struct drm_plane *plane;
+       struct drm_plane_state *old_plane_state, *new_plane_state;
+       struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
+@@ -7653,7 +7653,7 @@ static void amdgpu_dm_commit_planes(stru
+                       to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
+       int planes_count = 0, vpos, hpos;
+       unsigned long flags;
+-      uint32_t target_vblank, last_flip_vblank;
++      u32 target_vblank, last_flip_vblank;
+       bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
+       bool cursor_update = false;
+       bool pflip_present = false;
+@@ -8102,7 +8102,7 @@ static void amdgpu_dm_atomic_commit_tail
+       struct amdgpu_display_manager *dm = &adev->dm;
+       struct dm_atomic_state *dm_state;
+       struct dc_state *dc_state = NULL, *dc_state_temp = NULL;
+-      uint32_t i, j;
++      u32 i, j;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+       unsigned long flags;
+@@ -8732,7 +8732,7 @@ is_timing_unchanged_for_freesync(struct
+ }
+ static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) {
+-      uint64_t num, den, res;
++      u64 num, den, res;
+       struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
+       dm_new_crtc_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
+@@ -9908,7 +9908,7 @@ fail:
+ static bool is_dp_capable_without_timing_msa(struct dc *dc,
+                                            struct amdgpu_dm_connector *amdgpu_dm_connector)
+ {
+-      uint8_t dpcd_data;
++      u8 dpcd_data;
+       bool capable = false;
+       if (amdgpu_dm_connector->dc_link &&
+@@ -9927,7 +9927,7 @@ static bool is_dp_capable_without_timing
+ static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
+               unsigned int offset,
+               unsigned int total_length,
+-              uint8_t *data,
++              u8 *data,
+               unsigned int length,
+               struct amdgpu_hdmi_vsdb_info *vsdb)
+ {
+@@ -9982,7 +9982,7 @@ static bool dm_edid_parser_send_cea(stru
+ }
+ static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
+-              uint8_t *edid_ext, int len,
++              u8 *edid_ext, int len,
+               struct amdgpu_hdmi_vsdb_info *vsdb_info)
+ {
+       int i;
+@@ -10023,7 +10023,7 @@ static bool parse_edid_cea_dmcu(struct a
+ }
+ static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
+-              uint8_t *edid_ext, int len,
++              u8 *edid_ext, int len,
+               struct amdgpu_hdmi_vsdb_info *vsdb_info)
+ {
+       int i;
+@@ -10039,7 +10039,7 @@ static bool parse_edid_cea_dmub(struct a
+ }
+ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
+-              uint8_t *edid_ext, int len,
++              u8 *edid_ext, int len,
+               struct amdgpu_hdmi_vsdb_info *vsdb_info)
+ {
+       struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
+@@ -10053,7 +10053,7 @@ static bool parse_edid_cea(struct amdgpu
+ static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
+               struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
+ {
+-      uint8_t *edid_ext = NULL;
++      u8 *edid_ext = NULL;
+       int i;
+       bool valid_vsdb_found = false;
+@@ -10229,7 +10229,7 @@ void amdgpu_dm_trigger_timing_sync(struc
+ }
+ void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
+-                     uint32_t value, const char *func_name)
++                     u32 value, const char *func_name)
+ {
+ #ifdef DM_CHECK_ADDR_0
+       if (address == 0) {
+@@ -10244,7 +10244,7 @@ void dm_write_reg_func(const struct dc_c
+ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
+                         const char *func_name)
+ {
+-      uint32_t value;
++      u32 value;
+ #ifdef DM_CHECK_ADDR_0
+       if (address == 0) {
+               DC_ERR("invalid register read; address = 0\n");
diff --git a/queue-6.1/drm-amd-display-force-connector-state-when-bpc-changes-during-compliance.patch b/queue-6.1/drm-amd-display-force-connector-state-when-bpc-changes-during-compliance.patch
new file mode 100644 (file)
index 0000000..89496f4
--- /dev/null
@@ -0,0 +1,484 @@
+From stable-owner@vger.kernel.org Tue Jul 25 00:26:59 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Mon, 24 Jul 2023 17:26:35 -0500
+Subject: drm/amd/display: force connector state when bpc changes during compliance
+To: <stable@vger.kernel.org>
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230724222638.1477-5-mario.limonciello@amd.com>
+
+From: Qingqing Zhuo <qingqing.zhuo@amd.com>
+
+commit 028c4ccfb8127255d60f8d9edde96cacf2958082 upstream.
+
+[Why]
+During DP DSC compliance tests, bpc requested would
+change between sub-tests, which requires stream
+to be recommited.
+
+[How]
+Force connector to disconnect and reconnect whenever
+there is a bpc change in automated test.
+
+Reviewed-by: Jerry Zuo <Jerry.Zuo@amd.com>
+Acked-by: Alan Liu <HaoPing.Liu@amd.com>
+Signed-off-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
+Signed-off-by: hersen wu <hersenxs.wu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[ Adjustments for headers that were moved around in later commits. ]
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c         |   55 +++++
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h         |    5 
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  125 ++++++++++++
+ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c          |  139 +-------------
+ drivers/gpu/drm/amd/display/dc/dm_helpers.h               |    6 
+ 5 files changed, 209 insertions(+), 121 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -40,6 +40,9 @@
+ #include "dc/dc_stat.h"
+ #include "amdgpu_dm_trace.h"
+ #include "dc/inc/dc_link_ddc.h"
++#include "dpcd_defs.h"
++#include "dc/inc/link_dpcd.h"
++#include "link_service_types.h"
+ #include "vid.h"
+ #include "amdgpu.h"
+@@ -1273,6 +1276,21 @@ static void mmhub_read_system_context(st
+ }
++static void force_connector_state(
++      struct amdgpu_dm_connector *aconnector,
++      enum drm_connector_force force_state)
++{
++      struct drm_connector *connector = &aconnector->base;
++
++      mutex_lock(&connector->dev->mode_config.mutex);
++      aconnector->base.force = force_state;
++      mutex_unlock(&connector->dev->mode_config.mutex);
++
++      mutex_lock(&aconnector->hpd_lock);
++      drm_kms_helper_connector_hotplug_event(connector);
++      mutex_unlock(&aconnector->hpd_lock);
++}
++
+ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
+ {
+       struct hpd_rx_irq_offload_work *offload_work;
+@@ -1281,6 +1299,9 @@ static void dm_handle_hpd_rx_offload_wor
+       struct amdgpu_device *adev;
+       enum dc_connection_type new_connection_type = dc_connection_none;
+       unsigned long flags;
++      union test_response test_response;
++
++      memset(&test_response, 0, sizeof(test_response));
+       offload_work = container_of(work, struct hpd_rx_irq_offload_work, work);
+       aconnector = offload_work->offload_wq->aconnector;
+@@ -1305,8 +1326,24 @@ static void dm_handle_hpd_rx_offload_wor
+               goto skip;
+       mutex_lock(&adev->dm.dc_lock);
+-      if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST)
++      if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
+               dc_link_dp_handle_automated_test(dc_link);
++
++              if (aconnector->timing_changed) {
++                      /* force connector disconnect and reconnect */
++                      force_connector_state(aconnector, DRM_FORCE_OFF);
++                      msleep(100);
++                      force_connector_state(aconnector, DRM_FORCE_UNSPECIFIED);
++              }
++
++              test_response.bits.ACK = 1;
++
++              core_link_write_dpcd(
++              dc_link,
++              DP_TEST_RESPONSE,
++              &test_response.raw,
++              sizeof(test_response));
++      }
+       else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
+                       hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) &&
+                       dc_link_dp_allow_hpd_rx_irq(dc_link)) {
+@@ -3076,6 +3113,10 @@ void amdgpu_dm_update_connector_after_de
+                                                   aconnector->edid);
+               }
++              aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
++              if (!aconnector->timing_requested)
++                      dm_error("%s: failed to create aconnector->requested_timing\n", __func__);
++
+               drm_connector_update_edid_property(connector, aconnector->edid);
+               amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
+               update_connector_ext_caps(aconnector);
+@@ -3087,6 +3128,8 @@ void amdgpu_dm_update_connector_after_de
+               dc_sink_release(aconnector->dc_sink);
+               aconnector->dc_sink = NULL;
+               aconnector->edid = NULL;
++              kfree(aconnector->timing_requested);
++              aconnector->timing_requested = NULL;
+ #ifdef CONFIG_DRM_AMD_DC_HDCP
+               /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
+               if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
+@@ -3131,6 +3174,8 @@ static void handle_hpd_irq_helper(struct
+       if (aconnector->fake_enable)
+               aconnector->fake_enable = false;
++      aconnector->timing_changed = false;
++
+       if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
+               DRM_ERROR("KMS: Failed to detect connector\n");
+@@ -5896,6 +5941,14 @@ create_stream_for_sink(struct amdgpu_dm_
+                       stream, &mode, &aconnector->base, con_state, old_stream,
+                       requested_bpc);
++      if (aconnector->timing_changed) {
++              DC_LOG_DEBUG("%s: overriding timing for automated test, bpc %d, changing to %d\n",
++                              __func__,
++                              stream->timing.display_color_depth,
++                              aconnector->timing_requested->display_color_depth);
++              stream->timing = *aconnector->timing_requested;
++      }
++
+ #if defined(CONFIG_DRM_AMD_DC_DCN)
+       /* SST DSC determination policy */
+       update_dsc_caps(aconnector, sink, stream, &dsc_caps);
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+@@ -31,6 +31,7 @@
+ #include <drm/drm_connector.h>
+ #include <drm/drm_crtc.h>
+ #include <drm/drm_plane.h>
++#include "link_service_types.h"
+ /*
+  * This file contains the definition for amdgpu_display_manager
+@@ -650,6 +651,10 @@ struct amdgpu_dm_connector {
+       /* Record progress status of mst*/
+       uint8_t mst_status;
++
++      /* Automated testing */
++      bool timing_changed;
++      struct dc_crtc_timing *timing_requested;
+ };
+ static inline void amdgpu_dm_set_mst_status(uint8_t *status,
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+@@ -38,6 +38,9 @@
+ #include "amdgpu_dm.h"
+ #include "amdgpu_dm_irq.h"
+ #include "amdgpu_dm_mst_types.h"
++#include "dpcd_defs.h"
++#include "dc/inc/core_types.h"
++#include "dc_link_dp.h"
+ #include "dm_helpers.h"
+ #include "ddc_service_types.h"
+@@ -1056,6 +1059,128 @@ void dm_helpers_mst_enable_stream_featur
+                                        sizeof(new_downspread));
+ }
++bool dm_helpers_dp_handle_test_pattern_request(
++              struct dc_context *ctx,
++              const struct dc_link *link,
++              union link_test_pattern dpcd_test_pattern,
++              union test_misc dpcd_test_params)
++{
++      enum dp_test_pattern test_pattern;
++      enum dp_test_pattern_color_space test_pattern_color_space =
++                      DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
++      enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
++      enum dc_pixel_encoding requestPixelEncoding = PIXEL_ENCODING_UNDEFINED;
++      struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
++      struct pipe_ctx *pipe_ctx = NULL;
++      struct amdgpu_dm_connector *aconnector = link->priv;
++      int i;
++
++      for (i = 0; i < MAX_PIPES; i++) {
++              if (pipes[i].stream == NULL)
++                      continue;
++
++              if (pipes[i].stream->link == link && !pipes[i].top_pipe &&
++                      !pipes[i].prev_odm_pipe) {
++                      pipe_ctx = &pipes[i];
++                      break;
++              }
++      }
++
++      if (pipe_ctx == NULL)
++              return false;
++
++      switch (dpcd_test_pattern.bits.PATTERN) {
++      case LINK_TEST_PATTERN_COLOR_RAMP:
++              test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
++      break;
++      case LINK_TEST_PATTERN_VERTICAL_BARS:
++              test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
++      break; /* black and white */
++      case LINK_TEST_PATTERN_COLOR_SQUARES:
++              test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
++                              TEST_DYN_RANGE_VESA ?
++                              DP_TEST_PATTERN_COLOR_SQUARES :
++                              DP_TEST_PATTERN_COLOR_SQUARES_CEA);
++      break;
++      default:
++              test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
++      break;
++      }
++
++      if (dpcd_test_params.bits.CLR_FORMAT == 0)
++              test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
++      else
++              test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
++                              DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
++                              DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
++
++      switch (dpcd_test_params.bits.BPC) {
++      case 0: // 6 bits
++              requestColorDepth = COLOR_DEPTH_666;
++              break;
++      case 1: // 8 bits
++              requestColorDepth = COLOR_DEPTH_888;
++              break;
++      case 2: // 10 bits
++              requestColorDepth = COLOR_DEPTH_101010;
++              break;
++      case 3: // 12 bits
++              requestColorDepth = COLOR_DEPTH_121212;
++              break;
++      default:
++              break;
++      }
++
++      switch (dpcd_test_params.bits.CLR_FORMAT) {
++      case 0:
++              requestPixelEncoding = PIXEL_ENCODING_RGB;
++              break;
++      case 1:
++              requestPixelEncoding = PIXEL_ENCODING_YCBCR422;
++              break;
++      case 2:
++              requestPixelEncoding = PIXEL_ENCODING_YCBCR444;
++              break;
++      default:
++              requestPixelEncoding = PIXEL_ENCODING_RGB;
++              break;
++      }
++
++      if ((requestColorDepth != COLOR_DEPTH_UNDEFINED
++              && pipe_ctx->stream->timing.display_color_depth != requestColorDepth)
++              || (requestPixelEncoding != PIXEL_ENCODING_UNDEFINED
++              && pipe_ctx->stream->timing.pixel_encoding != requestPixelEncoding)) {
++              DC_LOG_DEBUG("%s: original bpc %d pix encoding %d, changing to %d  %d\n",
++                              __func__,
++                              pipe_ctx->stream->timing.display_color_depth,
++                              pipe_ctx->stream->timing.pixel_encoding,
++                              requestColorDepth,
++                              requestPixelEncoding);
++              pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
++              pipe_ctx->stream->timing.pixel_encoding = requestPixelEncoding;
++
++              dp_update_dsc_config(pipe_ctx);
++
++              aconnector->timing_changed = true;
++              /* store current timing */
++              if (aconnector->timing_requested)
++                      *aconnector->timing_requested = pipe_ctx->stream->timing;
++              else
++                      DC_LOG_ERROR("%s: timing storage failed\n", __func__);
++
++      }
++
++      dc_link_dp_set_test_pattern(
++              (struct dc_link *) link,
++              test_pattern,
++              test_pattern_color_space,
++              NULL,
++              NULL,
++              0);
++
++      return false;
++}
++
+ void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz)
+ {
+        // TODO
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+@@ -4264,124 +4264,6 @@ static void dp_test_send_phy_test_patter
+               test_pattern_size);
+ }
+-static void dp_test_send_link_test_pattern(struct dc_link *link)
+-{
+-      union link_test_pattern dpcd_test_pattern;
+-      union test_misc dpcd_test_params;
+-      enum dp_test_pattern test_pattern;
+-      enum dp_test_pattern_color_space test_pattern_color_space =
+-                      DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED;
+-      enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED;
+-      struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
+-      struct pipe_ctx *pipe_ctx = NULL;
+-      int i;
+-
+-      memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
+-      memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
+-
+-      for (i = 0; i < MAX_PIPES; i++) {
+-              if (pipes[i].stream == NULL)
+-                      continue;
+-
+-              if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
+-                      pipe_ctx = &pipes[i];
+-                      break;
+-              }
+-      }
+-
+-      if (pipe_ctx == NULL)
+-              return;
+-
+-      /* get link test pattern and pattern parameters */
+-      core_link_read_dpcd(
+-                      link,
+-                      DP_TEST_PATTERN,
+-                      &dpcd_test_pattern.raw,
+-                      sizeof(dpcd_test_pattern));
+-      core_link_read_dpcd(
+-                      link,
+-                      DP_TEST_MISC0,
+-                      &dpcd_test_params.raw,
+-                      sizeof(dpcd_test_params));
+-
+-      switch (dpcd_test_pattern.bits.PATTERN) {
+-      case LINK_TEST_PATTERN_COLOR_RAMP:
+-              test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
+-      break;
+-      case LINK_TEST_PATTERN_VERTICAL_BARS:
+-              test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
+-      break; /* black and white */
+-      case LINK_TEST_PATTERN_COLOR_SQUARES:
+-              test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
+-                              TEST_DYN_RANGE_VESA ?
+-                              DP_TEST_PATTERN_COLOR_SQUARES :
+-                              DP_TEST_PATTERN_COLOR_SQUARES_CEA);
+-      break;
+-      default:
+-              test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
+-      break;
+-      }
+-
+-      if (dpcd_test_params.bits.CLR_FORMAT == 0)
+-              test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_RGB;
+-      else
+-              test_pattern_color_space = dpcd_test_params.bits.YCBCR_COEFS ?
+-                              DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 :
+-                              DP_TEST_PATTERN_COLOR_SPACE_YCBCR601;
+-
+-      switch (dpcd_test_params.bits.BPC) {
+-      case 0: // 6 bits
+-              requestColorDepth = COLOR_DEPTH_666;
+-              break;
+-      case 1: // 8 bits
+-              requestColorDepth = COLOR_DEPTH_888;
+-              break;
+-      case 2: // 10 bits
+-              requestColorDepth = COLOR_DEPTH_101010;
+-              break;
+-      case 3: // 12 bits
+-              requestColorDepth = COLOR_DEPTH_121212;
+-              break;
+-      default:
+-              break;
+-      }
+-
+-      switch (dpcd_test_params.bits.CLR_FORMAT) {
+-      case 0:
+-              pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
+-              break;
+-      case 1:
+-              pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422;
+-              break;
+-      case 2:
+-              pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444;
+-              break;
+-      default:
+-              pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB;
+-              break;
+-      }
+-
+-
+-      if (requestColorDepth != COLOR_DEPTH_UNDEFINED
+-                      && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) {
+-              DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n",
+-                              __func__,
+-                              pipe_ctx->stream->timing.display_color_depth,
+-                              requestColorDepth);
+-              pipe_ctx->stream->timing.display_color_depth = requestColorDepth;
+-      }
+-
+-      dp_update_dsc_config(pipe_ctx);
+-
+-      dc_link_dp_set_test_pattern(
+-                      link,
+-                      test_pattern,
+-                      test_pattern_color_space,
+-                      NULL,
+-                      NULL,
+-                      0);
+-}
+-
+ static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video)
+ {
+       union audio_test_mode            dpcd_test_mode = {0};
+@@ -4494,8 +4376,25 @@ void dc_link_dp_handle_automated_test(st
+               test_response.bits.ACK = 0;
+       }
+       if (test_request.bits.LINK_TEST_PATTRN) {
+-              dp_test_send_link_test_pattern(link);
+-              test_response.bits.ACK = 1;
++              union test_misc dpcd_test_params;
++              union link_test_pattern dpcd_test_pattern;
++
++              memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
++              memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
++
++              /* get link test pattern and pattern parameters */
++              core_link_read_dpcd(
++                              link,
++                              DP_TEST_PATTERN,
++                              &dpcd_test_pattern.raw,
++                              sizeof(dpcd_test_pattern));
++              core_link_read_dpcd(
++                              link,
++                              DP_TEST_MISC0,
++                              &dpcd_test_params.raw,
++                              sizeof(dpcd_test_params));
++              test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link,
++                              dpcd_test_pattern, dpcd_test_params) ? 1 : 0;
+       }
+       if (test_request.bits.AUDIO_TEST_PATTERN) {
+--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h
++++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
+@@ -156,6 +156,12 @@ enum dc_edid_status dm_helpers_read_loca
+               struct dc_link *link,
+               struct dc_sink *sink);
++bool dm_helpers_dp_handle_test_pattern_request(
++              struct dc_context *ctx,
++              const struct dc_link *link,
++              union link_test_pattern dpcd_test_pattern,
++              union test_misc dpcd_test_params);
++
+ void dm_set_dcn_clocks(
+               struct dc_context *ctx,
+               struct dc_clocks *clks);
diff --git a/queue-6.1/drm-amd-display-use-max_dsc_bpp-in-amdgpu_dm.patch b/queue-6.1/drm-amd-display-use-max_dsc_bpp-in-amdgpu_dm.patch
new file mode 100644 (file)
index 0000000..924acdb
--- /dev/null
@@ -0,0 +1,86 @@
+From stable-owner@vger.kernel.org Tue Jul 25 00:26:52 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Mon, 24 Jul 2023 17:26:32 -0500
+Subject: drm/amd/display: use max_dsc_bpp in amdgpu_dm
+To: <stable@vger.kernel.org>
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230724222638.1477-2-mario.limonciello@amd.com>
+
+From: Hamza Mahfooz <hamza.mahfooz@amd.com>
+
+commit 6e5abe94c6eb9b281398e39819217e8fdd1c336f upstream.
+
+Since, the quirk is handled in the DRM core now, we can use that value
+instead of the internal value.
+
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c           |    6 ++----
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c |   11 +++++++++--
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -5714,16 +5714,14 @@ static void apply_dsc_policy_for_stream(
+ {
+       struct drm_connector *drm_connector = &aconnector->base;
+       uint32_t link_bandwidth_kbps;
+-      uint32_t max_dsc_target_bpp_limit_override = 0;
+       struct dc *dc = sink->ctx->dc;
+       uint32_t max_supported_bw_in_kbps, timing_bw_in_kbps;
+       uint32_t dsc_max_supported_bw_in_kbps;
++      uint32_t max_dsc_target_bpp_limit_override =
++              drm_connector->display_info.max_dsc_bpp;
+       link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
+                                                       dc_link_get_link_cap(aconnector->dc_link));
+-      if (stream->link && stream->link->local_sink)
+-              max_dsc_target_bpp_limit_override =
+-                      stream->link->local_sink->edid_caps.panel_patch.max_dsc_target_bpp_limit;
+       /* Set DSC policy according to dsc_clock_en */
+       dc_dsc_policy_set_enable_dsc_when_not_needed(
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -673,15 +673,18 @@ static void set_dsc_configs_from_fairnes
+               int count,
+               int k)
+ {
++      struct drm_connector *drm_connector;
+       int i;
+       for (i = 0; i < count; i++) {
++              drm_connector = &params[i].aconnector->base;
++
+               memset(&params[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg));
+               if (vars[i + k].dsc_enabled && dc_dsc_compute_config(
+                                       params[i].sink->ctx->dc->res_pool->dscs[0],
+                                       &params[i].sink->dsc_caps.dsc_dec_caps,
+                                       params[i].sink->ctx->dc->debug.dsc_min_slice_height_override,
+-                                      params[i].sink->edid_caps.panel_patch.max_dsc_target_bpp_limit,
++                                      drm_connector->display_info.max_dsc_bpp,
+                                       0,
+                                       params[i].timing,
+                                       &params[i].timing->dsc_cfg)) {
+@@ -723,12 +726,16 @@ static int bpp_x16_from_pbn(struct dsc_m
+       struct dc_dsc_config dsc_config;
+       u64 kbps;
++      struct drm_connector *drm_connector = &param.aconnector->base;
++      uint32_t max_dsc_target_bpp_limit_override =
++              drm_connector->display_info.max_dsc_bpp;
++
+       kbps = div_u64((u64)pbn * 994 * 8 * 54, 64);
+       dc_dsc_compute_config(
+                       param.sink->ctx->dc->res_pool->dscs[0],
+                       &param.sink->dsc_caps.dsc_dec_caps,
+                       param.sink->ctx->dc->debug.dsc_min_slice_height_override,
+-                      param.sink->edid_caps.panel_patch.max_dsc_target_bpp_limit,
++                      max_dsc_target_bpp_limit_override,
+                       (int) kbps, param.timing, &dsc_config);
+       return dsc_config.bits_per_pixel;
diff --git a/queue-6.1/drm-dp_mst-clear-msg_rdy-flag-before-sending-new-message.patch b/queue-6.1/drm-dp_mst-clear-msg_rdy-flag-before-sending-new-message.patch
new file mode 100644 (file)
index 0000000..d9da50d
--- /dev/null
@@ -0,0 +1,286 @@
+From stable-owner@vger.kernel.org Tue Jul 25 00:28:07 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Mon, 24 Jul 2023 17:26:34 -0500
+Subject: drm/dp_mst: Clear MSG_RDY flag before sending new message
+To: <stable@vger.kernel.org>
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230724222638.1477-4-mario.limonciello@amd.com>
+
+From: Wayne Lin <Wayne.Lin@amd.com>
+
+commit 72f1de49ffb90b29748284f27f1d6b829ab1de95 upstream.
+
+[Why]
+The sequence for collecting down_reply from source perspective should
+be:
+
+Request_n->repeat (get partial reply of Request_n->clear message ready
+flag to ack DPRX that the message is received) till all partial
+replies for Request_n are received->new Request_n+1.
+
+Now there is chance that drm_dp_mst_hpd_irq() will fire new down
+request in the tx queue when the down reply is incomplete. Source is
+restricted to generate interveleaved message transactions so we should
+avoid it.
+
+Also, while assembling partial reply packets, reading out DPCD DOWN_REP
+Sideband MSG buffer + clearing DOWN_REP_MSG_RDY flag should be
+wrapped up as a complete operation for reading out a reply packet.
+Kicking off a new request before clearing DOWN_REP_MSG_RDY flag might
+be risky. e.g. If the reply of the new request has overwritten the
+DPRX DOWN_REP Sideband MSG buffer before source writing one to clear
+DOWN_REP_MSG_RDY flag, source then unintentionally flushes the reply
+for the new request. Should handle the up request in the same way.
+
+[How]
+Separete drm_dp_mst_hpd_irq() into 2 steps. After acking the MST IRQ
+event, driver calls drm_dp_mst_hpd_irq_send_new_request() and might
+trigger drm_dp_mst_kick_tx() only when there is no on going message
+transaction.
+
+Changes since v1:
+* Reworked on review comments received
+-> Adjust the fix to let driver explicitly kick off new down request
+when mst irq event is handled and acked
+-> Adjust the commit message
+
+Changes since v2:
+* Adjust the commit message
+* Adjust the naming of the divided 2 functions and add a new input
+  parameter "ack".
+* Adjust code flow as per review comments.
+
+Changes since v3:
+* Update the function description of drm_dp_mst_hpd_irq_handle_event
+
+Changes since v4:
+* Change ack of drm_dp_mst_hpd_irq_handle_event() to be an array align
+  the size of esi[]
+
+Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
+Reviewed-by: Lyude Paul <lyude@redhat.com>
+Acked-by: Jani Nikula <jani.nikula@intel.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   30 ++++++------
+ drivers/gpu/drm/display/drm_dp_mst_topology.c     |   54 +++++++++++++++++++---
+ drivers/gpu/drm/i915/display/intel_dp.c           |    7 +-
+ drivers/gpu/drm/nouveau/dispnv50/disp.c           |   12 +++-
+ include/drm/display/drm_dp_mst_helper.h           |    7 ++
+ 5 files changed, 80 insertions(+), 30 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -3201,6 +3201,7 @@ static void dm_handle_mst_sideband_msg(s
+       while (dret == dpcd_bytes_to_read &&
+               process_count < max_process_count) {
++              u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
+               u8 retry;
+               dret = 0;
+@@ -3209,28 +3210,29 @@ static void dm_handle_mst_sideband_msg(s
+               DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+               /* handle HPD short pulse irq */
+               if (aconnector->mst_mgr.mst_state)
+-                      drm_dp_mst_hpd_irq(
+-                              &aconnector->mst_mgr,
+-                              esi,
+-                              &new_irq_handled);
++                      drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
++                                                      esi,
++                                                      ack,
++                                                      &new_irq_handled);
+               if (new_irq_handled) {
+                       /* ACK at DPCD to notify down stream */
+-                      const int ack_dpcd_bytes_to_write =
+-                              dpcd_bytes_to_read - 1;
+-
+                       for (retry = 0; retry < 3; retry++) {
+-                              u8 wret;
++                              ssize_t wret;
+-                              wret = drm_dp_dpcd_write(
+-                                      &aconnector->dm_dp_aux.aux,
+-                                      dpcd_addr + 1,
+-                                      &esi[1],
+-                                      ack_dpcd_bytes_to_write);
+-                              if (wret == ack_dpcd_bytes_to_write)
++                              wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
++                                                        dpcd_addr + 1,
++                                                        ack[1]);
++                              if (wret == 1)
+                                       break;
+                       }
++                      if (retry == 3) {
++                              DRM_ERROR("Failed to ack MST event.\n");
++                              return;
++                      }
++
++                      drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
+                       /* check if there is new irq to be handled */
+                       dret = drm_dp_dpcd_read(
+                               &aconnector->dm_dp_aux.aux,
+--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
+@@ -4053,17 +4053,28 @@ out:
+ }
+ /**
+- * drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
++ * drm_dp_mst_hpd_irq_handle_event() - MST hotplug IRQ handle MST event
+  * @mgr: manager to notify irq for.
+  * @esi: 4 bytes from SINK_COUNT_ESI
++ * @ack: 4 bytes used to ack events starting from SINK_COUNT_ESI
+  * @handled: whether the hpd interrupt was consumed or not
+  *
+- * This should be called from the driver when it detects a short IRQ,
++ * This should be called from the driver when it detects a HPD IRQ,
+  * along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
+- * topology manager will process the sideband messages received as a result
+- * of this.
++ * topology manager will process the sideband messages received
++ * as indicated in the DEVICE_SERVICE_IRQ_VECTOR_ESI0 and set the
++ * corresponding flags that Driver has to ack the DP receiver later.
++ *
++ * Note that driver shall also call
++ * drm_dp_mst_hpd_irq_send_new_request() if the 'handled' is set
++ * after calling this function, to try to kick off a new request in
++ * the queue if the previous message transaction is completed.
++ *
++ * See also:
++ * drm_dp_mst_hpd_irq_send_new_request()
+  */
+-int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled)
++int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr, const u8 *esi,
++                                  u8 *ack, bool *handled)
+ {
+       int ret = 0;
+       int sc;
+@@ -4078,18 +4089,47 @@ int drm_dp_mst_hpd_irq(struct drm_dp_mst
+       if (esi[1] & DP_DOWN_REP_MSG_RDY) {
+               ret = drm_dp_mst_handle_down_rep(mgr);
+               *handled = true;
++              ack[1] |= DP_DOWN_REP_MSG_RDY;
+       }
+       if (esi[1] & DP_UP_REQ_MSG_RDY) {
+               ret |= drm_dp_mst_handle_up_req(mgr);
+               *handled = true;
++              ack[1] |= DP_UP_REQ_MSG_RDY;
+       }
+-      drm_dp_mst_kick_tx(mgr);
+       return ret;
+ }
+-EXPORT_SYMBOL(drm_dp_mst_hpd_irq);
++EXPORT_SYMBOL(drm_dp_mst_hpd_irq_handle_event);
++
++/**
++ * drm_dp_mst_hpd_irq_send_new_request() - MST hotplug IRQ kick off new request
++ * @mgr: manager to notify irq for.
++ *
++ * This should be called from the driver when mst irq event is handled
++ * and acked. Note that new down request should only be sent when
++ * previous message transaction is completed. Source is not supposed to generate
++ * interleaved message transactions.
++ */
++void drm_dp_mst_hpd_irq_send_new_request(struct drm_dp_mst_topology_mgr *mgr)
++{
++      struct drm_dp_sideband_msg_tx *txmsg;
++      bool kick = true;
++      mutex_lock(&mgr->qlock);
++      txmsg = list_first_entry_or_null(&mgr->tx_msg_downq,
++                                       struct drm_dp_sideband_msg_tx, next);
++      /* If last transaction is not completed yet*/
++      if (!txmsg ||
++          txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND ||
++          txmsg->state == DRM_DP_SIDEBAND_TX_SENT)
++              kick = false;
++      mutex_unlock(&mgr->qlock);
++
++      if (kick)
++              drm_dp_mst_kick_tx(mgr);
++}
++EXPORT_SYMBOL(drm_dp_mst_hpd_irq_send_new_request);
+ /**
+  * drm_dp_mst_detect_port() - get connection status for an MST port
+  * @connector: DRM connector for this port
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -3804,9 +3804,7 @@ intel_dp_mst_hpd_irq(struct intel_dp *in
+ {
+       bool handled = false;
+-      drm_dp_mst_hpd_irq(&intel_dp->mst_mgr, esi, &handled);
+-      if (handled)
+-              ack[1] |= esi[1] & (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY);
++      drm_dp_mst_hpd_irq_handle_event(&intel_dp->mst_mgr, esi, ack, &handled);
+       if (esi[1] & DP_CP_IRQ) {
+               intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
+@@ -3881,6 +3879,9 @@ intel_dp_check_mst_status(struct intel_d
+               if (!intel_dp_ack_sink_irq_esi(intel_dp, ack))
+                       drm_dbg_kms(&i915->drm, "Failed to ack ESI\n");
++
++              if (ack[1] & (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY))
++                      drm_dp_mst_hpd_irq_send_new_request(&intel_dp->mst_mgr);
+       }
+       return link_ok;
+--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
+@@ -1473,22 +1473,26 @@ nv50_mstm_service(struct nouveau_drm *dr
+       u8 esi[8] = {};
+       while (handled) {
++              u8 ack[8] = {};
++
+               rc = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8);
+               if (rc != 8) {
+                       ret = false;
+                       break;
+               }
+-              drm_dp_mst_hpd_irq(&mstm->mgr, esi, &handled);
++              drm_dp_mst_hpd_irq_handle_event(&mstm->mgr, esi, ack, &handled);
+               if (!handled)
+                       break;
+-              rc = drm_dp_dpcd_write(aux, DP_SINK_COUNT_ESI + 1, &esi[1],
+-                                     3);
+-              if (rc != 3) {
++              rc = drm_dp_dpcd_writeb(aux, DP_SINK_COUNT_ESI + 1, ack[1]);
++
++              if (rc != 1) {
+                       ret = false;
+                       break;
+               }
++
++              drm_dp_mst_hpd_irq_send_new_request(&mstm->mgr);
+       }
+       if (!ret)
+--- a/include/drm/display/drm_dp_mst_helper.h
++++ b/include/drm/display/drm_dp_mst_helper.h
+@@ -815,8 +815,11 @@ void drm_dp_mst_topology_mgr_destroy(str
+ bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
+ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state);
+-int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled);
+-
++int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr,
++                                  const u8 *esi,
++                                  u8 *ack,
++                                  bool *handled);
++void drm_dp_mst_hpd_irq_send_new_request(struct drm_dp_mst_topology_mgr *mgr);
+ int
+ drm_dp_mst_detect_port(struct drm_connector *connector,
index a5321e5a9b3a05ceac221f9c38864369ae691297..9b54e19a76beed5e96e9e3371802e70dd434076b 100644 (file)
@@ -175,3 +175,10 @@ bpf-aggressively-forget-precise-markings-during-state-checkpointing.patch
 selftests-bpf-make-test_align-selftest-more-robust.patch
 selftests-bpf-workaround-verification-failure-for-fexit_bpf2bpf-func_replace_return_code.patch
 selftests-bpf-fix-sk_assign-on-s390x.patch
+drm-amd-display-use-max_dsc_bpp-in-amdgpu_dm.patch
+drm-amd-display-fix-some-coding-style-issues.patch
+drm-dp_mst-clear-msg_rdy-flag-before-sending-new-message.patch
+drm-amd-display-force-connector-state-when-bpc-changes-during-compliance.patch
+drm-amd-display-clean-up-errors-warnings-in-amdgpu_dm.c.patch
+drm-amd-display-fix-linux-dp-link-lost-handled-only-one-time.patch
+drm-amd-display-add-polling-method-to-handle-mst-reply-packet.patch