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.
@ -38,7 +38,7 @@
*/
#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"
@ -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;
char devinfo[256];
usbd_status r;
int s;
aprint_naive("\n");
@ -119,8 +120,13 @@ uhci_pci_attach(struct device *parent, struct device *self, void *aux)
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_STS,
bus_space_read_2(sc->sc.iot, sc->sc.ioh, UHCI_STS));
sc->sc_pc = pc;
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);
/* 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);
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) {
case PCI_USBREV_PRE_1_0: