mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
ASoC: cs35l56: Fix some cleanup memory leaks
Richard Fitzgerald <rf@opensource.cirrus.com> says: These are for-next. They are not urgent because it only leaks memory if the driver failed to component_probe or is removed, which wouldn't happen in normal use. This series fixes some memory leaks: - The memory allocated by wm_adsp/cs_dsp was not freed. - If component_probe() failed it didn't clean up. The addition of this cleanup in patch #3 exposes an existing possible double-free of the debugfs, which is fixed in patch #2. Link: https://patch.msgid.link/20260610093432.557375-1-rf@opensource.cirrus.com
This commit is contained in:
commit
3fd01f2e05
|
|
@ -1293,6 +1293,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_create_cal_debugfs, "SND_SOC_CS35L56_SHARED");
|
|||
void cs35l56_remove_cal_debugfs(struct cs35l56_base *cs35l56_base)
|
||||
{
|
||||
debugfs_remove_recursive(cs35l56_base->debugfs);
|
||||
cs35l56_base->debugfs = ERR_PTR(-ENOENT);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cs35l56_remove_cal_debugfs, "SND_SOC_CS35L56_SHARED");
|
||||
|
||||
|
|
|
|||
|
|
@ -1359,7 +1359,7 @@ VISIBLE_IF_KUNIT int cs35l56_set_fw_name(struct snd_soc_component *component)
|
|||
}
|
||||
EXPORT_SYMBOL_IF_KUNIT(cs35l56_set_fw_name);
|
||||
|
||||
static int cs35l56_component_probe(struct snd_soc_component *component)
|
||||
static int _cs35l56_component_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
|
||||
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
|
||||
|
|
@ -1459,6 +1459,17 @@ static void cs35l56_component_remove(struct snd_soc_component *component)
|
|||
cs35l56->component = NULL;
|
||||
}
|
||||
|
||||
static int cs35l56_component_probe(struct snd_soc_component *component)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = _cs35l56_component_probe(component);
|
||||
if (ret < 0)
|
||||
cs35l56_component_remove(component);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cs35l56_set_bias_level(struct snd_soc_component *component,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
|
|
@ -1997,11 +2008,14 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
|
|||
cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
|
||||
if (ret < 0) {
|
||||
dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n");
|
||||
goto err;
|
||||
goto err_remove_wm_adsp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_wm_adsp:
|
||||
wm_adsp2_remove(&cs35l56->dsp);
|
||||
|
||||
err:
|
||||
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
|
||||
regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
|
||||
|
|
@ -2110,6 +2124,8 @@ void cs35l56_remove(struct cs35l56_private *cs35l56)
|
|||
|
||||
destroy_workqueue(cs35l56->dsp_wq);
|
||||
|
||||
wm_adsp2_remove(&cs35l56->dsp);
|
||||
|
||||
pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
|
||||
pm_runtime_suspend(cs35l56->base.dev);
|
||||
pm_runtime_disable(cs35l56->base.dev);
|
||||
|
|
|
|||
|
|
@ -679,6 +679,9 @@ static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
|
|||
{
|
||||
struct wm_coeff_ctl *ctl = cs_ctl->priv;
|
||||
|
||||
if (!ctl)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&ctl->work);
|
||||
|
||||
kfree(ctl->name);
|
||||
|
|
@ -1167,7 +1170,14 @@ EXPORT_SYMBOL_GPL(wm_adsp2_component_probe);
|
|||
|
||||
int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component)
|
||||
{
|
||||
if (!dsp)
|
||||
return 0;
|
||||
|
||||
if (!dsp->component)
|
||||
return 0;
|
||||
|
||||
cs_dsp_cleanup_debugfs(&dsp->cs_dsp);
|
||||
dsp->component = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,14 +181,14 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
|
|||
}
|
||||
|
||||
dsp_msg = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_msg_write);
|
||||
if (dsp_msg) {
|
||||
if (dsp_msg == ACP_DSP_MSG_SET) {
|
||||
snd_sof_ipc_msgs_rx(sdev);
|
||||
acp_dsp_ipc_host_done(sdev);
|
||||
ipc_irq = true;
|
||||
}
|
||||
|
||||
dsp_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write);
|
||||
if (dsp_ack) {
|
||||
if (dsp_ack == ACP_DSP_ACK_SET) {
|
||||
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
|
||||
guard(spinlock_irq)(&sdev->ipc_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -377,6 +377,33 @@ void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src,
|
|||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, reg_offset + i, src[j]);
|
||||
}
|
||||
|
||||
static int acp_init_scratch_mem_ipc_flags(struct snd_sof_dev *sdev)
|
||||
{
|
||||
u32 dsp_msg_write, dsp_ack_write, host_msg_write, host_ack_write;
|
||||
|
||||
dsp_msg_write = sdev->debug_box.offset +
|
||||
offsetof(struct scratch_ipc_conf, sof_dsp_msg_write);
|
||||
dsp_ack_write = sdev->debug_box.offset +
|
||||
offsetof(struct scratch_ipc_conf, sof_dsp_ack_write);
|
||||
host_msg_write = sdev->debug_box.offset +
|
||||
offsetof(struct scratch_ipc_conf, sof_host_msg_write);
|
||||
host_ack_write = sdev->debug_box.offset +
|
||||
offsetof(struct scratch_ipc_conf, sof_host_ack_write);
|
||||
/* Initialize host message write flag */
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + host_msg_write, 0);
|
||||
|
||||
/* Initialize host ack write flag */
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + host_ack_write, 0);
|
||||
|
||||
/* Initialize DSP message write flag */
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_msg_write, 0);
|
||||
|
||||
/* Initialize DSP ack write flag */
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acp_memory_init(struct snd_sof_dev *sdev)
|
||||
{
|
||||
struct acp_dev_data *adata = sdev->pdata->hw_pdata;
|
||||
|
|
@ -384,6 +411,7 @@ static int acp_memory_init(struct snd_sof_dev *sdev)
|
|||
|
||||
snd_sof_dsp_update_bits(sdev, ACP_DSP_BAR, desc->dsp_intr_base + DSP_SW_INTR_CNTL_OFFSET,
|
||||
ACP_DSP_INTR_EN_MASK, ACP_DSP_INTR_EN_MASK);
|
||||
acp_init_scratch_mem_ipc_flags(sdev);
|
||||
init_dma_descriptor(adata);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,8 @@
|
|||
#define ACP_SRAM_PAGE_COUNT 128
|
||||
#define ACP6X_SDW_MAX_MANAGER_COUNT 2
|
||||
#define ACP70_SDW_MAX_MANAGER_COUNT ACP6X_SDW_MAX_MANAGER_COUNT
|
||||
#define ACP_DSP_MSG_SET 1
|
||||
#define ACP_DSP_ACK_SET 1
|
||||
|
||||
enum clock_source {
|
||||
ACP_CLOCK_96M = 0,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user