]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 27 May 2025 15:14:07 +0000 (17:14 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 27 May 2025 15:14:07 +0000 (17:14 +0200)
added patches:
drm-amdgpu-read-back-register-after-written-for-vcn-v4.0.5.patch
drm-amdgpu-vcn4.0.5-split-code-along-instances.patch
drm-i915-dp-fix-determining-sst-mst-mode-during-mtp-tu-state-computation.patch

queue-6.14/drm-amdgpu-read-back-register-after-written-for-vcn-v4.0.5.patch [new file with mode: 0644]
queue-6.14/drm-amdgpu-vcn4.0.5-split-code-along-instances.patch [new file with mode: 0644]
queue-6.14/drm-i915-dp-fix-determining-sst-mst-mode-during-mtp-tu-state-computation.patch [new file with mode: 0644]
queue-6.14/series

diff --git a/queue-6.14/drm-amdgpu-read-back-register-after-written-for-vcn-v4.0.5.patch b/queue-6.14/drm-amdgpu-read-back-register-after-written-for-vcn-v4.0.5.patch
new file mode 100644 (file)
index 0000000..20296b1
--- /dev/null
@@ -0,0 +1,54 @@
+From ee7360fc27d6045510f8fe459b5649b2af27811a Mon Sep 17 00:00:00 2001
+From: "David (Ming Qiang) Wu" <David.Wu3@amd.com>
+Date: Mon, 12 May 2025 15:14:43 -0400
+Subject: drm/amdgpu: read back register after written for VCN v4.0.5
+
+From: David (Ming Qiang) Wu <David.Wu3@amd.com>
+
+commit ee7360fc27d6045510f8fe459b5649b2af27811a upstream.
+
+On VCN v4.0.5 there is a race condition where the WPTR is not
+updated after starting from idle when doorbell is used. Adding
+register read-back after written at function end is to ensure
+all register writes are done before they can be used.
+
+Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12528
+Signed-off-by: David (Ming Qiang) Wu <David.Wu3@amd.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Tested-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 07c9db090b86e5211188e1b351303fbc673378cf)
+Cc: stable@vger.kernel.org
+Tested-by: Eric Naim <dnaim@cachyos.org>
+Signed-off-by: Eric Naim <dnaim@cachyos.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+@@ -983,6 +983,10 @@ static int vcn_v4_0_5_start_dpg_mode(str
+                       ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+                       VCN_RB1_DB_CTRL__EN_MASK);
++      /* Keeping one read-back to ensure all register writes are done, otherwise
++       * it may introduce race conditions */
++      RREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL);
++
+       return 0;
+ }
+@@ -1164,6 +1168,10 @@ static int vcn_v4_0_5_start(struct amdgp
+       WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+       fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
++      /* Keeping one read-back to ensure all register writes are done, otherwise
++       * it may introduce race conditions */
++      RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
++
+       return 0;
+ }
diff --git a/queue-6.14/drm-amdgpu-vcn4.0.5-split-code-along-instances.patch b/queue-6.14/drm-amdgpu-vcn4.0.5-split-code-along-instances.patch
new file mode 100644 (file)
index 0000000..d5a917b
--- /dev/null
@@ -0,0 +1,545 @@
+From ecc9ab4e924b7eb9e2c4a668162aaa1d9d60d08c Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Wed, 13 Nov 2024 12:21:18 -0500
+Subject: drm/amdgpu/vcn4.0.5: split code along instances
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit ecc9ab4e924b7eb9e2c4a668162aaa1d9d60d08c upstream.
+
+Split the code on a per instance basis.  This will allow
+us to use the per instance functions in the future to
+handle more things per instance.
+
+v2: squash in fix for stop() from Boyuan
+
+Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Tested-by: Eric Naim <dnaim@cachyos.org>
+Signed-off-by: Eric Naim <dnaim@cachyos.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c |  462 +++++++++++++++-----------------
+ 1 file changed, 229 insertions(+), 233 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+@@ -991,184 +991,179 @@ static int vcn_v4_0_5_start_dpg_mode(str
+  * vcn_v4_0_5_start - VCN start
+  *
+  * @adev: amdgpu_device pointer
++ * @i: instance to start
+  *
+  * Start VCN block
+  */
+-static int vcn_v4_0_5_start(struct amdgpu_device *adev)
++static int vcn_v4_0_5_start(struct amdgpu_device *adev, int i)
+ {
+       volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+       struct amdgpu_ring *ring;
+       uint32_t tmp;
+-      int i, j, k, r;
++      int j, k, r;
+-      for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+-              if (adev->pm.dpm_enabled)
+-                      amdgpu_dpm_enable_vcn(adev, true, i);
+-      }
+-
+-      for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+-              if (adev->vcn.harvest_config & (1 << i))
+-                      continue;
++      if (adev->vcn.harvest_config & (1 << i))
++              return 0;
+-              fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
++      if (adev->pm.dpm_enabled)
++              amdgpu_dpm_enable_vcn(adev, true, i);
+-              if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+-                      r = vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+-                      continue;
+-              }
++      fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+-              /* disable VCN power gating */
+-              vcn_v4_0_5_disable_static_power_gating(adev, i);
++      if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
++              return vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
+-              /* set VCN status busy */
+-              tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
+-              WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
+-
+-              /*SW clock gating */
+-              vcn_v4_0_5_disable_clock_gating(adev, i);
+-
+-              /* enable VCPU clock */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+-                              UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
+-
+-              /* disable master interrupt */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
+-                              ~UVD_MASTINT_EN__VCPU_EN_MASK);
+-
+-              /* enable LMI MC and UMC channels */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
+-                              ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+-
+-              tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+-              tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+-              tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+-              WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+-
+-              /* setup regUVD_LMI_CTRL */
+-              tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
+-              WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
+-                              UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+-                              UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
+-                              UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+-                              UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
+-
+-              /* setup regUVD_MPC_CNTL */
+-              tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
+-              tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
+-              tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
+-              WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
+-
+-              /* setup UVD_MPC_SET_MUXA0 */
+-              WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
+-                              ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
+-                               (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
+-                               (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
+-                               (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
+-
+-              /* setup UVD_MPC_SET_MUXB0 */
+-              WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
+-                              ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
+-                               (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
+-                               (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
+-                               (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
+-
+-              /* setup UVD_MPC_SET_MUX */
+-              WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
+-                              ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
+-                               (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
+-                               (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
+-
+-              vcn_v4_0_5_mc_resume(adev, i);
+-
+-              /* VCN global tiling registers */
+-              WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
+-                              adev->gfx.config.gb_addr_config);
+-
+-              /* unblock VCPU register access */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
+-                              ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+-
+-              /* release VCPU reset to boot */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+-                              ~UVD_VCPU_CNTL__BLK_RST_MASK);
+-
+-              for (j = 0; j < 10; ++j) {
+-                      uint32_t status;
+-
+-                      for (k = 0; k < 100; ++k) {
+-                              status = RREG32_SOC15(VCN, i, regUVD_STATUS);
+-                              if (status & 2)
+-                                      break;
+-                              mdelay(10);
+-                              if (amdgpu_emu_mode == 1)
+-                                      msleep(1);
+-                      }
++      /* disable VCN power gating */
++      vcn_v4_0_5_disable_static_power_gating(adev, i);
++
++      /* set VCN status busy */
++      tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
++      WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
++
++      /* SW clock gating */
++      vcn_v4_0_5_disable_clock_gating(adev, i);
++
++      /* enable VCPU clock */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
++               UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
++
++      /* disable master interrupt */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
++               ~UVD_MASTINT_EN__VCPU_EN_MASK);
++
++      /* enable LMI MC and UMC channels */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
++               ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
++
++      tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
++      tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
++      tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
++      WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
++
++      /* setup regUVD_LMI_CTRL */
++      tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
++      WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
++                   UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
++                   UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
++                   UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
++                   UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
++
++      /* setup regUVD_MPC_CNTL */
++      tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
++      tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
++      tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
++      WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
++
++      /* setup UVD_MPC_SET_MUXA0 */
++      WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
++                   ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
++                    (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
++                    (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
++                    (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
++
++      /* setup UVD_MPC_SET_MUXB0 */
++      WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
++                   ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
++                    (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
++                    (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
++                    (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
++
++      /* setup UVD_MPC_SET_MUX */
++      WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
++                   ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
++                    (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
++                    (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
++
++      vcn_v4_0_5_mc_resume(adev, i);
++
++      /* VCN global tiling registers */
++      WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
++                   adev->gfx.config.gb_addr_config);
++
++      /* unblock VCPU register access */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
++               ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
++
++      /* release VCPU reset to boot */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
++               ~UVD_VCPU_CNTL__BLK_RST_MASK);
++
++      for (j = 0; j < 10; ++j) {
++              uint32_t status;
++
++              for (k = 0; k < 100; ++k) {
++                      status = RREG32_SOC15(VCN, i, regUVD_STATUS);
++                      if (status & 2)
++                              break;
++                      mdelay(10);
++                      if (amdgpu_emu_mode == 1)
++                              msleep(1);
++              }
+-                      if (amdgpu_emu_mode == 1) {
+-                              r = -1;
+-                              if (status & 2) {
+-                                      r = 0;
+-                                      break;
+-                              }
+-                      } else {
++              if (amdgpu_emu_mode == 1) {
++                      r = -1;
++                      if (status & 2) {
+                               r = 0;
+-                              if (status & 2)
+-                                      break;
+-
+-                              dev_err(adev->dev,
+-                                      "VCN[%d] is not responding, trying to reset VCPU!!!\n", i);
+-                              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+-                                                      UVD_VCPU_CNTL__BLK_RST_MASK,
+-                                                      ~UVD_VCPU_CNTL__BLK_RST_MASK);
+-                              mdelay(10);
+-                              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+-                                              ~UVD_VCPU_CNTL__BLK_RST_MASK);
+-
+-                              mdelay(10);
+-                              r = -1;
++                              break;
+                       }
+-              }
++              } else {
++                      r = 0;
++                      if (status & 2)
++                              break;
++
++                      dev_err(adev->dev,
++                              "VCN[%d] is not responding, trying to reset VCPU!!!\n", i);
++                      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
++                               UVD_VCPU_CNTL__BLK_RST_MASK,
++                               ~UVD_VCPU_CNTL__BLK_RST_MASK);
++                      mdelay(10);
++                      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
++                               ~UVD_VCPU_CNTL__BLK_RST_MASK);
+-              if (r) {
+-                      dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
+-                      return r;
++                      mdelay(10);
++                      r = -1;
+               }
++      }
+-              /* enable master interrupt */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
+-                              UVD_MASTINT_EN__VCPU_EN_MASK,
+-                              ~UVD_MASTINT_EN__VCPU_EN_MASK);
+-
+-              /* clear the busy bit of VCN_STATUS */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
+-                              ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
+-
+-              ring = &adev->vcn.inst[i].ring_enc[0];
+-              WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
+-                              ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
+-                              VCN_RB1_DB_CTRL__EN_MASK);
+-
+-              WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
+-              WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+-              WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
+-
+-              tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+-              tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
+-              WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+-              fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
+-              WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
+-              WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
+-
+-              tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
+-              WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
+-              ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
+-
+-              tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
+-              tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
+-              WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
+-              fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
++      if (r) {
++              dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
++              return r;
+       }
++      /* enable master interrupt */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
++               UVD_MASTINT_EN__VCPU_EN_MASK,
++               ~UVD_MASTINT_EN__VCPU_EN_MASK);
++
++      /* clear the busy bit of VCN_STATUS */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
++               ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
++
++      ring = &adev->vcn.inst[i].ring_enc[0];
++      WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
++                   ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
++                   VCN_RB1_DB_CTRL__EN_MASK);
++
++      WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
++      WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
++      WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
++
++      tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
++      tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
++      WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
++      fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
++      WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
++      WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
++
++      tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
++      WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
++      ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
++
++      tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
++      tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
++      WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
++      fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
++
+       return 0;
+ }
+@@ -1204,88 +1199,87 @@ static void vcn_v4_0_5_stop_dpg_mode(str
+  * vcn_v4_0_5_stop - VCN stop
+  *
+  * @adev: amdgpu_device pointer
++ * @i: instance to stop
+  *
+  * Stop VCN block
+  */
+-static int vcn_v4_0_5_stop(struct amdgpu_device *adev)
++static int vcn_v4_0_5_stop(struct amdgpu_device *adev, int i)
+ {
+       volatile struct amdgpu_vcn4_fw_shared *fw_shared;
+       uint32_t tmp;
+-      int i, r = 0;
++      int r = 0;
+-      for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+-              if (adev->vcn.harvest_config & (1 << i))
+-                      continue;
+-
+-              fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+-              fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+-
+-              if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
+-                      vcn_v4_0_5_stop_dpg_mode(adev, i);
+-                      continue;
+-              }
+-
+-              /* wait for vcn idle */
+-              r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
+-              if (r)
+-                      return r;
+-
+-              tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
+-                      UVD_LMI_STATUS__READ_CLEAN_MASK |
+-                      UVD_LMI_STATUS__WRITE_CLEAN_MASK |
+-                      UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
+-              r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+-              if (r)
+-                      return r;
+-
+-              /* disable LMI UMC channel */
+-              tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
+-              tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
+-              WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
+-              tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
+-                      UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
+-              r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
+-              if (r)
+-                      return r;
+-
+-              /* block VCPU register access */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
+-                              UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
+-                              ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
+-
+-              /* reset VCPU */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
+-                              UVD_VCPU_CNTL__BLK_RST_MASK,
+-                              ~UVD_VCPU_CNTL__BLK_RST_MASK);
+-
+-              /* disable VCPU clock */
+-              WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
+-                              ~(UVD_VCPU_CNTL__CLK_EN_MASK));
+-
+-              /* apply soft reset */
+-              tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+-              tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
+-              WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+-              tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
+-              tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
+-              WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
+-
+-              /* clear status */
+-              WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
++      if (adev->vcn.harvest_config & (1 << i))
++              return 0;
+-              /* apply HW clock gating */
+-              vcn_v4_0_5_enable_clock_gating(adev, i);
++      fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
++      fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
+-              /* enable VCN power gating */
+-              vcn_v4_0_5_enable_static_power_gating(adev, i);
++      if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
++              vcn_v4_0_5_stop_dpg_mode(adev, i);
++              r = 0;
++              goto done;
+       }
+-      for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+-              if (adev->pm.dpm_enabled)
+-                      amdgpu_dpm_enable_vcn(adev, false, i);
+-      }
++      /* wait for vcn idle */
++      r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
++      if (r)
++              goto done;
++
++      tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
++              UVD_LMI_STATUS__READ_CLEAN_MASK |
++              UVD_LMI_STATUS__WRITE_CLEAN_MASK |
++              UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
++      r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
++      if (r)
++              goto done;
++
++      /* disable LMI UMC channel */
++      tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
++      tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
++      WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
++      tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
++              UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
++      r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
++      if (r)
++              goto done;
++
++      /* block VCPU register access */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
++               UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
++               ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
++
++      /* reset VCPU */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
++               UVD_VCPU_CNTL__BLK_RST_MASK,
++               ~UVD_VCPU_CNTL__BLK_RST_MASK);
++
++      /* disable VCPU clock */
++      WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
++               ~(UVD_VCPU_CNTL__CLK_EN_MASK));
++
++      /* apply soft reset */
++      tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
++      tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
++      WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
++      tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
++      tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
++      WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
++
++      /* clear status */
++      WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
++
++      /* apply HW clock gating */
++      vcn_v4_0_5_enable_clock_gating(adev, i);
++
++      /* enable VCN power gating */
++      vcn_v4_0_5_enable_static_power_gating(adev, i);
++
++done:
++      if (adev->pm.dpm_enabled)
++              amdgpu_dpm_enable_vcn(adev, false, i);
+-      return 0;
++      return r;
+ }
+ /**
+@@ -1537,15 +1531,17 @@ static int vcn_v4_0_5_set_powergating_st
+               enum amd_powergating_state state)
+ {
+       struct amdgpu_device *adev = ip_block->adev;
+-      int ret;
++      int ret = 0, i;
+       if (state == adev->vcn.cur_state)
+               return 0;
+-      if (state == AMD_PG_STATE_GATE)
+-              ret = vcn_v4_0_5_stop(adev);
+-      else
+-              ret = vcn_v4_0_5_start(adev);
++      for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
++              if (state == AMD_PG_STATE_GATE)
++                      ret |= vcn_v4_0_5_stop(adev, i);
++              else
++                      ret |= vcn_v4_0_5_start(adev, i);
++      }
+       if (!ret)
+               adev->vcn.cur_state = state;
diff --git a/queue-6.14/drm-i915-dp-fix-determining-sst-mst-mode-during-mtp-tu-state-computation.patch b/queue-6.14/drm-i915-dp-fix-determining-sst-mst-mode-during-mtp-tu-state-computation.patch
new file mode 100644 (file)
index 0000000..3c08592
--- /dev/null
@@ -0,0 +1,54 @@
+From 732b87a409667a370b87955c518e5d004de740b5 Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@intel.com>
+Date: Wed, 7 May 2025 18:19:53 +0300
+Subject: drm/i915/dp: Fix determining SST/MST mode during MTP TU state computation
+
+From: Imre Deak <imre.deak@intel.com>
+
+commit 732b87a409667a370b87955c518e5d004de740b5 upstream.
+
+Determining the SST/MST mode during state computation must be done based
+on the output type stored in the CRTC state, which in turn is set once
+based on the modeset connector's SST vs. MST type and will not change as
+long as the connector is using the CRTC. OTOH the MST mode indicated by
+the given connector's intel_dp::is_mst flag can change independently of
+the above output type, based on what sink is at any moment plugged to
+the connector.
+
+Fix the state computation accordingly.
+
+Cc: Jani Nikula <jani.nikula@intel.com>
+Fixes: f6971d7427c2 ("drm/i915/mst: adapt intel_dp_mtp_tu_compute_config() for 128b/132b SST")
+Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/4607
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Imre Deak <imre.deak@intel.com>
+Link: https://lore.kernel.org/r/20250507151953.251846-1-imre.deak@intel.com
+(cherry picked from commit 0f45696ddb2b901fbf15cb8d2e89767be481d59f)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+References: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14218
+[Rebased on v6.14.8 and added References link. (Imre)]
+Signed-off-by: Imre Deak <imre.deak@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_dp_mst.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+@@ -221,6 +221,7 @@ int intel_dp_mtp_tu_compute_config(struc
+               to_intel_connector(conn_state->connector);
+       const struct drm_display_mode *adjusted_mode =
+               &crtc_state->hw.adjusted_mode;
++      bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
+       fixed20_12 pbn_div;
+       int bpp, slots = -EINVAL;
+       int dsc_slice_count = 0;
+@@ -271,7 +272,7 @@ int intel_dp_mtp_tu_compute_config(struc
+                                        link_bpp_x16,
+                                        &crtc_state->dp_m_n);
+-              if (intel_dp->is_mst) {
++              if (is_mst) {
+                       int remote_bw_overhead;
+                       int remote_tu;
+                       fixed20_12 pbn;
index 7fa6f06634a343d5651ad6e513d588e94d1eef80..ce36a9914ad9caa65576c7b39cc312614873ebc5 100644 (file)
@@ -776,3 +776,6 @@ spi-spi-fsl-dspi-halt-the-module-after-a-new-message.patch
 spi-spi-fsl-dspi-reset-sr-flags-before-sending-a-new.patch
 drm-xe-use-xe_mmio_read32-to-read-mtcfg-register.patch
 err.h-move-iomem_err_ptr-to-err.h.patch
+drm-i915-dp-fix-determining-sst-mst-mode-during-mtp-tu-state-computation.patch
+drm-amdgpu-vcn4.0.5-split-code-along-instances.patch
+drm-amdgpu-read-back-register-after-written-for-vcn-v4.0.5.patch