Author: yongari
Date: Sun Jun 30 05:12:18 2013
New Revision: 252402
URL: http://svnweb.freebsd.org/changeset/base/252402

Log:
  Fix triggering false watchdog timeout when controller is in PAUSE
  state.  Previously it used to check if controller has sent a
  PAUSE frame to the remote peer.
  
  Reported by:  David Imhoff via Brad Smith <b...@openbsd.org>
  Submitted by: davidch (initial version)
  Reviewed by:  davidch, David Imhoff <dimhoff_de...@xs4all.nl>

Modified:
  head/sys/dev/bce/if_bce.c
  head/sys/dev/bce/if_bcereg.h

Modified: head/sys/dev/bce/if_bce.c
==============================================================================
--- head/sys/dev/bce/if_bce.c   Sun Jun 30 05:10:33 2013        (r252401)
+++ head/sys/dev/bce/if_bce.c   Sun Jun 30 05:12:18 2013        (r252402)
@@ -2077,10 +2077,12 @@ bce_miibus_statchg(device_t dev)
                DBPRINT(sc, BCE_INFO_PHY,
                    "%s(): Enabling RX flow control.\n", __FUNCTION__);
                BCE_SETBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN);
+               sc->bce_flags |= BCE_USING_RX_FLOW_CONTROL;
        } else {
                DBPRINT(sc, BCE_INFO_PHY,
                    "%s(): Disabling RX flow control.\n", __FUNCTION__);
                BCE_CLRBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN);
+               sc->bce_flags &= ~BCE_USING_RX_FLOW_CONTROL;
        }
 
        if ((IFM_OPTIONS(media_active) & IFM_ETH_TXPAUSE) != 0) {
@@ -7828,18 +7830,42 @@ bce_ioctl(struct ifnet *ifp, u_long comm
 static void
 bce_watchdog(struct bce_softc *sc)
 {
+       uint32_t status;
+
        DBENTER(BCE_EXTREME_SEND);
 
        BCE_LOCK_ASSERT(sc);
 
+       status = 0;
        /* If the watchdog timer hasn't expired then just exit. */
        if (sc->watchdog_timer == 0 || --sc->watchdog_timer)
                goto bce_watchdog_exit;
 
+       status = REG_RD(sc, BCE_EMAC_RX_STATUS);
        /* If pause frames are active then don't reset the hardware. */
-       /* ToDo: Should we reset the timer here? */
-       if (REG_RD(sc, BCE_EMAC_TX_STATUS) & BCE_EMAC_TX_STATUS_XOFFED)
-               goto bce_watchdog_exit;
+       if ((sc->bce_flags & BCE_USING_RX_FLOW_CONTROL) != 0) {
+               if ((status & BCE_EMAC_RX_STATUS_FFED) != 0) {
+                       /*
+                        * If link partner has us in XOFF state then wait for
+                        * the condition to clear.
+                        */
+                       sc->watchdog_timer = BCE_TX_TIMEOUT;
+                       goto bce_watchdog_exit;
+               } else if ((status & BCE_EMAC_RX_STATUS_FF_RECEIVED) != 0 &&
+                       (status & BCE_EMAC_RX_STATUS_N_RECEIVED) != 0) {
+                       /*
+                        * If we're not currently XOFF'ed but have recently
+                        * been XOFF'd/XON'd then assume that's delaying TX
+                        * this time around.
+                        */
+                       sc->watchdog_timer = BCE_TX_TIMEOUT;
+                       goto bce_watchdog_exit;
+               }
+               /*
+                * Any other condition is unexpected and the controller
+                * should be reset.
+                */
+       }
 
        BCE_PRINTF("%s(%d): Watchdog timeout occurred, resetting!\n",
            __FILE__, __LINE__);
@@ -7863,6 +7889,7 @@ bce_watchdog(struct bce_softc *sc)
        sc->bce_ifp->if_oerrors++;
 
 bce_watchdog_exit:
+       REG_WR(sc, BCE_EMAC_RX_STATUS, status);
        DBEXIT(BCE_EXTREME_SEND);
 }
 

Modified: head/sys/dev/bce/if_bcereg.h
==============================================================================
--- head/sys/dev/bce/if_bcereg.h        Sun Jun 30 05:10:33 2013        
(r252401)
+++ head/sys/dev/bce/if_bcereg.h        Sun Jun 30 05:12:18 2013        
(r252402)
@@ -6465,6 +6465,7 @@ struct bce_softc
 #define BCE_USING_MSIX_FLAG                    0x00000100
 #define BCE_PCIE_FLAG                          0x00000200
 #define BCE_USING_TX_FLOW_CONTROL              0x00000400
+#define BCE_USING_RX_FLOW_CONTROL              0x00000800
 
        /* Controller capability flags. */
        u32                     bce_cap_flags;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to