ALSA: pcmtest: stop timer before buffer is released
authorIvan Orlov <ivan.orlov0322@gmail.com>
Wed, 6 Dec 2023 22:32:11 +0000 (22:32 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 20 Jan 2024 10:51:42 +0000 (11:51 +0100)
[ Upstream commit eb99b1b72a424a79f56c972e0fd7ad01fe93a008 ]

Stop timer in the 'trigger' and 'sync_stop' callbacks since we want
the timer to be stopped before the DMA buffer is released. Otherwise,
it could trigger a kernel panic in some circumstances, for instance
when the DMA buffer is already released but the timer callback is
still running.

Signed-off-by: Ivan Orlov <ivan.orlov0322@gmail.com>
Link: https://lore.kernel.org/r/20231206223211.12761-1-ivan.orlov0322@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
sound/drivers/pcmtest.c

index b59b78a..b8bff55 100644 (file)
@@ -397,7 +397,6 @@ static int snd_pcmtst_pcm_close(struct snd_pcm_substream *substream)
        struct pcmtst_buf_iter *v_iter = substream->runtime->private_data;
 
        timer_shutdown_sync(&v_iter->timer_instance);
-       v_iter->substream = NULL;
        playback_capture_test = !v_iter->is_buf_corrupted;
        kfree(v_iter);
        return 0;
@@ -435,6 +434,7 @@ static int snd_pcmtst_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                // We can't call timer_shutdown_sync here, as it is forbidden to sleep here
                v_iter->suspend = true;
+               timer_delete(&v_iter->timer_instance);
                break;
        }
 
@@ -512,12 +512,22 @@ static int snd_pcmtst_ioctl(struct snd_pcm_substream *substream, unsigned int cm
        return snd_pcm_lib_ioctl(substream, cmd, arg);
 }
 
+static int snd_pcmtst_sync_stop(struct snd_pcm_substream *substream)
+{
+       struct pcmtst_buf_iter *v_iter = substream->runtime->private_data;
+
+       timer_delete_sync(&v_iter->timer_instance);
+
+       return 0;
+}
+
 static const struct snd_pcm_ops snd_pcmtst_playback_ops = {
        .open =         snd_pcmtst_pcm_open,
        .close =        snd_pcmtst_pcm_close,
        .trigger =      snd_pcmtst_pcm_trigger,
        .hw_params =    snd_pcmtst_pcm_hw_params,
        .ioctl =        snd_pcmtst_ioctl,
+       .sync_stop =    snd_pcmtst_sync_stop,
        .hw_free =      snd_pcmtst_pcm_hw_free,
        .prepare =      snd_pcmtst_pcm_prepare,
        .pointer =      snd_pcmtst_pcm_pointer,
@@ -530,6 +540,7 @@ static const struct snd_pcm_ops snd_pcmtst_capture_ops = {
        .hw_params =    snd_pcmtst_pcm_hw_params,
        .hw_free =      snd_pcmtst_pcm_hw_free,
        .ioctl =        snd_pcmtst_ioctl,
+       .sync_stop =    snd_pcmtst_sync_stop,
        .prepare =      snd_pcmtst_pcm_prepare,
        .pointer =      snd_pcmtst_pcm_pointer,
 };