AMD General

-----Original Message-----
From: amd-gfx <[email protected]> On Behalf Of Yang Wang
Sent: Tuesday, June 23, 2026 3:53 PM
To: [email protected]
Cc: Deucher, Alexander <[email protected]>; Zhang, Hawking 
<[email protected]>; Feng, Kenneth <[email protected]>
Subject: [PATCH 3/3] drm/amd/pm: Validate remaining legacy PPLIB table bounds

The legacy PPLIB parser still had paths that consumed VBIOS offsets, entry 
counts and clock-info indices before proving the referenced data fit within 
soft_pp_table_size. Malformed tables can trigger out-of-bounds reads while 
parsing clock-voltage, CAC, fan, PPM and phase-shedding data.

Add shared bounds checks for the remaining fixed and variable-length legacy 
subtables. Also validate UVD/VCE clock-info indices before indexing their 
clock-info arrays.

Signed-off-by: Yang Wang <[email protected]>
---
 .../amd/pm/powerplay/hwmgr/processpptables.c  | 427 ++++++++++++++----
 1 file changed, 338 insertions(+), 89 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c 
b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
index b2e1123844ec..678c31abe4c4 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
@@ -55,6 +55,159 @@ static bool pp_table_has_space(struct pp_hwmgr *hwmgr, 
size_t offset,
        return offset <= table_size && size <= table_size - offset;  }

