Commit e15f8a9b authored by Navid Emamdoost's avatar Navid Emamdoost Committed by Greg Kroah-Hartman

drm/amdgpu: fix multiple memory leaks in acp_hw_init

[ Upstream commit 57be09c6 ]

In acp_hw_init there are some allocations that needs to be released in
case of failure:

1- adev->acp.acp_genpd should be released if any allocation attemp for
adev->acp.acp_cell, adev->acp.acp_res or i2s_pdata fails.
2- all of those allocations should be released if
mfd_add_hotplug_devices or pm_genpd_add_device fail.
3- Release is needed in case of time out values expire.
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarNavid Emamdoost <navid.emamdoost@gmail.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent c57c2135
...@@ -276,7 +276,7 @@ static int acp_hw_init(void *handle) ...@@ -276,7 +276,7 @@ static int acp_hw_init(void *handle)
u32 val = 0; u32 val = 0;
u32 count = 0; u32 count = 0;
struct device *dev; struct device *dev;
struct i2s_platform_data *i2s_pdata; struct i2s_platform_data *i2s_pdata = NULL;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
...@@ -317,20 +317,21 @@ static int acp_hw_init(void *handle) ...@@ -317,20 +317,21 @@ static int acp_hw_init(void *handle)
adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell), adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell),
GFP_KERNEL); GFP_KERNEL);
if (adev->acp.acp_cell == NULL) if (adev->acp.acp_cell == NULL) {
return -ENOMEM; r = -ENOMEM;
goto failure;
}
adev->acp.acp_res = kcalloc(5, sizeof(struct resource), GFP_KERNEL); adev->acp.acp_res = kcalloc(5, sizeof(struct resource), GFP_KERNEL);
if (adev->acp.acp_res == NULL) { if (adev->acp.acp_res == NULL) {
kfree(adev->acp.acp_cell); r = -ENOMEM;
return -ENOMEM; goto failure;
} }
i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), GFP_KERNEL); i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), GFP_KERNEL);
if (i2s_pdata == NULL) { if (i2s_pdata == NULL) {
kfree(adev->acp.acp_res); r = -ENOMEM;
kfree(adev->acp.acp_cell); goto failure;
return -ENOMEM;
} }
switch (adev->asic_type) { switch (adev->asic_type) {
...@@ -427,7 +428,7 @@ static int acp_hw_init(void *handle) ...@@ -427,7 +428,7 @@ static int acp_hw_init(void *handle)
r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell,
ACP_DEVS); ACP_DEVS);
if (r) if (r)
return r; goto failure;
if (adev->asic_type != CHIP_STONEY) { if (adev->asic_type != CHIP_STONEY) {
for (i = 0; i < ACP_DEVS ; i++) { for (i = 0; i < ACP_DEVS ; i++) {
...@@ -435,7 +436,7 @@ static int acp_hw_init(void *handle) ...@@ -435,7 +436,7 @@ static int acp_hw_init(void *handle)
r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev); r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev);
if (r) { if (r) {
dev_err(dev, "Failed to add dev to genpd\n"); dev_err(dev, "Failed to add dev to genpd\n");
return r; goto failure;
} }
} }
} }
...@@ -454,7 +455,8 @@ static int acp_hw_init(void *handle) ...@@ -454,7 +455,8 @@ static int acp_hw_init(void *handle)
break; break;
if (--count == 0) { if (--count == 0) {
dev_err(&adev->pdev->dev, "Failed to reset ACP\n"); dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
return -ETIMEDOUT; r = -ETIMEDOUT;
goto failure;
} }
udelay(100); udelay(100);
} }
...@@ -471,7 +473,8 @@ static int acp_hw_init(void *handle) ...@@ -471,7 +473,8 @@ static int acp_hw_init(void *handle)
break; break;
if (--count == 0) { if (--count == 0) {
dev_err(&adev->pdev->dev, "Failed to reset ACP\n"); dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
return -ETIMEDOUT; r = -ETIMEDOUT;
goto failure;
} }
udelay(100); udelay(100);
} }
...@@ -480,6 +483,13 @@ static int acp_hw_init(void *handle) ...@@ -480,6 +483,13 @@ static int acp_hw_init(void *handle)
val &= ~ACP_SOFT_RESET__SoftResetAud_MASK; val &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val); cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
return 0; return 0;
failure:
kfree(i2s_pdata);
kfree(adev->acp.acp_res);
kfree(adev->acp.acp_cell);
kfree(adev->acp.acp_genpd);
return r;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment