- 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
This commit is contained in:
Marius Strobl 2013-05-30 20:54:17 +00:00
parent d03c0883ad
commit 939ce643ea

View File

@ -7876,7 +7876,7 @@ bce_watchdog(struct bce_softc *sc)
/* 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(