History

Merge tag 'amd-drm-fixes-6.13-2024-12-04' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes

amd-drm-fixes-6.13-2024-12-04: amdgpu: - Jpeg work handler fix for VCN 1.0 - HDP flush fixes - ACPI EDID sanity check - OLED panel backlight fix - DC YCbCr fix - DC Detile buffer size debugging - DC prefetch calculation fix - DC VTotal handling fix - DC HBlank fix - ISP fix - SR-IOV fix - Workload profile fixes - DCN 4.0.1 resume fix amdkfd: - GC 12.x fix - GC 9.4.x fix

Simona Vetter committed 1 year ago

Commit 1995e7d2 parents 471f3a2 73dae6549 files · +1031 −615Browse files

Unified · Split

49 files
  1. drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +64 −26
  2. drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c +8 −4
  3. drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c +5 −2
  4. drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c +4 −2
  5. drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c +4 −2
  6. drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c +4 −2
  7. drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c +1 −1
  8. drivers/gpu/drm/amd/amdkfd/kfd_crat.c +6 −0
  9. drivers/gpu/drm/amd/amdkfd/kfd_device.c +3 −0
  10. drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +2 −0
  11. drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +10 −3
  12. drivers/gpu/drm/amd/display/dc/core/dc.c +18 −0
  13. drivers/gpu/drm/amd/display/dc/core/dc_resource.c +41 −1
  14. drivers/gpu/drm/amd/display/dc/dc.h +4 −0
  15. drivers/gpu/drm/amd/display/dc/dc_spl_translate.c +1 −1
  16. drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c +1 −0
  17. drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c +44 −4
  18. drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +2 −1
  19. drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +6 −1
  20. drivers/gpu/drm/amd/display/dc/inc/core_types.h +3 −0
  21. drivers/gpu/drm/amd/display/dc/link/link_dpms.c +2 −1
  22. drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +23 −0
  23. drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c +1 −0
  24. drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c +1 −0
  25. drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c +1 −0
  26. drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +7 −0
  27. drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h +3 −0
  28. drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +1 −0
  29. drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +1 −0
  30. drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c +1 −0
  31. drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +2 −0
  32. drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +1 −0
  33. drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +2 −0
  34. drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +2 −0
  35. drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +1 −0
  36. drivers/gpu/drm/amd/display/modules/freesync/freesync.c +12 −1
  37. drivers/gpu/drm/amd/pm/amdgpu_pm.c +5 −1
  38. drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +92 −77
  39. drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +10 −7
  40. drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +95 −72
  41. drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +101 −69
  42. drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +102 −69
  43. drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +13 −28
  44. drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +13 −30
  45. drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +96 −79
  46. drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +85 −54
  47. drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +98 −67
  48. drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +25 −8
  49. drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +4 −2
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c+64−26
@@ -145,7 +145,7 @@ const char *amdgpu_asic_name[] = { · 144 unmodified lines
145145 "LAST",
146146 };
147147
148−#define AMDGPU_IP_BLK_MASK_ALL GENMASK(AMDGPU_MAX_IP_NUM - 1, 0)
148+#define AMDGPU_IP_BLK_MASK_ALL GENMASK(AMDGPU_MAX_IP_NUM, 0)
149149 /*
150150 * Default init level where all blocks are expected to be initialized. This is
151151 * the level of initialization expected by default and also after a full reset
@@ -3670,9 +3670,11 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) · 3518 unmodified lines
36703670 continue;
36713671
36723672 r = block->version->funcs->hw_init(&adev->ip_blocks[i]);
3673− DRM_INFO("RE-INIT-early: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
3674− if (r)
3673+ if (r) {
3674+ dev_err(adev->dev, "RE-INIT-early: %s failed\n",
3675+ block->version->funcs->name);
36753676 return r;
3677+ }
36763678 block->status.hw = true;
36773679 }
36783680 }
@@ -3682,7 +3684,8 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) · 3 unmodified lines
36823684
36833685 static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev)
36843686 {
3685− int i, r;
3687+ struct amdgpu_ip_block *block;
3688+ int i, r = 0;
36863689
36873690 static enum amd_ip_block_type ip_order[] = {
36883691 AMD_IP_BLOCK_TYPE_SMC,
@@ -3697,34 +3700,28 @@ static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev) · 8 unmodified lines
36973700 };
36983701
36993702 for (i = 0; i < ARRAY_SIZE(ip_order); i++) {
3700− int j;
3701− struct amdgpu_ip_block *block;
3702−
3703− for (j = 0; j < adev->num_ip_blocks; j++) {
3704− block = &adev->ip_blocks[j];
3703+ block = amdgpu_device_ip_get_ip_block(adev, ip_order[i]);
37053704
3706− if (block->version->type != ip_order[i] ||
3707− !block->status.valid ||
3708− block->status.hw)
3709− continue;
3705+ if (!block)
3706+ continue;
37103707
3708+ if (block->status.valid && !block->status.hw) {
37113709 if (block->version->type == AMD_IP_BLOCK_TYPE_SMC) {
3712− r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
3713− if (r)
3714− return r;
3710+ r = amdgpu_ip_block_resume(block);
37153711 } else {
3716− r = block->version->funcs->hw_init(&adev->ip_blocks[i]);
3717− if (r) {
3718− DRM_ERROR("hw_init of IP block <%s> failed %d\n",
3719− adev->ip_blocks[i].version->funcs->name, r);
3720− return r;
3721− }
3722− block->status.hw = true;
3712+ r = block->version->funcs->hw_init(block);
37233713 }
3714+
3715+ if (r) {
3716+ dev_err(adev->dev, "RE-INIT-late: %s failed\n",
3717+ block->version->funcs->name);
3718+ break;
3719+ }
3720+ block->status.hw = true;
37243721 }
37253722 }
37263723
3727− return 0;
3724+ return r;
37283725 }
37293726
37303727 /**
@@ -3765,7 +3762,7 @@ static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev) · 34 unmodified lines
37653762 *
37663763 * @adev: amdgpu_device pointer
37673764 *
3768− * First resume function for hardware IPs. The list of all the hardware
3765+ * Second resume function for hardware IPs. The list of all the hardware
37693766 * IPs that make up the asic is walked and the resume callbacks are run for
37703767 * all blocks except COMMON, GMC, and IH. resume puts the hardware into a
37713768 * functional state after a suspend and updates the software state as
@@ -3783,6 +3780,7 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev) · 11 unmodified lines
37833780 if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
37843781 adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
37853782 adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
3783+ adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE ||
37863784 adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
37873785 continue;
37883786 r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
@@ -3793,6 +3791,36 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev) · 4 unmodified lines
37933791 return 0;
37943792 }
37953793
3794+/**
3795+ * amdgpu_device_ip_resume_phase3 - run resume for hardware IPs
3796+ *
3797+ * @adev: amdgpu_device pointer
3798+ *
3799+ * Third resume function for hardware IPs. The list of all the hardware
3800+ * IPs that make up the asic is walked and the resume callbacks are run for
3801+ * all DCE. resume puts the hardware into a functional state after a suspend
3802+ * and updates the software state as necessary. This function is also used
3803+ * for restoring the GPU after a GPU reset.
3804+ *
3805+ * Returns 0 on success, negative error code on failure.
3806+ */
3807+static int amdgpu_device_ip_resume_phase3(struct amdgpu_device *adev)
3808+{
3809+ int i, r;
3810+
3811+ for (i = 0; i < adev->num_ip_blocks; i++) {
3812+ if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw)
3813+ continue;
3814+ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) {
3815+ r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
3816+ if (r)
3817+ return r;
3818+ }
3819+ }
3820+
3821+ return 0;
3822+}
3823+
37963824 /**
37973825 * amdgpu_device_ip_resume - run resume for hardware IPs
37983826 *
@@ -3822,6 +3850,13 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev) · 23 unmodified lines
38223850 if (adev->mman.buffer_funcs_ring->sched.ready)
38233851 amdgpu_ttm_set_buffer_funcs_status(adev, true);
38243852
3853+ if (r)
3854+ return r;
3855+
3856+ amdgpu_fence_driver_hw_init(adev);
3857+
3858+ r = amdgpu_device_ip_resume_phase3(adev);
3859+
38253860 return r;
38263861 }
38273862
@@ -4902,7 +4937,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool notify_clients) · 1074 unmodified lines
49024937 dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
49034938 goto exit;
49044939 }
4905− amdgpu_fence_driver_hw_init(adev);
49064940
49074941 if (!adev->in_s0ix) {
49084942 r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
@@ -5487,6 +5521,10 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context) · 578 unmodified lines
54875521 if (tmp_adev->mman.buffer_funcs_ring->sched.ready)
54885522 amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true);
54895523
5524+ r = amdgpu_device_ip_resume_phase3(tmp_adev);
5525+ if (r)
5526+ goto out;
5527+
54905528 if (vram_lost)
54915529 amdgpu_device_fill_reset_magic(tmp_adev);
54925530
drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c+8−4
@@ -40,10 +40,12 @@ · 39 unmodified lines
4040 static void hdp_v4_0_flush_hdp(struct amdgpu_device *adev,
4141 struct amdgpu_ring *ring)
4242 {
43− if (!ring || !ring->funcs->emit_wreg)
43+ if (!ring || !ring->funcs->emit_wreg) {
4444 WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
45− else
45+ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
46+ } else {
4647 amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
48+ }
4749 }
4850
4951 static void hdp_v4_0_invalidate_hdp(struct amdgpu_device *adev,
@@ -54,11 +56,13 @@ static void hdp_v4_0_invalidate_hdp(struct amdgpu_device *adev, · 4 unmodified lines
5456 amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 4, 5))
5557 return;
5658
57− if (!ring || !ring->funcs->emit_wreg)
59+ if (!ring || !ring->funcs->emit_wreg) {
5860 WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1);
59− else
61+ RREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE);
62+ } else {
6063 amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
6164 HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1);
65+ }
6266 }
6367
6468 static void hdp_v4_0_query_ras_error_count(struct amdgpu_device *adev,
drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c+5−2
@@ -31,10 +31,12 @@ · 30 unmodified lines
3131 static void hdp_v5_0_flush_hdp(struct amdgpu_device *adev,
3232 struct amdgpu_ring *ring)
3333 {
34− if (!ring || !ring->funcs->emit_wreg)
34+ if (!ring || !ring->funcs->emit_wreg) {
3535 WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
36− else
36+ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
37+ } else {
3738 amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
39+ }
3840 }
3941
4042 static void hdp_v5_0_invalidate_hdp(struct amdgpu_device *adev,
@@ -42,6 +44,7 @@ static void hdp_v5_0_invalidate_hdp(struct amdgpu_device *adev, · 1 unmodified line
4244 {
4345 if (!ring || !ring->funcs->emit_wreg) {
4446 WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1);
47+ RREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE);
4548 } else {
4649 amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
4750 HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1);
drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c+4−2
@@ -31,13 +31,15 @@ · 30 unmodified lines
3131 static void hdp_v5_2_flush_hdp(struct amdgpu_device *adev,
3232 struct amdgpu_ring *ring)
3333 {
34− if (!ring || !ring->funcs->emit_wreg)
34+ if (!ring || !ring->funcs->emit_wreg) {
3535 WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2,
3636 0);
37− else
37+ RREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
38+ } else {
3839 amdgpu_ring_emit_wreg(ring,
3940 (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2,
4041 0);
42+ }
4143 }
4244
4345 static void hdp_v5_2_update_mem_power_gating(struct amdgpu_device *adev,
drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c+4−2
@@ -34,10 +34,12 @@ · 33 unmodified lines
3434 static void hdp_v6_0_flush_hdp(struct amdgpu_device *adev,
3535 struct amdgpu_ring *ring)
3636 {
37− if (!ring || !ring->funcs->emit_wreg)
37+ if (!ring || !ring->funcs->emit_wreg) {
3838 WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
39− else
39+ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
40+ } else {
4041 amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
42+ }
4143 }
4244
4345 static void hdp_v6_0_update_clock_gating(struct amdgpu_device *adev,
drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c+4−2
@@ -31,10 +31,12 @@ · 30 unmodified lines
3131 static void hdp_v7_0_flush_hdp(struct amdgpu_device *adev,
3232 struct amdgpu_ring *ring)
3333 {
34− if (!ring || !ring->funcs->emit_wreg)
34+ if (!ring || !ring->funcs->emit_wreg) {
3535 WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
36− else
36+ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
37+ } else {
3738 amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
39+ }
3840 }
3941
4042 static void hdp_v7_0_update_clock_gating(struct amdgpu_device *adev,
drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c+1−1
@@ -604,7 +604,7 @@ static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev) · 603 unmodified lines
604604 static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
605605 {
606606 struct amdgpu_device *adev = ring->adev;
607− bool set_clocks = !cancel_delayed_work_sync(&adev->jpeg.idle_work);
607+ bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
608608 int cnt = 0;
609609
610610 mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
drivers/gpu/drm/amd/amdkfd/kfd_crat.c+6−0
@@ -1510,6 +1510,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev, · 1509 unmodified lines
15101510 if (adev->gfx.config.gc_tcp_size_per_cu) {
15111511 pcache_info[i].cache_size = adev->gfx.config.gc_tcp_size_per_cu;
15121512 pcache_info[i].cache_level = 1;
1513+ /* Cacheline size not available in IP discovery for gc943,gc944 */
1514+ pcache_info[i].cache_line_size = 128;
15131515 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
15141516 CRAT_CACHE_FLAGS_DATA_CACHE |
15151517 CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1521,6 +1523,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev, · 5 unmodified lines
15211523 pcache_info[i].cache_size =
15221524 adev->gfx.config.gc_l1_instruction_cache_size_per_sqc;
15231525 pcache_info[i].cache_level = 1;
1526+ pcache_info[i].cache_line_size = 64;
15241527 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
15251528 CRAT_CACHE_FLAGS_INST_CACHE |
15261529 CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1531,6 +1534,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev, · 4 unmodified lines
15311534 if (adev->gfx.config.gc_l1_data_cache_size_per_sqc) {
15321535 pcache_info[i].cache_size = adev->gfx.config.gc_l1_data_cache_size_per_sqc;
15331536 pcache_info[i].cache_level = 1;
1537+ pcache_info[i].cache_line_size = 64;
15341538 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
15351539 CRAT_CACHE_FLAGS_DATA_CACHE |
15361540 CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1541,6 +1545,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev, · 4 unmodified lines
15411545 if (adev->gfx.config.gc_tcc_size) {
15421546 pcache_info[i].cache_size = adev->gfx.config.gc_tcc_size;
15431547 pcache_info[i].cache_level = 2;
1548+ pcache_info[i].cache_line_size = 128;
15441549 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
15451550 CRAT_CACHE_FLAGS_DATA_CACHE |
15461551 CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1551,6 +1556,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev, · 4 unmodified lines
15511556 if (adev->gmc.mall_size) {
15521557 pcache_info[i].cache_size = adev->gmc.mall_size / 1024;
15531558 pcache_info[i].cache_level = 3;
1559+ pcache_info[i].cache_line_size = 64;
15541560 pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
15551561 CRAT_CACHE_FLAGS_DATA_CACHE |
15561562 CRAT_CACHE_FLAGS_SIMD_CACHE);
drivers/gpu/drm/amd/amdkfd/kfd_device.c+3−0
@@ -235,6 +235,9 @@ static void kfd_device_info_init(struct kfd_dev *kfd, · 234 unmodified lines
235235 */
236236 kfd->device_info.needs_pci_atomics = true;
237237 kfd->device_info.no_atomic_fw_version = kfd->adev->gfx.rs64_enable ? 509 : 0;
238+ } else if (gc_version < IP_VERSION(13, 0, 0)) {
239+ kfd->device_info.needs_pci_atomics = true;
240+ kfd->device_info.no_atomic_fw_version = 2090;
238241 } else {
239242 kfd->device_info.needs_pci_atomics = true;
240243 }
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c+2−0
@@ -3481,6 +3481,8 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) · 3480 unmodified lines
34813481 caps->aux_support = false;
34823482 else if (amdgpu_backlight == 1)
34833483 caps->aux_support = true;
3484+ if (caps->aux_support)
3485+ aconnector->dc_link->backlight_control_type = BACKLIGHT_CONTROL_AMD_AUX;
34843486
34853487 luminance_range = &conn_base->display_info.luminance_range;
34863488
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c+10−3
@@ -907,14 +907,14 @@ dm_helpers_probe_acpi_edid(void *data, u8 *buf, unsigned int block, size_t len) · 906 unmodified lines
907907 struct drm_connector *connector = data;
908908 struct acpi_device *acpidev = ACPI_COMPANION(connector->dev->dev);
909909 unsigned char start = block * EDID_LENGTH;
910− void *edid;
910+ struct edid *edid;
911911 int r;
912912
913913 if (!acpidev)
914914 return -ENODEV;
915915
916916 /* fetch the entire edid from BIOS */
917− r = acpi_video_get_edid(acpidev, ACPI_VIDEO_DISPLAY_LCD, -1, &edid);
917+ r = acpi_video_get_edid(acpidev, ACPI_VIDEO_DISPLAY_LCD, -1, (void *)&edid);
918918 if (r < 0) {
919919 drm_dbg(connector->dev, "Failed to get EDID from ACPI: %d\n", r);
920920 return r;
@@ -924,7 +924,14 @@ dm_helpers_probe_acpi_edid(void *data, u8 *buf, unsigned int block, size_t len) · 3 unmodified lines
924924 goto cleanup;
925925 }
926926
927− memcpy(buf, edid + start, len);
927+ /* sanity check */
928+ if (edid->revision < 4 || !(edid->input & DRM_EDID_INPUT_DIGITAL) ||
929+ (edid->input & DRM_EDID_DIGITAL_TYPE_MASK) == DRM_EDID_DIGITAL_TYPE_UNDEF) {
930+ r = -EINVAL;
931+ goto cleanup;
932+ }
933+
934+ memcpy(buf, (void *)edid + start, len);
928935 r = 0;
929936
930937 cleanup:
drivers/gpu/drm/amd/display/dc/core/dc.c+18−0
@@ -6109,3 +6109,21 @@ struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state · 6108 unmodified lines
61096109 profile.power_level = dc->res_pool->funcs->get_power_profile(context);
61106110 return profile;
61116111 }
6112+
6113+/*
6114+ **********************************************************************************
6115+ * dc_get_det_buffer_size_from_state() - extracts detile buffer size from dc state
6116+ *
6117+ * Called when DM wants to log detile buffer size from dc_state
6118+ *
6119+ **********************************************************************************
6120+ */
6121+unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context)
6122+{
6123+ struct dc *dc = context->clk_mgr->ctx->dc;
6124+
6125+ if (dc->res_pool->funcs->get_det_buffer_size)
6126+ return dc->res_pool->funcs->get_det_buffer_size(context);
6127+ else
6128+ return 0;
6129+}
drivers/gpu/drm/amd/display/dc/core/dc_resource.c+41−1
@@ -2094,7 +2094,8 @@ int resource_get_odm_slice_dst_width(struct pipe_ctx *otg_master, · 2093 unmodified lines
20942094 count = resource_get_odm_slice_count(otg_master);
20952095 h_active = timing->h_addressable +
20962096 timing->h_border_left +
2097− timing->h_border_right;
2097+ timing->h_border_right +
2098+ otg_master->hblank_borrow;
20982099 width = h_active / count;
20992100
21002101 if (otg_master->stream_res.tg)
@@ -4026,6 +4027,41 @@ fail: · 1925 unmodified lines
40264027 return res;
40274028 }
40284029
4030+/**
4031+ * decide_hblank_borrow - Decides the horizontal blanking borrow value for a given pipe context.
4032+ * @pipe_ctx: Pointer to the pipe context structure.
4033+ *
4034+ * This function calculates the horizontal blanking borrow value for a given pipe context based on the
4035+ * display stream compression (DSC) configuration. If the horizontal active pixels (hactive) are less
4036+ * than the total width of the DSC slices, it sets the hblank_borrow value to the difference. If the
4037+ * total horizontal timing minus the hblank_borrow value is less than 32, it resets the hblank_borrow
4038+ * value to 0.
4039+ */
4040+static void decide_hblank_borrow(struct pipe_ctx *pipe_ctx)
4041+{
4042+ uint32_t hactive;
4043+ uint32_t ceil_slice_width;
4044+ struct dc_stream_state *stream = NULL;
4045+
4046+ if (!pipe_ctx)
4047+ return;
4048+
4049+ stream = pipe_ctx->stream;
4050+
4051+ if (stream->timing.flags.DSC) {
4052+ hactive = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
4053+
4054+ /* Assume if determined slices does not divide Hactive evenly, Hborrow is needed for padding*/
4055+ if (hactive % stream->timing.dsc_cfg.num_slices_h != 0) {
4056+ ceil_slice_width = (hactive / stream->timing.dsc_cfg.num_slices_h) + 1;
4057+ pipe_ctx->hblank_borrow = ceil_slice_width * stream->timing.dsc_cfg.num_slices_h - hactive;
4058+
4059+ if (stream->timing.h_total - hactive - pipe_ctx->hblank_borrow < 32)
4060+ pipe_ctx->hblank_borrow = 0;
4061+ }
4062+ }
4063+}
4064+
40294065 /**
40304066 * dc_validate_global_state() - Determine if hardware can support a given state
40314067 *
@@ -4064,6 +4100,10 @@ enum dc_status dc_validate_global_state( · 32 unmodified lines
40644100 if (pipe_ctx->stream != stream)
40654101 continue;
40664102
4103+ /* Decide whether hblank borrow is needed and save it in pipe_ctx */
4104+ if (dc->debug.enable_hblank_borrow)
4105+ decide_hblank_borrow(pipe_ctx);
4106+
40674107 if (dc->res_pool->funcs->patch_unknown_plane_state &&
40684108 pipe_ctx->plane_state &&
40694109 pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
drivers/gpu/drm/amd/display/dc/dc.h+4−0
@@ -290,6 +290,7 @@ struct dc_caps { · 289 unmodified lines
290290 uint16_t subvp_vertical_int_margin_us;
291291 bool seamless_odm;
292292 uint32_t max_v_total;
293+ bool vtotal_limited_by_fp2;
293294 uint32_t max_disp_clock_khz_at_vmin;
294295 uint8_t subvp_drr_vblank_start_margin_us;
295296 bool cursor_not_scaled;
@@ -1068,6 +1069,7 @@ struct dc_debug_options { · 772 unmodified lines
10681069 unsigned int scale_to_sharpness_policy;
10691070 bool skip_full_updated_if_possible;
10701071 unsigned int enable_oled_edp_power_up_opt;
1072+ bool enable_hblank_borrow;
10711073 };
10721074
10731075
@@ -2550,6 +2552,8 @@ struct dc_power_profile { · 1476 unmodified lines
25502552
25512553 struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state *context);
25522554
2555+unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context);
2556+
25532557 /* DSC Interfaces */
25542558 #include "dc_dsc.h"
25552559
drivers/gpu/drm/amd/display/dc/dc_spl_translate.c+1−1
@@ -120,7 +120,7 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl · 119 unmodified lines
120120 spl_in->odm_slice_index = resource_get_odm_slice_index(pipe_ctx);
121121 // Make spl input basic out info output_size width point to stream h active
122122 spl_in->basic_out.output_size.width =
123− stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
123+ stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->hblank_borrow;
124124 // Make spl input basic out info output_size height point to v active
125125 spl_in->basic_out.output_size.height =
126126 stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c+1−0
@@ -1222,6 +1222,7 @@ static dml_bool_t CalculatePrefetchSchedule(struct display_mode_lib_scratch_st * · 1221 unmodified lines
12221222 s->dst_y_prefetch_oto = s->Tvm_oto_lines + 2 * s->Tr0_oto_lines + s->Lsw_oto;
12231223
12241224 s->dst_y_prefetch_equ = p->VStartup - (*p->TSetup + dml_max(p->TWait + p->TCalc, *p->Tdmdl)) / s->LineTime - (*p->DSTYAfterScaler + (dml_float_t) *p->DSTXAfterScaler / (dml_float_t)p->myPipe->HTotal);
1225+ s->dst_y_prefetch_equ = dml_min(s->dst_y_prefetch_equ, 63.75); // limit to the reg limit of U6.2 for DST_Y_PREFETCH
12251226
12261227 #ifdef __DML_VBA_DEBUG__
12271228 dml_print("DML::%s: HTotal = %u\n", __func__, p->myPipe->HTotal);
drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c+44−4
@@ -339,11 +339,22 @@ void dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out *dml_in · 338 unmodified lines
339339 // }
340340 }
341341
342+static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
343+{
344+ unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
345+
346+ if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
347+ max_hw_v_total -= stream->timing.v_front_porch + 1;
348+ }
349+
350+ return max_hw_v_total;
351+}
352+
342353 static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg *timing,
343354 struct dc_stream_state *stream,
344355 struct dml2_context *dml_ctx)
345356 {
346− unsigned int hblank_start, vblank_start;
357+ unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz;
347358
348359 timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
349360 timing->v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
@@ -371,11 +382,23 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf · 21 unmodified lines
371382 - stream->timing.v_border_top - stream->timing.v_border_bottom;
372383
373384 timing->drr_config.enabled = stream->ignore_msa_timing_param;
374− timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz;
375385 timing->drr_config.drr_active_variable = stream->vrr_active_variable;
376386 timing->drr_config.drr_active_fixed = stream->vrr_active_fixed;
377387 timing->drr_config.disallowed = !stream->allow_freesync;
378388
389+ /* limit min refresh rate to DC cap */
390+ min_hardware_refresh_in_uhz = stream->timing.min_refresh_in_uhz;
391+ if (stream->ctx->dc->caps.max_v_total != 0) {
392+ min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
393+ (stream->timing.h_total * (long long)calc_max_hardware_v_total(stream)));
394+ }
395+
396+ if (stream->timing.min_refresh_in_uhz > min_hardware_refresh_in_uhz) {
397+ timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz;
398+ } else {
399+ timing->drr_config.min_refresh_uhz = min_hardware_refresh_in_uhz;
400+ }
401+
379402 if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
380403 stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
381404 timing->drr_config.max_instant_vtotal_delta = dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase(stream, false);
@@ -422,6 +445,21 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf · 40 unmodified lines
422445 timing->vblank_nom = timing->v_total - timing->v_active;
423446 }
424447
448+/**
449+ * adjust_dml21_hblank_timing_config_from_pipe_ctx - Adjusts the horizontal blanking timing configuration
450+ * based on the pipe context.
451+ * @timing: Pointer to the dml2_timing_cfg structure to be adjusted.
452+ * @pipe: Pointer to the pipe_ctx structure containing the horizontal blanking borrow value.
453+ *
454+ * This function modifies the horizontal active and blank end timings by adding and subtracting
455+ * the horizontal blanking borrow value from the pipe context, respectively.
456+ */
457+static void adjust_dml21_hblank_timing_config_from_pipe_ctx(struct dml2_timing_cfg *timing, struct pipe_ctx *pipe)
458+{
459+ timing->h_active += pipe->hblank_borrow;
460+ timing->h_blank_end -= pipe->hblank_borrow;
461+}
462+
425463 static void populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg *output,
426464 struct dc_stream_state *stream, const struct pipe_ctx *pipe)
427465 {
@@ -709,6 +747,7 @@ static const struct scaler_data *get_scaler_data_for_plane( · 281 unmodified lines
709747 temp_pipe->plane_state = pipe->plane_state;
710748 temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps;
711749 temp_pipe->stream_res = pipe->stream_res;
750+ temp_pipe->hblank_borrow = pipe->hblank_borrow;
712751 dml_ctx->config.callbacks.build_scaling_params(temp_pipe);
713752 break;
714753 }
@@ -973,6 +1012,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s · 258 unmodified lines
9731012
9741013 ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__);
9751014 populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx);
1015+ adjust_dml21_hblank_timing_config_from_pipe_ctx(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, &context->res_ctx.pipe_ctx[stream_index]);
9761016 populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]);
9771017 populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index]);
9781018
@@ -1111,12 +1151,12 @@ void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_ · 132 unmodified lines
11111151 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
11121152 union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
11131153
1114− hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right;
1154+ hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right + pipe_ctx->hblank_borrow;
11151155 vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top;
11161156 hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch;
11171157 vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch;
11181158
1119− hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right;
1159+ hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right - pipe_ctx->hblank_borrow;
11201160 vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;
11211161
11221162 if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c+2−1
@@ -1049,7 +1049,8 @@ void dcn32_update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) · 1048 unmodified lines
10491049 }
10501050
10511051 /* Enable DSC hw block */
1052− dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
1052+ dsc_cfg.pic_width = (stream->timing.h_addressable + pipe_ctx->hblank_borrow +
1053+ stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
10531054 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
10541055 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
10551056 dsc_cfg.color_depth = stream->timing.display_color_depth;
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c+6−1
@@ -820,6 +820,7 @@ enum dc_status dcn401_enable_stream_timing( · 819 unmodified lines
820820 int opp_cnt = 1;
821821 int opp_inst[MAX_PIPES] = {0};
822822 struct pipe_ctx *opp_heads[MAX_PIPES] = {0};
823+ struct dc_crtc_timing patched_crtc_timing = stream->timing;
823824 bool manual_mode;
824825 unsigned int tmds_div = PIXEL_RATE_DIV_NA;
825826 unsigned int unused_div = PIXEL_RATE_DIV_NA;
@@ -874,9 +875,13 @@ enum dc_status dcn401_enable_stream_timing( · 48 unmodified lines
874875 if (dc->hwseq->funcs.PLAT_58856_wa && (!dc_is_dp_signal(stream->signal)))
875876 dc->hwseq->funcs.PLAT_58856_wa(context, pipe_ctx);
876877
878+ /* if we are borrowing from hblank, h_addressable needs to be adjusted */
879+ if (dc->debug.enable_hblank_borrow)
880+ patched_crtc_timing.h_addressable = patched_crtc_timing.h_addressable + pipe_ctx->hblank_borrow;
881+
877882 pipe_ctx->stream_res.tg->funcs->program_timing(
878883 pipe_ctx->stream_res.tg,
879− &stream->timing,
884+ &patched_crtc_timing,
880885 pipe_ctx->pipe_dlg_param.vready_offset,
881886 pipe_ctx->pipe_dlg_param.vstartup_start,
882887 pipe_ctx->pipe_dlg_param.vupdate_offset,
drivers/gpu/drm/amd/display/dc/inc/core_types.h+3−0
@@ -219,6 +219,7 @@ struct resource_funcs { · 218 unmodified lines
219219 * Get indicator of power from a context that went through full validation
220220 */
221221 int (*get_power_profile)(const struct dc_state *context);
222+ unsigned int (*get_det_buffer_size)(const struct dc_state *context);
222223 };
223224
224225 struct audio_support{
@@ -477,6 +478,8 @@ struct pipe_ctx { · 252 unmodified lines
477478 /* subvp_index: only valid if the pipe is a SUBVP_MAIN*/
478479 uint8_t subvp_index;
479480 struct pixel_rate_divider pixel_rate_divider;
481+ /* pixels borrowed from hblank to hactive */
482+ uint8_t hblank_borrow;
480483 };
481484
482485 /* Data used for dynamic link encoder assignment.
drivers/gpu/drm/amd/display/dc/link/link_dpms.c+2−1
@@ -808,7 +808,8 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) · 807 unmodified lines
808808 enum optc_dsc_mode optc_dsc_mode;
809809
810810 /* Enable DSC hw block */
811− dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
811+ dsc_cfg.pic_width = (stream->timing.h_addressable + pipe_ctx->hblank_borrow +
812+ stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
812813 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
813814 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
814815 dsc_cfg.color_depth = stream->timing.display_color_depth;
drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c+23−0
@@ -1510,6 +1510,7 @@ bool dcn20_split_stream_for_odm( · 1509 unmodified lines
15101510
15111511 if (prev_odm_pipe->plane_state) {
15121512 struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data;
1513+ struct output_pixel_processor *opp = next_odm_pipe->stream_res.opp;
15131514 int new_width;
15141515
15151516 /* HACTIVE halved for odm combine */
@@ -1543,7 +1544,28 @@ bool dcn20_split_stream_for_odm( · 27 unmodified lines
15431544 sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int(
15441545 sd->ratios.horz_c, sd->h_active - sd->recout.x));
15451546 sd->recout.x = 0;
1547+
1548+ /*
1549+ * When odm is used in YcbCr422 or 420 colour space, a split screen
1550+ * will be seen with the previous calculations since the extra left
1551+ * edge pixel is accounted for in fmt but not in viewport.
1552+ *
1553+ * Below are calculations which fix the split by fixing the calculations
1554+ * if there is an extra left edge pixel.
1555+ */
1556+ if (opp && opp->funcs->opp_get_left_edge_extra_pixel_count
1557+ && opp->funcs->opp_get_left_edge_extra_pixel_count(
1558+ opp, next_odm_pipe->stream->timing.pixel_encoding,
1559+ resource_is_pipe_type(next_odm_pipe, OTG_MASTER)) == 1) {
1560+ sd->h_active += 1;
1561+ sd->recout.width += 1;
1562+ sd->viewport.x -= dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
1563+ sd->viewport_c.x -= dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
1564+ sd->viewport_c.width += dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
1565+ sd->viewport.width += dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
1566+ }
15461567 }
1568+
15471569 if (!next_odm_pipe->top_pipe)
15481570 next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
15491571 else
@@ -2132,6 +2154,7 @@ bool dcn20_fast_validate_bw( · 582 unmodified lines
21322154 ASSERT(0);
21332155 }
21342156 }
2157+
21352158 /* Actual dsc count per stream dsc validation*/
21362159 if (!dcn20_validate_dsc(dc, context)) {
21372160 context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] =
drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c+1−0
@@ -2353,6 +2353,7 @@ static bool dcn30_resource_construct( · 2352 unmodified lines
23532353
23542354 dc->caps.dp_hdmi21_pcon_support = true;
23552355 dc->caps.max_v_total = (1 << 15) - 1;
2356+ dc->caps.vtotal_limited_by_fp2 = true;
23562357
23572358 /* read VBIOS LTTPR caps */
23582359 {
drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c+1−0
@@ -1233,6 +1233,7 @@ static bool dcn302_resource_construct( · 1232 unmodified lines
12331233 dc->caps.extended_aux_timeout_support = true;
12341234 dc->caps.dmcub_support = true;
12351235 dc->caps.max_v_total = (1 << 15) - 1;
1236+ dc->caps.vtotal_limited_by_fp2 = true;
12361237
12371238 /* Color pipeline capabilities */
12381239 dc->caps.color.dpp.dcn_arch = 1;
drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c+1−0
@@ -1178,6 +1178,7 @@ static bool dcn303_resource_construct( · 1177 unmodified lines
11781178 dc->caps.extended_aux_timeout_support = true;
11791179 dc->caps.dmcub_support = true;
11801180 dc->caps.max_v_total = (1 << 15) - 1;
1181+ dc->caps.vtotal_limited_by_fp2 = true;
11811182
11821183 /* Color pipeline capabilities */
11831184 dc->caps.color.dpp.dcn_arch = 1;
drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c+7−0
@@ -1720,6 +1720,12 @@ int dcn31_populate_dml_pipes_from_context( · 1719 unmodified lines
17201720 return pipe_cnt;
17211721 }
17221722
1723+unsigned int dcn31_get_det_buffer_size(
1724+ const struct dc_state *context)
1725+{
1726+ return context->bw_ctx.dml.ip.det_buffer_size_kbytes;
1727+}
1728+
17231729 void dcn31_calculate_wm_and_dlg(
17241730 struct dc *dc, struct dc_state *context,
17251731 display_e2e_pipe_params_st *pipes,
@@ -1842,6 +1848,7 @@ static struct resource_funcs dcn31_res_pool_funcs = { · 116 unmodified lines
18421848 .update_bw_bounding_box = dcn31_update_bw_bounding_box,
18431849 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
18441850 .get_panel_config_defaults = dcn31_get_panel_config_defaults,
1851+ .get_det_buffer_size = dcn31_get_det_buffer_size,
18451852 };
18461853
18471854 static struct clock_source *dcn30_clock_source_create(
drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h+3−0
@@ -63,6 +63,9 @@ struct resource_pool *dcn31_create_resource_pool( · 62 unmodified lines
6363 const struct dc_init_data *init_data,
6464 struct dc *dc);
6565
66+unsigned int dcn31_get_det_buffer_size(
67+ const struct dc_state *context);
68+
6669 /*temp: B0 specific before switch to dcn313 headers*/
6770 #ifndef regPHYPLLF_PIXCLK_RESYNC_CNTL
6871 #define regPHYPLLF_PIXCLK_RESYNC_CNTL 0x007e
drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c+1−0
@@ -1777,6 +1777,7 @@ static struct resource_funcs dcn314_res_pool_funcs = { · 1776 unmodified lines
17771777 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
17781778 .get_panel_config_defaults = dcn314_get_panel_config_defaults,
17791779 .get_preferred_eng_id_dpia = dcn314_get_preferred_eng_id_dpia,
1780+ .get_det_buffer_size = dcn31_get_det_buffer_size,
17801781 };
17811782
17821783 static struct clock_source *dcn30_clock_source_create(
drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c+1−0
@@ -1845,6 +1845,7 @@ static struct resource_funcs dcn315_res_pool_funcs = { · 1844 unmodified lines
18451845 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
18461846 .get_panel_config_defaults = dcn315_get_panel_config_defaults,
18471847 .get_power_profile = dcn315_get_power_profile,
1848+ .get_det_buffer_size = dcn31_get_det_buffer_size,
18481849 };
18491850
18501851 static bool dcn315_resource_construct(
drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c+1−0
@@ -1719,6 +1719,7 @@ static struct resource_funcs dcn316_res_pool_funcs = { · 1718 unmodified lines
17191719 .update_bw_bounding_box = dcn316_update_bw_bounding_box,
17201720 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
17211721 .get_panel_config_defaults = dcn316_get_panel_config_defaults,
1722+ .get_det_buffer_size = dcn31_get_det_buffer_size,
17221723 };
17231724
17241725 static bool dcn316_resource_construct(
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c+2−0
@@ -2189,6 +2189,7 @@ static bool dcn32_resource_construct( · 2188 unmodified lines
21892189 dc->caps.dmcub_support = true;
21902190 dc->caps.seamless_odm = true;
21912191 dc->caps.max_v_total = (1 << 15) - 1;
2192+ dc->caps.vtotal_limited_by_fp2 = true;
21922193
21932194 /* Color pipeline capabilities */
21942195 dc->caps.color.dpp.dcn_arch = 1;
@@ -2803,6 +2804,7 @@ struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head( · 608 unmodified lines
28032804 free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx];
28042805 free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx];
28052806 free_pipe->plane_res.mpcc_inst = pool->dpps[free_pipe_idx]->inst;
2807+ free_pipe->hblank_borrow = otg_master->hblank_borrow;
28062808 if (free_pipe->stream->timing.flags.DSC == 1) {
28072809 dcn20_acquire_dsc(free_pipe->stream->ctx->dc,
28082810 &new_ctx->res_ctx,
drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c+1−0
@@ -1742,6 +1742,7 @@ static bool dcn321_resource_construct( · 1741 unmodified lines
17421742 dc->caps.extended_aux_timeout_support = true;
17431743 dc->caps.dmcub_support = true;
17441744 dc->caps.max_v_total = (1 << 15) - 1;
1745+ dc->caps.vtotal_limited_by_fp2 = true;
17451746
17461747 /* Color pipeline capabilities */
17471748 dc->caps.color.dpp.dcn_arch = 1;
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c+2−0
@@ -1778,6 +1778,7 @@ static struct resource_funcs dcn35_res_pool_funcs = { · 1777 unmodified lines
17781778 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
17791779 .get_panel_config_defaults = dcn35_get_panel_config_defaults,
17801780 .get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia,
1781+ .get_det_buffer_size = dcn31_get_det_buffer_size,
17811782 };
17821783
17831784 static bool dcn35_resource_construct(
@@ -1849,6 +1850,7 @@ static bool dcn35_resource_construct( · 65 unmodified lines
18491850 dc->caps.zstate_support = true;
18501851 dc->caps.ips_support = true;
18511852 dc->caps.max_v_total = (1 << 15) - 1;
1853+ dc->caps.vtotal_limited_by_fp2 = true;
18521854
18531855 /* Color pipeline capabilities */
18541856 dc->caps.color.dpp.dcn_arch = 1;
drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c+2−0
@@ -1757,6 +1757,7 @@ static struct resource_funcs dcn351_res_pool_funcs = { · 1756 unmodified lines
17571757 .patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
17581758 .get_panel_config_defaults = dcn35_get_panel_config_defaults,
17591759 .get_preferred_eng_id_dpia = dcn351_get_preferred_eng_id_dpia,
1760+ .get_det_buffer_size = dcn31_get_det_buffer_size,
17601761 };
17611762
17621763 static bool dcn351_resource_construct(
@@ -1828,6 +1829,7 @@ static bool dcn351_resource_construct( · 65 unmodified lines
18281829 dc->caps.zstate_support = true;
18291830 dc->caps.ips_support = true;
18301831 dc->caps.max_v_total = (1 << 15) - 1;
1832+ dc->caps.vtotal_limited_by_fp2 = true;
18311833
18321834 /* Color pipeline capabilities */
18331835 dc->caps.color.dpp.dcn_arch = 1;
drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c+1−0
@@ -1864,6 +1864,7 @@ static bool dcn401_resource_construct( · 1863 unmodified lines
18641864 dc->caps.extended_aux_timeout_support = true;
18651865 dc->caps.dmcub_support = true;
18661866 dc->caps.max_v_total = (1 << 15) - 1;
1867+ dc->caps.vtotal_limited_by_fp2 = true;
18671868
18681869 if (ASICREV_IS_GC_12_0_1_A0(dc->ctx->asic_id.hw_internal_rev))
18691870 dc->caps.dcc_plane_width_limit = 7680;
drivers/gpu/drm/amd/display/modules/freesync/freesync.c+12−1
@@ -122,6 +122,17 @@ static unsigned int calc_duration_in_us_from_v_total( · 121 unmodified lines
122122 return duration_in_us;
123123 }
124124
125+static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
126+{
127+ unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
128+
129+ if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
130+ max_hw_v_total -= stream->timing.v_front_porch + 1;
131+ }
132+
133+ return max_hw_v_total;
134+}
135+
125136 unsigned int mod_freesync_calc_v_total_from_refresh(
126137 const struct dc_stream_state *stream,
127138 unsigned int refresh_in_uhz)
@@ -1016,7 +1027,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, · 888 unmodified lines
10161027
10171028 if (stream->ctx->dc->caps.max_v_total != 0 && stream->timing.h_total != 0) {
10181029 min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
1019− (stream->timing.h_total * (long long)stream->ctx->dc->caps.max_v_total));
1030+ (stream->timing.h_total * (long long)calc_max_hardware_v_total(stream)));
10201031 }
10211032 /* Limit minimum refresh rate to what can be supported by hardware */
10221033 min_refresh_in_uhz = min_hardware_refresh_in_uhz > in_config->min_refresh_in_uhz ?
drivers/gpu/drm/amd/pm/amdgpu_pm.c+5−1
@@ -1361,7 +1361,11 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, · 1360 unmodified lines
13611361 * create a custom set of heuristics, write a string of numbers to the file
13621362 * starting with the number of the custom profile along with a setting
13631363 * for each heuristic parameter. Due to differences across asic families
1364− * the heuristic parameters vary from family to family.
1364+ * the heuristic parameters vary from family to family. Additionally,
1365+ * you can apply the custom heuristics to different clock domains. Each
1366+ * clock domain is considered a distinct operation so if you modify the
1367+ * gfxclk heuristics and then the memclk heuristics, the all of the
1368+ * custom heuristics will be retained until you switch to another profile.
13651369 *
13661370 */
13671371
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c+92−77
@@ -72,6 +72,10 @@ static int smu_set_power_limit(void *handle, uint32_t limit); · 71 unmodified lines
7272 static int smu_set_fan_speed_rpm(void *handle, uint32_t speed);
7373 static int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled);
7474 static int smu_set_mp1_state(void *handle, enum pp_mp1_state mp1_state);
75+static void smu_power_profile_mode_get(struct smu_context *smu,
76+ enum PP_SMC_POWER_PROFILE profile_mode);
77+static void smu_power_profile_mode_put(struct smu_context *smu,
78+ enum PP_SMC_POWER_PROFILE profile_mode);
7579
7680 static int smu_sys_get_pp_feature_mask(void *handle,
7781 char *buf)
@@ -1259,42 +1263,19 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block) · 1181 unmodified lines
12591263 INIT_WORK(&smu->interrupt_work, smu_interrupt_work_fn);
12601264 atomic64_set(&smu->throttle_int_counter, 0);
12611265 smu->watermarks_bitmap = 0;
1262− smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
1263− smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
1264− smu->user_dpm_profile.user_workload_mask = 0;
12651266
12661267 atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
12671268 atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
12681269 atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);
12691270 atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);
12701271
1271− smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
1272− smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
1273− smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
1274− smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
1275− smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;
1276− smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
1277− smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
1278−
12791272 if (smu->is_apu ||
1280− !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {
1281− smu->driver_workload_mask =
1282− 1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
1283− } else {
1284− smu->driver_workload_mask =
1285− 1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
1286− smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1287− }
1288−
1289− smu->workload_mask = smu->driver_workload_mask |
1290− smu->user_dpm_profile.user_workload_mask;
1291− smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
1292− smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1293− smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
1294− smu->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO;
1295− smu->workload_setting[4] = PP_SMC_POWER_PROFILE_VR;
1296− smu->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;
1297− smu->workload_setting[6] = PP_SMC_POWER_PROFILE_CUSTOM;
1273+ !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))
1274+ smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
1275+ else
1276+ smu->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1277+ smu_power_profile_mode_get(smu, smu->power_profile_mode);
1278+
12981279 smu->display_config = &adev->pm.pm_display_cfg;
12991280
13001281 smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
@@ -1347,6 +1328,11 @@ static int smu_sw_fini(struct amdgpu_ip_block *ip_block) · 46 unmodified lines
13471328 return ret;
13481329 }
13491330
1331+ if (smu->custom_profile_params) {
1332+ kfree(smu->custom_profile_params);
1333+ smu->custom_profile_params = NULL;
1334+ }
1335+
13501336 smu_fini_microcode(smu);
13511337
13521338 return 0;
@@ -2131,6 +2117,9 @@ static int smu_suspend(struct amdgpu_ip_block *ip_block) · 778 unmodified lines
21312117 if (!ret)
21322118 adev->gfx.gfx_off_entrycount = count;
21332119
2120+ /* clear this on suspend so it will get reprogrammed on resume */
2121+ smu->workload_mask = 0;
2122+
21342123 return 0;
21352124 }
21362125
@@ -2243,25 +2232,49 @@ static int smu_enable_umd_pstate(void *handle, · 106 unmodified lines
22432232 }
22442233
22452234 static int smu_bump_power_profile_mode(struct smu_context *smu,
2246− long *param,
2247− uint32_t param_size)
2235+ long *custom_params,
2236+ u32 custom_params_max_idx)
22482237 {
2249− int ret = 0;
2238+ u32 workload_mask = 0;
2239+ int i, ret = 0;
2240+
2241+ for (i = 0; i < PP_SMC_POWER_PROFILE_COUNT; i++) {
2242+ if (smu->workload_refcount[i])
2243+ workload_mask |= 1 << i;
2244+ }
2245+
2246+ if (smu->workload_mask == workload_mask)
2247+ return 0;
22502248
22512249 if (smu->ppt_funcs->set_power_profile_mode)
2252− ret = smu->ppt_funcs->set_power_profile_mode(smu, param, param_size);
2250+ ret = smu->ppt_funcs->set_power_profile_mode(smu, workload_mask,
2251+ custom_params,
2252+ custom_params_max_idx);
2253+
2254+ if (!ret)
2255+ smu->workload_mask = workload_mask;
22532256
22542257 return ret;
22552258 }
22562259
2260+static void smu_power_profile_mode_get(struct smu_context *smu,
2261+ enum PP_SMC_POWER_PROFILE profile_mode)
2262+{
2263+ smu->workload_refcount[profile_mode]++;
2264+}
2265+
2266+static void smu_power_profile_mode_put(struct smu_context *smu,
2267+ enum PP_SMC_POWER_PROFILE profile_mode)
2268+{
2269+ if (smu->workload_refcount[profile_mode])
2270+ smu->workload_refcount[profile_mode]--;
2271+}
2272+
22572273 static int smu_adjust_power_state_dynamic(struct smu_context *smu,
22582274 enum amd_dpm_forced_level level,
2259− bool skip_display_settings,
2260− bool init)
2275+ bool skip_display_settings)
22612276 {
22622277 int ret = 0;
2263− int index = 0;
2264− long workload[1];
22652278 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
22662279
22672280 if (!skip_display_settings) {
@@ -2298,14 +2311,8 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu, · 30 unmodified lines
22982311 }
22992312
23002313 if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
2301− smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
2302− index = fls(smu->workload_mask);
2303− index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
2304− workload[0] = smu->workload_setting[index];
2305−
2306− if (init || smu->power_profile_mode != workload[0])
2307− smu_bump_power_profile_mode(smu, workload, 0);
2308− }
2314+ smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
2315+ smu_bump_power_profile_mode(smu, NULL, 0);
23092316
23102317 return ret;
23112318 }
@@ -2324,13 +2331,13 @@ static int smu_handle_task(struct smu_context *smu, · 12 unmodified lines
23242331 ret = smu_pre_display_config_changed(smu);
23252332 if (ret)
23262333 return ret;
2327− ret = smu_adjust_power_state_dynamic(smu, level, false, false);
2334+ ret = smu_adjust_power_state_dynamic(smu, level, false);
23282335 break;
23292336 case AMD_PP_TASK_COMPLETE_INIT:
2330− ret = smu_adjust_power_state_dynamic(smu, level, true, true);
2337+ ret = smu_adjust_power_state_dynamic(smu, level, true);
23312338 break;
23322339 case AMD_PP_TASK_READJUST_POWER_STATE:
2333− ret = smu_adjust_power_state_dynamic(smu, level, true, false);
2340+ ret = smu_adjust_power_state_dynamic(smu, level, true);
23342341 break;
23352342 default:
23362343 break;
@@ -2352,12 +2359,11 @@ static int smu_handle_dpm_task(void *handle, · 15 unmodified lines
23522359
23532360 static int smu_switch_power_profile(void *handle,
23542361 enum PP_SMC_POWER_PROFILE type,
2355− bool en)
2362+ bool enable)
23562363 {
23572364 struct smu_context *smu = handle;
23582365 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
2359− long workload[1];
2360− uint32_t index;
2366+ int ret;
23612367
23622368 if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
23632369 return -EOPNOTSUPP;
@@ -2365,24 +2371,21 @@ static int smu_switch_power_profile(void *handle, · 1 unmodified line
23652371 if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
23662372 return -EINVAL;
23672373
2368− if (!en) {
2369− smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);
2370− index = fls(smu->workload_mask);
2371− index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
2372− workload[0] = smu->workload_setting[index];
2373− } else {
2374− smu->driver_workload_mask |= (1 << smu->workload_priority[type]);
2375− index = fls(smu->workload_mask);
2376− index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
2377− workload[0] = smu->workload_setting[index];
2378− }
2379−
2380− smu->workload_mask = smu->driver_workload_mask |
2381− smu->user_dpm_profile.user_workload_mask;
2382−
23832374 if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
2384− smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
2385− smu_bump_power_profile_mode(smu, workload, 0);
2375+ smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
2376+ if (enable)
2377+ smu_power_profile_mode_get(smu, type);
2378+ else
2379+ smu_power_profile_mode_put(smu, type);
2380+ ret = smu_bump_power_profile_mode(smu, NULL, 0);
2381+ if (ret) {
2382+ if (enable)
2383+ smu_power_profile_mode_put(smu, type);
2384+ else
2385+ smu_power_profile_mode_get(smu, type);
2386+ return ret;
2387+ }
2388+ }
23862389
23872390 return 0;
23882391 }
@@ -3074,21 +3077,33 @@ static int smu_set_power_profile_mode(void *handle, · 685 unmodified lines
30743077 uint32_t param_size)
30753078 {
30763079 struct smu_context *smu = handle;
3077− int ret;
3080+ bool custom = false;
3081+ int ret = 0;
30783082
30793083 if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||
30803084 !smu->ppt_funcs->set_power_profile_mode)
30813085 return -EOPNOTSUPP;
30823086
3083− if (smu->user_dpm_profile.user_workload_mask &
3084− (1 << smu->workload_priority[param[param_size]]))
3085− return 0;
3087+ if (param[param_size] == PP_SMC_POWER_PROFILE_CUSTOM) {
3088+ custom = true;
3089+ /* clear frontend mask so custom changes propogate */
3090+ smu->workload_mask = 0;
3091+ }
30863092
3087− smu->user_dpm_profile.user_workload_mask =
3088− (1 << smu->workload_priority[param[param_size]]);
3089− smu->workload_mask = smu->user_dpm_profile.user_workload_mask |
3090− smu->driver_workload_mask;
3091− ret = smu_bump_power_profile_mode(smu, param, param_size);
3093+ if ((param[param_size] != smu->power_profile_mode) || custom) {
3094+ /* clear the old user preference */
3095+ smu_power_profile_mode_put(smu, smu->power_profile_mode);
3096+ /* set the new user preference */
3097+ smu_power_profile_mode_get(smu, param[param_size]);
3098+ ret = smu_bump_power_profile_mode(smu,
3099+ custom ? param : NULL,
3100+ custom ? param_size : 0);
3101+ if (ret)
3102+ smu_power_profile_mode_put(smu, param[param_size]);
3103+ else
3104+ /* store the user's preference */
3105+ smu->power_profile_mode = param[param_size];
3106+ }
30923107
30933108 return ret;
30943109 }
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h+10−7
@@ -240,7 +240,6 @@ struct smu_user_dpm_profile { · 239 unmodified lines
240240 /* user clock state information */
241241 uint32_t clk_mask[SMU_CLK_COUNT];
242242 uint32_t clk_dependency;
243− uint32_t user_workload_mask;
244243 };
245244
246245 #define SMU_TABLE_INIT(tables, table_id, s, a, d) \
@@ -557,12 +556,13 @@ struct smu_context { · 310 unmodified lines
557556 uint32_t hard_min_uclk_req_from_dal;
558557 bool disable_uclk_switch;
559558
559+ /* asic agnostic workload mask */
560560 uint32_t workload_mask;
561− uint32_t driver_workload_mask;
562− uint32_t workload_priority[WORKLOAD_POLICY_MAX];
563− uint32_t workload_setting[WORKLOAD_POLICY_MAX];
561+ /* default/user workload preference */
564562 uint32_t power_profile_mode;
565− uint32_t default_power_profile_mode;
563+ uint32_t workload_refcount[PP_SMC_POWER_PROFILE_COUNT];
564+ /* backend specific custom workload settings */
565+ long *custom_profile_params;
566566 bool pm_enabled;
567567 bool is_apu;
568568
@@ -733,9 +733,12 @@ struct pptable_funcs { · 164 unmodified lines
733733 * @set_power_profile_mode: Set a power profile mode. Also used to
734734 * create/set custom power profile modes.
735735 * &input: Power profile mode parameters.
736− * &size: Size of &input.
736+ * &workload_mask: mask of workloads to enable
737+ * &custom_params: custom profile parameters
738+ * &custom_params_max_idx: max valid idx into custom_params
737739 */
738− int (*set_power_profile_mode)(struct smu_context *smu, long *input, uint32_t size);
740+ int (*set_power_profile_mode)(struct smu_context *smu, u32 workload_mask,
741+ long *custom_params, u32 custom_params_max_idx);
739742
740743 /**
741744 * @dpm_set_vcn_enable: Enable/disable VCN engine dynamic power
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c+95−72
@@ -1445,97 +1445,120 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu, · 1444 unmodified lines
14451445 return size;
14461446 }
14471447
1448−static int arcturus_set_power_profile_mode(struct smu_context *smu,
1449− long *input,
1450− uint32_t size)
1448+#define ARCTURUS_CUSTOM_PARAMS_COUNT 10
1449+#define ARCTURUS_CUSTOM_PARAMS_CLOCK_COUNT 2
1450+#define ARCTURUS_CUSTOM_PARAMS_SIZE (ARCTURUS_CUSTOM_PARAMS_CLOCK_COUNT * ARCTURUS_CUSTOM_PARAMS_COUNT * sizeof(long))
1451+
1452+static int arcturus_set_power_profile_mode_coeff(struct smu_context *smu,
1453+ long *input)
14511454 {
14521455 DpmActivityMonitorCoeffInt_t activity_monitor;
1453− int workload_type = 0;
1454− uint32_t profile_mode = input[size];
1455− int ret = 0;
1456+ int ret, idx;
14561457
1457− if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1458− dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
1459− return -EINVAL;
1458+ ret = smu_cmn_update_table(smu,
1459+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1460+ WORKLOAD_PPLIB_CUSTOM_BIT,
1461+ (void *)(&activity_monitor),
1462+ false);
1463+ if (ret) {
1464+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1465+ return ret;
14601466 }
14611467
1462− if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
1463− (smu->smc_fw_version >= 0x360d00)) {
1464− if (size != 10)
1465− return -EINVAL;
1468+ idx = 0 * ARCTURUS_CUSTOM_PARAMS_COUNT;
1469+ if (input[idx]) {
1470+ /* Gfxclk */
1471+ activity_monitor.Gfx_FPS = input[idx + 1];
1472+ activity_monitor.Gfx_UseRlcBusy = input[idx + 2];
1473+ activity_monitor.Gfx_MinActiveFreqType = input[idx + 3];
1474+ activity_monitor.Gfx_MinActiveFreq = input[idx + 4];
1475+ activity_monitor.Gfx_BoosterFreqType = input[idx + 5];
1476+ activity_monitor.Gfx_BoosterFreq = input[idx + 6];
1477+ activity_monitor.Gfx_PD_Data_limit_c = input[idx + 7];
1478+ activity_monitor.Gfx_PD_Data_error_coeff = input[idx + 8];
1479+ activity_monitor.Gfx_PD_Data_error_rate_coeff = input[idx + 9];
1480+ }
1481+ idx = 1 * ARCTURUS_CUSTOM_PARAMS_COUNT;
1482+ if (input[idx]) {
1483+ /* Uclk */
1484+ activity_monitor.Mem_FPS = input[idx + 1];
1485+ activity_monitor.Mem_UseRlcBusy = input[idx + 2];
1486+ activity_monitor.Mem_MinActiveFreqType = input[idx + 3];
1487+ activity_monitor.Mem_MinActiveFreq = input[idx + 4];
1488+ activity_monitor.Mem_BoosterFreqType = input[idx + 5];
1489+ activity_monitor.Mem_BoosterFreq = input[idx + 6];
1490+ activity_monitor.Mem_PD_Data_limit_c = input[idx + 7];
1491+ activity_monitor.Mem_PD_Data_error_coeff = input[idx + 8];
1492+ activity_monitor.Mem_PD_Data_error_rate_coeff = input[idx + 9];
1493+ }
14661494
1467− ret = smu_cmn_update_table(smu,
1468− SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1469− WORKLOAD_PPLIB_CUSTOM_BIT,
1470− (void *)(&activity_monitor),
1471− false);
1472− if (ret) {
1473− dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1474− return ret;
1475− }
1495+ ret = smu_cmn_update_table(smu,
1496+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1497+ WORKLOAD_PPLIB_CUSTOM_BIT,
1498+ (void *)(&activity_monitor),
1499+ true);
1500+ if (ret) {
1501+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
1502+ return ret;
1503+ }
14761504
1477− switch (input[0]) {
1478− case 0: /* Gfxclk */
1479− activity_monitor.Gfx_FPS = input[1];
1480− activity_monitor.Gfx_UseRlcBusy = input[2];
1481− activity_monitor.Gfx_MinActiveFreqType = input[3];
1482− activity_monitor.Gfx_MinActiveFreq = input[4];
1483− activity_monitor.Gfx_BoosterFreqType = input[5];
1484− activity_monitor.Gfx_BoosterFreq = input[6];
1485− activity_monitor.Gfx_PD_Data_limit_c = input[7];
1486− activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1487− activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1488− break;
1489− case 1: /* Uclk */
1490− activity_monitor.Mem_FPS = input[1];
1491− activity_monitor.Mem_UseRlcBusy = input[2];
1492− activity_monitor.Mem_MinActiveFreqType = input[3];
1493− activity_monitor.Mem_MinActiveFreq = input[4];
1494− activity_monitor.Mem_BoosterFreqType = input[5];
1495− activity_monitor.Mem_BoosterFreq = input[6];
1496− activity_monitor.Mem_PD_Data_limit_c = input[7];
1497− activity_monitor.Mem_PD_Data_error_coeff = input[8];
1498− activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1499− break;
1500− default:
1505+ return ret;
1506+}
1507+
1508+static int arcturus_set_power_profile_mode(struct smu_context *smu,
1509+ u32 workload_mask,
1510+ long *custom_params,
1511+ u32 custom_params_max_idx)
1512+{
1513+ u32 backend_workload_mask = 0;
1514+ int ret, idx = -1, i;
1515+
1516+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
1517+ &backend_workload_mask);
1518+
1519+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
1520+ if (smu->smc_fw_version < 0x360d00)
15011521 return -EINVAL;
1522+ if (!smu->custom_profile_params) {
1523+ smu->custom_profile_params =
1524+ kzalloc(ARCTURUS_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
1525+ if (!smu->custom_profile_params)
1526+ return -ENOMEM;
15021527 }
1503−
1504− ret = smu_cmn_update_table(smu,
1505− SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1506− WORKLOAD_PPLIB_CUSTOM_BIT,
1507− (void *)(&activity_monitor),
1508− true);
1528+ if (custom_params && custom_params_max_idx) {
1529+ if (custom_params_max_idx != ARCTURUS_CUSTOM_PARAMS_COUNT)
1530+ return -EINVAL;
1531+ if (custom_params[0] >= ARCTURUS_CUSTOM_PARAMS_CLOCK_COUNT)
1532+ return -EINVAL;
1533+ idx = custom_params[0] * ARCTURUS_CUSTOM_PARAMS_COUNT;
1534+ smu->custom_profile_params[idx] = 1;
1535+ for (i = 1; i < custom_params_max_idx; i++)
1536+ smu->custom_profile_params[idx + i] = custom_params[i];
1537+ }
1538+ ret = arcturus_set_power_profile_mode_coeff(smu,
1539+ smu->custom_profile_params);
15091540 if (ret) {
1510− dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
1541+ if (idx != -1)
1542+ smu->custom_profile_params[idx] = 0;
15111543 return ret;
15121544 }
1513− }
1514−
1515− /*
1516− * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
1517− * Not all profile modes are supported on arcturus.
1518− */
1519− workload_type = smu_cmn_to_asic_specific_index(smu,
1520− CMN2ASIC_MAPPING_WORKLOAD,
1521− profile_mode);
1522− if (workload_type < 0) {
1523− dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on arcturus\n", profile_mode);
1524− return -EINVAL;
1545+ } else if (smu->custom_profile_params) {
1546+ memset(smu->custom_profile_params, 0, ARCTURUS_CUSTOM_PARAMS_SIZE);
15251547 }
15261548
15271549 ret = smu_cmn_send_smc_msg_with_param(smu,
1528− SMU_MSG_SetWorkloadMask,
1529− smu->workload_mask,
1530− NULL);
1550+ SMU_MSG_SetWorkloadMask,
1551+ backend_workload_mask,
1552+ NULL);
15311553 if (ret) {
1532− dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
1554+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
1555+ workload_mask);
1556+ if (idx != -1)
1557+ smu->custom_profile_params[idx] = 0;
15331558 return ret;
15341559 }
15351560
1536− smu_cmn_assign_power_profile(smu);
1537−
1538− return 0;
1561+ return ret;
15391562 }
15401563
15411564 static int arcturus_set_performance_level(struct smu_context *smu,
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c+101−69
@@ -2006,90 +2006,122 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf) · 2005 unmodified lines
20062006 return size;
20072007 }
20082008
2009−static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
2009+#define NAVI10_CUSTOM_PARAMS_COUNT 10
2010+#define NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT 3
2011+#define NAVI10_CUSTOM_PARAMS_SIZE (NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT * NAVI10_CUSTOM_PARAMS_COUNT * sizeof(long))
2012+
2013+static int navi10_set_power_profile_mode_coeff(struct smu_context *smu,
2014+ long *input)
20102015 {
20112016 DpmActivityMonitorCoeffInt_t activity_monitor;
2012− int workload_type, ret = 0;
2017+ int ret, idx;
20132018
2014− smu->power_profile_mode = input[size];
2019+ ret = smu_cmn_update_table(smu,
2020+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2021+ (void *)(&activity_monitor), false);
2022+ if (ret) {
2023+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2024+ return ret;
2025+ }
20152026
2016− if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
2017− dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
2018− return -EINVAL;
2027+ idx = 0 * NAVI10_CUSTOM_PARAMS_COUNT;
2028+ if (input[idx]) {
2029+ /* Gfxclk */
2030+ activity_monitor.Gfx_FPS = input[idx + 1];
2031+ activity_monitor.Gfx_MinFreqStep = input[idx + 2];
2032+ activity_monitor.Gfx_MinActiveFreqType = input[idx + 3];
2033+ activity_monitor.Gfx_MinActiveFreq = input[idx + 4];
2034+ activity_monitor.Gfx_BoosterFreqType = input[idx + 5];
2035+ activity_monitor.Gfx_BoosterFreq = input[idx + 6];
2036+ activity_monitor.Gfx_PD_Data_limit_c = input[idx + 7];
2037+ activity_monitor.Gfx_PD_Data_error_coeff = input[idx + 8];
2038+ activity_monitor.Gfx_PD_Data_error_rate_coeff = input[idx + 9];
2039+ }
2040+ idx = 1 * NAVI10_CUSTOM_PARAMS_COUNT;
2041+ if (input[idx]) {
2042+ /* Socclk */
2043+ activity_monitor.Soc_FPS = input[idx + 1];
2044+ activity_monitor.Soc_MinFreqStep = input[idx + 2];
2045+ activity_monitor.Soc_MinActiveFreqType = input[idx + 3];
2046+ activity_monitor.Soc_MinActiveFreq = input[idx + 4];
2047+ activity_monitor.Soc_BoosterFreqType = input[idx + 5];
2048+ activity_monitor.Soc_BoosterFreq = input[idx + 6];
2049+ activity_monitor.Soc_PD_Data_limit_c = input[idx + 7];
2050+ activity_monitor.Soc_PD_Data_error_coeff = input[idx + 8];
2051+ activity_monitor.Soc_PD_Data_error_rate_coeff = input[idx + 9];
2052+ }
2053+ idx = 2 * NAVI10_CUSTOM_PARAMS_COUNT;
2054+ if (input[idx]) {
2055+ /* Memclk */
2056+ activity_monitor.Mem_FPS = input[idx + 1];
2057+ activity_monitor.Mem_MinFreqStep = input[idx + 2];
2058+ activity_monitor.Mem_MinActiveFreqType = input[idx + 3];
2059+ activity_monitor.Mem_MinActiveFreq = input[idx + 4];
2060+ activity_monitor.Mem_BoosterFreqType = input[idx + 5];
2061+ activity_monitor.Mem_BoosterFreq = input[idx + 6];
2062+ activity_monitor.Mem_PD_Data_limit_c = input[idx + 7];
2063+ activity_monitor.Mem_PD_Data_error_coeff = input[idx + 8];
2064+ activity_monitor.Mem_PD_Data_error_rate_coeff = input[idx + 9];
2065+ }
2066+
2067+ ret = smu_cmn_update_table(smu,
2068+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2069+ (void *)(&activity_monitor), true);
2070+ if (ret) {
2071+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
2072+ return ret;
20192073 }
20202074
2021− if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
2022− if (size != 10)
2023− return -EINVAL;
2075+ return ret;
2076+}
20242077
2025− ret = smu_cmn_update_table(smu,
2026− SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2027− (void *)(&activity_monitor), false);
2028− if (ret) {
2029− dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2030− return ret;
2031− }
2078+static int navi10_set_power_profile_mode(struct smu_context *smu,
2079+ u32 workload_mask,
2080+ long *custom_params,
2081+ u32 custom_params_max_idx)
2082+{
2083+ u32 backend_workload_mask = 0;
2084+ int ret, idx = -1, i;
20322085
2033− switch (input[0]) {
2034− case 0: /* Gfxclk */
2035− activity_monitor.Gfx_FPS = input[1];
2036− activity_monitor.Gfx_MinFreqStep = input[2];
2037− activity_monitor.Gfx_MinActiveFreqType = input[3];
2038− activity_monitor.Gfx_MinActiveFreq = input[4];
2039− activity_monitor.Gfx_BoosterFreqType = input[5];
2040− activity_monitor.Gfx_BoosterFreq = input[6];
2041− activity_monitor.Gfx_PD_Data_limit_c = input[7];
2042− activity_monitor.Gfx_PD_Data_error_coeff = input[8];
2043− activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
2044− break;
2045− case 1: /* Socclk */
2046− activity_monitor.Soc_FPS = input[1];
2047− activity_monitor.Soc_MinFreqStep = input[2];
2048− activity_monitor.Soc_MinActiveFreqType = input[3];
2049− activity_monitor.Soc_MinActiveFreq = input[4];
2050− activity_monitor.Soc_BoosterFreqType = input[5];
2051− activity_monitor.Soc_BoosterFreq = input[6];
2052− activity_monitor.Soc_PD_Data_limit_c = input[7];
2053− activity_monitor.Soc_PD_Data_error_coeff = input[8];
2054− activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
2055− break;
2056− case 2: /* Memclk */
2057− activity_monitor.Mem_FPS = input[1];
2058− activity_monitor.Mem_MinFreqStep = input[2];
2059− activity_monitor.Mem_MinActiveFreqType = input[3];
2060− activity_monitor.Mem_MinActiveFreq = input[4];
2061− activity_monitor.Mem_BoosterFreqType = input[5];
2062− activity_monitor.Mem_BoosterFreq = input[6];
2063− activity_monitor.Mem_PD_Data_limit_c = input[7];
2064− activity_monitor.Mem_PD_Data_error_coeff = input[8];
2065− activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
2066− break;
2067− default:
2068− return -EINVAL;
2069− }
2086+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
2087+ &backend_workload_mask);
20702088
2071− ret = smu_cmn_update_table(smu,
2072− SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2073− (void *)(&activity_monitor), true);
2089+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
2090+ if (!smu->custom_profile_params) {
2091+ smu->custom_profile_params = kzalloc(NAVI10_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
2092+ if (!smu->custom_profile_params)
2093+ return -ENOMEM;
2094+ }
2095+ if (custom_params && custom_params_max_idx) {
2096+ if (custom_params_max_idx != NAVI10_CUSTOM_PARAMS_COUNT)
2097+ return -EINVAL;
2098+ if (custom_params[0] >= NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT)
2099+ return -EINVAL;
2100+ idx = custom_params[0] * NAVI10_CUSTOM_PARAMS_COUNT;
2101+ smu->custom_profile_params[idx] = 1;
2102+ for (i = 1; i < custom_params_max_idx; i++)
2103+ smu->custom_profile_params[idx + i] = custom_params[i];
2104+ }
2105+ ret = navi10_set_power_profile_mode_coeff(smu,
2106+ smu->custom_profile_params);
20742107 if (ret) {
2075− dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
2108+ if (idx != -1)
2109+ smu->custom_profile_params[idx] = 0;
20762110 return ret;
20772111 }
2112+ } else if (smu->custom_profile_params) {
2113+ memset(smu->custom_profile_params, 0, NAVI10_CUSTOM_PARAMS_SIZE);
20782114 }
20792115
2080− /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
2081− workload_type = smu_cmn_to_asic_specific_index(smu,
2082− CMN2ASIC_MAPPING_WORKLOAD,
2083− smu->power_profile_mode);
2084− if (workload_type < 0)
2085− return -EINVAL;
2086−
20872116 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
2088− smu->workload_mask, NULL);
2089− if (ret)
2090− dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
2091− else
2092− smu_cmn_assign_power_profile(smu);
2117+ backend_workload_mask, NULL);
2118+ if (ret) {
2119+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
2120+ workload_mask);
2121+ if (idx != -1)
2122+ smu->custom_profile_params[idx] = 0;
2123+ return ret;
2124+ }
20932125
20942126 return ret;
20952127 }
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c+102−69
@@ -1708,93 +1708,126 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char * · 1707 unmodified lines
17081708 return size;
17091709 }
17101710
1711−static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1711+#define SIENNA_CICHLID_CUSTOM_PARAMS_COUNT 10
1712+#define SIENNA_CICHLID_CUSTOM_PARAMS_CLOCK_COUNT 3
1713+#define SIENNA_CICHLID_CUSTOM_PARAMS_SIZE (SIENNA_CICHLID_CUSTOM_PARAMS_CLOCK_COUNT * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT * sizeof(long))
1714+
1715+static int sienna_cichlid_set_power_profile_mode_coeff(struct smu_context *smu,
1716+ long *input)
17121717 {
17131718
17141719 DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
17151720 DpmActivityMonitorCoeffInt_t *activity_monitor =
17161721 &(activity_monitor_external.DpmActivityMonitorCoeffInt);
1717− int workload_type, ret = 0;
1722+ int ret, idx;
17181723
1719− smu->power_profile_mode = input[size];
1724+ ret = smu_cmn_update_table(smu,
1725+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1726+ (void *)(&activity_monitor_external), false);
1727+ if (ret) {
1728+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1729+ return ret;
1730+ }
17201731
1721− if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1722− dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
1723− return -EINVAL;
1732+ idx = 0 * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT;
1733+ if (input[idx]) {
1734+ /* Gfxclk */
1735+ activity_monitor->Gfx_FPS = input[idx + 1];
1736+ activity_monitor->Gfx_MinFreqStep = input[idx + 2];
1737+ activity_monitor->Gfx_MinActiveFreqType = input[idx + 3];
1738+ activity_monitor->Gfx_MinActiveFreq = input[idx + 4];
1739+ activity_monitor->Gfx_BoosterFreqType = input[idx + 5];
1740+ activity_monitor->Gfx_BoosterFreq = input[idx + 6];
1741+ activity_monitor->Gfx_PD_Data_limit_c = input[idx + 7];
1742+ activity_monitor->Gfx_PD_Data_error_coeff = input[idx + 8];
1743+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[idx + 9];
1744+ }
1745+ idx = 1 * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT;
1746+ if (input[idx]) {
1747+ /* Socclk */
1748+ activity_monitor->Fclk_FPS = input[idx + 1];
1749+ activity_monitor->Fclk_MinFreqStep = input[idx + 2];
1750+ activity_monitor->Fclk_MinActiveFreqType = input[idx + 3];
1751+ activity_monitor->Fclk_MinActiveFreq = input[idx + 4];
1752+ activity_monitor->Fclk_BoosterFreqType = input[idx + 5];
1753+ activity_monitor->Fclk_BoosterFreq = input[idx + 6];
1754+ activity_monitor->Fclk_PD_Data_limit_c = input[idx + 7];
1755+ activity_monitor->Fclk_PD_Data_error_coeff = input[idx + 8];
1756+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[idx + 9];
1757+ }
1758+ idx = 2 * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT;
1759+ if (input[idx]) {
1760+ /* Memclk */
1761+ activity_monitor->Mem_FPS = input[idx + 1];
1762+ activity_monitor->Mem_MinFreqStep = input[idx + 2];
1763+ activity_monitor->Mem_MinActiveFreqType = input[idx + 3];
1764+ activity_monitor->Mem_MinActiveFreq = input[idx + 4];
1765+ activity_monitor->Mem_BoosterFreqType = input[idx + 5];
1766+ activity_monitor->Mem_BoosterFreq = input[idx + 6];
1767+ activity_monitor->Mem_PD_Data_limit_c = input[idx + 7];
1768+ activity_monitor->Mem_PD_Data_error_coeff = input[idx + 8];
1769+ activity_monitor->Mem_PD_Data_error_rate_coeff = input[idx + 9];
17241770 }
17251771
1726− if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1727− if (size != 10)
1728− return -EINVAL;
1772+ ret = smu_cmn_update_table(smu,
1773+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1774+ (void *)(&activity_monitor_external), true);
1775+ if (ret) {
1776+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
1777+ return ret;
1778+ }
17291779
1730− ret = smu_cmn_update_table(smu,
1731− SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1732− (void *)(&activity_monitor_external), false);
1733− if (ret) {
1734− dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1735− return ret;
1736− }
1780+ return ret;
1781+}
17371782
1738− switch (input[0]) {
1739− case 0: /* Gfxclk */
1740− activity_monitor->Gfx_FPS = input[1];
1741− activity_monitor->Gfx_MinFreqStep = input[2];
1742− activity_monitor->Gfx_MinActiveFreqType = input[3];
1743− activity_monitor->Gfx_MinActiveFreq = input[4];
1744− activity_monitor->Gfx_BoosterFreqType = input[5];
1745− activity_monitor->Gfx_BoosterFreq = input[6];
1746− activity_monitor->Gfx_PD_Data_limit_c = input[7];
1747− activity_monitor->Gfx_PD_Data_error_coeff = input[8];
1748− activity_monitor->Gfx_PD_Data_error_rate_coeff = input[9];
1749− break;
1750− case 1: /* Socclk */
1751− activity_monitor->Fclk_FPS = input[1];
1752− activity_monitor->Fclk_MinFreqStep = input[2];
1753− activity_monitor->Fclk_MinActiveFreqType = input[3];
1754− activity_monitor->Fclk_MinActiveFreq = input[4];
1755− activity_monitor->Fclk_BoosterFreqType = input[5];
1756− activity_monitor->Fclk_BoosterFreq = input[6];
1757− activity_monitor->Fclk_PD_Data_limit_c = input[7];
1758− activity_monitor->Fclk_PD_Data_error_coeff = input[8];
1759− activity_monitor->Fclk_PD_Data_error_rate_coeff = input[9];
1760− break;
1761− case 2: /* Memclk */
1762− activity_monitor->Mem_FPS = input[1];
1763− activity_monitor->Mem_MinFreqStep = input[2];
1764− activity_monitor->Mem_MinActiveFreqType = input[3];
1765− activity_monitor->Mem_MinActiveFreq = input[4];
1766− activity_monitor->Mem_BoosterFreqType = input[5];
1767− activity_monitor->Mem_BoosterFreq = input[6];
1768− activity_monitor->Mem_PD_Data_limit_c = input[7];
1769− activity_monitor->Mem_PD_Data_error_coeff = input[8];
1770− activity_monitor->Mem_PD_Data_error_rate_coeff = input[9];
1771− break;
1772− default:
1773− return -EINVAL;
1774− }
1783+static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu,
1784+ u32 workload_mask,
1785+ long *custom_params,
1786+ u32 custom_params_max_idx)
1787+{
1788+ u32 backend_workload_mask = 0;
1789+ int ret, idx = -1, i;
1790+
1791+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
1792+ &backend_workload_mask);
17751793
1776− ret = smu_cmn_update_table(smu,
1777− SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1778− (void *)(&activity_monitor_external), true);
1794+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
1795+ if (!smu->custom_profile_params) {
1796+ smu->custom_profile_params =
1797+ kzalloc(SIENNA_CICHLID_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
1798+ if (!smu->custom_profile_params)
1799+ return -ENOMEM;
1800+ }
1801+ if (custom_params && custom_params_max_idx) {
1802+ if (custom_params_max_idx != SIENNA_CICHLID_CUSTOM_PARAMS_COUNT)
1803+ return -EINVAL;
1804+ if (custom_params[0] >= SIENNA_CICHLID_CUSTOM_PARAMS_CLOCK_COUNT)
1805+ return -EINVAL;
1806+ idx = custom_params[0] * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT;
1807+ smu->custom_profile_params[idx] = 1;
1808+ for (i = 1; i < custom_params_max_idx; i++)
1809+ smu->custom_profile_params[idx + i] = custom_params[i];
1810+ }
1811+ ret = sienna_cichlid_set_power_profile_mode_coeff(smu,
1812+ smu->custom_profile_params);
17791813 if (ret) {
1780− dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
1814+ if (idx != -1)
1815+ smu->custom_profile_params[idx] = 0;
17811816 return ret;
17821817 }
1818+ } else if (smu->custom_profile_params) {
1819+ memset(smu->custom_profile_params, 0, SIENNA_CICHLID_CUSTOM_PARAMS_SIZE);
17831820 }
17841821
1785− /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1786− workload_type = smu_cmn_to_asic_specific_index(smu,
1787− CMN2ASIC_MAPPING_WORKLOAD,
1788− smu->power_profile_mode);
1789− if (workload_type < 0)
1790− return -EINVAL;
1791−
17921822 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1793− smu->workload_mask, NULL);
1794− if (ret)
1795− dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
1796− else
1797− smu_cmn_assign_power_profile(smu);
1823+ backend_workload_mask, NULL);
1824+ if (ret) {
1825+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
1826+ workload_mask);
1827+ if (idx != -1)
1828+ smu->custom_profile_params[idx] = 0;
1829+ return ret;
1830+ }
17981831
17991832 return ret;
18001833 }
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c+13−28
@@ -1056,42 +1056,27 @@ static int vangogh_get_power_profile_mode(struct smu_context *smu, · 1055 unmodified lines
10561056 return size;
10571057 }
10581058
1059−static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1059+static int vangogh_set_power_profile_mode(struct smu_context *smu,
1060+ u32 workload_mask,
1061+ long *custom_params,
1062+ u32 custom_params_max_idx)
10601063 {
1061− int workload_type, ret;
1062− uint32_t profile_mode = input[size];
1064+ u32 backend_workload_mask = 0;
1065+ int ret;
10631066
1064− if (profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
1065− dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
1066− return -EINVAL;
1067− }
1068−
1069− if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||
1070− profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)
1071− return 0;
1072−
1073− /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1074− workload_type = smu_cmn_to_asic_specific_index(smu,
1075− CMN2ASIC_MAPPING_WORKLOAD,
1076− profile_mode);
1077− if (workload_type < 0) {
1078− dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on VANGOGH\n",
1079− profile_mode);
1080− return -EINVAL;
1081− }
1067+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
1068+ &backend_workload_mask);
10821069
10831070 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
1084− smu->workload_mask,
1085− NULL);
1071+ backend_workload_mask,
1072+ NULL);
10861073 if (ret) {
1087− dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
1088− workload_type);
1074+ dev_err_once(smu->adev->dev, "Fail to set workload mask 0x%08x\n",
1075+ workload_mask);
10891076 return ret;
10901077 }
10911078
1092− smu_cmn_assign_power_profile(smu);
1093−
1094− return 0;
1079+ return ret;
10951080 }
10961081
10971082 static int vangogh_set_soft_freq_limited_range(struct smu_context *smu,
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c+13−30
@@ -864,44 +864,27 @@ static int renoir_force_clk_levels(struct smu_context *smu, · 863 unmodified lines
864864 return ret;
865865 }
866866
867−static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
867+static int renoir_set_power_profile_mode(struct smu_context *smu,
868+ u32 workload_mask,
869+ long *custom_params,
870+ u32 custom_params_max_idx)
868871 {
869− int workload_type, ret;
870− uint32_t profile_mode = input[size];
872+ int ret;
873+ u32 backend_workload_mask = 0;
871874
872− if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
873− dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
874− return -EINVAL;
875− }
876−
877− if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||
878− profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)
879− return 0;
880−
881− /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
882− workload_type = smu_cmn_to_asic_specific_index(smu,
883− CMN2ASIC_MAPPING_WORKLOAD,
884− profile_mode);
885− if (workload_type < 0) {
886− /*
887− * TODO: If some case need switch to powersave/default power mode
888− * then can consider enter WORKLOAD_COMPUTE/WORKLOAD_CUSTOM for power saving.
889− */
890− dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on RENOIR\n", profile_mode);
891− return -EINVAL;
892− }
875+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
876+ &backend_workload_mask);
893877
894878 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
895− smu->workload_mask,
896− NULL);
879+ backend_workload_mask,
880+ NULL);
897881 if (ret) {
898− dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
882+ dev_err_once(smu->adev->dev, "Failed to set workload mask 0x08%x\n",
883+ workload_mask);
899884 return ret;
900885 }
901886
902− smu_cmn_assign_power_profile(smu);
903−
904− return 0;
887+ return ret;
905888 }
906889
907890 static int renoir_set_peak_clock_by_device(struct smu_context *smu)
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c+96−79
@@ -2571,82 +2571,76 @@ static int smu_v13_0_0_get_power_profile_mode(struct smu_context *smu, · 2570 unmodified lines
25712571 return size;
25722572 }
25732573
2574−static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
2575− long *input,
2576− uint32_t size)
2574+#define SMU_13_0_0_CUSTOM_PARAMS_COUNT 9
2575+#define SMU_13_0_0_CUSTOM_PARAMS_CLOCK_COUNT 2
2576+#define SMU_13_0_0_CUSTOM_PARAMS_SIZE (SMU_13_0_0_CUSTOM_PARAMS_CLOCK_COUNT * SMU_13_0_0_CUSTOM_PARAMS_COUNT * sizeof(long))
2577+
2578+static int smu_v13_0_0_set_power_profile_mode_coeff(struct smu_context *smu,
2579+ long *input)
25772580 {
25782581 DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
25792582 DpmActivityMonitorCoeffInt_t *activity_monitor =
25802583 &(activity_monitor_external.DpmActivityMonitorCoeffInt);
2581− int workload_type, ret = 0;
2582− u32 workload_mask;
2583−
2584− smu->power_profile_mode = input[size];
2584+ int ret, idx;
25852585
2586− if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
2587− dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
2588− return -EINVAL;
2586+ ret = smu_cmn_update_table(smu,
2587+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
2588+ WORKLOAD_PPLIB_CUSTOM_BIT,
2589+ (void *)(&activity_monitor_external),
2590+ false);
2591+ if (ret) {
2592+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2593+ return ret;
25892594 }
25902595
2591− if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
2592− if (size != 9)
2593− return -EINVAL;
2594−
2595− ret = smu_cmn_update_table(smu,
2596− SMU_TABLE_ACTIVITY_MONITOR_COEFF,
2597− WORKLOAD_PPLIB_CUSTOM_BIT,
2598− (void *)(&activity_monitor_external),
2599− false);
2600− if (ret) {
2601− dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2602− return ret;
2603− }
2604−
2605− switch (input[0]) {
2606− case 0: /* Gfxclk */
2607− activity_monitor->Gfx_FPS = input[1];
2608− activity_monitor->Gfx_MinActiveFreqType = input[2];
2609− activity_monitor->Gfx_MinActiveFreq = input[3];
2610− activity_monitor->Gfx_BoosterFreqType = input[4];
2611− activity_monitor->Gfx_BoosterFreq = input[5];
2612− activity_monitor->Gfx_PD_Data_limit_c = input[6];
2613− activity_monitor->Gfx_PD_Data_error_coeff = input[7];
2614− activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
2615− break;
2616− case 1: /* Fclk */
2617− activity_monitor->Fclk_FPS = input[1];
2618− activity_monitor->Fclk_MinActiveFreqType = input[2];
2619− activity_monitor->Fclk_MinActiveFreq = input[3];
2620− activity_monitor->Fclk_BoosterFreqType = input[4];
2621− activity_monitor->Fclk_BoosterFreq = input[5];
2622− activity_monitor->Fclk_PD_Data_limit_c = input[6];
2623− activity_monitor->Fclk_PD_Data_error_coeff = input[7];
2624− activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
2625− break;
2626− default:
2627− return -EINVAL;
2628− }
2596+ idx = 0 * SMU_13_0_0_CUSTOM_PARAMS_COUNT;
2597+ if (input[idx]) {
2598+ /* Gfxclk */
2599+ activity_monitor->Gfx_FPS = input[idx + 1];
2600+ activity_monitor->Gfx_MinActiveFreqType = input[idx + 2];
2601+ activity_monitor->Gfx_MinActiveFreq = input[idx + 3];
2602+ activity_monitor->Gfx_BoosterFreqType = input[idx + 4];
2603+ activity_monitor->Gfx_BoosterFreq = input[idx + 5];
2604+ activity_monitor->Gfx_PD_Data_limit_c = input[idx + 6];
2605+ activity_monitor->Gfx_PD_Data_error_coeff = input[idx + 7];
2606+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[idx + 8];
2607+ }
2608+ idx = 1 * SMU_13_0_0_CUSTOM_PARAMS_COUNT;
2609+ if (input[idx]) {
2610+ /* Fclk */
2611+ activity_monitor->Fclk_FPS = input[idx + 1];
2612+ activity_monitor->Fclk_MinActiveFreqType = input[idx + 2];
2613+ activity_monitor->Fclk_MinActiveFreq = input[idx + 3];
2614+ activity_monitor->Fclk_BoosterFreqType = input[idx + 4];
2615+ activity_monitor->Fclk_BoosterFreq = input[idx + 5];
2616+ activity_monitor->Fclk_PD_Data_limit_c = input[idx + 6];
2617+ activity_monitor->Fclk_PD_Data_error_coeff = input[idx + 7];
2618+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[idx + 8];
2619+ }
26292620
2630− ret = smu_cmn_update_table(smu,
2631− SMU_TABLE_ACTIVITY_MONITOR_COEFF,
2632− WORKLOAD_PPLIB_CUSTOM_BIT,
2633− (void *)(&activity_monitor_external),
2634− true);
2635− if (ret) {
2636− dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
2637− return ret;
2638− }
2621+ ret = smu_cmn_update_table(smu,
2622+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
2623+ WORKLOAD_PPLIB_CUSTOM_BIT,
2624+ (void *)(&activity_monitor_external),
2625+ true);
2626+ if (ret) {
2627+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
2628+ return ret;
26392629 }
26402630
2641− /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
2642− workload_type = smu_cmn_to_asic_specific_index(smu,
2643− CMN2ASIC_MAPPING_WORKLOAD,
2644− smu->power_profile_mode);
2631+ return ret;
2632+}
26452633
2646− if (workload_type < 0)
2647− return -EINVAL;
2634+static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
2635+ u32 workload_mask,
2636+ long *custom_params,
2637+ u32 custom_params_max_idx)
2638+{
2639+ u32 backend_workload_mask = 0;
2640+ int workload_type, ret, idx = -1, i;
26482641
2649− workload_mask = 1 << workload_type;
2642+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
2643+ &backend_workload_mask);
26502644
26512645 /* Add optimizations for SMU13.0.0/10. Reuse the power saving profile */
26522646 if ((amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0) &&
@@ -2658,24 +2652,47 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu, · 5 unmodified lines
26582652 CMN2ASIC_MAPPING_WORKLOAD,
26592653 PP_SMC_POWER_PROFILE_POWERSAVING);
26602654 if (workload_type >= 0)
2661− workload_mask |= 1 << workload_type;
2655+ backend_workload_mask |= 1 << workload_type;
26622656 }
26632657
2664− smu->workload_mask |= workload_mask;
2665− ret = smu_cmn_send_smc_msg_with_param(smu,
2666− SMU_MSG_SetWorkloadMask,
2667− smu->workload_mask,
2668− NULL);
2669− if (!ret) {
2670− smu_cmn_assign_power_profile(smu);
2671− if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) {
2672− workload_type = smu_cmn_to_asic_specific_index(smu,
2673− CMN2ASIC_MAPPING_WORKLOAD,
2674− PP_SMC_POWER_PROFILE_FULLSCREEN3D);
2675− smu->power_profile_mode = smu->workload_mask & (1 << workload_type)
2676− ? PP_SMC_POWER_PROFILE_FULLSCREEN3D
2677− : PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
2658+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
2659+ if (!smu->custom_profile_params) {
2660+ smu->custom_profile_params =
2661+ kzalloc(SMU_13_0_0_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
2662+ if (!smu->custom_profile_params)
2663+ return -ENOMEM;
26782664 }
2665+ if (custom_params && custom_params_max_idx) {
2666+ if (custom_params_max_idx != SMU_13_0_0_CUSTOM_PARAMS_COUNT)
2667+ return -EINVAL;
2668+ if (custom_params[0] >= SMU_13_0_0_CUSTOM_PARAMS_CLOCK_COUNT)
2669+ return -EINVAL;
2670+ idx = custom_params[0] * SMU_13_0_0_CUSTOM_PARAMS_COUNT;
2671+ smu->custom_profile_params[idx] = 1;
2672+ for (i = 1; i < custom_params_max_idx; i++)
2673+ smu->custom_profile_params[idx + i] = custom_params[i];
2674+ }
2675+ ret = smu_v13_0_0_set_power_profile_mode_coeff(smu,
2676+ smu->custom_profile_params);
2677+ if (ret) {
2678+ if (idx != -1)
2679+ smu->custom_profile_params[idx] = 0;
2680+ return ret;
2681+ }
2682+ } else if (smu->custom_profile_params) {
2683+ memset(smu->custom_profile_params, 0, SMU_13_0_0_CUSTOM_PARAMS_SIZE);
2684+ }
2685+
2686+ ret = smu_cmn_send_smc_msg_with_param(smu,
2687+ SMU_MSG_SetWorkloadMask,
2688+ backend_workload_mask,
2689+ NULL);
2690+ if (ret) {
2691+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
2692+ workload_mask);
2693+ if (idx != -1)
2694+ smu->custom_profile_params[idx] = 0;
2695+ return ret;
26792696 }
26802697
26812698 return ret;
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c+85−54
@@ -2530,79 +2530,110 @@ out: · 2529 unmodified lines
25302530 return result;
25312531 }
25322532
2533−static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
2533+#define SMU_13_0_7_CUSTOM_PARAMS_COUNT 8
2534+#define SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT 2
2535+#define SMU_13_0_7_CUSTOM_PARAMS_SIZE (SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT * SMU_13_0_7_CUSTOM_PARAMS_COUNT * sizeof(long))
2536+
2537+static int smu_v13_0_7_set_power_profile_mode_coeff(struct smu_context *smu,
2538+ long *input)
25342539 {
25352540
25362541 DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
25372542 DpmActivityMonitorCoeffInt_t *activity_monitor =
25382543 &(activity_monitor_external.DpmActivityMonitorCoeffInt);
2539− int workload_type, ret = 0;
2544+ int ret, idx;
25402545
2541− smu->power_profile_mode = input[size];
2546+ ret = smu_cmn_update_table(smu,
2547+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2548+ (void *)(&activity_monitor_external), false);
2549+ if (ret) {
2550+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2551+ return ret;
2552+ }
25422553
2543− if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {
2544− dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
2545− return -EINVAL;
2554+ idx = 0 * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
2555+ if (input[idx]) {
2556+ /* Gfxclk */
2557+ activity_monitor->Gfx_ActiveHystLimit = input[idx + 1];
2558+ activity_monitor->Gfx_IdleHystLimit = input[idx + 2];
2559+ activity_monitor->Gfx_FPS = input[idx + 3];
2560+ activity_monitor->Gfx_MinActiveFreqType = input[idx + 4];
2561+ activity_monitor->Gfx_BoosterFreqType = input[idx + 5];
2562+ activity_monitor->Gfx_MinActiveFreq = input[idx + 6];
2563+ activity_monitor->Gfx_BoosterFreq = input[idx + 7];
2564+ }
2565+ idx = 1 * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
2566+ if (input[idx]) {
2567+ /* Fclk */
2568+ activity_monitor->Fclk_ActiveHystLimit = input[idx + 1];
2569+ activity_monitor->Fclk_IdleHystLimit = input[idx + 2];
2570+ activity_monitor->Fclk_FPS = input[idx + 3];
2571+ activity_monitor->Fclk_MinActiveFreqType = input[idx + 4];
2572+ activity_monitor->Fclk_BoosterFreqType = input[idx + 5];
2573+ activity_monitor->Fclk_MinActiveFreq = input[idx + 6];
2574+ activity_monitor->Fclk_BoosterFreq = input[idx + 7];
25462575 }
25472576
2548− if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
2549− if (size != 8)
2550− return -EINVAL;
2577+ ret = smu_cmn_update_table(smu,
2578+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2579+ (void *)(&activity_monitor_external), true);
2580+ if (ret) {
2581+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
2582+ return ret;
2583+ }
25512584
2552− ret = smu_cmn_update_table(smu,
2553− SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2554− (void *)(&activity_monitor_external), false);
2555− if (ret) {
2556− dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
2557− return ret;
2558− }
2585+ return ret;
2586+}
25592587
2560− switch (input[0]) {
2561− case 0: /* Gfxclk */
2562− activity_monitor->Gfx_ActiveHystLimit = input[1];
2563− activity_monitor->Gfx_IdleHystLimit = input[2];
2564− activity_monitor->Gfx_FPS = input[3];
2565− activity_monitor->Gfx_MinActiveFreqType = input[4];
2566− activity_monitor->Gfx_BoosterFreqType = input[5];
2567− activity_monitor->Gfx_MinActiveFreq = input[6];
2568− activity_monitor->Gfx_BoosterFreq = input[7];
2569− break;
2570− case 1: /* Fclk */
2571− activity_monitor->Fclk_ActiveHystLimit = input[1];
2572− activity_monitor->Fclk_IdleHystLimit = input[2];
2573− activity_monitor->Fclk_FPS = input[3];
2574− activity_monitor->Fclk_MinActiveFreqType = input[4];
2575− activity_monitor->Fclk_BoosterFreqType = input[5];
2576− activity_monitor->Fclk_MinActiveFreq = input[6];
2577− activity_monitor->Fclk_BoosterFreq = input[7];
2578− break;
2579− default:
2580− return -EINVAL;
2588+static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu,
2589+ u32 workload_mask,
2590+ long *custom_params,
2591+ u32 custom_params_max_idx)
2592+{
2593+ u32 backend_workload_mask = 0;
2594+ int ret, idx = -1, i;
2595+
2596+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
2597+ &backend_workload_mask);
2598+
2599+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
2600+ if (!smu->custom_profile_params) {
2601+ smu->custom_profile_params =
2602+ kzalloc(SMU_13_0_7_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
2603+ if (!smu->custom_profile_params)
2604+ return -ENOMEM;
25812605 }
2582−
2583− ret = smu_cmn_update_table(smu,
2584− SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
2585− (void *)(&activity_monitor_external), true);
2606+ if (custom_params && custom_params_max_idx) {
2607+ if (custom_params_max_idx != SMU_13_0_7_CUSTOM_PARAMS_COUNT)
2608+ return -EINVAL;
2609+ if (custom_params[0] >= SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT)
2610+ return -EINVAL;
2611+ idx = custom_params[0] * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
2612+ smu->custom_profile_params[idx] = 1;
2613+ for (i = 1; i < custom_params_max_idx; i++)
2614+ smu->custom_profile_params[idx + i] = custom_params[i];
2615+ }
2616+ ret = smu_v13_0_7_set_power_profile_mode_coeff(smu,
2617+ smu->custom_profile_params);
25862618 if (ret) {
2587− dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
2619+ if (idx != -1)
2620+ smu->custom_profile_params[idx] = 0;
25882621 return ret;
25892622 }
2623+ } else if (smu->custom_profile_params) {
2624+ memset(smu->custom_profile_params, 0, SMU_13_0_7_CUSTOM_PARAMS_SIZE);
25902625 }
25912626
2592− /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
2593− workload_type = smu_cmn_to_asic_specific_index(smu,
2594− CMN2ASIC_MAPPING_WORKLOAD,
2595− smu->power_profile_mode);
2596− if (workload_type < 0)
2597− return -EINVAL;
2598−
25992627 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
2600− smu->workload_mask, NULL);
2628+ backend_workload_mask, NULL);
26012629
2602− if (ret)
2603− dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
2604− else
2605− smu_cmn_assign_power_profile(smu);
2630+ if (ret) {
2631+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
2632+ workload_mask);
2633+ if (idx != -1)
2634+ smu->custom_profile_params[idx] = 0;
2635+ return ret;
2636+ }
26062637
26072638 return ret;
26082639 }
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c+98−67
@@ -1739,89 +1739,120 @@ static int smu_v14_0_2_get_power_profile_mode(struct smu_context *smu, · 1738 unmodified lines
17391739 return size;
17401740 }
17411741
1742−static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
1743− long *input,
1744− uint32_t size)
1742+#define SMU_14_0_2_CUSTOM_PARAMS_COUNT 9
1743+#define SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT 2
1744+#define SMU_14_0_2_CUSTOM_PARAMS_SIZE (SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT * SMU_14_0_2_CUSTOM_PARAMS_COUNT * sizeof(long))
1745+
1746+static int smu_v14_0_2_set_power_profile_mode_coeff(struct smu_context *smu,
1747+ long *input)
17451748 {
17461749 DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
17471750 DpmActivityMonitorCoeffInt_t *activity_monitor =
17481751 &(activity_monitor_external.DpmActivityMonitorCoeffInt);
1749− int workload_type, ret = 0;
1750− uint32_t current_profile_mode = smu->power_profile_mode;
1751− smu->power_profile_mode = input[size];
1752+ int ret, idx;
17521753
1753− if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
1754− dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
1755− return -EINVAL;
1754+ ret = smu_cmn_update_table(smu,
1755+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1756+ WORKLOAD_PPLIB_CUSTOM_BIT,
1757+ (void *)(&activity_monitor_external),
1758+ false);
1759+ if (ret) {
1760+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1761+ return ret;
17561762 }
17571763
1758− if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1759− if (size != 9)
1760− return -EINVAL;
1764+ idx = 0 * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
1765+ if (input[idx]) {
1766+ /* Gfxclk */
1767+ activity_monitor->Gfx_FPS = input[idx + 1];
1768+ activity_monitor->Gfx_MinActiveFreqType = input[idx + 2];
1769+ activity_monitor->Gfx_MinActiveFreq = input[idx + 3];
1770+ activity_monitor->Gfx_BoosterFreqType = input[idx + 4];
1771+ activity_monitor->Gfx_BoosterFreq = input[idx + 5];
1772+ activity_monitor->Gfx_PD_Data_limit_c = input[idx + 6];
1773+ activity_monitor->Gfx_PD_Data_error_coeff = input[idx + 7];
1774+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[idx + 8];
1775+ }
1776+ idx = 1 * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
1777+ if (input[idx]) {
1778+ /* Fclk */
1779+ activity_monitor->Fclk_FPS = input[idx + 1];
1780+ activity_monitor->Fclk_MinActiveFreqType = input[idx + 2];
1781+ activity_monitor->Fclk_MinActiveFreq = input[idx + 3];
1782+ activity_monitor->Fclk_BoosterFreqType = input[idx + 4];
1783+ activity_monitor->Fclk_BoosterFreq = input[idx + 5];
1784+ activity_monitor->Fclk_PD_Data_limit_c = input[idx + 6];
1785+ activity_monitor->Fclk_PD_Data_error_coeff = input[idx + 7];
1786+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[idx + 8];
1787+ }
17611788
1762− ret = smu_cmn_update_table(smu,
1763− SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1764− WORKLOAD_PPLIB_CUSTOM_BIT,
1765− (void *)(&activity_monitor_external),
1766− false);
1767− if (ret) {
1768− dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
1769− return ret;
1770− }
1789+ ret = smu_cmn_update_table(smu,
1790+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1791+ WORKLOAD_PPLIB_CUSTOM_BIT,
1792+ (void *)(&activity_monitor_external),
1793+ true);
1794+ if (ret) {
1795+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
1796+ return ret;
1797+ }
17711798
1772− switch (input[0]) {
1773− case 0: /* Gfxclk */
1774− activity_monitor->Gfx_FPS = input[1];
1775− activity_monitor->Gfx_MinActiveFreqType = input[2];
1776− activity_monitor->Gfx_MinActiveFreq = input[3];
1777− activity_monitor->Gfx_BoosterFreqType = input[4];
1778− activity_monitor->Gfx_BoosterFreq = input[5];
1779− activity_monitor->Gfx_PD_Data_limit_c = input[6];
1780− activity_monitor->Gfx_PD_Data_error_coeff = input[7];
1781− activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
1782− break;
1783− case 1: /* Fclk */
1784− activity_monitor->Fclk_FPS = input[1];
1785− activity_monitor->Fclk_MinActiveFreqType = input[2];
1786− activity_monitor->Fclk_MinActiveFreq = input[3];
1787− activity_monitor->Fclk_BoosterFreqType = input[4];
1788− activity_monitor->Fclk_BoosterFreq = input[5];
1789− activity_monitor->Fclk_PD_Data_limit_c = input[6];
1790− activity_monitor->Fclk_PD_Data_error_coeff = input[7];
1791− activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
1792− break;
1793− default:
1794− return -EINVAL;
1795− }
1799+ return ret;
1800+}
17961801
1797− ret = smu_cmn_update_table(smu,
1798− SMU_TABLE_ACTIVITY_MONITOR_COEFF,
1799− WORKLOAD_PPLIB_CUSTOM_BIT,
1800− (void *)(&activity_monitor_external),
1801− true);
1802− if (ret) {
1803− dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
1804− return ret;
1805− }
1806− }
1802+static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
1803+ u32 workload_mask,
1804+ long *custom_params,
1805+ u32 custom_params_max_idx)
1806+{
1807+ u32 backend_workload_mask = 0;
1808+ int ret, idx = -1, i;
1809+
1810+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
1811+ &backend_workload_mask);
18071812
1808− if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE)
1813+ /* disable deep sleep if compute is enabled */
1814+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_COMPUTE))
18091815 smu_v14_0_deep_sleep_control(smu, false);
1810− else if (current_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE)
1816+ else
18111817 smu_v14_0_deep_sleep_control(smu, true);
18121818
1813− /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1814− workload_type = smu_cmn_to_asic_specific_index(smu,
1815− CMN2ASIC_MAPPING_WORKLOAD,
1816− smu->power_profile_mode);
1817− if (workload_type < 0)
1818− return -EINVAL;
1819+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
1820+ if (!smu->custom_profile_params) {
1821+ smu->custom_profile_params =
1822+ kzalloc(SMU_14_0_2_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
1823+ if (!smu->custom_profile_params)
1824+ return -ENOMEM;
1825+ }
1826+ if (custom_params && custom_params_max_idx) {
1827+ if (custom_params_max_idx != SMU_14_0_2_CUSTOM_PARAMS_COUNT)
1828+ return -EINVAL;
1829+ if (custom_params[0] >= SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT)
1830+ return -EINVAL;
1831+ idx = custom_params[0] * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
1832+ smu->custom_profile_params[idx] = 1;
1833+ for (i = 1; i < custom_params_max_idx; i++)
1834+ smu->custom_profile_params[idx + i] = custom_params[i];
1835+ }
1836+ ret = smu_v14_0_2_set_power_profile_mode_coeff(smu,
1837+ smu->custom_profile_params);
1838+ if (ret) {
1839+ if (idx != -1)
1840+ smu->custom_profile_params[idx] = 0;
1841+ return ret;
1842+ }
1843+ } else if (smu->custom_profile_params) {
1844+ memset(smu->custom_profile_params, 0, SMU_14_0_2_CUSTOM_PARAMS_SIZE);
1845+ }
18191846
18201847 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1821− smu->workload_mask, NULL);
1822−
1823− if (!ret)
1824− smu_cmn_assign_power_profile(smu);
1848+ backend_workload_mask, NULL);
1849+ if (ret) {
1850+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
1851+ workload_mask);
1852+ if (idx != -1)
1853+ smu->custom_profile_params[idx] = 0;
1854+ return ret;
1855+ }
18251856
18261857 return ret;
18271858 }
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c+25−8
@@ -1144,14 +1144,6 @@ int smu_cmn_set_mp1_state(struct smu_context *smu, · 1143 unmodified lines
11441144 return ret;
11451145 }
11461146
1147−void smu_cmn_assign_power_profile(struct smu_context *smu)
1148−{
1149− uint32_t index;
1150− index = fls(smu->workload_mask);
1151− index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
1152− smu->power_profile_mode = smu->workload_setting[index];
1153−}
1154−
11551147 bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev)
11561148 {
11571149 struct pci_dev *p = NULL;
@@ -1229,3 +1221,28 @@ void smu_cmn_generic_plpd_policy_desc(struct smu_dpm_policy *policy) · 71 unmodified lines
12291221 {
12301222 policy->desc = &xgmi_plpd_policy_desc;
12311223 }
1224+
1225+void smu_cmn_get_backend_workload_mask(struct smu_context *smu,
1226+ u32 workload_mask,
1227+ u32 *backend_workload_mask)
1228+{
1229+ int workload_type;
1230+ u32 profile_mode;
1231+
1232+ *backend_workload_mask = 0;
1233+
1234+ for (profile_mode = 0; profile_mode < PP_SMC_POWER_PROFILE_COUNT; profile_mode++) {
1235+ if (!(workload_mask & (1 << profile_mode)))
1236+ continue;
1237+
1238+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1239+ workload_type = smu_cmn_to_asic_specific_index(smu,
1240+ CMN2ASIC_MAPPING_WORKLOAD,
1241+ profile_mode);
1242+
1243+ if (workload_type < 0)
1244+ continue;
1245+
1246+ *backend_workload_mask |= 1 << workload_type;
1247+ }
1248+}
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h+4−2
@@ -130,8 +130,6 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev); · 129 unmodified lines
130130 int smu_cmn_set_mp1_state(struct smu_context *smu,
131131 enum pp_mp1_state mp1_state);
132132
133−void smu_cmn_assign_power_profile(struct smu_context *smu);
134−
135133 /*
136134 * Helper function to make sysfs_emit_at() happy. Align buf to
137135 * the current page boundary and record the offset.
@@ -149,5 +147,9 @@ bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev); · 11 unmodified lines
149147 void smu_cmn_generic_soc_policy_desc(struct smu_dpm_policy *policy);
150148 void smu_cmn_generic_plpd_policy_desc(struct smu_dpm_policy *policy);
151149
150+void smu_cmn_get_backend_workload_mask(struct smu_context *smu,
151+ u32 workload_mask,
152+ u32 *backend_workload_mask);
153+
152154 #endif
153155 #endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t