ASoC: samsung: i2s: Add spinlock in place of local_irq_* calls
It seems this driver hasn't been updated for SMP, as local_irq_save/ local_irq_restore don't provide proper protection of read/modify/write of the device's registers on such systems. Introduce a spinlock serializing access to the register region, it will be helpful later when I2SMOD, I2SPSR registers are made also accessible through the clk API. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
872c26bd80
commit
f36705366a
1 changed files with 13 additions and 5 deletions
|
@ -94,6 +94,10 @@ struct i2s_dai {
|
|||
u32 suspend_i2scon;
|
||||
u32 suspend_i2spsr;
|
||||
const struct samsung_i2s_variant_regs *variant_regs;
|
||||
|
||||
/* Spinlock protecting access to the device's registers */
|
||||
spinlock_t spinlock;
|
||||
spinlock_t *lock;
|
||||
};
|
||||
|
||||
/* Lock for cross i/f checks */
|
||||
|
@ -867,10 +871,10 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
|
|||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
local_irq_save(flags);
|
||||
spin_lock_irqsave(i2s->lock, flags);
|
||||
|
||||
if (config_setup(i2s)) {
|
||||
local_irq_restore(flags);
|
||||
spin_unlock_irqrestore(i2s->lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -879,12 +883,12 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
|
|||
else
|
||||
i2s_txctrl(i2s, 1);
|
||||
|
||||
local_irq_restore(flags);
|
||||
spin_unlock_irqrestore(i2s->lock, flags);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
local_irq_save(flags);
|
||||
spin_lock_irqsave(i2s->lock, flags);
|
||||
|
||||
if (capture) {
|
||||
i2s_rxctrl(i2s, 0);
|
||||
|
@ -894,7 +898,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
|
|||
i2s_fifo(i2s, FIC_TXFLUSH);
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
spin_unlock_irqrestore(i2s->lock, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1157,6 +1161,9 @@ static int samsung_i2s_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_init(&pri_dai->spinlock);
|
||||
pri_dai->lock = &pri_dai->spinlock;
|
||||
|
||||
if (!np) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!res) {
|
||||
|
@ -1234,6 +1241,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sec_dai->lock = &pri_dai->spinlock;
|
||||
sec_dai->variant_regs = pri_dai->variant_regs;
|
||||
sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
|
||||
sec_dai->dma_playback.ch_name = "tx-sec";
|
||||
|
|
Loading…
Reference in a new issue