diff options
author | marius <marius@FreeBSD.org> | 2013-05-30 20:54:17 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2013-05-30 20:54:17 +0000 |
commit | 3bedef3bedc5c3327e688ac94891ec1a53a132ad (patch) | |
tree | 72fa61674c330cad08b9008b776712b8d14d31bb /sys/dev/bce | |
parent | cc86f133652d396d6f3dac311d20761a9ee00ad9 (diff) | |
download | FreeBSD-src-3bedef3bedc5c3327e688ac94891ec1a53a132ad.zip FreeBSD-src-3bedef3bedc5c3327e688ac94891ec1a53a132ad.tar.gz |
- Checking for spurious interrupts is only necessary when using INTx.
Actually, this may be further optimized for controller variants
supporting one-shot MSIs but I'm lacking the necessary hardware for
testing.
- Add some missing synchronization of the statistics and status DMA
maps.
MFC after: 1 week
Diffstat (limited to 'sys/dev/bce')
-rw-r--r-- | sys/dev/bce/if_bce.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c index ed3b9cb..cdf9517 100644 --- a/sys/dev/bce/if_bce.c +++ b/sys/dev/bce/if_bce.c @@ -7876,7 +7876,7 @@ bce_watchdog_exit: /* interrupt causes (PHY, TX, RX). */ /* */ /* Returns: */ -/* 0 for success, positive value for failure. */ +/* Nothing. */ /****************************************************************************/ static void bce_intr(void *xsc) @@ -7898,16 +7898,16 @@ bce_intr(void *xsc) DBRUN(sc->interrupts_generated++); /* Synchnorize before we read from interface's status block */ - bus_dmamap_sync(sc->status_tag, sc->status_map, - BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_POSTREAD); /* - * If the hardware status block index - * matches the last value read by the - * driver and we haven't asserted our - * interrupt then there's nothing to do. + * If the hardware status block index matches the last value read + * by the driver and we haven't asserted our interrupt then there's + * nothing to do. This may only happen in case of INTx due to the + * interrupt arriving at the CPU before the status block is updated. */ - if ((sc->status_block->status_idx == sc->last_status_idx) && + if ((sc->bce_flags & (BCE_USING_MSI_FLAG | BCE_USING_MSIX_FLAG)) == 0 && + sc->status_block->status_idx == sc->last_status_idx && (REG_RD(sc, BCE_PCICFG_MISC_STATUS) & BCE_PCICFG_MISC_STATUS_INTA_VALUE)) { DBPRINT(sc, BCE_VERBOSE_INTR, "%s(): Spurious interrupt.\n", @@ -7995,11 +7995,9 @@ bce_intr(void *xsc) if ((hw_rx_cons == sc->hw_rx_cons) && (hw_tx_cons == sc->hw_tx_cons)) break; - } - bus_dmamap_sync(sc->status_tag, sc->status_map, - BUS_DMASYNC_PREREAD); + bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_PREREAD); /* Re-enable interrupts. */ bce_enable_intr(sc, 0); @@ -8124,6 +8122,8 @@ bce_stats_update(struct bce_softc *sc) ifp = sc->bce_ifp; + bus_dmamap_sync(sc->stats_tag, sc->stats_map, BUS_DMASYNC_POSTREAD); + stats = (struct statistics_block *) sc->stats_block; /* @@ -8651,6 +8651,8 @@ bce_sysctl_stats_clear(SYSCTL_HANDLER_ARGS) stats = (struct statistics_block *) sc->stats_block; bzero(stats, sizeof(struct statistics_block)); + bus_dmamap_sync(sc->stats_tag, sc->stats_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* Clear the internal H/W statistics counters. */ REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW); @@ -10636,6 +10638,8 @@ bce_dump_status_block(struct bce_softc *sc) { struct status_block *sblk; + bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_POSTREAD); + sblk = sc->status_block; BCE_PRINTF( @@ -10698,6 +10702,8 @@ bce_dump_stats_block(struct bce_softc *sc) { struct statistics_block *sblk; + bus_dmamap_sync(sc->stats_tag, sc->stats_map, BUS_DMASYNC_POSTREAD); + sblk = sc->stats_block; BCE_PRINTF( |