mirror of
https://github.com/torvalds/linux.git
synced 2024-11-13 23:51:39 +00:00
ASoC: Intel: avs: Update stream status in a separate thread
Function snd_pcm_period_elapsed() is part of sequence servicing HDAudio stream IRQs. It's called under Global Interrupt Enable (GIE) disabled - no HDAudio interrupts will be raised. At the same time, the function may end up calling __snd_pcm_xrun() or snd_pcm_drain_done(). On the avs-driver side, this translates to IPCs and as GIE is disabled, these will never complete successfully. Improve system stability by scheduling stream-IRQ handling in a separate thread. Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://patch.msgid.link/20241008083758.756578-1-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
8380dbf1b9
commit
0dbb186c35
@ -28,6 +28,7 @@
|
||||
#include "avs.h"
|
||||
#include "cldma.h"
|
||||
#include "messages.h"
|
||||
#include "pcm.h"
|
||||
|
||||
static u32 pgctl_mask = AZX_PGCTL_LSRMD_MASK;
|
||||
module_param(pgctl_mask, uint, 0444);
|
||||
@ -247,7 +248,7 @@ static void hdac_stream_update_pos(struct hdac_stream *stream, u64 buffer_size)
|
||||
static void hdac_update_stream(struct hdac_bus *bus, struct hdac_stream *stream)
|
||||
{
|
||||
if (stream->substream) {
|
||||
snd_pcm_period_elapsed(stream->substream);
|
||||
avs_period_elapsed(stream->substream);
|
||||
} else if (stream->cstream) {
|
||||
u64 buffer_size = stream->cstream->runtime->buffer_size;
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <sound/soc-component.h>
|
||||
#include "avs.h"
|
||||
#include "path.h"
|
||||
#include "pcm.h"
|
||||
#include "topology.h"
|
||||
#include "../../codecs/hda.h"
|
||||
|
||||
@ -30,6 +31,7 @@ struct avs_dma_data {
|
||||
struct hdac_ext_stream *host_stream;
|
||||
};
|
||||
|
||||
struct work_struct period_elapsed_work;
|
||||
struct snd_pcm_substream *substream;
|
||||
};
|
||||
|
||||
@ -56,6 +58,22 @@ avs_dai_find_path_template(struct snd_soc_dai *dai, bool is_fe, int direction)
|
||||
return dw->priv;
|
||||
}
|
||||
|
||||
static void avs_period_elapsed_work(struct work_struct *work)
|
||||
{
|
||||
struct avs_dma_data *data = container_of(work, struct avs_dma_data, period_elapsed_work);
|
||||
|
||||
snd_pcm_period_elapsed(data->substream);
|
||||
}
|
||||
|
||||
void avs_period_elapsed(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||
struct avs_dma_data *data = snd_soc_dai_get_dma_data(dai, substream);
|
||||
|
||||
schedule_work(&data->period_elapsed_work);
|
||||
}
|
||||
|
||||
static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
@ -77,6 +95,7 @@ static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_d
|
||||
data->substream = substream;
|
||||
data->template = template;
|
||||
data->adev = adev;
|
||||
INIT_WORK(&data->period_elapsed_work, avs_period_elapsed_work);
|
||||
snd_soc_dai_set_dma_data(dai, substream, data);
|
||||
|
||||
if (rtd->dai_link->ignore_suspend)
|
||||
|
16
sound/soc/intel/avs/pcm.h
Normal file
16
sound/soc/intel/avs/pcm.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright(c) 2024 Intel Corporation
|
||||
*
|
||||
* Authors: Cezary Rojewski <cezary.rojewski@intel.com>
|
||||
* Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_SOC_INTEL_AVS_PCM_H
|
||||
#define __SOUND_SOC_INTEL_AVS_PCM_H
|
||||
|
||||
#include <sound/pcm.h>
|
||||
|
||||
void avs_period_elapsed(struct snd_pcm_substream *substream);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user