Date: Sun, 30 Jun 2013 05:12:18 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r252402 - head/sys/dev/bce Message-ID: <201306300512.r5U5CIQL055599@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <brad@OpenBSD.org> Submitted by: davidch (initial version) Reviewed by: davidch, David Imhoff <dimhoff_devel@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306300512.r5U5CIQL055599>