+static int get_pplib_subtable(struct pp_hwmgr *hwmgr,
+                             const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
+                             u16 table_offset, size_t table_size,
+                             const void **table)
+{
+       PP_ASSERT_WITH_CODE((table_offset != 0),
+                           "Invalid PowerPlay Table!", return -1);
+       PP_ASSERT_WITH_CODE((pp_table_has_space(hwmgr, table_offset,
+                                               table_size)),
+                           "Invalid PowerPlay Table!", return -1);
+
+       *table = (const void *)(((unsigned long)powerplay_table) +
+table_offset);
+
+       return 0;
+}
+
+static int validate_pplib_table_entries(struct pp_hwmgr *hwmgr,
+                                       u16 table_offset, size_t entries_offset,
+                                       u8 num_entries, size_t entry_size) {
+       size_t table_size;
+
+       PP_ASSERT_WITH_CODE((num_entries != 0),
+                           "Invalid PowerPlay Table!", return -1);
+
+       table_size = entries_offset + num_entries * entry_size;
+       PP_ASSERT_WITH_CODE((pp_table_has_space(hwmgr, table_offset,
+                                               table_size)),
+                           "Invalid PowerPlay Table!", return -1);
+
+       return 0;
+}
+
+static int validate_pplib_optional_table_entries(struct pp_hwmgr *hwmgr,
+                                       u16 table_offset, size_t entries_offset,
+                                       u8 num_entries, size_t entry_size) {
+       size_t table_size;
+
+       table_size = entries_offset + num_entries * entry_size;
+       PP_ASSERT_WITH_CODE((pp_table_has_space(hwmgr, table_offset,
+                                               table_size)),
+                           "Invalid PowerPlay Table!", return -1);
+
+       return 0;
+}
+
+static int get_pplib_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
+                       const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
+                       u16 table_offset,
+                       const ATOM_PPLIB_Clock_Voltage_Dependency_Table 
**table) {
+       const ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;
+       int ret;
+
+       ret = get_pplib_subtable(hwmgr, powerplay_table, table_offset,
+                                sizeof(*dep_table), (const void **)&dep_table);
+       if (ret)
+               return ret;
+
+       ret = validate_pplib_table_entries(hwmgr, table_offset,
+                                          
offsetof(ATOM_PPLIB_Clock_Voltage_Dependency_Table,
+                                                   entries),
+                                          dep_table->ucNumEntries,
+                                          
sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record));
+       if (ret)
+               return ret;
+
+       *table = dep_table;
+
+       return 0;
+}
+
+static int get_pplib_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
+                       const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
+                       u16 table_offset,
+                       const ATOM_PPLIB_Clock_Voltage_Limit_Table **table) {
+       const ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
+       int ret;
+
+       ret = get_pplib_subtable(hwmgr, powerplay_table, table_offset,
+                                sizeof(*limit_table),
+                                (const void **)&limit_table);
+       if (ret)
+               return ret;
+
+       ret = validate_pplib_table_entries(hwmgr, table_offset,
+                                          
offsetof(ATOM_PPLIB_Clock_Voltage_Limit_Table,
+                                                   entries),
+                                          limit_table->ucNumEntries,
+                                          
sizeof(ATOM_PPLIB_Clock_Voltage_Limit_Record));
+       if (ret)
+               return ret;
+
+       *table = limit_table;
+
+       return 0;
+}
+
+static int get_pplib_cac_leakage_table(struct pp_hwmgr *hwmgr,
+                       const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
+                       u16 table_offset,
+                       const ATOM_PPLIB_CAC_Leakage_Table **table) {
+       const ATOM_PPLIB_CAC_Leakage_Table *leakage_table;
+       int ret;
+
+       ret = get_pplib_subtable(hwmgr, powerplay_table, table_offset,
+                                sizeof(*leakage_table),
+                                (const void **)&leakage_table);
+       if (ret)
+               return ret;
+
+       ret = validate_pplib_optional_table_entries(hwmgr, table_offset,
+                                          
offsetof(ATOM_PPLIB_CAC_Leakage_Table,
+                                                   entries),
+                                          leakage_table->ucNumEntries,
+                                          
sizeof(ATOM_PPLIB_CAC_Leakage_Record));
+       if (ret)
+               return ret;
+
+       *table = leakage_table;
+
+       return 0;
+}
+
+static int get_pplib_phase_shedding_table(struct pp_hwmgr *hwmgr,
+                       const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
+                       u16 table_offset,
+                       const ATOM_PPLIB_PhaseSheddingLimits_Table **table) {
+       const ATOM_PPLIB_PhaseSheddingLimits_Table *phase_table;
+       int ret;
+
+       ret = get_pplib_subtable(hwmgr, powerplay_table, table_offset,
+                                sizeof(*phase_table), (const void 
**)&phase_table);
+       if (ret)
+               return ret;
+
+       ret = validate_pplib_optional_table_entries(hwmgr, table_offset,
+                                          
offsetof(ATOM_PPLIB_PhaseSheddingLimits_Table,
+                                                   entries),
+                                          phase_table->ucNumEntries,
+                                          
sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record));
+       if (ret)
+               return ret;
+
+       *table = phase_table;
+
+       return 0;
+}
+
 static const ATOM_PPLIB_EXTENDEDHEADER *  get_extended_header(struct pp_hwmgr 
*hwmgr,
                    const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, @@ 
-1143,14 +1296,36 @@ static int init_thermal_controller(
         if (powerplay_table->usTableSize >= 
sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
                const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
                        (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
+               u16 fan_table_offset;

                if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) {
                        hwmgr->thermal_controller.use_hw_fan_control = 1;
                        return 0;
                } else {
-                       const ATOM_PPLIB_FANTABLE *fan_table =
-                               (const ATOM_PPLIB_FANTABLE *)(((unsigned 
long)powerplay_table) +
-                                                             
le16_to_cpu(powerplay_table3->usFanTableOffset));
+                       const ATOM_PPLIB_FANTABLE *fan_table;
+                       size_t fan_table_size;
+
+                       fan_table_offset = 
le16_to_cpu(powerplay_table3->usFanTableOffset);
+                       if (!pp_table_has_space(hwmgr, fan_table_offset,
+                                               sizeof(*fan_table)))
+                               return -EINVAL;
+
+                       fan_table = (const ATOM_PPLIB_FANTABLE *)
+                               (((unsigned long)powerplay_table) + 
fan_table_offset);
+                       if (fan_table->ucFanTableFormat >= 7)
+                               fan_table_size = sizeof(ATOM_PPLIB_FANTABLE5);
+                       else if (fan_table->ucFanTableFormat >= 6)
+                               fan_table_size = sizeof(ATOM_PPLIB_FANTABLE4);
+                       else if (fan_table->ucFanTableFormat >= 3)
+                               fan_table_size = sizeof(ATOM_PPLIB_FANTABLE3);
+                       else if (fan_table->ucFanTableFormat >= 2)
+                               fan_table_size = sizeof(ATOM_PPLIB_FANTABLE2);
+                       else
+                               fan_table_size = sizeof(ATOM_PPLIB_FANTABLE);
+
+                       if (!pp_table_has_space(hwmgr, fan_table_offset,
+                                               fan_table_size))
+                               return -EINVAL;

                        if (1 <= fan_table->ucFanTableFormat) {
                                
hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst = @@ -1176,16 
+1351,14 @@ static int init_thermal_controller(

                        if (2 <= fan_table->ucFanTableFormat) {
                                const ATOM_PPLIB_FANTABLE2 *fan_table2 =
-                                       (const ATOM_PPLIB_FANTABLE2 
*)(((unsigned long)powerplay_table) +
-                                                                      
le16_to_cpu(powerplay_table3->usFanTableOffset));
+                                       (const ATOM_PPLIB_FANTABLE2 *)fan_table;
                                
hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
                                        le16_to_cpu(fan_table2->usTMax);
                        }

                        if (3 <= fan_table->ucFanTableFormat) {
                                const ATOM_PPLIB_FANTABLE3 *fan_table3 =
-                                       (const ATOM_PPLIB_FANTABLE3 *) 
(((unsigned long)powerplay_table) +
-                                                                       
le16_to_cpu(powerplay_table3->usFanTableOffset));
+                                       (const ATOM_PPLIB_FANTABLE3 *)fan_table;

                                
hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode =
                                        fan_table3->ucFanControlMode;
@@ -1206,8 +1379,7 @@ static int init_thermal_controller(

                        if (6 <= fan_table->ucFanTableFormat) {
                                const ATOM_PPLIB_FANTABLE4 *fan_table4 =
-                                       (const ATOM_PPLIB_FANTABLE4 
*)(((unsigned long)powerplay_table) +
-                                                                      
le16_to_cpu(powerplay_table3->usFanTableOffset));
+                                       (const ATOM_PPLIB_FANTABLE4 *)fan_table;

                                
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                            
PHM_PlatformCaps_FanSpeedInTableIsRPM);
@@ -1218,8 +1390,7 @@ static int init_thermal_controller(

                        if (7 <= fan_table->ucFanTableFormat) {
                                const ATOM_PPLIB_FANTABLE5 *fan_table5 =
-                                       (const ATOM_PPLIB_FANTABLE5 
*)(((unsigned long)powerplay_table) +
-                                                                      
le16_to_cpu(powerplay_table3->usFanTableOffset));
+                                       (const ATOM_PPLIB_FANTABLE5 *)fan_table;

                                if (0x67A2 == adev->pdev->device ||
                                    0x67A9 == adev->pdev->device || @@ -1351,8 
+1522,14 @@ static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
        uvd_table->count = table->numEntries;

        for (i = 0; i < table->numEntries; i++) {
-               const UVDClockInfo *entry =
-                       &array->entries[table->entries[i].ucUVDClockInfoIndex];
+               const UVDClockInfo *entry;
+
+               if (table->entries[i].ucUVDClockInfoIndex >= 
array->ucNumEntries) {
+                       kfree(uvd_table);
+                       return -EINVAL;
+               }
+
+               entry = &array->entries[table->entries[i].ucUVDClockInfoIndex];
                uvd_table->entries[i].v = (unsigned 
long)le16_to_cpu(table->entries[i].usVoltage);
                uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh 
<< 16)
                                         | le16_to_cpu(entry->usVClkLow);
@@ -1380,7 +1557,14 @@ static int get_vce_clock_voltage_limit_table(struct 
pp_hwmgr *hwmgr,

        vce_table->count = table->numEntries;
        for (i = 0; i < table->numEntries; i++) {
-               const VCEClockInfo *entry = 
&array->entries[table->entries[i].ucVCEClockInfoIndex];
+               const VCEClockInfo *entry;
+
+               if (table->entries[i].ucVCEClockInfoIndex >= 
array->ucNumEntries) {
+                       kfree(vce_table);
+                       return -EINVAL;
+               }
+
+               entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];

                vce_table->entries[i].v = (unsigned 
long)le16_to_cpu(table->entries[i].usVoltage);
                vce_table->entries[i].evclk = ((unsigned 
long)entry->ucEVClkHigh << 16) @@ -1474,12 +1658,20 @@ static int 
init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
                const VCEClockInfoArray *array = (const VCEClockInfoArray *)
                                (((unsigned long) powerplay_table) +
                                vce_clock_info_array_offset);
-               const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
-                               (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table 
*)
-                               (((unsigned long) powerplay_table) + 
table_offset);
-               result = get_vce_clock_voltage_limit_table(hwmgr,
-                               
&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
-                               table, array);
+               const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table;
+
+               result = get_pplib_subtable(hwmgr, powerplay_table, 
table_offset,
+                               sizeof(*table), (const void **)&table);
+               if (!result)
+                       result = validate_pplib_optional_table_entries(hwmgr, 
table_offset,
+                               
offsetof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table,
+                                        entries),
+                               table->numEntries,
+                               
sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
+               if (!result)
+                       result = get_vce_clock_voltage_limit_table(hwmgr,
+                                       
&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
+                                       table, array);
        }

        uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, 
powerplay_table); @@ -1489,40 +1681,78 @@ static int 
init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
                const UVDClockInfoArray *array = (const UVDClockInfoArray *)
                                (((unsigned long) powerplay_table) +
                                uvd_clock_info_array_offset);
-               const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
-                               (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table 
*)
-                               (((unsigned long) powerplay_table) + 
table_offset);
-               result = get_uvd_clock_voltage_limit_table(hwmgr,
-                               
&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
+               const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable;
+
+               result = get_pplib_subtable(hwmgr, powerplay_table, 
table_offset,
+                               sizeof(*ptable), (const void **)&ptable);
+               if (!result)
+                       result = validate_pplib_optional_table_entries(hwmgr, 
table_offset,
+                               
offsetof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table,
+                                        entries),
+                               ptable->numEntries,
+                               
sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
+               if (!result)
+                       result = get_uvd_clock_voltage_limit_table(hwmgr,
+                                       
&hwmgr->dyn_state.uvd_clock_voltage_dependency_table,
+                                       ptable, array);
        }

        table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
                                                            powerplay_table);

        if (table_offset > 0) {
-               const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
-                               (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
-                               (((unsigned long) powerplay_table) + 
table_offset);
-               result = get_samu_clock_voltage_limit_table(hwmgr,
-                               
&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
+               const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable;
+
+               result = get_pplib_subtable(hwmgr, powerplay_table, 
table_offset,
+                               sizeof(*ptable), (const void **)&ptable);
+               if (!result)
+                       result = validate_pplib_optional_table_entries(hwmgr, 
table_offset,
+                               offsetof(ATOM_PPLIB_SAMClk_Voltage_Limit_Table,
+                                        entries),
+                               ptable->numEntries,
+                               sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));
+               if (!result)
+                       result = get_samu_clock_voltage_limit_table(hwmgr,
+                                       
&hwmgr->dyn_state.samu_clock_voltage_dependency_table,
+                                       ptable);
        }

        table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
                                                             powerplay_table);

        if (table_offset > 0) {
-               const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
-                               (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
-                               (((unsigned long) powerplay_table) + 
table_offset);
-               result = get_acp_clock_voltage_limit_table(hwmgr,
-                               
&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
+               const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable;
+
+               result = get_pplib_subtable(hwmgr, powerplay_table, 
table_offset,
+                               sizeof(*ptable), (const void **)&ptable);
+               if (!result)
+                       result = validate_pplib_optional_table_entries(hwmgr, 
table_offset,
+                               offsetof(ATOM_PPLIB_ACPClk_Voltage_Limit_Table,
+                                        entries),
+                               ptable->numEntries,
+                               sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));
+               if (!result)
+                       result = get_acp_clock_voltage_limit_table(hwmgr,
+                                       
&hwmgr->dyn_state.acp_clock_voltage_dependency_table,
+                                       ptable);
        }

        table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
        if (table_offset > 0) {
-               UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + 
table_offset);
+               const void *tune_table;
+               UCHAR rev_id;

-               if (rev_id > 0) {
+               if (!pp_table_has_space(hwmgr, table_offset, sizeof(rev_id)))
+                       return -EINVAL;
+
+               rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + 
table_offset);
+               result = get_pplib_subtable(hwmgr, powerplay_table, 
table_offset,
+                               (rev_id > 0) ?
+                               sizeof(ATOM_PPLIB_POWERTUNE_Table_V1) :
+                               sizeof(ATOM_PPLIB_POWERTUNE_Table),
+                               (const void **)&tune_table);
AK: A non zero result will cause SCLK/MCLK/VDDCI/MVDD table to skip. Is it Ok? 
Was it same in earlier code?
+
+               if (!result && rev_id > 0) {
                        const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
                                (const ATOM_PPLIB_POWERTUNE_Table_V1 *)
                                (((unsigned long) powerplay_table) + 
table_offset); @@ -1531,7 +1761,7 @@ static int 
init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
                                
le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
                        
hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
                                le16_to_cpu(tune_table->usTjMax);
-               } else {
+               } else if (!result) {
                        const ATOM_PPLIB_POWERTUNE_Table *tune_table =
                                (const ATOM_PPLIB_POWERTUNE_Table *)
                                (((unsigned long) powerplay_table) + 
table_offset); @@ -1546,35 +1776,44 @@ static int 
init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
                const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
                                (const ATOM_PPLIB_POWERPLAYTABLE4 
*)powerplay_table;
                if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
-                       table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
-                               (((unsigned long) powerplay_table4) +
-                                
le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
-                       result = get_clock_voltage_dependency_table(hwmgr,
-                               &hwmgr->dyn_state.vddc_dependency_on_sclk, 
table);
+                       result = get_pplib_clock_voltage_dependency_table(hwmgr,
+                               powerplay_table,
+                               
le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset),
+                               (const 
ATOM_PPLIB_Clock_Voltage_Dependency_Table **)&table);
+                       if (!result)
+                               result = 
get_clock_voltage_dependency_table(hwmgr,
+                                       
&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
                }

                if (result == 0 && (0 != 
powerplay_table4->usVddciDependencyOnMCLKOffset)) {
-                       table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
-                               (((unsigned long) powerplay_table4) +
-                                
le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
-                       result = get_clock_voltage_dependency_table(hwmgr,
-                               &hwmgr->dyn_state.vddci_dependency_on_mclk, 
table);
+                       result = get_pplib_clock_voltage_dependency_table(hwmgr,
+                               powerplay_table,
+                               
le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset),
+                               (const 
ATOM_PPLIB_Clock_Voltage_Dependency_Table **)&table);
+                       if (!result)
+                               result = 
get_clock_voltage_dependency_table(hwmgr,
+                                       
&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
                }

                if (result == 0 && (0 != 
powerplay_table4->usVddcDependencyOnMCLKOffset)) {
-                       table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
-                               (((unsigned long) powerplay_table4) +
-                                
le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
-                       result = get_clock_voltage_dependency_table(hwmgr,
-                               &hwmgr->dyn_state.vddc_dependency_on_mclk, 
table);
+                       result = get_pplib_clock_voltage_dependency_table(hwmgr,
+                               powerplay_table,
+                               
le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset),
+                               (const 
ATOM_PPLIB_Clock_Voltage_Dependency_Table **)&table);
+                       if (!result)
+                               result = 
get_clock_voltage_dependency_table(hwmgr,
+                                       
&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
                }

                if (result == 0 && (0 != 
powerplay_table4->usMaxClockVoltageOnDCOffset)) {
-                       limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
-                               (((unsigned long) powerplay_table4) +
-                                
le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
-                       result = get_clock_voltage_limit(hwmgr,
-                               &hwmgr->dyn_state.max_clock_voltage_on_dc, 
limit_table);
+                       result = get_pplib_clock_voltage_limit_table(hwmgr,
+                               powerplay_table,
+                               
le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset),
+                               (const ATOM_PPLIB_Clock_Voltage_Limit_Table 
**)&limit_table);
+                       if (!result)
+                               result = get_clock_voltage_limit(hwmgr,
+                                       
&hwmgr->dyn_state.max_clock_voltage_on_dc,
+                                       limit_table);
                }

                if (result == 0 && (NULL != 
hwmgr->dyn_state.vddc_dependency_on_mclk) && @@ -1589,11 +1828,14 @@ static int 
init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
                                hwmgr->dyn_state.vddc_dependency_on_sclk);

                if (result == 0 && (0 != 
powerplay_table4->usMvddDependencyOnMCLKOffset)) {
-                       table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
-                               (((unsigned long) powerplay_table4) +
-                                
le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
-                       result = get_clock_voltage_dependency_table(hwmgr,
-                               &hwmgr->dyn_state.mvdd_dependency_on_mclk, 
table);
+                       result = get_pplib_clock_voltage_dependency_table(hwmgr,
+                               powerplay_table,
+                               
le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset),
+                               (const 
ATOM_PPLIB_Clock_Voltage_Dependency_Table **)&table);
+                       if (!result)
+                               result = 
get_clock_voltage_dependency_table(hwmgr,
+                                       
&hwmgr->dyn_state.mvdd_dependency_on_mclk,
+                                       table);
                }
        }

@@ -1601,10 +1843,13 @@ static int init_clock_voltage_dependency(struct 
pp_hwmgr *hwmgr,
                                                                
powerplay_table);

        if (table_offset > 0) {
-               table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
-                       (((unsigned long) powerplay_table) + table_offset);
-               result = get_clock_voltage_dependency_table(hwmgr,
-                       &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
+               result = get_pplib_clock_voltage_dependency_table(hwmgr,
+                       powerplay_table, table_offset,
+                       (const ATOM_PPLIB_Clock_Voltage_Dependency_Table 
**)&table);
+               if (!result)
+                       result = get_clock_voltage_dependency_table(hwmgr,
+                               &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk,
+                               table);
        }

        return result;
@@ -1676,12 +1921,6 @@ static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
            sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
                const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
                                (const ATOM_PPLIB_POWERPLAYTABLE5 
*)powerplay_table;
-               const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
-                               (const ATOM_PPLIB_POWERPLAYTABLE4 *)
-                               (&ptable5->basicTable4);
-               const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
-                               (const ATOM_PPLIB_POWERPLAYTABLE3 *)
-                               (&ptable4->basicTable3);
                const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
                uint16_t table_offset;
                ATOM_PPLIB_PPM_Table *atom_ppm_table; @@ -1711,28 +1950,34 @@ 
static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
                hwmgr->dyn_state.cac_leakage_table = NULL;

                if (0 != ptable5->usCACLeakageTableOffset) {
-                       const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
-                               (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned 
long)ptable5) +
-                               le16_to_cpu(ptable5->usCACLeakageTableOffset));
-                       result = get_cac_leakage_table(hwmgr,
-                               &hwmgr->dyn_state.cac_leakage_table, 
pCAC_leakage_table);
+                       const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table;
+
+                       result = get_pplib_cac_leakage_table(hwmgr, 
powerplay_table,
+                               le16_to_cpu(ptable5->usCACLeakageTableOffset),
+                               &pCAC_leakage_table);
+                       if (!result)
+                               result = get_cac_leakage_table(hwmgr,
+                                       &hwmgr->dyn_state.cac_leakage_table,
+                                       pCAC_leakage_table);
                }

                hwmgr->platform_descriptor.LoadLineSlope = 
le16_to_cpu(ptable5->usLoadLineSlope);

                hwmgr->dyn_state.ppm_parameter_table = NULL;

-               if (0 != ptable3->usExtendendedHeaderOffset) {
-                       extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
-                                       (((unsigned long)powerplay_table) +
-                                       
le16_to_cpu(ptable3->usExtendendedHeaderOffset));
+               extended_header = get_extended_header(hwmgr, powerplay_table,
+                                                     
SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5);
+               if (extended_header) {
                        if ((extended_header->usPPMTableOffset > 0) &&
                                le16_to_cpu(extended_header->usSize) >=
                                    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
                                table_offset = 
le16_to_cpu(extended_header->usPPMTableOffset);
-                               atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
-                                       (((unsigned long)powerplay_table) + 
table_offset);
-                               if (0 == 
get_platform_power_management_table(hwmgr, atom_ppm_table))
+                               result = get_pplib_subtable(hwmgr, 
powerplay_table,
+                                       table_offset, sizeof(*atom_ppm_table),
+                                       (const void **)&atom_ppm_table);
AK: Same as patch 2 may be causing regression, previous failure was silent and 
does not affected result

Thanks & Regards
Asad
+                               if (!result &&
+                                   !get_platform_power_management_table(hwmgr,
+                                                                        
atom_ppm_table))
                                        
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                                
PHM_PlatformCaps_EnablePlatformPowerManagement);
                        }
@@ -1750,13 +1995,17 @@ static int init_phase_shedding_table(struct pp_hwmgr 
*hwmgr,
                                (const ATOM_PPLIB_POWERPLAYTABLE4 
*)powerplay_table;

                if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
-                       const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
-                               (ATOM_PPLIB_PhaseSheddingLimits_Table *)
-                               (((unsigned long)powerplay_table4) +
-                               
le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
+                       const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable;
                        struct phm_phase_shedding_limits_table *table;
                        unsigned long i;
+                       int result;

+                       result = get_pplib_phase_shedding_table(hwmgr,
+                               powerplay_table,
+                               
le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset),
+                               &ptable);
+                       if (result)
+                               return result;

                        table = kzalloc(struct_size(table, entries, 
ptable->ucNumEntries),
                                        GFP_KERNEL);
--
2.47.3

Reply via email to