summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Beck <beck@cvs.openbsd.org>2006-06-02 05:58:25 +0000
committerBob Beck <beck@cvs.openbsd.org>2006-06-02 05:58:25 +0000
commitad578685d095c60c83441c0b5e2a4fd1e9d18f35 (patch)
treebebc096e5a75bcd283a3ac2d0de11855147d7380
parent9dad167bcdea88f520c3d679c06e6bc3a4964f5c (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.c16
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);