mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-04 14:56:48 +07:00
ASoC: rsnd: don't call snd_pcm_period_elapsed() under spin lock
'a9e1ac1a9e4585b5("ASoC: rsnd: spin lock for interrupt handler")' added spin lock under interrupt handler to solve HW restart issue. OTOH, current rsnd driver calls snd_pcm_period_elapsed() from rsnd_dai_pointer_update(). but, it will be called under spin lock if SSI was PIO mode. If it was called under spin lock, it will call snd_pcm_update_state() -> snd_pcm_drain_done(). Then, it calls rsnd_soc_dai_trigger() and will be dead-lock. This patch doesn't call rsnd_dai_pointer_update() under spin lock Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Keita Kobayashi <keita.kobayashi.ym@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
12927a8f80
commit
75defee0f1
@ -302,7 +302,7 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional)
|
||||
return pos;
|
||||
}
|
||||
|
||||
void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
|
||||
bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
|
||||
{
|
||||
io->byte_pos += byte;
|
||||
|
||||
@ -319,8 +319,24 @@ void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte)
|
||||
io->next_period_byte = io->byte_per_period;
|
||||
}
|
||||
|
||||
snd_pcm_period_elapsed(substream);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io)
|
||||
{
|
||||
struct snd_pcm_substream *substream = io->substream;
|
||||
|
||||
/*
|
||||
* this function should be called...
|
||||
*
|
||||
* - if rsnd_dai_pointer_update() returns true
|
||||
* - without spin lock
|
||||
*/
|
||||
|
||||
snd_pcm_period_elapsed(substream);
|
||||
}
|
||||
|
||||
static void rsnd_dai_stream_init(struct rsnd_dai_stream *io,
|
||||
|
@ -36,7 +36,10 @@ static void rsnd_dmaen_complete(void *data)
|
||||
{
|
||||
struct rsnd_dma *dma = (struct rsnd_dma *)data;
|
||||
struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
|
||||
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
|
||||
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
|
||||
bool elapsed = false;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Renesas sound Gen1 needs 1 DMAC,
|
||||
@ -49,8 +52,14 @@ static void rsnd_dmaen_complete(void *data)
|
||||
* rsnd_dai_pointer_update() will be called twice,
|
||||
* ant it will breaks io->byte_pos
|
||||
*/
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
rsnd_dai_pointer_update(io, io->byte_per_period);
|
||||
elapsed = rsnd_dai_pointer_update(io, io->byte_per_period);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
if (elapsed)
|
||||
rsnd_dai_period_elapsed(io);
|
||||
}
|
||||
|
||||
static void rsnd_dmaen_stop(struct rsnd_dma *dma)
|
||||
|
@ -355,7 +355,8 @@ struct rsnd_dai {
|
||||
|
||||
struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id);
|
||||
|
||||
void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
|
||||
bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
|
||||
void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io);
|
||||
int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
|
||||
|
||||
/*
|
||||
|
@ -426,6 +426,7 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
|
||||
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
|
||||
int is_dma = rsnd_ssi_is_dma_mode(mod);
|
||||
u32 status;
|
||||
bool elapsed = false;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
@ -451,7 +452,7 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
|
||||
else
|
||||
*buf = rsnd_mod_read(mod, SSIRDR);
|
||||
|
||||
rsnd_dai_pointer_update(io, sizeof(*buf));
|
||||
elapsed = rsnd_dai_pointer_update(io, sizeof(*buf));
|
||||
}
|
||||
|
||||
/* DMA only */
|
||||
@ -476,6 +477,9 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
|
||||
rsnd_ssi_interrupt_out:
|
||||
spin_unlock(&priv->lock);
|
||||
|
||||
if (elapsed)
|
||||
rsnd_dai_period_elapsed(io);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user