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