aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/cmipci.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-04-10 21:34:56 +0200
committerTakashi Iwai <tiwai@suse.de>2010-04-10 21:34:56 +0200
commit27762b2ce16d5c6f7bc8ab1aad1b9179076f997a (patch)
tree04108617a1ccc18e3cef39e780c67460da9d5a0d /sound/pci/cmipci.c
parent7b7b9042263f5cafb6ce85b3764375a8de7e22da (diff)
parent29aac005ff4dc8a5f50b80f4e5c4f59b21c0fb50 (diff)
downloadkernel_replicant_linux-27762b2ce16d5c6f7bc8ab1aad1b9179076f997a.tar.gz
kernel_replicant_linux-27762b2ce16d5c6f7bc8ab1aad1b9179076f997a.tar.bz2
kernel_replicant_linux-27762b2ce16d5c6f7bc8ab1aad1b9179076f997a.zip
Merge branch 'fix/misc' into topic/usb
Diffstat (limited to 'sound/pci/cmipci.c')
-rw-r--r--sound/pci/cmipci.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 1ded64e05643..329968edca9b 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -941,13 +941,21 @@ static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci
struct snd_pcm_substream *substream)
{
size_t ptr;
- unsigned int reg;
+ unsigned int reg, rem, tries;
+
if (!rec->running)
return 0;
#if 1 // this seems better..
reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2;
- ptr = rec->dma_size - (snd_cmipci_read_w(cm, reg) + 1);
- ptr >>= rec->shift;
+ for (tries = 0; tries < 3; tries++) {
+ rem = snd_cmipci_read_w(cm, reg);
+ if (rem < rec->dma_size)
+ goto ok;
+ }
+ printk(KERN_ERR "cmipci: invalid PCM pointer: %#x\n", rem);
+ return SNDRV_PCM_POS_XRUN;
+ok:
+ ptr = (rec->dma_size - (rem + 1)) >> rec->shift;
#else
reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1;
ptr = snd_cmipci_read(cm, reg) - rec->offset;