drm/amdgpu: fix multiple memory leaks in acp_hw_init
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: Christian König <christian.koenig@amd.com> Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>alistair/sunxi64-5.4-dsi
parent
815fb4c9d7
commit
57be09c6e8
|
@ -189,7 +189,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;
|
||||||
|
|
||||||
|
@ -231,20 +231,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) {
|
||||||
|
@ -341,14 +342,14 @@ 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;
|
||||||
|
|
||||||
for (i = 0; i < ACP_DEVS ; i++) {
|
for (i = 0; i < ACP_DEVS ; i++) {
|
||||||
dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
|
dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +368,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);
|
||||||
}
|
}
|
||||||
|
@ -384,7 +386,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);
|
||||||
}
|
}
|
||||||
|
@ -393,6 +396,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue