Skip to content

Commit 02299d9

Browse files
morimotobroonie
authored andcommitted
ASoC: rsnd: spin lock for interrupt handler
Renesas R-Car driver interrupt handler was not locked before. But now, SSI/SRC interrupt handler calls restart function which should be called under spin lock. Below error might happen witout this patch. Unable to handle kernel NULL pointer dereference at virtual address 00000048 pgd = edfac000 [00000048] *pgd=6e0f0831, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] SMP ARM CPU: 0 PID: 2009 Comm: aplay Not tainted 4.1.0-rc2-dirty #4 Hardware name: Generic R8A7790 (Flattened Device Tree) task: eeac9040 ti: eebe8000 task.ti: eebe8000 PC is at rsnd_get_adinr+0x28/0x60 LR is at rsnd_src_ssiu_start+0xdc/0x19c pc : [<c0409790>] lr : [<c040c068>] psr: a0000193 sp : eebe9e58 ip : eebe9e68 fp : eebe9e64 r10: c06ed9d0 r9 : ee919d10 r8 : 00000001 r7 : 00000001 r6 : ee1cb090 r5 : 00000000 r4 : edcaa418 r3 : 00000000 r2 : eea8ce00 r1 : 80000193 r0 : edcaa418 ... Reported-by: Cao Minh Hiep <cm-hiep@jinso.co.jp> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Keita Kobayashi <keita.kobayashi.ym@renesas.com> Tested by: Cao Minh Hiep <cm-hiep@jinso.co.jp> Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent e8a07d6 commit 02299d9

File tree

4 files changed

+30
-10
lines changed

4 files changed

+30
-10
lines changed

sound/soc/sh/rcar/core.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ void rsnd_mod_quit(struct rsnd_mod *mod)
170170
clk_unprepare(mod->clk);
171171
}
172172

173+
int rsnd_mod_is_working(struct rsnd_mod *mod)
174+
{
175+
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
176+
177+
/* see rsnd_dai_stream_init/quit() */
178+
return !!io->substream;
179+
}
180+
173181
/*
174182
* settting function
175183
*/
@@ -362,7 +370,7 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
362370
int ret;
363371
unsigned long flags;
364372

365-
rsnd_lock(priv, flags);
373+
spin_lock_irqsave(&priv->lock, flags);
366374

367375
switch (cmd) {
368376
case SNDRV_PCM_TRIGGER_START:
@@ -400,7 +408,7 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
400408
}
401409

402410
dai_trigger_end:
403-
rsnd_unlock(priv, flags);
411+
spin_unlock_irqrestore(&priv->lock, flags);
404412

405413
return ret;
406414
}

sound/soc/sh/rcar/rsnd.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ int rsnd_mod_init(struct rsnd_mod *mod,
303303
int id);
304304
void rsnd_mod_quit(struct rsnd_mod *mod);
305305
char *rsnd_mod_name(struct rsnd_mod *mod);
306+
int rsnd_mod_is_working(struct rsnd_mod *mod);
306307
struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod);
307308

308309
/*
@@ -449,8 +450,6 @@ struct rsnd_priv {
449450
#define rsnd_priv_to_pdev(priv) ((priv)->pdev)
450451
#define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev))
451452
#define rsnd_priv_to_info(priv) ((priv)->info)
452-
#define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
453-
#define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)
454453

455454
/*
456455
* rsnd_kctrl

sound/soc/sh/rcar/src.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,13 @@ static int _rsnd_src_stop_gen2(struct rsnd_mod *mod)
673673
static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data)
674674
{
675675
struct rsnd_mod *mod = data;
676-
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
676+
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
677+
678+
spin_lock(&priv->lock);
677679

678-
if (!io)
679-
return IRQ_NONE;
680+
/* ignore all cases if not working */
681+
if (!rsnd_mod_is_working(mod))
682+
goto rsnd_src_interrupt_gen2_out;
680683

681684
if (rsnd_src_error_record_gen2(mod)) {
682685
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
@@ -692,6 +695,8 @@ static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data)
692695
else
693696
dev_warn(dev, "no more SRC restart\n");
694697
}
698+
rsnd_src_interrupt_gen2_out:
699+
spin_unlock(&priv->lock);
695700

696701
return IRQ_HANDLED;
697702
}

sound/soc/sh/rcar/ssi.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,15 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
423423
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
424424
struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
425425
int is_dma = rsnd_ssi_is_dma_mode(mod);
426-
u32 status = rsnd_mod_read(mod, SSISR);
426+
u32 status;
427+
428+
spin_lock(&priv->lock);
427429

428-
if (!io)
429-
return IRQ_NONE;
430+
/* ignore all cases if not working */
431+
if (!rsnd_mod_is_working(mod))
432+
goto rsnd_ssi_interrupt_out;
433+
434+
status = rsnd_mod_read(mod, SSISR);
430435

431436
/* PIO only */
432437
if (!is_dma && (status & DIRQ)) {
@@ -466,6 +471,9 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
466471

467472
rsnd_ssi_record_error(ssi, status);
468473

474+
rsnd_ssi_interrupt_out:
475+
spin_unlock(&priv->lock);
476+
469477
return IRQ_HANDLED;
470478
}
471479

0 commit comments

Comments
 (0)