Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f488d9fcc84692ca0060b4e16c1c61a8d514cea8
Commit:     f488d9fcc84692ca0060b4e16c1c61a8d514cea8
Parent:     ac3e37412c195f1b48fe06327eb4ad0c072a1222
Author:     Hans-Christian Egtvedt <[EMAIL PROTECTED]>
AuthorDate: Mon Dec 17 17:30:06 2007 +0100
Committer:  Jaroslav Kysela <[EMAIL PROTECTED]>
CommitDate: Thu Jan 31 17:29:39 2008 +0100

    [ALSA] at73c213: replace spinlock in mixer functions with a mutex
    
    This patch fixes the locking bug in the at73c213 SPI sound driver. This bug 
was
    triggered because spinlocks were wrapped around the spi_sync call which 
might
    sleep. The fix was to add a mutex to the sound driver and replace the 
spinlocks
    in the mixer functions with mutex lock/unlock.
    Tested on STK1000/STK1002.
    
    Signed-off-by: Hans-Christian Egtvedt <[EMAIL PROTECTED]>
    Signed-off-by: Takashi Iwai <[EMAIL PROTECTED]>
    Signed-off-by: Jaroslav Kysela <[EMAIL PROTECTED]>
---
 sound/spi/at73c213.c |   34 +++++++++++++++++++---------------
 1 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index bfe17b3..5e8cf9f 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
@@ -76,8 +77,10 @@ struct snd_at73c213 {
        u8                              spi_rbuffer[2];
        /* Image of the SPI registers in AT73C213. */
        u8                              reg_image[18];
-       /* Protect registers against concurrent access. */
+       /* Protect SSC registers against concurrent access. */
        spinlock_t                      lock;
+       /* Protect mixer registers against concurrent access. */
+       struct mutex                    mixer_lock;
 };
 
 #define get_chip(card) ((struct snd_at73c213 *)card->private_data)
@@ -398,7 +401,7 @@ static int snd_at73c213_mono_get(struct snd_kcontrol 
*kcontrol,
        int mask = (kcontrol->private_value >> 16) & 0xff;
        int invert = (kcontrol->private_value >> 24) & 0xff;
 
-       spin_lock_irq(&chip->lock);
+       mutex_lock(&chip->mixer_lock);
 
        ucontrol->value.integer.value[0] =
                (chip->reg_image[reg] >> shift) & mask;
@@ -407,7 +410,7 @@ static int snd_at73c213_mono_get(struct snd_kcontrol 
*kcontrol,
                ucontrol->value.integer.value[0] =
                        mask - ucontrol->value.integer.value[0];
 
-       spin_unlock_irq(&chip->lock);
+       mutex_unlock(&chip->mixer_lock);
 
        return 0;
 }
@@ -428,13 +431,13 @@ static int snd_at73c213_mono_put(struct snd_kcontrol 
*kcontrol,
                val = mask - val;
        val <<= shift;
 
-       spin_lock_irq(&chip->lock);
+       mutex_lock(&chip->mixer_lock);
 
        val = (chip->reg_image[reg] & ~(mask << shift)) | val;
        change = val != chip->reg_image[reg];
        retval = snd_at73c213_write_reg(chip, reg, val);
 
-       spin_unlock_irq(&chip->lock);
+       mutex_unlock(&chip->mixer_lock);
 
        if (retval)
                return retval;
@@ -470,7 +473,7 @@ static int snd_at73c213_stereo_get(struct snd_kcontrol 
*kcontrol,
        int mask = (kcontrol->private_value >> 24) & 0xff;
        int invert = (kcontrol->private_value >> 22) & 1;
 
-       spin_lock_irq(&chip->lock);
+       mutex_lock(&chip->mixer_lock);
 
        ucontrol->value.integer.value[0] =
                (chip->reg_image[left_reg] >> shift_left) & mask;
@@ -484,7 +487,7 @@ static int snd_at73c213_stereo_get(struct snd_kcontrol 
*kcontrol,
                        mask - ucontrol->value.integer.value[1];
        }
 
-       spin_unlock_irq(&chip->lock);
+       mutex_unlock(&chip->mixer_lock);
 
        return 0;
 }
@@ -511,7 +514,7 @@ static int snd_at73c213_stereo_put(struct snd_kcontrol 
*kcontrol,
        val1 <<= shift_left;
        val2 <<= shift_right;
 
-       spin_lock_irq(&chip->lock);
+       mutex_lock(&chip->mixer_lock);
 
        val1 = (chip->reg_image[left_reg] & ~(mask << shift_left)) | val1;
        val2 = (chip->reg_image[right_reg] & ~(mask << shift_right)) | val2;
@@ -519,16 +522,16 @@ static int snd_at73c213_stereo_put(struct snd_kcontrol 
*kcontrol,
                || val2 != chip->reg_image[right_reg];
        retval = snd_at73c213_write_reg(chip, left_reg, val1);
        if (retval) {
-               spin_unlock_irq(&chip->lock);
+               mutex_unlock(&chip->mixer_lock);
                goto out;
        }
        retval = snd_at73c213_write_reg(chip, right_reg, val2);
        if (retval) {
-               spin_unlock_irq(&chip->lock);
+               mutex_unlock(&chip->mixer_lock);
                goto out;
        }
 
-       spin_unlock_irq(&chip->lock);
+       mutex_unlock(&chip->mixer_lock);
 
        return change;
 
@@ -546,7 +549,7 @@ static int snd_at73c213_mono_switch_get(struct snd_kcontrol 
*kcontrol,
        int shift = (kcontrol->private_value >> 8) & 0xff;
        int invert = (kcontrol->private_value >> 24) & 0xff;
 
-       spin_lock_irq(&chip->lock);
+       mutex_lock(&chip->mixer_lock);
 
        ucontrol->value.integer.value[0] =
                (chip->reg_image[reg] >> shift) & 0x01;
@@ -555,7 +558,7 @@ static int snd_at73c213_mono_switch_get(struct snd_kcontrol 
*kcontrol,
                ucontrol->value.integer.value[0] =
                        0x01 - ucontrol->value.integer.value[0];
 
-       spin_unlock_irq(&chip->lock);
+       mutex_unlock(&chip->mixer_lock);
 
        return 0;
 }
@@ -580,14 +583,14 @@ static int snd_at73c213_mono_switch_put(struct 
snd_kcontrol *kcontrol,
                val = mask - val;
        val <<= shift;
 
-       spin_lock_irq(&chip->lock);
+       mutex_lock(&chip->mixer_lock);
 
        val |= (chip->reg_image[reg] & ~(mask << shift));
        change = val != chip->reg_image[reg];
 
        retval = snd_at73c213_write_reg(chip, reg, val);
 
-       spin_unlock_irq(&chip->lock);
+       mutex_unlock(&chip->mixer_lock);
 
        if (retval)
                return retval;
@@ -884,6 +887,7 @@ static int __devinit snd_at73c213_dev_init(struct snd_card 
*card,
                return irq;
 
        spin_lock_init(&chip->lock);
+       mutex_init(&chip->mixer_lock);
        chip->card = card;
        chip->irq = -1;
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to