From 1c583063a5c769fe2ec604752e383972c69e6d9b Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 24 Mar 2010 07:10:54 +0100 Subject: ALSA: cmipci: work around invalid PCM pointer When the CMI8738 FRAME2 register is read, the chip sometimes (probably when wrapping around) returns an invalid value that would be outside the programmed DMA buffer. This leads to an inconsistent PCM pointer that is likely to result in an underrun. To work around this, read the register multiple times until we get a valid value; the error state seems to be very short-lived. Signed-off-by: Clemens Ladisch Reported-and-tested-by: Matija Nalis Cc: Signed-off-by: Takashi Iwai --- sound/pci/cmipci.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'sound/pci') 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; -- cgit v1.2.3 From e1f7f02b45cf33a774d56e505ce1718af9392f5e Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Thu, 25 Mar 2010 22:38:15 -0700 Subject: ALSA: ac97: Add IBM ThinkPad R40e to Headphone/Line Jack Sense blacklist BugLink: https://launchpad.net/bugs/303789 This model needs both 'Headphone Jack Sense' and 'Line Jack Sense' muted for audible audio, so just add its SSID to the blacklist and don't enumerate the controls. Signed-off-by: Daniel T Chen Cc: Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_patch.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/pci') diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 1caf5e3c1f6a..1a59b71c5432 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1852,6 +1852,7 @@ static unsigned int ad1981_jacks_blacklist[] = { 0x10140523, /* Thinkpad R40 */ 0x10140534, /* Thinkpad X31 */ 0x10140537, /* Thinkpad T41p */ + 0x1014053e, /* Thinkpad R40e */ 0x10140554, /* Thinkpad T42p/R50p */ 0x10140567, /* Thinkpad T43p 2668-G7U */ 0x10140581, /* Thinkpad X41-2527 */ -- cgit v1.2.3 From 5cd165e7057020884e430941c24454d3df9a799d Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Sun, 28 Mar 2010 13:32:34 -0700 Subject: ALSA: ac97: Add Toshiba P500 to ac97 jack sense blacklist BugLink: https://launchpad.net/bugs/481058 The OR has verified that both 'Headphone Jack Sense' and 'Line Jack Sense' need to be muted for sound to be audible, so just add the machine's SSID to the ac97 jack sense blacklist. Reported-by: Richard Gagne Tested-by: Richard Gagne Cc: Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai --- sound/pci/ac97/ac97_patch.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/pci') diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 1a59b71c5432..e68c98ef4041 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1859,6 +1859,7 @@ static unsigned int ad1981_jacks_blacklist[] = { 0x10280160, /* Dell Dimension 2400 */ 0x104380b0, /* Asus A7V8X-MX */ 0x11790241, /* Toshiba Satellite A-15 S127 */ + 0x1179ff10, /* Toshiba P500 */ 0x144dc01a, /* Samsung NP-X20C004/SEG */ 0 /* end */ }; -- cgit v1.2.3 From a0fd4345f928d72a56e27b23e4cd28c94bf36be5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 2 Apr 2010 14:47:59 +0200 Subject: ALSA: echoaudio - Eliminate use after free Use the call to snd_card_free in the error handling code at the end of the function, as in the other error cases. A simplified version of the semantic patch that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E,E2; @@ snd_card_free(E) ... ( E = E2 | * E ) // Signed-off-by: Julia Lawall Signed-off-by: Takashi Iwai --- sound/pci/echoaudio/echoaudio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 8dab82d7d19d..668a5ec04499 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -2184,10 +2184,9 @@ static int __devinit snd_echo_probe(struct pci_dev *pci, goto ctl_error; #endif - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); + err = snd_card_register(card); + if (err < 0) goto ctl_error; - } snd_printk(KERN_INFO "Card registered: %s\n", card->longname); pci_set_drvdata(pci, chip); -- cgit v1.2.3 From b0cc58a25d04160d39a80e436847eaa2fbc5aa09 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 6 Apr 2010 19:31:26 +0300 Subject: ALSA: mixart: range checking proc file The original code doesn't take into consideration that the value of MIXART_BA0_SIZE - pos can be less than zero which would lead to a large unsigned value for "count". Also I moved the check that read size is a multiple of 4 bytes below the code that adjusts "count". Signed-off-by: Dan Carpenter Cc: Acked-by: Linus Torvalds Signed-off-by: Takashi Iwai --- sound/pci/mixart/mixart.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'sound/pci') diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 7e8e7da592a9..ea4256b08a38 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1161,13 +1161,15 @@ static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private unsigned long count, unsigned long pos) { struct mixart_mgr *mgr = entry->private_data; + unsigned long maxsize; - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ - if(count <= 0) + if (pos >= MIXART_BA0_SIZE) return 0; - if(pos + count > MIXART_BA0_SIZE) - count = (long)(MIXART_BA0_SIZE - pos); - if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count)) + maxsize = MIXART_BA0_SIZE - pos; + if (count > maxsize) + count = maxsize; + count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ + if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) return -EFAULT; return count; } @@ -1180,13 +1182,15 @@ static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private unsigned long count, unsigned long pos) { struct mixart_mgr *mgr = entry->private_data; + unsigned long maxsize; - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ - if(count <= 0) + if (pos > MIXART_BA1_SIZE) return 0; - if(pos + count > MIXART_BA1_SIZE) - count = (long)(MIXART_BA1_SIZE - pos); - if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count)) + maxsize = MIXART_BA1_SIZE - pos; + if (count > maxsize) + count = maxsize; + count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ + if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) return -EFAULT; return count; } -- cgit v1.2.3