diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-03-10 21:39:02 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-03-10 21:39:02 +0000 |
commit | 9657221bd37244e298bc2f32d429a73f0c539fb4 (patch) | |
tree | 4728093625f0f68e3e375e9e6a75799b220eae44 /sys/dev/pci | |
parent | f34f42fc46e81183449c79fa48c8af5cc22a005f (diff) |
in bge_intr() also check the PCI State register to see if there
are really any interrupts to service.
Based on the Linux tg3 driver though the Broadcom bcm5700 driver
does the same thing.
Diffstat (limited to 'sys/dev/pci')
-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 */ |