Update of /cvsroot/alsa/alsa-kernel/pci
In directory sc8-pr-cvs1:/tmp/cvs-serv1088
Modified Files:
es1968.c
Log Message:
- fixed corruption of stream linked list in the interrupt handler.
- clean up the unnecessary atomic_t and spinlocks.
Index: es1968.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/es1968.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -r1.46 -r1.47
--- es1968.c 5 Aug 2003 12:43:10 -0000 1.46
+++ es1968.c 5 Aug 2003 12:45:12 -0000 1.47
@@ -583,9 +583,8 @@
/* Maestro Stuff */
u16 maestro_map[32];
- atomic_t bobclient; /* active timer instancs */
+ int bobclient; /* active timer instancs */
int bob_freq; /* timer frequency */
- spinlock_t bob_lock;
struct semaphore memory_mutex; /* memory lock */
/* APU states */
@@ -884,13 +883,11 @@
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
+/* call with substream spinlock */
static void snd_es1968_bob_inc(es1968_t *chip, int freq)
{
- unsigned long flags;
-
- spin_lock_irqsave(&chip->bob_lock, flags);
- atomic_inc(&chip->bobclient);
- if (atomic_read(&chip->bobclient) == 1) {
+ chip->bobclient++;
+ if (chip->bobclient == 1) {
chip->bob_freq = freq;
snd_es1968_bob_start(chip);
} else if (chip->bob_freq < freq) {
@@ -898,35 +895,29 @@
chip->bob_freq = freq;
snd_es1968_bob_start(chip);
}
- spin_unlock_irqrestore(&chip->bob_lock, flags);
}
+/* call with substream spinlock */
static void snd_es1968_bob_dec(es1968_t *chip)
{
- unsigned long flags;
-
- spin_lock_irqsave(&chip->bob_lock, flags);
- atomic_dec(&chip->bobclient);
- if (atomic_read(&chip->bobclient) <= 0)
+ chip->bobclient--;
+ if (chip->bobclient <= 0)
snd_es1968_bob_stop(chip);
else if (chip->bob_freq > ESM_BOB_FREQ) {
/* check reduction of timer frequency */
struct list_head *p;
int max_freq = ESM_BOB_FREQ;
- spin_lock(&chip->substream_lock);
list_for_each(p, &chip->substream_list) {
esschan_t *es = list_entry(p, esschan_t, list);
if (max_freq < es->bob_freq)
max_freq = es->bob_freq;
}
- spin_unlock(&chip->substream_lock);
if (max_freq != chip->bob_freq) {
snd_es1968_bob_stop(chip);
chip->bob_freq = max_freq;
snd_es1968_bob_start(chip);
}
}
- spin_unlock_irqrestore(&chip->bob_lock, flags);
}
static int
@@ -992,13 +983,7 @@
static void snd_es1968_pcm_start(es1968_t *chip, esschan_t *es)
{
- unsigned long flags;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- if (es->running) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return;
- }
+ spin_lock(&chip->reg_lock);
__apu_set_register(chip, es->apu[0], 5, es->base[0]);
snd_es1968_trigger_apu(chip, es->apu[0], es->apu_mode[0]);
if (es->mode == ESM_MODE_CAPTURE) {
@@ -1013,27 +998,19 @@
snd_es1968_trigger_apu(chip, es->apu[3], es->apu_mode[3]);
}
}
- es->running = 1;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
}
static void snd_es1968_pcm_stop(es1968_t *chip, esschan_t *es)
{
- unsigned long flags;
-
- spin_lock_irqsave(&chip->reg_lock, flags);
- if (! es->running) {
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- return;
- }
+ spin_lock(&chip->reg_lock);
snd_es1968_trigger_apu(chip, es->apu[0], 0);
snd_es1968_trigger_apu(chip, es->apu[1], 0);
if (es->mode == ESM_MODE_CAPTURE) {
snd_es1968_trigger_apu(chip, es->apu[2], 0);
snd_es1968_trigger_apu(chip, es->apu[3], 0);
}
- es->running = 0;
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock(&chip->reg_lock);
}
/* set the wavecache control reg */
@@ -1334,30 +1311,28 @@
esschan_t *es = snd_magic_cast(esschan_t, substream->runtime->private_data,
return -ENXIO);
unsigned long flags;
+ spin_lock_irqsave(&chip->substream_lock, flags);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
if (es->running)
- return 0;
+ break;
snd_es1968_bob_inc(chip, es->bob_freq);
es->count = 0;
es->hwptr = 0;
snd_es1968_pcm_start(chip, es);
- spin_lock_irqsave(&chip->substream_lock, flags);
- list_add(&es->list, &chip->substream_list);
- spin_unlock_irqrestore(&chip->substream_lock, flags);
+ es->running = 1;
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
if (! es->running)
- return 0;
+ break;
snd_es1968_pcm_stop(chip, es);
- spin_lock_irqsave(&chip->substream_lock, flags);
- list_del(&es->list);
- spin_unlock_irqrestore(&chip->substream_lock, flags);
+ es->running = 0;
snd_es1968_bob_dec(chip);
break;
}
+ spin_unlock_irqrestore(&chip->substream_lock, flags);
return 0;
}
@@ -1634,6 +1609,7 @@
snd_pcm_runtime_t *runtime = substream->runtime;
esschan_t *es;
int apu1;
+ unsigned long flags;
/* search 2 APUs */
apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY);
@@ -1653,13 +1629,16 @@
es->running = 0;
es->substream = substream;
es->mode = ESM_MODE_PLAY;
- INIT_LIST_HEAD(&es->list);
runtime->private_data = es;
runtime->hw = snd_es1968_playback;
runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max =
calc_available_memory_size(chip);
+ spin_lock_irqsave(&chip->substream_lock, flags);
+ list_add(&es->list, &chip->substream_list);
+ spin_unlock_irqrestore(&chip->substream_lock, flags);
+
return 0;
}
@@ -1691,6 +1670,7 @@
es1968_t *chip = snd_pcm_substream_chip(substream);
esschan_t *es;
int apu1, apu2;
+ unsigned long flags;
apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE);
if (apu1 < 0)
@@ -1719,7 +1699,6 @@
es->running = 0;
es->substream = substream;
es->mode = ESM_MODE_CAPTURE;
- INIT_LIST_HEAD(&es->list);
/* get mixbuffer */
if ((es->mixbuf = snd_es1968_new_memory(chip, ESM_MIXBUF_SIZE)) == NULL) {
@@ -1734,6 +1713,10 @@
runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max =
calc_available_memory_size(chip) - 1024;
+ spin_lock_irqsave(&chip->substream_lock, flags);
+ list_add(&es->list, &chip->substream_list);
+ spin_unlock_irqrestore(&chip->substream_lock, flags);
+
return 0;
}
@@ -1741,9 +1724,14 @@
{
es1968_t *chip = snd_pcm_substream_chip(substream);
esschan_t *es;
+ unsigned long flags;
+
if (substream->runtime->private_data == NULL)
return 0;
es = snd_magic_cast(esschan_t, substream->runtime->private_data, return
-ENXIO);
+ spin_lock_irqsave(&chip->substream_lock, flags);
+ list_del(&es->list);
+ spin_unlock_irqrestore(&chip->substream_lock, flags);
snd_es1968_free_apu_pair(chip, es->apu[0]);
snd_magic_kfree(es);
@@ -1754,9 +1742,14 @@
{
es1968_t *chip = snd_pcm_substream_chip(substream);
esschan_t *es;
+ unsigned long flags;
+
if (substream->runtime->private_data == NULL)
return 0;
es = snd_magic_cast(esschan_t, substream->runtime->private_data, return
-ENXIO);
+ spin_lock_irqsave(&chip->substream_lock, flags);
+ list_del(&es->list);
+ spin_unlock_irqrestore(&chip->substream_lock, flags);
snd_es1968_free_memory(chip, es->mixbuf);
snd_es1968_free_apu_pair(chip, es->apu[0]);
snd_es1968_free_apu_pair(chip, es->apu[2]);
@@ -2035,14 +2028,12 @@
}
if (event & ESM_SOUND_IRQ) {
- struct list_head *p, *n;
+ struct list_head *p;
spin_lock(&chip->substream_lock);
- /* we need to use list_for_each_safe here since the substream
- * can be deleted in period_elapsed().
- */
- list_for_each_safe(p, n, &chip->substream_list) {
+ list_for_each(p, &chip->substream_list) {
esschan_t *es = list_entry(p, esschan_t, list);
- snd_es1968_update_pcm(chip, es);
+ if (es->running)
+ snd_es1968_update_pcm(chip, es);
}
spin_unlock(&chip->substream_lock);
}
@@ -2467,7 +2458,7 @@
snd_ac97_resume(chip->ac97);
/* start timer again */
- if (atomic_read(&chip->bobclient))
+ if (chip->bobclient)
snd_es1968_bob_start(chip);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -2612,8 +2603,6 @@
/* Clear Apu Map */
for (i = 0; i < NR_APUS; i++)
chip->apu[i] = ESM_APU_FREE;
-
- atomic_set(&chip->bobclient, 0);
/* just to be sure */
pci_set_master(pci);
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog