-BEGIN PGP SIGNED MESSAGE-
Hash: RIPEMD160
HI all,
Finally I discovered my problem :-)
The following patch fixes SMP hangs w/ cmpci v5.64 ( k244-ac17 ).
- --- linux-244ac/drivers/sound/cmpci.c Fri May 25 05:26:27 2001
+++ linux/drivers/sound/cmpci.c Fri May 25 20:14:49 2001
@@ -1,5 +1,4 @@
/
*/
- -
/*
* cmpci.c -- C-Media PCI audio driver.
*
@@ -76,6 +75,10 @@
*was calling prog_dmabuf with s->lock held, call missing
*unlock_kernel in cm_midi_release
*
+ *Fri May 25 2001 - Carlos Eduardo Gorges <[EMAIL PROTECTED]>
+ *- some drivers cleanups
+ *- spin[un]locks revision ( fix SMP support )
+ *
*/
/
*/
@@ -226,10 +229,6 @@
#define SND_DEV_DSP16 5
- -#define set_dac1_rate set_adc_rate
- -#define stop_dac1 stop_adc
- -#define get_dmadac1 get_dmaadc
- -
/* - */
struct cm_state {
@@ -342,7 +341,6 @@
/* - */
static struct cm_state *devs;
- -static struct cm_state *devaudio;
static unsigned long wavetable_mem;
/* - */
@@ -577,8 +575,8 @@
{
unsigned long flags;
- - spin_lock_irqsave(&s->lock, flags);
set_spdifout(s, rate);
+ spin_lock_irqsave(&s->lock, flags);
/* enable AC3 */
if (rate == 48000 || rate == 44100) {
// mute DAC
@@ -697,7 +695,7 @@
if (s->curr_channels <= 2)
set_spdifout(s, rate);
if (s->status & DO_DUAL_DAC)
- - set_dac1_rate(s, rate);
+ set_adc_rate(s, rate);
}
/* - */
@@ -759,12 +757,16 @@
extern inline void enable_dac(struct cm_state *s)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&s->lock, flags);
if (!(s->enable & CM_ENABLE_CH1)) {
/* enable channel */
s->enable |= CM_ENABLE_CH1;
outb(s->enable, s->iobase + CODEC_CMI_FUNCTRL0 + 2);
}
maskb(s->iobase + CODEC_CMI_FUNCTRL0, ~8, 0);
+ spin_unlock_irqrestore(&s->lock, flags);
if (s->status & DO_DUAL_DAC)
enable_adc(s);
}
@@ -794,7 +796,7 @@
}
spin_unlock_irqrestore(&s->lock, flags);
if (s->status & DO_DUAL_DAC)
- - stop_dac1(s);
+ stop_adc(s);
}
static void start_adc(struct cm_state *s)
@@ -819,7 +821,9 @@
if ((s->dma_adc.mapped || s->dma_adc.count > 0) && s->dma_adc.ready) {
/* enable interrupt */
// maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, 1);
- - enable_dac(s);
+ spin_unlock_irqrestore(&s->lock, flags);
+ enable_dac(s);
+ spin_lock_irqsave(&s->lock, flags);
}
spin_unlock_irqrestore(&s->lock, flags);
}
@@ -832,7 +836,9 @@
if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
/* enable interrupt */
maskb(s->iobase + CODEC_CMI_INT_HLDCLR + 2, ~0, 2);
+ spin_unlock_irqrestore(&s->lock, flags);
enable_dac(s);
+ spin_lock_irqsave(&s->lock, flags);
}
spin_unlock_irqrestore(&s->lock, flags);
if (s->status & DO_DUAL_DAC)
@@ -848,7 +854,11 @@
spin_lock_irqsave(&s->lock, flags);
if ((channels > 2) && (channels <= s->max_channels)
&& (((s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK) == (CM_CFMT_STEREO |
CM_CFMT_16BIT))) {
+
+ spin_unlock_irqrestore(&s->lock, flags);
set_spdifout(s, 0);
+ spin_lock_irqsave(&s->lock, flags);
+
if (s->capability & CAN_MULTI_CH_HW) {
// NXCHG
maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0, 0x80);
@@ -880,8 +890,11 @@
fmts |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT;
fmts |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT;
fmts |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT;
+
+ spin_unlock_irqrestore(&s->lock, flags);
set_fmt(s, fmtm, fmts);
- - set_dac1_rate(s, s->ratedac);
+ set_adc_rate(s, s->ratedac);
+ spin_lock_irqsave(&s->lock, flags);
}
// N4SPK3D, disable 4 speaker mode (analog duplicate)
if (s->speakers > 2)
@@ -925,7 +938,6 @@
db->mapped = db->ready = 0;
}
- -
/* Ch1 is used for playback, Ch0 is used for recording */
static int prog_dmabuf(struct cm_state *s, unsigned rec)
@@ -939,7 +951,6 @@
unsigned char fmt;
unsigned long flags;
- - spin_lock_irqsave(&s->lock, flags);
fmt = s