AMD General The series is: Reviewed-by: Tao Zhou <[email protected]>
> -----Original Message----- > From: amd-gfx <[email protected]> On Behalf Of Ce > Sun > Sent: Monday, May 18, 2026 2:59 PM > To: [email protected] > Cc: Zhang, Hawking <[email protected]>; Chai, Thomas > <[email protected]>; Zhou1, Tao <[email protected]>; Yang, Stanley > <[email protected]>; Sun, Ce(Overlord) <[email protected]> > Subject: [PATCH v1 2/2] drm/amdgpu: Fix memory leak of i2s_pdata in ACP > initialization > > Currently, the i2s_pdata structure is dynamically allocated in > acp_hw_init() but never freed in both the error handling path and the > acp_hw_fini() cleanup path, causing a permanent memory leak. > > Signed-off-by: Ce Sun <[email protected]> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 76 ++++++++++++------------- > drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h | 1 + > 2 files changed, 39 insertions(+), 38 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > index 381ef205b0df..c1307dfccf92 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > @@ -228,7 +228,6 @@ static int acp_hw_init(struct amdgpu_ip_block > *ip_block) > u64 acp_base; > u32 val = 0; > u32 count = 0; > - struct i2s_platform_data *i2s_pdata = NULL; > > struct amdgpu_device *adev = ip_block->adev; > > @@ -273,18 +272,18 @@ static int acp_hw_init(struct amdgpu_ip_block > *ip_block) > goto failure; > } > > - i2s_pdata = kcalloc(1, sizeof(struct i2s_platform_data), > GFP_KERNEL); > - if (!i2s_pdata) { > + adev->acp.i2s_pdata = kcalloc(1, sizeof(struct > i2s_platform_data), GFP_KERNEL); > + if (!adev->acp.i2s_pdata) { > r = -ENOMEM; > goto failure; > } > > - i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET | > - DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > - i2s_pdata[0].cap = DWC_I2S_PLAY | DWC_I2S_RECORD; > - i2s_pdata[0].snd_rates = SNDRV_PCM_RATE_8000_96000; > - i2s_pdata[0].i2s_reg_comp1 = > ACP_I2S_COMP1_CAP_REG_OFFSET; > - i2s_pdata[0].i2s_reg_comp2 = > ACP_I2S_COMP2_CAP_REG_OFFSET; > + adev->acp.i2s_pdata[0].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET | > + > DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > + adev->acp.i2s_pdata[0].cap = DWC_I2S_PLAY | > DWC_I2S_RECORD; > + adev->acp.i2s_pdata[0].snd_rates = > SNDRV_PCM_RATE_8000_96000; > + adev->acp.i2s_pdata[0].i2s_reg_comp1 = > ACP_I2S_COMP1_CAP_REG_OFFSET; > + adev->acp.i2s_pdata[0].i2s_reg_comp2 = > ACP_I2S_COMP2_CAP_REG_OFFSET; > > adev->acp.acp_res[0].name = "acp2x_dma"; > adev->acp.acp_res[0].flags = IORESOURCE_MEM; @@ -312,7 > +311,7 @@ static int acp_hw_init(struct amdgpu_ip_block *ip_block) > adev->acp.acp_cell[1].id = 1; > adev->acp.acp_cell[1].num_resources = 1; > adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1]; > - adev->acp.acp_cell[1].platform_data = &i2s_pdata[0]; > + adev->acp.acp_cell[1].platform_data = &adev- > >acp.i2s_pdata[0]; > adev->acp.acp_cell[1].pdata_size = sizeof(struct > i2s_platform_data); > r = mfd_add_devices(adev->acp.parent, 0, adev- > >acp.acp_cell, 2, NULL, 0, NULL); > if (r) > @@ -338,53 +337,53 @@ static int acp_hw_init(struct amdgpu_ip_block > *ip_block) > goto failure; > } > > - i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), > GFP_KERNEL); > - if (!i2s_pdata) { > + adev->acp.i2s_pdata = kcalloc(3, sizeof(struct > i2s_platform_data), GFP_KERNEL); > + if (!adev->acp.i2s_pdata) { > r = -ENOMEM; > goto failure; > } > > switch (adev->asic_type) { > case CHIP_STONEY: > - i2s_pdata[0].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET | > - DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > + adev->acp.i2s_pdata[0].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET | > + > DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > break; > default: > - i2s_pdata[0].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET; > + adev->acp.i2s_pdata[0].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET; > } > - i2s_pdata[0].cap = DWC_I2S_PLAY; > - i2s_pdata[0].snd_rates = SNDRV_PCM_RATE_8000_96000; > - i2s_pdata[0].i2s_reg_comp1 = > ACP_I2S_COMP1_PLAY_REG_OFFSET; > - i2s_pdata[0].i2s_reg_comp2 = > ACP_I2S_COMP2_PLAY_REG_OFFSET; > + adev->acp.i2s_pdata[0].cap = DWC_I2S_PLAY; > + adev->acp.i2s_pdata[0].snd_rates = > SNDRV_PCM_RATE_8000_96000; > + adev->acp.i2s_pdata[0].i2s_reg_comp1 = > ACP_I2S_COMP1_PLAY_REG_OFFSET; > + adev->acp.i2s_pdata[0].i2s_reg_comp2 = > ACP_I2S_COMP2_PLAY_REG_OFFSET; > switch (adev->asic_type) { > case CHIP_STONEY: > - i2s_pdata[1].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET | > - DW_I2S_QUIRK_COMP_PARAM1 | > - DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > + adev->acp.i2s_pdata[1].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET | > + > DW_I2S_QUIRK_COMP_PARAM1 | > + > DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > break; > default: > - i2s_pdata[1].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET | > - DW_I2S_QUIRK_COMP_PARAM1; > + adev->acp.i2s_pdata[1].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET | > + > DW_I2S_QUIRK_COMP_PARAM1; > } > > - i2s_pdata[1].cap = DWC_I2S_RECORD; > - i2s_pdata[1].snd_rates = SNDRV_PCM_RATE_8000_96000; > - i2s_pdata[1].i2s_reg_comp1 = > ACP_I2S_COMP1_CAP_REG_OFFSET; > - i2s_pdata[1].i2s_reg_comp2 = > ACP_I2S_COMP2_CAP_REG_OFFSET; > + adev->acp.i2s_pdata[1].cap = DWC_I2S_RECORD; > + adev->acp.i2s_pdata[1].snd_rates = > SNDRV_PCM_RATE_8000_96000; > + adev->acp.i2s_pdata[1].i2s_reg_comp1 = > ACP_I2S_COMP1_CAP_REG_OFFSET; > + adev->acp.i2s_pdata[1].i2s_reg_comp2 = > ACP_I2S_COMP2_CAP_REG_OFFSET; > > - i2s_pdata[2].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET; > + adev->acp.i2s_pdata[2].quirks = > DW_I2S_QUIRK_COMP_REG_OFFSET; > switch (adev->asic_type) { > case CHIP_STONEY: > - i2s_pdata[2].quirks |= > DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > + adev->acp.i2s_pdata[2].quirks |= > DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > break; > default: > break; > } > > - i2s_pdata[2].cap = DWC_I2S_PLAY | DWC_I2S_RECORD; > - i2s_pdata[2].snd_rates = SNDRV_PCM_RATE_8000_96000; > - i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET; > - i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET; > + adev->acp.i2s_pdata[2].cap = DWC_I2S_PLAY | > DWC_I2S_RECORD; > + adev->acp.i2s_pdata[2].snd_rates = > SNDRV_PCM_RATE_8000_96000; > + adev->acp.i2s_pdata[2].i2s_reg_comp1 = > ACP_BT_COMP1_REG_OFFSET; > + adev->acp.i2s_pdata[2].i2s_reg_comp2 = > ACP_BT_COMP2_REG_OFFSET; > > adev->acp.acp_res[0].name = "acp2x_dma"; > adev->acp.acp_res[0].flags = IORESOURCE_MEM; @@ - > 422,21 +421,21 @@ static int acp_hw_init(struct amdgpu_ip_block *ip_block) > adev->acp.acp_cell[1].id = 1; > adev->acp.acp_cell[1].num_resources = 1; > adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1]; > - adev->acp.acp_cell[1].platform_data = &i2s_pdata[0]; > + adev->acp.acp_cell[1].platform_data = &adev- > >acp.i2s_pdata[0]; > adev->acp.acp_cell[1].pdata_size = sizeof(struct > i2s_platform_data); > > adev->acp.acp_cell[2].name = "designware-i2s"; > adev->acp.acp_cell[2].id = 2; > adev->acp.acp_cell[2].num_resources = 1; > adev->acp.acp_cell[2].resources = &adev->acp.acp_res[2]; > - adev->acp.acp_cell[2].platform_data = &i2s_pdata[1]; > + adev->acp.acp_cell[2].platform_data = &adev- > >acp.i2s_pdata[1]; > adev->acp.acp_cell[2].pdata_size = sizeof(struct > i2s_platform_data); > > adev->acp.acp_cell[3].name = "designware-i2s"; > adev->acp.acp_cell[3].id = 3; > adev->acp.acp_cell[3].num_resources = 1; > adev->acp.acp_cell[3].resources = &adev->acp.acp_res[3]; > - adev->acp.acp_cell[3].platform_data = &i2s_pdata[2]; > + adev->acp.acp_cell[3].platform_data = &adev- > >acp.i2s_pdata[2]; > adev->acp.acp_cell[3].pdata_size = sizeof(struct > i2s_platform_data); > > r = mfd_add_devices(adev->acp.parent, 0, adev- > >acp.acp_cell, ACP_DEVS, NULL, 0, NULL); @@ -493,7 +492,7 @@ static int > acp_hw_init(struct amdgpu_ip_block *ip_block) > return 0; > > failure: > - kfree(i2s_pdata); > + kfree(adev->acp.i2s_pdata); > kfree(adev->acp.acp_res); > kfree(adev->acp.acp_cell); > kfree(adev->acp.acp_genpd); > @@ -558,6 +557,7 @@ static int acp_hw_fini(struct amdgpu_ip_block > *ip_block) > acp_genpd_remove_device); > > mfd_remove_devices(adev->acp.parent); > + kfree(adev->acp.i2s_pdata); > kfree(adev->acp.acp_res); > kfree(adev->acp.acp_genpd); > kfree(adev->acp.acp_cell); > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h > index a288ce25c176..13b48c582314 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h > @@ -35,6 +35,7 @@ struct amdgpu_acp { > struct mfd_cell *acp_cell; > struct resource *acp_res; > struct acp_pm_domain *acp_genpd; > + struct i2s_platform_data *i2s_pdata; > }; > > extern const struct amdgpu_ip_block_version acp_ip_block; > -- > 2.34.1
