ASoC: nau8824: Fix semaphore is released unexpectedly
authorSJLIN0 <SJLIN0@nuvoton.com>
Thu, 15 Sep 2022 01:28:00 +0000 (09:28 +0800)
committerMark Brown <broonie@kernel.org>
Mon, 19 Sep 2022 17:35:23 +0000 (18:35 +0100)
On resuming, we anticipate that the jack is detected before playback
or capture. Therefore, we use semaphore to control the jack detection
done without any bothering. During booting, the driver launches jack
detection and releases the semaphore. However, it doesn't perceive the
maniputation of semaphore is not like resuming procedure. This makes
the semaphore's count value become to 2. There is more than one thread
can enter into the critical section. This may get unexpected situation
and make some chaos.

Signed-off-by: SJLIN0 <SJLIN0@nuvoton.com>
Signed-off-by: Wallace Lin <savagecin@gmail.com>
Link: https://lore.kernel.org/r/20220915012800.825196-1-SJLIN0@nuvoton.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/nau8824.c
sound/soc/codecs/nau8824.h

index 1559645..4f19fd9 100644 (file)
@@ -901,7 +901,10 @@ static void nau8824_jdet_work(struct work_struct *work)
                NAU8824_IRQ_KEY_RELEASE_DIS |
                NAU8824_IRQ_KEY_SHORT_PRESS_DIS, 0);
 
-       nau8824_sema_release(nau8824);
+       if (nau8824->resume_lock) {
+               nau8824_sema_release(nau8824);
+               nau8824->resume_lock = false;
+       }
 }
 
 static void nau8824_setup_auto_irq(struct nau8824 *nau8824)
@@ -966,7 +969,10 @@ static irqreturn_t nau8824_interrupt(int irq, void *data)
                /* release semaphore held after resume,
                 * and cancel jack detection
                 */
-               nau8824_sema_release(nau8824);
+               if (nau8824->resume_lock) {
+                       nau8824_sema_release(nau8824);
+                       nau8824->resume_lock = false;
+               }
                cancel_work_sync(&nau8824->jdet_work);
        } else if (active_irq & NAU8824_KEY_SHORT_PRESS_IRQ) {
                int key_status, button_pressed;
@@ -1524,6 +1530,7 @@ static int __maybe_unused nau8824_suspend(struct snd_soc_component *component)
 static int __maybe_unused nau8824_resume(struct snd_soc_component *component)
 {
        struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
+       int ret;
 
        regcache_cache_only(nau8824->regmap, false);
        regcache_sync(nau8824->regmap);
@@ -1531,7 +1538,10 @@ static int __maybe_unused nau8824_resume(struct snd_soc_component *component)
                /* Hold semaphore to postpone playback happening
                 * until jack detection done.
                 */
-               nau8824_sema_acquire(nau8824, 0);
+               nau8824->resume_lock = true;
+               ret = nau8824_sema_acquire(nau8824, 0);
+               if (ret)
+                       nau8824->resume_lock = false;
                enable_irq(nau8824->irq);
        }
 
@@ -1940,6 +1950,7 @@ static int nau8824_i2c_probe(struct i2c_client *i2c)
        nau8824->regmap = devm_regmap_init_i2c(i2c, &nau8824_regmap_config);
        if (IS_ERR(nau8824->regmap))
                return PTR_ERR(nau8824->regmap);
+       nau8824->resume_lock = false;
        nau8824->dev = dev;
        nau8824->irq = i2c->irq;
        sema_init(&nau8824->jd_sem, 1);
index de4bae8..5fcfc43 100644 (file)
@@ -436,6 +436,7 @@ struct nau8824 {
        struct semaphore jd_sem;
        int fs;
        int irq;
+       int resume_lock;
        int micbias_voltage;
        int vref_impedance;
        int jkdet_polarity;