Two solid problems occur with the sound/pci/ich
driver for the ICH2 (Intel 82801BA I/O Controller
Hub) on Dell Optiplex 150 PCs. One problem
(a fatal hang) occurs under 4.4-RELEASE,
4.4-STABLE, and 5.0-CURRENT (as of yesterday).
I have a temporary fix for the fatal hang,
but don't claim to understand the Intel ICH2
enough to know if it is "universal" (e.g.,
the right thing.). I doubt it's comprehensive
enough. Problems:
1) Systems hang on boot (perhaps half the
time) due to a never-cleared interrupt
condition. The audio device sometimes
comes up with an initial error condition
(X_SR_DCH); this interrupt is never
"dismissed/cleared" by the ich_intr()
interrupt handler; ich_intr() livelocks
(runs constantly). I have a quick ugly
work-around fix (listed below) for this.
Maybe the real fix would involve the device
init routine.
2) Microphone input doesn't work, the error
"pcm0: record interrupt timeout, channel dead"
always occurs (it doesn't look like any
channel other than PCM_PLAY is ever even
triggered in the 4.4-RELEASE or 4.4-STABLE
code). The microphone works OK in 5.0-CURRENT.
This problem is just due to the phase-in
of the features in the sound/pci/ich driver
code and appears to be expected behavior
when looked at long enough...
The hang-on boot problem is potentially serious
because it is difficult to identify and
precludes unattended reboot (in normal use
one can just attempt reboot until the device
comes up without the DCH error, i.e., "clean").
Here is how I kludge/fixed the hang on boot
problem (again, I'm not claiming this is the
"right" fix, but the systems have never hung
on boot with it in, and without it they hang
about half to a third the time).
===
/*--- BRM ---*/
void ich_err_reset( struct sc_info *sc, struct sc_chinfo *ch, int i );
void ich_err_reset( struct sc_info *sc, struct sc_chinfo *ch, int i ) {
u_int32_t gc,gs;
gc = ich_rd(sc, ICH_REG_GLOB_CNT, 2);
/* printf( " GC=%x ", gc ); */
if( gc & ICH_GLOB_CTL_PRES ) {
gs = ich_rd(sc, ICH_REG_GLOB_STA, 2);
/* printf( " GS=%x ", gs ); */
ich_wr( sc, ICH_REG_GLOB_STA, gs, 2 );
}
}
/*--- End BRM ---*/
static void
ich_intr(void *p)
{
struct sc_info *sc = (struct sc_info *)p;
struct sc_chinfo *ch;
u_int32_t cbi, lbi, lvi, st;
int i;
for (i = 0; i < 3; i++) {
ch = &sc->ch[i];
/* check channel status */
st = ich_rd(sc, ch->regbase + ICH_REG_X_SR, 2);
#if 1
/*--- BRM ---*/
if( st & (ICH_X_SR_FIFOE | ICH_X_SR_DCH ) ) {
ich_err_reset( sc, ch, i );
/* printf( "ER!" ); */
}
/*--- end BRM ---*/
#endif
...etc
===
This checks the ICH_REG_X_DCH (DMA Controller
Halted) bit. If this error bit is set, a read
of the Global control reg is done to see if
a "primary resume" interrupt is pending; if
so a read/write of the global status reg seems
to clear the interrupt... Other than checking
for FIFO overrun, this interrupt handler appears
to do no error checking, so when the device
comes up with DMA Halted condition asserted
a livelock hang occurs... (I'm not sure I
even know what a "primary resume" interrupt
on the audio ICH device is, although it sounds
maybe like an interesting corner case;
apologies for lack of time to slowly RTFM :)
=== 5.0-CURRENT
>uname -a
FreeBSD dellcur 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Thu Dec 13 16:47:16 IST 2001
root@:/usr/obj/usr/src/sys/GENERIC i386
>cat /dev/sndstat
FreeBSD Audio Driver (newpcm)
Installed devices:
pcm0: at io 0xd800, 0xdc40 irq 10 bufsz 16384 (1p/2r/0v
channels duplex default)
>dmesg | egrep irq
agp0: mem
0xff00-0xff07,0xf800-0xfbff irq 9 at device 2.0 on pci0
xl0: <3Com 3c905C-TX Fast Etherlink XL> port 0xec80-0xecff mem 0xfdfffc00-0xfdfffc7f
irq 11 at device 12.0 on pci1
ata0: at 0x1f0 irq 14 on atapci0
ata1: at 0x170 irq 15 on atapci0
uhci0: port 0xff80-0xff9f irq 11 at
device 31.2 on pci0
uhci1: port 0xff60-0xff7f irq 11 at
device 31.4 on pci0
pcm0: port 0xdc40-0xdc7f,0xd800-0xd8ff irq 10 at device 31.5 on
pci0
fdc0: port 0x3f7,0x3f0-0x3f5 irq 6 on acpi0
atkbdc0: port 0x64,0x60 irq 1 on acpi0
atkbd0: flags 0x1 irq 1 on atkbdc0
psm0: irq 12 on atkbdc0
sio0 port 0x3f8-0x3ff irq 4 on acpi0
sio1 port 0x2f8-0x2ff irq 3 on acpi0
ppc0 port 0x778-0x77f,0x378-0x37f irq 7 on acpi0
4.4-STABLE =
>uname -a
FreeBSD dell2 4.4-STABLE FreeBSD 4.4-STABLE #0: Tue Dec 11 11:37:12 IST 2001
root@dell2:/usr/src/sys/compile/DELL2 i386
>cat /dev/sndstat
FreeBSD Audio Driver (newpcm) Dec 11 2001 11:36:46
Installed devices:
pcm0: at io 0xd800, 0xdc40 irq 10 (1p