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 19:07:42 +0100 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: <200301221234.33054.tais.hansen@osd.dk> <200301231337.13089.tais.hansen@osd.dk> <200301231850.44138.tais.hansen@osd.dk> Mime-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: multipart/mixed; boundary="Multipart_Thu_Jan_23_19:07:42_2003-1" Return-path: In-Reply-To: <200301231850.44138.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_19:07:42_2003-1 Content-Type: text/plain; charset=US-ASCII At Thu, 23 Jan 2003 18:50:38 +0100, Tais M. Hansen wrote: > > On Thursday 23 January 2003 16:08, Takashi Iwai wrote: > > > 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. > > thanks. > > it seems really the index value was not updated correctly by the > > chip. > > ok, take 4: please try the new one... > > Same as before, log output attached. :) the next one is to put all logs to /var/log/debug. and will show more verbose. Takashi --Multipart_Thu_Jan_23_19:07:42_2003-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="via-pointer-test5.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 18:05:17 -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,10 +528,20 @@ /* 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); +#ifdef POINTER_DEBUG + snd_printd("period elapsed\n"); +#endif snd_pcm_period_elapsed(viadev->substream); spin_lock(&chip->reg_lock); } @@ -585,17 +611,26 @@ /* check the validity of the calculated position */ if (size < count || (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))) { #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); + snd_printd("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; +#ifdef POINTER_DEBUG + snd_printd("intr_cnt = %d, idx = %d, size = %d\n", viadev->intr_cnt, idx, size); +#endif + if (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2)) { + snd_printd("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; + snd_printd("invalid via82xx_cur_ptr (2), using last valid pointer\n"); + return viadev->lastpos; } } } @@ -648,7 +683,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_19:07:42_2003-1-- ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com