Pepper: Spotfix for write silence
David DSH [Fri, 18 Nov 2016 18:28:49 +0000 (10:28 -0800)]
Have the timer grab the lock to prevent task accessing the pcm_buffer to
get bad pointer.

Bug 1842498

Change-Id: I7f9691ceceeb8e7bb8dc00bd68617b91c4275c30
Signed-off-by: David DSH <ddastoussthi@nvidia.com>
Reviewed-on: http://git-master/r/1256442
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>

drivers/hid/hid-atv-jarvis.c

index ed3cc39..eeb14e9 100644 (file)
@@ -961,13 +961,6 @@ static uint snd_atvr_decode_from_fifo(struct snd_pcm_substream *substream)
 {
        uint i;
        struct snd_atvr *atvr_snd = snd_pcm_substream_chip(substream);
-
-       if (!spin_trylock(&atvr_snd->s_substream_lock)) {
-               pr_info("%s: trylock fail\n", __func__);
-               return 0;
-
-       }
-
        uint readable = atomic_fifo_available_to_read(
                &atvr_snd->fifo_controller);
        for (i = 0; i < readable; i++) {
@@ -989,7 +982,6 @@ static uint snd_atvr_decode_from_fifo(struct snd_pcm_substream *substream)
 
                atomic_fifo_advance_read(&atvr_snd->fifo_controller, 1);
        }
-       spin_unlock(&atvr_snd->s_substream_lock);
 
        return readable;
 }
@@ -1022,6 +1014,12 @@ static void snd_atvr_timer_callback(unsigned long data)
        smp_rmb();
        if (!atvr_snd->timer_enabled)
                return;
+
+       if (!spin_trylock(&atvr_snd->s_substream_lock)) {
+               pr_info("%s: trylock fail\n", __func__);
+               goto lock_err;
+       }
+
        atvr_snd->timer_callback_count++;
 
        switch (atvr_snd->timer_state) {
@@ -1068,11 +1066,14 @@ static void snd_atvr_timer_callback(unsigned long data)
                                atvr_snd,
                                atvr_snd->write_index,
                                frames_to_silence);
+               spin_unlock(&atvr_snd->s_substream_lock);
                /* This can cause snd_atvr_pcm_trigger() to be called, which
                 * may try to stop the timer. */
                snd_atvr_handle_frame_advance(substream, frames_to_silence);
-       }
+       } else
+               spin_unlock(&atvr_snd->s_substream_lock);
 
+lock_err:
        smp_rmb();
        if (atvr_snd->timer_enabled)
                snd_atvr_schedule_timer(substream);