Be paranoid about disabling interrupts and acknowledging any pending

interrupts while attaching uhci. Fixes recent problems with uvm_fault
during uhci attach, which appear to be caused by a pending interrupt
left over from the device while it was operating in legacy support mode
under the control of the BIOS.

Patch by joerg@ because his was better than mine.
This commit is contained in:
gavan 2007-11-24 02:13:49 +00:00
parent b79e2bcb32
commit 33bf6486d0

View File

@ -1,4 +1,4 @@
/* $NetBSD: uhci_pci.c,v 1.37 2007/10/19 12:00:56 ad Exp $ */ /* $NetBSD: uhci_pci.c,v 1.38 2007/11/24 02:13:49 gavan Exp $ */
/* /*
* Copyright (c) 1998 The NetBSD Foundation, Inc. * Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uhci_pci.c,v 1.37 2007/10/19 12:00:56 ad Exp $"); __KERNEL_RCSID(0, "$NetBSD: uhci_pci.c,v 1.38 2007/11/24 02:13:49 gavan Exp $");
#include "ehci.h" #include "ehci.h"
@ -105,6 +105,7 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
const char *devname = sc->sc.sc_bus.bdev.dv_xname; const char *devname = sc->sc.sc_bus.bdev.dv_xname;
char devinfo[256]; char devinfo[256];
usbd_status r; usbd_status r;
int s;
aprint_naive("\n"); aprint_naive("\n");
@ -119,8 +120,13 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
return; return;
} }
/* Disable interrupts, so we don't get any spurious ones. */ /*
* Disable interrupts, so we don't get any spurious ones.
* Acknolewdge all pending interrupts.
*/
bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0); bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0);
bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_STS,
bus_space_read_2(sc->sc.iot, sc->sc.ioh, UHCI_STS));
sc->sc_pc = pc; sc->sc_pc = pc;
sc->sc_tag = tag; sc->sc_tag = tag;
@ -147,8 +153,17 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
} }
aprint_normal("%s: interrupting at %s\n", devname, intrstr); aprint_normal("%s: interrupting at %s\n", devname, intrstr);
/* Set LEGSUP register to its default value. */ /*
* Set LEGSUP register to its default value.
* This can reenable or trigger interrupts, so protect against them
* and explicitly disable and ACK them afterwards.
*/
s = splhardusb();
pci_conf_write(pc, tag, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN); pci_conf_write(pc, tag, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN);
bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_INTR, 0);
bus_space_write_2(sc->sc.iot, sc->sc.ioh, UHCI_STS,
bus_space_read_2(sc->sc.iot, sc->sc.ioh, UHCI_STS));
splx(s);
switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) { switch(pci_conf_read(pc, tag, PCI_USBREV) & PCI_USBREV_MASK) {
case PCI_USBREV_PRE_1_0: case PCI_USBREV_PRE_1_0: