From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: Re: [Alsa-user] Upgrade problems -addendum Date: Thu, 23 Jan 2003 16:08:51 +0100 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: <200301221234.33054.tais.hansen@osd.dk> <200301231215.29675.tais.hansen@osd.dk> <200301231337.13089.tais.hansen@osd.dk> Mime-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: multipart/mixed; boundary="Multipart_Thu_Jan_23_16:08:51_2003-1" Return-path: In-Reply-To: <200301231337.13089.tais.hansen@osd.dk> Errors-To: alsa-devel-admin@lists.sourceforge.net List-Help: List-Post: List-Subscribe: , List-Unsubscribe: , List-Archive: To: "Tais M. Hansen" Cc: alsa-devel@lists.sourceforge.net List-Id: alsa-devel@alsa-project.org --Multipart_Thu_Jan_23_16:08:51_2003-1 Content-Type: text/plain; charset=US-ASCII At Thu, 23 Jan 2003 13:36:53 +0100, Tais M. Hansen wrote: > > > > Well... Ogg123 freezes the same way as with test1. Artsd no longer fails > > > with "cpu overload", but it's constantly busy and can't play sound. > > > ... > > hmm, it'd better to start from the beginning. > > please try the attached patch (solely). > > this will generate bunch of debug messages at each interrupt but won't > > improve any behavior. > > so, it would be enough to run only once or twice if you got bad > > playback. > > from the obtained log, we'll be able to know whether the interrupt is > > properly generated, or at which condition, the read of register value > > fails. > > Okay, fresh cvs checkout. Enabled POINTER_DEBUG and applied the > via-pointer-debug.dif. > > Ogg123 freezes/stalls without ever making a sound, like with the previous test > and test3 patches. Log output is attached. > > Aplay plays a wav-file fine. No problems noticed. Log output is attached. > > When artsd is started a short piece of noise is looped, as described earlier. > Can't play any sound through arts. Log output attached. thanks. it seems really the index value was not updated correctly by the chip. ok, take 4: please try the new one... Takashi --Multipart_Thu_Jan_23_16:08:51_2003-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="via-pointer-test4.dif" Content-Transfer-Encoding: 7bit Index: alsa-kernel/pci/via82xx.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/pci/via82xx.c,v retrieving revision 1.21 diff -u -r1.21 via82xx.c --- alsa-kernel/pci/via82xx.c 22 Jan 2003 14:21:05 -0000 1.21 +++ alsa-kernel/pci/via82xx.c 23 Jan 2003 15:05:35 -0000 @@ -230,7 +230,10 @@ u32 *table; /* physical address + flag */ dma_addr_t table_addr; struct snd_via_sg_table *idx_table; + int *period_idx; + unsigned int periods; /* for recovery from the unexpected pointer */ + unsigned int intr_cnt; unsigned int lastpos; unsigned int bufsize; unsigned int bufsize2; @@ -262,11 +265,17 @@ if (! dev->idx_table) return -ENOMEM; } + if (! dev->period_idx) { + dev->period_idx = kmalloc(sizeof(int) * VIA_TABLE_SIZE, GFP_KERNEL); + if (! dev->period_idx) + return -ENOMEM; + } /* fill the entries */ idx = 0; ofs = 0; for (i = 0; i < periods; i++) { + dev->period_idx[i] = idx; rest = fragsize; /* fill descriptors for a period. * a period can be split to several descriptors if it's @@ -303,6 +312,7 @@ dev->tbl_entries = idx; dev->bufsize = periods * fragsize; dev->bufsize2 = dev->bufsize / 2; + dev->periods = periods; return 0; } @@ -318,6 +328,10 @@ kfree(dev->idx_table); dev->idx_table = NULL; } + if (dev->period_idx) { + kfree(dev->period_idx); + dev->period_idx = NULL; + } } @@ -481,10 +495,12 @@ /* disable interrupts */ outb(0x00, port + VIA_REG_OFFSET_CONTROL); /* clear interrupts */ - outb(0x03, port + VIA_REG_OFFSET_STATUS); - outb(0x00, port + VIA_REG_OFFSET_TYPE); /* for via686 */ + outb(0x07, port + VIA_REG_OFFSET_STATUS); + if (chip->chip_type == TYPE_VIA686) + outb(0x00, port + VIA_REG_OFFSET_TYPE); outl(0, port + VIA_REG_OFFSET_CURR_PTR); viadev->lastpos = 0; + viadev->intr_cnt = 0; } @@ -512,9 +528,16 @@ /* check status for each stream */ for (i = 0; i < chip->num_devs; i++) { viadev_t *viadev = &chip->devs[i]; - if (inb(chip->port + viadev->reg_offset) & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG)) { - outb(VIA_REG_STAT_FLAG | VIA_REG_STAT_EOL, VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset); + unsigned long port = chip->port + viadev->reg_offset; /* STATUS */ + unsigned char status = inb(port) & 0x07; + if (! status) + continue; + outb(status, port); /* ack */ + if (status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG)) { if (viadev->substream && viadev->running) { + viadev->intr_cnt++; + if (viadev->intr_cnt >= viadev->periods) + viadev->intr_cnt = 0; spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(viadev->substream); spin_lock(&chip->reg_lock); @@ -587,15 +610,21 @@ #ifdef POINTER_DEBUG printk("fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); #endif - /* count register returns full size when end of buffer is reached */ if (size != count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr, using last valid pointer\n"); - res = viadev->lastpos; + /* recover from the interrupt position */ + idx = viadev->period_idx[viadev->intr_cnt]; + size = viadev->idx_table[idx].size; + res = viadev->idx_table[idx].offset + size - count; + if (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2)) { + snd_printd(KERN_ERR "invalid via82xx_cur_ptr, using last valid pointer\n"); + return viadev->lastpos; + } } else { + /* count register returns full size when end of buffer is reached */ res = viadev->idx_table[idx].offset + size; if (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2)) { snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), using last valid pointer\n"); - res = viadev->lastpos; + return viadev->lastpos; } } } @@ -648,7 +677,7 @@ return 0; spin_lock(&chip->reg_lock); count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset); - idx = count >> 24; + idx = (count >> 24) & viadev->tbl_entries; count &= 0xffffff; res = calc_linear_pos(viadev, idx, count); spin_unlock(&chip->reg_lock); --Multipart_Thu_Jan_23_16:08:51_2003-1-- ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com