Author: marius
Date: Sun Jun  9 13:58:37 2013
New Revision: 251574
URL: http://svnweb.freebsd.org/changeset/base/251574

Log:
  MFC: r251159
  
  - 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.

Modified:
  stable/9/sys/dev/bce/if_bce.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/bce/if_bce.c
==============================================================================
--- stable/9/sys/dev/bce/if_bce.c       Sun Jun  9 13:50:14 2013        
(r251573)
+++ stable/9/sys/dev/bce/if_bce.c       Sun Jun  9 13:58:37 2013        
(r251574)
@@ -7873,7 +7873,7 @@ bce_watchdog_exit:
 /* interrupt causes (PHY, TX, RX).                                          */
 /*                                                                          */
 /* Returns:                                                                 */
-/*   0 for success, positive value for failure.                             */
+/*   Nothing.                                                               */
 /****************************************************************************/
 static void
 bce_intr(void *xsc)
@@ -7895,16 +7895,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",
@@ -7992,11 +7992,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);
@@ -8121,6 +8119,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;
 
        /*
@@ -8648,6 +8648,8 @@ bce_sysctl_stats_clear(SYSCTL_HANDLER_AR
 
                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);
@@ -10633,6 +10635,8 @@ bce_dump_status_block(struct bce_softc *
 {
        struct status_block *sblk;
 
+       bus_dmamap_sync(sc->status_tag, sc->status_map, BUS_DMASYNC_POSTREAD);
+
        sblk = sc->status_block;
 
        BCE_PRINTF(
@@ -10695,6 +10699,8 @@ bce_dump_stats_block(struct bce_softc *s
 {
        struct statistics_block *sblk;
 
+       bus_dmamap_sync(sc->stats_tag, sc->stats_map, BUS_DMASYNC_POSTREAD);
+
        sblk = sc->stats_block;
 
        BCE_PRINTF(
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to