DF-4117 / fix.diff
Fix for DF-4117 (cypress-side halves): free eg_pi on cypress_dpm_init early failures instead of leaking it, and make cypress_dpm_fini idempotent (NULL ps/priv after kfree so a fini after a failed init cannot double-free). MUST be combined with the shared rv7xx_parse_power_table error-path fix (free ps_priv[0..i-1], NULL rdev->pm.dpm.ps at rv770_dpm.c:2306-2310) — identical to the DF-4023/DF-3973 family fix, reproduced at the bottom of this file. --- a/sys/dev/drm/radeon/cypress_dpm.c +++ b/sys/dev/drm/radeon/cypress_dpm.c @@ -2044,12 +2044,18 @@ pi->max_vddc_in_table = 0; ret = r600_get_platform_caps(rdev); - if (ret) + if (ret) { + kfree(eg_pi); + rdev->pm.dpm.priv = NULL; return ret; + } ret = rv7xx_parse_power_table(rdev); - if (ret) + if (ret) { + kfree(eg_pi); + rdev->pm.dpm.priv = NULL; return ret; + } if (rdev->pm.dpm.voltage_response_time == 0) rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT; @@ -2151,7 +2157,9 @@ kfree(rdev->pm.dpm.ps[i].ps_priv); } kfree(rdev->pm.dpm.ps); + rdev->pm.dpm.ps = NULL; kfree(rdev->pm.dpm.priv); + rdev->pm.dpm.priv = NULL; } bool cypress_dpm_vblank_too_short(struct radeon_device *rdev) Shared-site half of the DF-4117 fix (rv7xx_parse_power_table error path, serves rv770/btc/cypress dispatches): --- a/sys/dev/drm/radeon/rv770_dpm.c +++ b/sys/dev/drm/radeon/rv770_dpm.c @@ -2305,7 +2305,10 @@ u8 *idx; ps = kzalloc(sizeof(struct rv7xx_ps), GFP_KERNEL); if (ps == NULL) { + while (i > 0) + kfree(rdev->pm.dpm.ps[--i].ps_priv); kfree(rdev->pm.dpm.ps); + rdev->pm.dpm.ps = NULL; return -ENOMEM; } rdev->pm.dpm.ps[i].ps_priv = ps; |