summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/if_bge.c61
-rw-r--r--sys/dev/pci/if_bgereg.h4
2 files changed, 36 insertions, 29 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c
index 603040de2c2..35120952a7f 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.135 2006/02/21 01:45:47 brad Exp $ */
+/* $OpenBSD: if_bge.c,v 1.136 2006/03/10 21:39:01 brad Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
@@ -2420,35 +2420,42 @@ bge_intr(void *xsc)
sc = xsc;
ifp = &sc->arpcom.ac_if;
- /* Make sure this is really our interrupt. */
- if (!(sc->bge_rdata->bge_status_block.bge_status &
- BGE_STATFLAG_UPDATED))
- return (0);
-
- /* Ack interrupt and stop others from occurring. */
- CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
-
- 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 ||
- sc->bge_link_evt)
- bge_link_upd(sc);
-
- if (ifp->if_flags & IFF_RUNNING) {
- /* Check RX return ring producer/consumer */
- bge_rxeof(sc);
-
- /* Check TX ring producer/consumer */
- bge_txeof(sc);
- }
+ /* It is possible for the interrupt to arrive before
+ * the status block is updated prior to the interrupt.
+ * 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) ||
+ (!(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);
+
+ 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 ||
+ sc->bge_link_evt)
+ bge_link_upd(sc);
+
+ if (ifp->if_flags & IFF_RUNNING) {
+ /* Check RX return ring producer/consumer */
+ bge_rxeof(sc);
+
+ /* Check TX ring producer/consumer */
+ bge_txeof(sc);
+ }
- /* Re-enable interrupts. */
- CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
+ /* Re-enable interrupts. */
+ CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
- if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
- bge_start(ifp);
+ if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
+ bge_start(ifp);
- return (1);
+ return (1);
+ } else
+ return (0);
}
void
diff --git a/sys/dev/pci/if_bgereg.h b/sys/dev/pci/if_bgereg.h
index a3e0a04f3dc..f552d95daa3 100644
--- a/sys/dev/pci/if_bgereg.h
+++ b/sys/dev/pci/if_bgereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bgereg.h,v 1.42 2006/02/21 01:45:48 brad Exp $ */
+/* $OpenBSD: if_bgereg.h,v 1.43 2006/03/10 21:39:01 brad Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
@@ -343,7 +343,7 @@
* register is set.
*/
#define BGE_PCISTATE_FORCE_RESET 0x00000001
-#define BGE_PCISTATE_INTR_STATE 0x00000002
+#define BGE_PCISTATE_INTR_NOT_ACTIVE 0x00000002
#define BGE_PCISTATE_PCI_BUSMODE 0x00000004 /* 1 = PCI, 0 = PCI-X */
#define BGE_PCISTATE_PCI_BUSSPEED 0x00000008 /* 1 = 33/66, 0 = 66/133 */
#define BGE_PCISTATE_32BIT_BUS 0x00000010 /* 1 = 32bit, 0 = 64bit */