diff options
author | Bob Beck <beck@cvs.openbsd.org> | 2006-06-02 05:58:25 +0000 |
---|---|---|
committer | Bob Beck <beck@cvs.openbsd.org> | 2006-06-02 05:58:25 +0000 |
commit | ad578685d095c60c83441c0b5e2a4fd1e9d18f35 (patch) | |
tree | bebc096e5a75bcd283a3ac2d0de11855147d7380 | |
parent | 9dad167bcdea88f520c3d679c06e6bc3a4964f5c (diff) |
Deja-vu - again I make bge stop claiming all interrupts for it's own.
This appears to have been due to driver changes and the fact that
the status word seems to not be cleared. linux may have the same bug.
freebsd does clear the status word with and atomic read and clear
ops. we instead do best effort here to check for the interrupt being
ours by reading the status from the status block to a local copy,
then clearing the status word once we enter the interrupt handler
and using the local copy for checking link status
ok jason@
-rw-r--r-- | sys/dev/pci/if_bge.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 57f51da8edf..71cbebd5d08 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bge.c,v 1.150 2006/05/31 23:40:08 brad Exp $ */ +/* $OpenBSD: if_bge.c,v 1.151 2006/06/02 05:58:24 beck Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -2419,6 +2419,7 @@ bge_intr(void *xsc) { struct bge_softc *sc; struct ifnet *ifp; + u_int32_t statusword; sc = xsc; ifp = &sc->arpcom.ac_if; @@ -2428,17 +2429,22 @@ bge_intr(void *xsc) * Reading the PCI State register will confirm whether the * interrupt is ours and will flush the status block. */ - if ((sc->bge_rdata->bge_status_block.bge_status & - BGE_STATFLAG_UPDATED) || + + /* read status word from status block */ + statusword = sc->bge_rdata->bge_status_block.bge_status; + + if ((statusword & BGE_STATFLAG_UPDATED) || (!(CSR_READ_4(sc, BGE_PCI_PCISTATE) & BGE_PCISTATE_INTR_NOT_ACTIVE))) { /* Ack interrupt and stop others from occurring. */ CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1); + + /* clear status word */ + sc->bge_rdata->bge_status_block.bge_status = 0; if ((BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5700 && sc->bge_chipid != BGE_CHIPID_BCM5700_B1) || - sc->bge_rdata->bge_status_block.bge_status & - BGE_STATFLAG_LINKSTATE_CHANGED || + statusword & BGE_STATFLAG_LINKSTATE_CHANGED || sc->bge_link_evt) bge_link_upd(sc); |