AMD General

> -----Original Message-----
> From: Kamal, Asad <[email protected]>
> Sent: Tuesday, June 23, 2026 7:45 PM
> To: Wang, Yang(Kevin) <[email protected]>; amd-
> [email protected]
> Cc: Deucher, Alexander <[email protected]>; Zhang, Hawking
> <[email protected]>; Feng, Kenneth <[email protected]>
> Subject: RE: [PATCH 2/3] drm/amd/pm: Validate Tonga PPTable subtable
> bounds
>
> 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 2/3] drm/amd/pm: Validate Tonga PPTable subtable bounds
>
> Tonga PPTable parsing also relies on VBIOS offsets, revision fields and entry
> counts for several subtables. Malformed data can cause out-of-bounds reads,
> while voltage lookup tables can overrun their fixed-size destination arrays.
>
> Add common bounds helpers and validate fixed subtables, dynamic entry
> arrays and revision-specific layouts before consuming voltage lookup,
> dependency, PCIE, power-tune, hard-limit, thermal, fan, GPIO, PPM and VCE
> state data.
>
> Signed-off-by: Yang Wang <[email protected]>
> ---
>  .../powerplay/hwmgr/process_pptables_v1_0.c   | 604 +++++++++++++++---
>  1 file changed, 519 insertions(+), 85 deletions(-)
>
> diff --git
> a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c
> b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c
> index 94c1e2c10370..831f5e240105 100644
> --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c
> +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c
> @@ -150,6 +150,368 @@ static const void *get_powerplay_table(struct
> pp_hwmgr *hwmgr)
>         return table_address;
>  }
>
> +static bool tonga_pp_table_has_space(struct pp_hwmgr *hwmgr, size_t
> offset,
> +                                    size_t size) {
> +       size_t table_size = hwmgr->soft_pp_table_size;
> +
> +       return offset <= table_size && size <= table_size - offset; }
> +
> +static int get_tonga_subtable(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_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((tonga_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_tonga_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((tonga_pp_table_has_space(hwmgr,
> table_offset,
> +                                                     table_size)),
> +                           "Invalid PowerPlay Table!", return -1);
> +
> +       return 0;
> +}
> +
> +static int get_tonga_voltage_lookup_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               u16 table_offset, uint32_t max_levels,
> +               const ATOM_Tonga_Voltage_Lookup_Table **lookup_table) {
> +       const ATOM_Tonga_Voltage_Lookup_Table *table;
> +       size_t table_size;
> +       int ret;
> +
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*table), (const void **)&table);
> +       if (ret)
> +               return ret;
> +
> +       PP_ASSERT_WITH_CODE((table->ucNumEntries != 0 &&
> +                            table->ucNumEntries <= max_levels),
> +                           "Invalid PowerPlay Table!", return -1);
> +
> +       table_size = offsetof(ATOM_Tonga_Voltage_Lookup_Table, entries) +
> +               table->ucNumEntries *
> sizeof(ATOM_Tonga_Voltage_Lookup_Record);
> +       PP_ASSERT_WITH_CODE((tonga_pp_table_has_space(hwmgr,
> table_offset,
> +                                                     table_size)),
> +                           "Invalid PowerPlay Table!", return -1);
> +
> +       *lookup_table = table;
> +
> +       return 0;
> +}
> +
> +static int get_tonga_mclk_dependency_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const ATOM_Tonga_MCLK_Dependency_Table **mclk_dep_table) {
> +       const ATOM_Tonga_MCLK_Dependency_Table *table;
> +       u16 table_offset;
> +       int ret;
> +
> +       table_offset = le16_to_cpu(powerplay_table-
> >usMclkDependencyTableOffset);
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*table), (const void **)&table);
> +       if (ret)
> +               return ret;
> +
> +       ret = validate_tonga_table_entries(hwmgr, table_offset,
> +                                          
> offsetof(ATOM_Tonga_MCLK_Dependency_Table,
> +                                                   entries),
> +                                          table->ucNumEntries,
> +                                          
> sizeof(ATOM_Tonga_MCLK_Dependency_Record));
> +       if (ret)
> +               return ret;
> +
> +       *mclk_dep_table = table;
> +
> +       return 0;
> +}
> +
> +static int get_tonga_mm_dependency_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const ATOM_Tonga_MM_Dependency_Table **mm_dep_table) {
> +       const ATOM_Tonga_MM_Dependency_Table *table;
> +       u16 table_offset;
> +       int ret;
> +
> +       table_offset = le16_to_cpu(powerplay_table-
> >usMMDependencyTableOffset);
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*table), (const void **)&table);
> +       if (ret)
> +               return ret;
> +
> +       ret = validate_tonga_table_entries(hwmgr, table_offset,
> +                                          
> offsetof(ATOM_Tonga_MM_Dependency_Table,
> +                                                   entries),
> +                                          table->ucNumEntries,
> +                                          
> sizeof(ATOM_Tonga_MM_Dependency_Record));
> +       if (ret)
> +               return ret;
> +
> +       *mm_dep_table = table;
> +
> +       return 0;
> +}
> +
> +static int get_tonga_sclk_dependency_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const PPTable_Generic_SubTable_Header **sclk_dep_table) {
> +       const PPTable_Generic_SubTable_Header *header;
> +       u16 table_offset;
> +       size_t entries_offset;
> +       size_t entry_size;
> +       u8 num_entries;
> +       int ret;
> +
> +       table_offset = le16_to_cpu(powerplay_table-
> >usSclkDependencyTableOffset);
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*header), (const void **)&header);
> +       if (ret)
> +               return ret;
> +
> +       if (header->ucRevId < 1) {
> +               const ATOM_Tonga_SCLK_Dependency_Table *table =
> +                       (const ATOM_Tonga_SCLK_Dependency_Table
> + *)header;
> +
> +               entries_offset = offsetof(ATOM_Tonga_SCLK_Dependency_Table,
> entries);
> +               entry_size = sizeof(ATOM_Tonga_SCLK_Dependency_Record);
> +               num_entries = table->ucNumEntries;
> +       } else {
> +               const ATOM_Polaris_SCLK_Dependency_Table *table =
> +                       (const ATOM_Polaris_SCLK_Dependency_Table
> + *)header;
> +
> +               entries_offset = offsetof(ATOM_Polaris_SCLK_Dependency_Table,
> entries);
> +               entry_size = sizeof(ATOM_Polaris_SCLK_Dependency_Record);
> +               num_entries = table->ucNumEntries;
> +       }
> +
> +       ret = validate_tonga_table_entries(hwmgr, table_offset, 
> entries_offset,
> +                                          num_entries, entry_size);
> +       if (ret)
> +               return ret;
> +
> +       *sclk_dep_table = header;
> +
> +       return 0;
> +}
> +
> +static int get_tonga_pcie_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const PPTable_Generic_SubTable_Header **pcie_table) {
> +       const PPTable_Generic_SubTable_Header *header;
> +       u16 table_offset;
> +       size_t entries_offset;
> +       size_t entry_size;
> +       u8 num_entries;
> +       int ret;
> +
> +       table_offset = le16_to_cpu(powerplay_table->usPCIETableOffset);
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*header), (const void **)&header);
> +       if (ret)
> +               return ret;
> +
> +       if (header->ucRevId < 1) {
> +               const ATOM_Tonga_PCIE_Table *table =
> +                       (const ATOM_Tonga_PCIE_Table *)header;
> +
> +               entries_offset = offsetof(ATOM_Tonga_PCIE_Table, entries);
> +               entry_size = sizeof(ATOM_Tonga_PCIE_Record);
> +               num_entries = table->ucNumEntries;
> +       } else {
> +               const ATOM_Polaris10_PCIE_Table *table =
> +                       (const ATOM_Polaris10_PCIE_Table *)header;
> +
> +               entries_offset = offsetof(ATOM_Polaris10_PCIE_Table, entries);
> +               entry_size = sizeof(ATOM_Polaris10_PCIE_Record);
> +               num_entries = table->ucNumEntries;
> +       }
> +
> +       ret = validate_tonga_table_entries(hwmgr, table_offset, 
> entries_offset,
> +                                          num_entries, entry_size);
> +       if (ret)
> +               return ret;
> +
> +       *pcie_table = header;
> +
> +       return 0;
> +}
> +
> +static int get_tonga_hard_limit_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const ATOM_Tonga_Hard_Limit_Table **hard_limit_table) {
> +       const ATOM_Tonga_Hard_Limit_Table *table;
> +       u16 table_offset;
> +       int ret;
> +
> +       table_offset = le16_to_cpu(powerplay_table->usHardLimitTableOffset);
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*table), (const void **)&table);
> +       if (ret)
> +               return ret;
> +
> +       ret = validate_tonga_table_entries(hwmgr, table_offset,
> +                                          
> offsetof(ATOM_Tonga_Hard_Limit_Table,
> +                                                   entries),
> +                                          table->ucNumEntries,
> +                                          
> sizeof(ATOM_Tonga_Hard_Limit_Record));
> +       if (ret)
> +               return ret;
> +
> +       *hard_limit_table = table;
> +
> +       return 0;
> +}
> +
> +static int get_tonga_thermal_controller_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const ATOM_Tonga_Thermal_Controller **thermal_controller) {
> +       u16 table_offset;
> +
> +       table_offset =
> +le16_to_cpu(powerplay_table->usThermalControllerOffset);
> +
> +       return get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                 sizeof(**thermal_controller),
> +                                 (const void **)thermal_controller); }
> +
> +static int get_tonga_fan_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const PPTable_Generic_SubTable_Header **fan_table) {
> +       const PPTable_Generic_SubTable_Header *header;
> +       u16 table_offset;
> +       size_t table_size;
> +       int ret;
> +
> +       table_offset = le16_to_cpu(powerplay_table->usFanTableOffset);
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*header), (const void **)&header);
> +       if (ret)
> +               return ret;
> +
> +       if (header->ucRevId < 8)
> +               table_size = sizeof(ATOM_Tonga_Fan_Table);
> +       else if (header->ucRevId == 8)
> +               table_size = sizeof(ATOM_Fiji_Fan_Table);
> +       else
> +               table_size = sizeof(ATOM_Polaris_Fan_Table);
> +
> +       PP_ASSERT_WITH_CODE((tonga_pp_table_has_space(hwmgr,
> table_offset,
> +                                                     table_size)),
> +                           "Invalid PowerPlay Table!", return -1);
> +
> +       *fan_table = header;
> +
> +       return 0;
> +}
> +
> +static int get_tonga_power_tune_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const PPTable_Generic_SubTable_Header **power_tune_table) {
> +       const PPTable_Generic_SubTable_Header *header;
> +       u16 table_offset;
> +       size_t table_size;
> +       int ret;
> +
> +       table_offset = le16_to_cpu(powerplay_table->usPowerTuneTableOffset);
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*header), (const void **)&header);
> +       if (ret)
> +               return ret;
> +
> +       if (header->ucRevId < 3)
> +               table_size = sizeof(ATOM_Tonga_PowerTune_Table);
> +       else if (header->ucRevId < 4)
> +               table_size = sizeof(ATOM_Fiji_PowerTune_Table);
> +       else
> +               table_size = sizeof(ATOM_Polaris_PowerTune_Table);
> +
> +       PP_ASSERT_WITH_CODE((tonga_pp_table_has_space(hwmgr,
> table_offset,
> +                                                     table_size)),
> +                           "Invalid PowerPlay Table!", return -1);
> +
> +       *power_tune_table = header;
> +
> +       return 0;
> +}
> +
> +static int get_tonga_ppm_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const ATOM_Tonga_PPM_Table **ppm_table) {
> +       u16 table_offset;
> +
> +       table_offset = le16_to_cpu(powerplay_table->usPPMTableOffset);
> +
> +       return get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                 sizeof(**ppm_table), (const void
> + **)ppm_table); }
> +
> +static int get_tonga_gpio_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const ATOM_Tonga_GPIO_Table **gpio_table) {
> +       u16 table_offset;
> +
> +       table_offset = le16_to_cpu(powerplay_table->usGPIOTableOffset);
> +
> +       return get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                 sizeof(**gpio_table), (const void
> + **)gpio_table); }
> +
> +static int get_tonga_vce_state_table(struct pp_hwmgr *hwmgr,
> +               const ATOM_Tonga_POWERPLAYTABLE *powerplay_table,
> +               const ATOM_Tonga_VCE_State_Table **vce_state_table) {
> +       const ATOM_Tonga_VCE_State_Table *table;
> +       u16 table_offset;
> +       int ret;
> +
> +       table_offset = le16_to_cpu(powerplay_table->usVCEStateTableOffset);
> +       ret = get_tonga_subtable(hwmgr, powerplay_table, table_offset,
> +                                sizeof(*table), (const void **)&table);
> +       if (ret)
> +               return ret;
> +
> +       ret = validate_tonga_table_entries(hwmgr, table_offset,
> +                                          
> offsetof(ATOM_Tonga_VCE_State_Table,
> +                                                   entries),
> +                                          table->ucNumEntries,
> +                                          
> sizeof(ATOM_Tonga_VCE_State_Record));
> +       if (ret)
> +               return ret;
> +
> +       *vce_state_table = table;
> +
> +       return 0;
> +}
> +
>  static int get_vddc_lookup_table(
>                 struct pp_hwmgr *hwmgr,
>                 phm_ppt_v1_voltage_lookup_table **lookup_table, @@ -198,7
> +560,7 @@ static int get_vddc_lookup_table(
>   */
>  static int get_platform_power_management_table(
>                 struct pp_hwmgr *hwmgr,
> -               ATOM_Tonga_PPM_Table *atom_ppm_table)
> +               const ATOM_Tonga_PPM_Table *atom_ppm_table)
>  {
>         struct phm_ppm_table *ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
>         struct phm_ppt_v1_information *pp_table_information = @@ -246,7
> +608,7 @@ static int init_dpm_2_parameters(  {
>         int result = 0;
>         struct phm_ppt_v1_information *pp_table_information = (struct
> phm_ppt_v1_information *)(hwmgr->pptable);
> -       ATOM_Tonga_PPM_Table *atom_ppm_table;
> +       const ATOM_Tonga_PPM_Table *atom_ppm_table;
>         uint32_t disable_ppm = 0;
>         uint32_t disable_power_control = 0;
>
> @@ -275,30 +637,37 @@ static int init_dpm_2_parameters(
>         }
>
>         if (0 != powerplay_table->usVddcLookupTableOffset) {
> -               const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable =
> -                       (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned
> long)powerplay_table) +
> -                       
> le16_to_cpu(powerplay_table->usVddcLookupTableOffset));
> -
> -               result = get_vddc_lookup_table(hwmgr,
> -                       &pp_table_information->vddc_lookup_table, 
> pVddcCACTable,
> 16);
> +               const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable;
> +
> +               result = get_tonga_voltage_lookup_table(hwmgr, 
> powerplay_table,
> +                               
> le16_to_cpu(powerplay_table->usVddcLookupTableOffset),
> +                               16, &pVddcCACTable);
> +               if (!result)
> +                       result = get_vddc_lookup_table(hwmgr,
> +                               &pp_table_information->vddc_lookup_table,
> +                               pVddcCACTable, 16);
>         }
>
> -       if (0 != powerplay_table->usVddgfxLookupTableOffset) {
> -               const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable =
> -                       (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned
> long)powerplay_table) +
> -                       
> le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset));
> +       if (!result && 0 != powerplay_table->usVddgfxLookupTableOffset) {
> +               const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable;
>
> -               result = get_vddc_lookup_table(hwmgr,
> -                       &pp_table_information->vddgfx_lookup_table,
> pVddgfxCACTable, 16);
> +               result = get_tonga_voltage_lookup_table(hwmgr, 
> powerplay_table,
> +                               le16_to_cpu(powerplay_table-
> >usVddgfxLookupTableOffset),
> +                               16, &pVddgfxCACTable);
> +               if (!result)
> +                       result = get_vddc_lookup_table(hwmgr,
> +                               &pp_table_information->vddgfx_lookup_table,
> +                               pVddgfxCACTable, 16);
>         }
>
>         disable_ppm = 0;
>         if (0 == disable_ppm) {
> -               atom_ppm_table = (ATOM_Tonga_PPM_Table *)
> -                       (((unsigned long)powerplay_table) +
> le16_to_cpu(powerplay_table->usPPMTableOffset));
> -
>                 if (0 != powerplay_table->usPPMTableOffset) {
> -                       if (get_platform_power_management_table(hwmgr,
> atom_ppm_table) == 0) {
> +                       result = get_tonga_ppm_table(hwmgr, powerplay_table,
> +                                                    &atom_ppm_table);
> Will this not cause regression, earlier result was not touched, now if PPM
> table fails bounds validation, result is set to -1 which may cause
> pp_tables_v1_0_initialize() to bail out entirely

Thanks , will update in next version.

Best Regards,
Kevin
> +                       if (!result &&
> +                           get_platform_power_management_table(hwmgr,
> +
> + atom_ppm_table) == 0) {
>                                 
> phm_cap_set(hwmgr->platform_descriptor.platformCaps,
>
> PHM_PlatformCaps_EnablePlatformPowerManagement);
>                         }
> @@ -792,28 +1161,13 @@ static int init_clock_voltage_dependency(
>         int result = 0;
>         struct phm_ppt_v1_information *pp_table_information =
>                 (struct phm_ppt_v1_information *)(hwmgr->pptable);
> -
> -       const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table =
> -               (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)
> powerplay_table) +
> -               le16_to_cpu(powerplay_table->usMMDependencyTableOffset));
> -       const PPTable_Generic_SubTable_Header *pPowerTuneTable =
> -               (const PPTable_Generic_SubTable_Header *)(((unsigned long)
> powerplay_table) +
> -               le16_to_cpu(powerplay_table->usPowerTuneTableOffset));
> -       const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
> -               (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)
> powerplay_table) +
> -               le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
> -       const PPTable_Generic_SubTable_Header *sclk_dep_table =
> -               (const PPTable_Generic_SubTable_Header *)(((unsigned long)
> powerplay_table) +
> -               le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
> -       const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
> -               (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long)
> powerplay_table) +
> -               le16_to_cpu(powerplay_table->usHardLimitTableOffset));
> -       const PPTable_Generic_SubTable_Header *pcie_table =
> -               (const PPTable_Generic_SubTable_Header *)(((unsigned long)
> powerplay_table) +
> -               le16_to_cpu(powerplay_table->usPCIETableOffset));
> -       const ATOM_Tonga_GPIO_Table *gpio_table =
> -               (const ATOM_Tonga_GPIO_Table *)(((unsigned long)
> powerplay_table) +
> -               le16_to_cpu(powerplay_table->usGPIOTableOffset));
> +       const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table;
> +       const PPTable_Generic_SubTable_Header *pPowerTuneTable;
> +       const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table;
> +       const PPTable_Generic_SubTable_Header *sclk_dep_table;
> +       const ATOM_Tonga_Hard_Limit_Table *pHardLimits;
> +       const PPTable_Generic_SubTable_Header *pcie_table;
> +       const ATOM_Tonga_GPIO_Table *gpio_table;
>
>         pp_table_information->vdd_dep_on_sclk = NULL;
>         pp_table_information->vdd_dep_on_mclk = NULL; @@ -821,29 +1175,58
> @@ static int init_clock_voltage_dependency(
>         pp_table_information->pcie_table = NULL;
>         pp_table_information->gpio_table = NULL;
>
> -       if (powerplay_table->usMMDependencyTableOffset != 0)
> -               result = get_mm_clock_voltage_table(hwmgr,
> -               &pp_table_information->mm_dep_table, mm_dependency_table);
> +       if (powerplay_table->usMMDependencyTableOffset != 0) {
> +               result = get_tonga_mm_dependency_table(hwmgr,
> powerplay_table,
> +                                                      &mm_dependency_table);
> +               if (!result)
> +                       result = get_mm_clock_voltage_table(hwmgr,
> +                               &pp_table_information->mm_dep_table,
> +                               mm_dependency_table);
> +       }
>
> -       if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0)
> -               result = get_cac_tdp_table(hwmgr,
> -               &pp_table_information->cac_dtp_table, pPowerTuneTable);
> +       if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0) {
> +               result = get_tonga_power_tune_table(hwmgr, powerplay_table,
> +                                                   &pPowerTuneTable);
> +               if (!result)
> +                       result = get_cac_tdp_table(hwmgr,
> +                               &pp_table_information->cac_dtp_table,
> +                               pPowerTuneTable);
> +       }
>
> -       if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0)
> -               result = get_sclk_voltage_dependency_table(hwmgr,
> -               &pp_table_information->vdd_dep_on_sclk, sclk_dep_table);
> +       if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0) 
> {
> +               result = get_tonga_sclk_dependency_table(hwmgr,
> powerplay_table,
> +                                                        &sclk_dep_table);
> +               if (!result)
> +                       result = get_sclk_voltage_dependency_table(hwmgr,
> +                               &pp_table_information->vdd_dep_on_sclk,
> +                               sclk_dep_table);
> +       }
>
> -       if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0)
> -               result = get_mclk_voltage_dependency_table(hwmgr,
> -               &pp_table_information->vdd_dep_on_mclk, mclk_dep_table);
> +       if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0)
> {
> +               result = get_tonga_mclk_dependency_table(hwmgr,
> powerplay_table,
> +                                                        &mclk_dep_table);
> +               if (!result)
> +                       result = get_mclk_voltage_dependency_table(hwmgr,
> +                               &pp_table_information->vdd_dep_on_mclk,
> +                               mclk_dep_table);
> +       }
>
> -       if (result == 0 && powerplay_table->usPCIETableOffset != 0)
> -               result = get_pcie_table(hwmgr,
> -               &pp_table_information->pcie_table, pcie_table);
> +       if (result == 0 && powerplay_table->usPCIETableOffset != 0) {
> +               result = get_tonga_pcie_table(hwmgr, powerplay_table,
> +                                             &pcie_table);
> +               if (!result)
> +                       result = get_pcie_table(hwmgr,
> +                               &pp_table_information->pcie_table, 
> pcie_table);
> +       }
>
> -       if (result == 0 && powerplay_table->usHardLimitTableOffset != 0)
> -               result = get_hard_limits(hwmgr,
> -               &pp_table_information->max_clock_voltage_on_dc, pHardLimits);
> +       if (result == 0 && powerplay_table->usHardLimitTableOffset != 0) {
> +               result = get_tonga_hard_limit_table(hwmgr, powerplay_table,
> +                                                   &pHardLimits);
> +               if (!result)
> +                       result = get_hard_limits(hwmgr,
> +                               
> &pp_table_information->max_clock_voltage_on_dc,
> +                               pHardLimits);
> +       }
>
>         hwmgr->dyn_state.max_clock_voltage_on_dc.sclk =
>                 pp_table_information->max_clock_voltage_on_dc.sclk;
> @@ -864,9 +1247,13 @@ static int init_clock_voltage_dependency(
>                 result = get_valid_clk(hwmgr, &pp_table_information-
> >valid_sclk_values,
>                 pp_table_information->vdd_dep_on_sclk);
>
> -       if (!result && gpio_table)
> -               result = get_gpio_table(hwmgr, 
> &pp_table_information->gpio_table,
> -                               gpio_table);
> +       if (!result && powerplay_table->usGPIOTableOffset) {
> +               result = get_tonga_gpio_table(hwmgr, powerplay_table,
> +                                             &gpio_table);
> +               if (!result)
> +                       result = get_gpio_table(hwmgr,
> +                               &pp_table_information->gpio_table, 
> gpio_table);
> +       }
>
>         return result;
>  }
> @@ -911,14 +1298,17 @@ static int init_thermal_controller(
>                 )
>  {
>         const PPTable_Generic_SubTable_Header *fan_table;
> -       ATOM_Tonga_Thermal_Controller *thermal_controller;
> +       const ATOM_Tonga_Thermal_Controller *thermal_controller;
> +       int ret;
>
> -       thermal_controller = (ATOM_Tonga_Thermal_Controller *)
> -               (((unsigned long)powerplay_table) +
> -               le16_to_cpu(powerplay_table->usThermalControllerOffset));
>         PP_ASSERT_WITH_CODE((0 != powerplay_table-
> >usThermalControllerOffset),
>                 "Thermal controller table not set!", return -1);
>
> +       ret = get_tonga_thermal_controller_table(hwmgr, powerplay_table,
> +                                                &thermal_controller);
> +       if (ret)
> +               return ret;
> +
>         hwmgr->thermal_controller.ucType = thermal_controller->ucType;
>         hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine;
>         hwmgr->thermal_controller.ucI2cAddress = thermal_controller-
> >ucI2cAddress; @@ -946,12 +1336,13 @@ static int init_thermal_controller(
>                 return 0;
>         }
>
> -       fan_table = (const PPTable_Generic_SubTable_Header *)
> -               (((unsigned long)powerplay_table) +
> -               le16_to_cpu(powerplay_table->usFanTableOffset));
> -
>         PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset),
>                 "Fan table not set!", return -1);
> +
> +       ret = get_tonga_fan_table(hwmgr, powerplay_table, &fan_table);
> +       if (ret)
> +               return ret;
> +
>         PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId),
>                 "Unsupported fan table format!", return -1);
>
> @@ -1313,13 +1704,15 @@ static int
> ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr)  {
>         const ATOM_Tonga_POWERPLAYTABLE *pp_table =
> get_powerplay_table(hwmgr);
>         const ATOM_Tonga_VCE_State_Table *vce_state_table;
> +       int ret;
>
>
>         if (pp_table == NULL)
>                 return 0;
>
> -       vce_state_table = (void *)pp_table +
> -                       le16_to_cpu(pp_table->usVCEStateTableOffset);
> +       ret = get_tonga_vce_state_table(hwmgr, pp_table, &vce_state_table);
> +       if (ret)
> +               return 0;
>
>         return vce_state_table->ucNumEntries;  } @@ -1328,18 +1721,39 @@
> static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr,
> uint32_t i
>                 struct amd_vce_state *vce_state, void **clock_info, uint32_t 
> *flag)  {
>         const ATOM_Tonga_VCE_State_Record *vce_state_record;
> -       ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
> +       ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record = NULL;
> +       ATOM_Polaris_SCLK_Dependency_Record *polaris_sclk_dep_record =
> + NULL;
>         ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
>         ATOM_Tonga_MM_Dependency_Record *mm_dep_record;
>         const ATOM_Tonga_POWERPLAYTABLE *pptable =
> get_powerplay_table(hwmgr);
> -       const ATOM_Tonga_VCE_State_Table *vce_state_table =
> (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable)
> -                                                         + 
> le16_to_cpu(pptable-
> >usVCEStateTableOffset));
> -       const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table =
> (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable)
> -                                                         + 
> le16_to_cpu(pptable-
> >usSclkDependencyTableOffset));
> -       const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
> (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable)
> -                                                         + 
> le16_to_cpu(pptable-
> >usMclkDependencyTableOffset));
> -       const ATOM_Tonga_MM_Dependency_Table *mm_dep_table =
> (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable)
> -                                                         + 
> le16_to_cpu(pptable-
> >usMMDependencyTableOffset));
> +       const ATOM_Tonga_VCE_State_Table *vce_state_table;
> +       const PPTable_Generic_SubTable_Header *sclk_dep_table_header;
> +       const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table;
> +       const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table;
> +       const ATOM_Tonga_MM_Dependency_Table *mm_dep_table;
> +       int ret;
> +
> +       if (!pptable)
> +               return -EINVAL;
> +
> +       ret = get_tonga_vce_state_table(hwmgr, pptable, &vce_state_table);
> +       if (ret)
> +               return ret;
> +
> +       ret = get_tonga_sclk_dependency_table(hwmgr, pptable,
> +                                             &sclk_dep_table_header);
> +       if (ret)
> +               return ret;
> +       sclk_dep_table = (const ATOM_Tonga_SCLK_Dependency_Table *)
> +               sclk_dep_table_header;
> +
> +       ret = get_tonga_mclk_dependency_table(hwmgr, pptable,
> &mclk_dep_table);
> +       if (ret)
> +               return ret;
> +
> +       ret = get_tonga_mm_dependency_table(hwmgr, pptable,
> &mm_dep_table);
> +       if (ret)
> +               return ret;
>
>         PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries),
>                          "Requested state entry ID is out of range!", @@ 
> -1348,10
> +1762,27 @@ static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr
> *hwmgr, uint32_t i
>         vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
>                                         ATOM_Tonga_VCE_State_Record,
>                                         entries, vce_state_table, i);
> -       sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
> -                                       ATOM_Tonga_SCLK_Dependency_Record,
> -                                       entries, sclk_dep_table,
> -                                       vce_state_record->ucSCLKIndex);
> +       PP_ASSERT_WITH_CODE((vce_state_record->ucSCLKIndex <
> +                            sclk_dep_table->ucNumEntries),
> +                           "Invalid PowerPlay Table!", return -EINVAL);
> +       PP_ASSERT_WITH_CODE((vce_state_record->ucVCEClockIndex <
> +                            mm_dep_table->ucNumEntries),
> +                           "Invalid PowerPlay Table!", return -EINVAL);
> +       PP_ASSERT_WITH_CODE((mclk_dep_table->ucNumEntries != 0),
> +                           "Invalid PowerPlay Table!", return -EINVAL);
> +
> +       if (sclk_dep_table_header->ucRevId < 1)
> +               sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
> +                                               
> ATOM_Tonga_SCLK_Dependency_Record,
> +                                               entries, sclk_dep_table,
> +                                               
> vce_state_record->ucSCLKIndex);
> +       else
> +               polaris_sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
> +                                               
> ATOM_Polaris_SCLK_Dependency_Record,
> +                                               entries,
> +                                               
> (ATOM_Polaris_SCLK_Dependency_Table *)
> +                                               sclk_dep_table_header,
> +
> + vce_state_record->ucSCLKIndex);
>         mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
>                                         ATOM_Tonga_MM_Dependency_Record,
>                                         entries, mm_dep_table, @@ -1360,7 
> +1791,10 @@
> static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr,
> uint32_t i
>
>         vce_state->evclk = le32_to_cpu(mm_dep_record->ulEClk);
>         vce_state->ecclk = le32_to_cpu(mm_dep_record->ulEClk);
> -       vce_state->sclk = le32_to_cpu(sclk_dep_record->ulSclk);
> +       if (sclk_dep_record)
> +               vce_state->sclk = le32_to_cpu(sclk_dep_record->ulSclk);
> +       else
> +               vce_state->sclk =
> + le32_to_cpu(polaris_sclk_dep_record->ulSclk);
>
>         if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries)
>                 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
> --
> 2.47.3
>

Reply via email to