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.nawro...@samsung.com>
---
 sound/soc/samsung/i2s.c |   18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 2bac719..20cc51f 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -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";
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to