From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932682Ab2JJXGp (ORCPT ); Wed, 10 Oct 2012 19:06:45 -0400 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:50635 "EHLO out1-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932645Ab2JJXD3 (ORCPT ); Wed, 10 Oct 2012 19:03:29 -0400 X-Sasl-enc: 0ASeLERdKbg5HeMmeYfbVdCC3MxnYPdPa2rjaTH/yxdW 1349910207 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Greg Kroah-Hartman , alan@lxorguk.ukuu.org.uk, Omair Mohammed Abdullah , Vinod Koul , Takashi Iwai Subject: [ 067/122] ALSA: aloop - add locking to timer access Date: Thu, 11 Oct 2012 07:53:53 +0900 Message-Id: <20121010225350.196951543@linuxfoundation.org> X-Mailer: git-send-email 1.8.0.rc0.18.gf84667d In-Reply-To: <20121010225337.989799482@linuxfoundation.org> References: <20121010225337.989799482@linuxfoundation.org> User-Agent: quilt/0.60-2.1.2 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.6-stable review patch. If anyone has any objections, please let me know. ------------------ From: Omair Mohammed Abdullah commit d4f1e48bd11e3df6a26811f7a1f06c4225d92f7d upstream. When the loopback timer handler is running, calling del_timer() (for STOP trigger) will not wait for the handler to complete before deactivating the timer. The timer gets rescheduled in the handler as usual. Then a subsequent START trigger will try to start the timer using add_timer() with a timer pending leading to a kernel panic. Serialize the calls to add_timer() and del_timer() using a spin lock to avoid this. Signed-off-by: Omair Mohammed Abdullah Signed-off-by: Vinod Koul Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/drivers/aloop.c | 6 ++++++ 1 file changed, 6 insertions(+) --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -120,6 +120,7 @@ struct loopback_pcm { unsigned int last_drift; unsigned long last_jiffies; struct timer_list timer; + spinlock_t timer_lock; }; static struct platform_device *devices[SNDRV_CARDS]; @@ -170,6 +171,7 @@ static void loopback_timer_start(struct unsigned long tick; unsigned int rate_shift = get_rate_shift(dpcm); + spin_lock(&dpcm->timer_lock); if (rate_shift != dpcm->pcm_rate_shift) { dpcm->pcm_rate_shift = rate_shift; dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); @@ -182,12 +184,15 @@ static void loopback_timer_start(struct tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; dpcm->timer.expires = jiffies + tick; add_timer(&dpcm->timer); + spin_unlock(&dpcm->timer_lock); } static inline void loopback_timer_stop(struct loopback_pcm *dpcm) { + spin_lock(&dpcm->timer_lock); del_timer(&dpcm->timer); dpcm->timer.expires = 0; + spin_unlock(&dpcm->timer_lock); } #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) @@ -667,6 +672,7 @@ static int loopback_open(struct snd_pcm_ dpcm->substream = substream; setup_timer(&dpcm->timer, loopback_timer_function, (unsigned long)dpcm); + spin_lock_init(&dpcm->timer_lock); cable = loopback->cables[substream->number][dev]; if (!cable) {