summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2007-01-15 22:51:06 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2007-01-15 22:51:06 +0000
commit5cce5ed7380b8a037a337ffeedac4d3079974326 (patch)
tree78fc8fea1fb9f1a0844057af5e24766587b9478e /sys/dev/pci
parent1f3f3a83cb1daef72683b0333a405c407d92dd40 (diff)
Report flow control status.
From brad@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_em.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 12fbf2dd94a..1238e841017 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-/* $OpenBSD: if_em.c,v 1.163 2006/12/27 14:33:04 kettenis Exp $ */
+/* $OpenBSD: if_em.c,v 1.164 2007/01/15 22:51:05 kettenis Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -795,7 +795,7 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct em_softc *sc = ifp->if_softc;
u_char fiber_type = IFM_1000_SX;
- u_int16_t gsr;
+ u_int16_t ar, lpar, gsr;
INIT_DEBUGOUT("em_media_status: begin");
@@ -835,6 +835,21 @@ em_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
else
ifmr->ifm_active |= IFM_HDX;
+ if (ifmr->ifm_active & IFM_FDX) {
+ em_read_phy_reg(&sc->hw, PHY_AUTONEG_ADV, &ar);
+ em_read_phy_reg(&sc->hw, PHY_LP_ABILITY, &lpar);
+
+ if ((ar & NWAY_AR_PAUSE) && (lpar & NWAY_LPAR_PAUSE))
+ ifmr->ifm_active |= IFM_FLOW | IFM_ETH_TXPAUSE |
+ IFM_ETH_TXPAUSE;
+ else if (!(ar & NWAY_AR_PAUSE) && (ar & NWAY_AR_ASM_DIR) &&
+ (lpar & NWAY_LPAR_PAUSE) && (lpar & NWAY_LPAR_ASM_DIR))
+ ifmr->ifm_active |= IFM_FLOW | IFM_ETH_TXPAUSE;
+ else if ((ar & NWAY_AR_PAUSE) && (ar & NWAY_AR_ASM_DIR) &&
+ !(lpar & NWAY_LPAR_PAUSE) && (lpar & NWAY_LPAR_ASM_DIR))
+ ifmr->ifm_active |= IFM_FLOW | IFM_ETH_RXPAUSE;
+ }
+
if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_1000_T) {
em_read_phy_reg(&sc->hw, PHY_1000T_STATUS, &gsr);
if (gsr & SR_1000T_MS_CONFIG_RES)