diff options
-rw-r--r-- | sys/dev/pci/if_bge.c | 61 | ||||
-rw-r--r-- | sys/dev/pci/if_bgereg.h | 4 |
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 */ |