r600_parse_extended_power_table() uses manual kfree() calls for some
early allocation failures, but the freed pointers are left in the
dynamic power-management state. If device teardown later calls
r600_free_extended_power_table(), those stale pointers can be freed
again.

Use the common extended power table cleanup helper for those early
failure paths as well, and clear each pointer after freeing it so
repeated cleanup stays safe.

Signed-off-by: Ruoyu Wang <[email protected]>
---
 drivers/gpu/drm/radeon/r600_dpm.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r600_dpm.c 
b/drivers/gpu/drm/radeon/r600_dpm.c
index 83f1ae31cbdbc..9755e717ca8bb 100644
--- a/drivers/gpu/drm/radeon/r600_dpm.c
+++ b/drivers/gpu/drm/radeon/r600_dpm.c
@@ -932,7 +932,7 @@ int r600_parse_extended_power_table(struct radeon_device 
*rdev)
                        ret = 
r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
                                                               dep_table);
                        if (ret) {
-                               
kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
+                               r600_free_extended_power_table(rdev);
                                return ret;
                        }
                }
@@ -943,8 +943,7 @@ int r600_parse_extended_power_table(struct radeon_device 
*rdev)
                        ret = 
r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
                                                               dep_table);
                        if (ret) {
-                               
kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
-                               
kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);
+                               r600_free_extended_power_table(rdev);
                                return ret;
                        }
                }
@@ -955,9 +954,7 @@ int r600_parse_extended_power_table(struct radeon_device 
*rdev)
                        ret = 
r600_parse_clk_voltage_dep_table(&rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
                                                               dep_table);
                        if (ret) {
-                               
kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
-                               
kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);
-                               
kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries);
+                               r600_free_extended_power_table(rdev);
                                return ret;
                        }
                }
@@ -1296,17 +1293,29 @@ void r600_free_extended_power_table(struct 
radeon_device *rdev)
        struct radeon_dpm_dynamic_state *dyn_state = &rdev->pm.dpm.dyn_state;
 
        kfree(dyn_state->vddc_dependency_on_sclk.entries);
+       dyn_state->vddc_dependency_on_sclk.entries = NULL;
        kfree(dyn_state->vddci_dependency_on_mclk.entries);
+       dyn_state->vddci_dependency_on_mclk.entries = NULL;
        kfree(dyn_state->vddc_dependency_on_mclk.entries);
+       dyn_state->vddc_dependency_on_mclk.entries = NULL;
        kfree(dyn_state->mvdd_dependency_on_mclk.entries);
+       dyn_state->mvdd_dependency_on_mclk.entries = NULL;
        kfree(dyn_state->cac_leakage_table.entries);
+       dyn_state->cac_leakage_table.entries = NULL;
        kfree(dyn_state->phase_shedding_limits_table.entries);
+       dyn_state->phase_shedding_limits_table.entries = NULL;
        kfree(dyn_state->ppm_table);
+       dyn_state->ppm_table = NULL;
        kfree(dyn_state->cac_tdp_table);
+       dyn_state->cac_tdp_table = NULL;
        kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
+       dyn_state->vce_clock_voltage_dependency_table.entries = NULL;
        kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
+       dyn_state->uvd_clock_voltage_dependency_table.entries = NULL;
        kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
+       dyn_state->samu_clock_voltage_dependency_table.entries = NULL;
        kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
+       dyn_state->acp_clock_voltage_dependency_table.entries = NULL;
 }
 
 enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev,
-- 
2.51.0

Reply via email to