summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-11-18 18:52:14 +0100
committerJaroslav Kysela <perex@suse.cz>2006-01-03 12:29:08 +0100
commitb32425ac93370e1ba5556110e662f896b2e143b3 (patch)
treec5837ee90c16d2aa358e399f2ad79ca4eb770e94
parent2eb061f41cf74f829bfe90a9c79c765172be9f0b (diff)
downloadlinux-b32425ac93370e1ba5556110e662f896b2e143b3.tar.gz
[ALSA] Fix possible races in timer callbacks
Fix possible races in timer callbacks.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/core/timer.c5
-rw-r--r--sound/drivers/dummy.c10
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c5
-rw-r--r--sound/drivers/opl3/opl3_midi.c5
-rw-r--r--sound/pci/korg1212/korg1212.c5
-rw-r--r--sound/synth/emux/emux_synth.c5
6 files changed, 20 insertions, 15 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 74637cef6d2c..6aad411dd7b8 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -662,12 +662,13 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
 	struct snd_timer_instance *ti, *ts;
 	unsigned long resolution, ticks;
 	struct list_head *p, *q, *n, *ack_list_head;
+	unsigned long flags;
 	int use_tasklet = 0;
 
 	if (timer == NULL)
 		return;
 
-	spin_lock(&timer->lock);
+	spin_lock_irqsave(&timer->lock, flags);
 
 	/* remember the current resolution */
 	if (timer->hw.c_resolution)
@@ -752,7 +753,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
 
 	/* do we have any slow callbacks? */
 	use_tasklet = !list_empty(&timer->sack_list_head);
-	spin_unlock(&timer->lock);
+	spin_unlock_irqrestore(&timer->lock, flags);
 
 	if (use_tasklet)
 		tasklet_hi_schedule(&timer->task_queue);
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index a276f7c80360..186117571745 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -231,8 +231,9 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
 static void snd_card_dummy_pcm_timer_function(unsigned long data)
 {
 	struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)data;
+	unsigned long flags;
 	
-	spin_lock(&dpcm->lock);
+	spin_lock_irqsave(&dpcm->lock, flags);
 	dpcm->timer.expires = 1 + jiffies;
 	add_timer(&dpcm->timer);
 	dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
@@ -240,11 +241,10 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data)
 	dpcm->pcm_buf_pos %= dpcm->pcm_size;
 	if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
 		dpcm->pcm_irq_pos %= dpcm->pcm_count;
-		spin_unlock(&dpcm->lock);
+		spin_unlock_irqrestore(&dpcm->lock, flags);
 		snd_pcm_period_elapsed(dpcm->substream);
-		spin_lock(&dpcm->lock);
-	}
-	spin_unlock(&dpcm->lock);
+	} else
+		spin_unlock_irqrestore(&dpcm->lock, flags);
 }
 
 static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index ee67b522d259..8687ae3c66b8 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -133,12 +133,13 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg
 static void snd_mpu401_uart_timer(unsigned long data)
 {
 	struct snd_mpu401 *mpu = (struct snd_mpu401 *)data;
+	unsigned long flags;
 
-	spin_lock(&mpu->timer_lock);
+	spin_lock_irqsave(&mpu->timer_lock, flags);
 	/*mpu->mode |= MPU401_MODE_TIMER;*/
 	mpu->timer.expires = 1 + jiffies;
 	add_timer(&mpu->timer);
-	spin_unlock(&mpu->timer_lock);
+	spin_unlock_irqrestore(&mpu->timer_lock, flags);
 	if (mpu->rmidi)
 		_snd_mpu401_uart_interrupt(mpu);
 }
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 48c480e050ce..1b6f227af370 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -238,10 +238,11 @@ void snd_opl3_timer_func(unsigned long data)
 {
 
 	struct snd_opl3 *opl3 = (struct snd_opl3 *)data;
+	unsigned long flags;
 	int again = 0;
 	int i;
 
-	spin_lock(&opl3->sys_timer_lock);
+	spin_lock_irqsave(&opl3->sys_timer_lock, flags);
 	for (i = 0; i < opl3->max_voices; i++) {
 		struct snd_opl3_voice *vp = &opl3->voices[i];
 		if (vp->state > 0 && vp->note_off_check) {
@@ -257,7 +258,7 @@ void snd_opl3_timer_func(unsigned long data)
 	} else {
 		opl3->sys_timer_status = 0;
 	}
-	spin_unlock(&opl3->sys_timer_lock);
+	spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
 }
 
 /*
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index a8a6a5c41a7f..4eddb512c12f 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -609,8 +609,9 @@ static void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212)
 static void snd_korg1212_timer_func(unsigned long data)
 {
         struct snd_korg1212 *korg1212 = (struct snd_korg1212 *) data;
+	unsigned long flags;
 	
-	spin_lock(&korg1212->lock);
+	spin_lock_irqsave(&korg1212->lock, flags);
 	if (korg1212->sharedBufferPtr->cardCommand == 0) {
 		/* ack'ed */
 		korg1212->stop_pending_cnt = 0;
@@ -632,7 +633,7 @@ static void snd_korg1212_timer_func(unsigned long data)
 					   stateName[korg1212->cardState]);
 		}
 	}
-	spin_unlock(&korg1212->lock);
+	spin_unlock_irqrestore(&korg1212->lock, flags);
 }
 
 static int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212)
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index c387a83a655e..24705d15ebd8 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -205,9 +205,10 @@ void snd_emux_timer_callback(unsigned long data)
 {
 	struct snd_emux *emu = (struct snd_emux *) data;
 	struct snd_emux_voice *vp;
+	unsigned long flags;
 	int ch, do_again = 0;
 
-	spin_lock(&emu->voice_lock);
+	spin_lock_irqsave(&emu->voice_lock, flags);
 	for (ch = 0; ch < emu->max_voices; ch++) {
 		vp = &emu->voices[ch];
 		if (vp->state == SNDRV_EMUX_ST_PENDING) {
@@ -225,7 +226,7 @@ void snd_emux_timer_callback(unsigned long data)
 		emu->timer_active = 1;
 	} else
 		emu->timer_active = 0;
-	spin_unlock(&emu->voice_lock);
+	spin_unlock_irqrestore(&emu->voice_lock, flags);
 }
 
 /*