DF-4000 / fix.diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | --- a/sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c +++ b/sys/dev/drm/amd/powerplay/smumgr/iceland_smumgr.c @@ -974,10 +974,16 @@ uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; uint8_t count = 0; int result = 0; + uint32_t sclk_count; memset(levels, 0x00, level_array_size); - for (i = 0; i < dpm_table->sclk_table.count; i++) { + /* The VBIOS-provided SCLK DPM count is unclamped upstream; the SMC + * state table only has SMU71_MAX_LEVELS_GRAPHICS slots. */ + sclk_count = min(dpm_table->sclk_table.count, + (uint32_t)SMU71_MAX_LEVELS_GRAPHICS); + + for (i = 0; i < sclk_count; i++) { result = iceland_populate_single_graphic_level(hwmgr, dpm_table->sclk_table.dpm_levels[i].value, &(smu_data->smc_state_table.GraphicsLevel[i])); @@ -993,12 +999,12 @@ smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; /* set highest level watermark to high */ - if (dpm_table->sclk_table.count > 1) - smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = + if (sclk_count > 1) + smu_data->smc_state_table.GraphicsLevel[sclk_count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; + (uint8_t)sclk_count; data->dpm_level_enable_mask.sclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); @@ -1023,7 +1029,7 @@ /* set pcieDpmLevel to highest_pcie_level_enabled*/ - for (i = 2; i < dpm_table->sclk_table.count; i++) { + for (i = 2; i < sclk_count; i++) { smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; } @@ -1355,10 +1361,16 @@ uint32_t level_array_size = sizeof(SMU71_Discrete_MemoryLevel) * SMU71_MAX_LEVELS_MEMORY; SMU71_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; uint32_t i; + uint32_t mclk_count; memset(levels, 0x00, level_array_size); - for (i = 0; i < dpm_table->mclk_table.count; i++) { + /* The VBIOS-provided MCLK DPM count is unclamped upstream; the SMC + * state table only has SMU71_MAX_LEVELS_MEMORY slots. */ + mclk_count = min(dpm_table->mclk_table.count, + (uint32_t)SMU71_MAX_LEVELS_MEMORY); + + for (i = 0; i < mclk_count; i++) { PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), "can not populate memory level as memory clock is zero", return -EINVAL); result = iceland_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, @@ -1379,10 +1391,10 @@ smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); - smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)mclk_count; data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); /* set highest level watermark to high*/ - smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + smu_data->smc_state_table.MemoryLevel[mclk_count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; /* level count will send to smc once at init smc table and never change*/ result = smu7_copy_bytes_to_smc(hwmgr, @@ -1618,8 +1630,10 @@ memset(&arb_regs, 0x00, sizeof(SMU71_Discrete_MCArbDramTimingTable)); - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + for (i = 0; i < data->dpm_table.sclk_table.count && + i < SMU71_MAX_LEVELS_GRAPHICS; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count && + j < SMU71_MAX_LEVELS_MEMORY; j++) { result = iceland_populate_memory_timing_parameters (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, data->dpm_table.mclk_table.dpm_levels[j].value, @@ -1758,7 +1772,8 @@ int res; uint32_t i; - for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + for (i = 0; i < data->dpm_table.mclk_table.count && + i < SMU71_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT; i++) { res = iceland_convert_mc_reg_table_entry_to_smc( hwmgr, data->dpm_table.mclk_table.dpm_levels[i].value, @@ -1795,7 +1810,9 @@ return smu7_copy_bytes_to_smc(hwmgr, address, (uint8_t *)&smu_data->mc_regs.data[0], - sizeof(SMU71_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, + sizeof(SMU71_Discrete_MCRegisterSet) * + min(data->dpm_table.mclk_table.count, + (uint32_t)SMU71_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT), SMC_RAM_END); } |