Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 May 2012 04:32:27 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r236217 - stable/8/sys/dev/bce
Message-ID:  <201205290432.q4T4WR85052571@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Tue May 29 04:32:27 2012
New Revision: 236217
URL: http://svn.freebsd.org/changeset/base/236217

Log:
  MFC r235816:
    Make IPMI work in the bce driver even when the interface is
    configured down.  Formerly, IPMI communication was lost whenever the
    interface was not up.  The reason was that the BCE_EMAC_MODE
    register was not configured with the correct media settings.  There
    are two parts to the fix.
  
    First, resetting the chip in bce_reset() causes the BCE_EMAC_MODE
    register to be initialized to a default value that does not
    necessarily correspond to the actual media settings.  The fix
    implemented here is a bit of a hack.  Ideally, at the end of
    bce_reset() we would poll the PHY to determine the negotiated media,
    and then we would set the BCE_EMAC_MODE register accordingly.  That
    is difficult, since the PHY is abstracted behind the MII layer and is
    not supposed to be queried directly from the MAC driver.  Instead,
    we read the BCE_EMAC_MODE register at the beginning of bce_reset()
    and then restore its media bits to their original values before
    returning.  If IPMI is up and running, then the link is already
    established and the BCE_EMAC_MODE register is already set appropriately
    when bce_reset() is called.  If IPMI is not running, no harm is
    done by preserving the BCE_EMAC_MODE settings.  The driver will set
    the register properly once the interface is configured up and link
    is established.
  
    Second, bce_miibus_statchg() is sometimes called when the link is
    down.  In that case, the reported media settings are invalid.
    Formerly, the driver used them anyway to setup the BCE_EMAC_MODE
    register.  We now avoid changing any MAC registers unless link is
    active and the reported media settings are valid.
  
    Submitted by:	jdp
    Tested by:	jdp

Modified:
  stable/8/sys/dev/bce/if_bce.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/boot/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/e1000/   (props changed)

Modified: stable/8/sys/dev/bce/if_bce.c
==============================================================================
--- stable/8/sys/dev/bce/if_bce.c	Tue May 29 04:30:02 2012	(r236216)
+++ stable/8/sys/dev/bce/if_bce.c	Tue May 29 04:32:27 2012	(r236217)
@@ -2062,6 +2062,11 @@ bce_miibus_statchg(device_t dev)
 		media_status = mii->mii_media_status;
 	}
 
+	/* Ignore invalid media status. */
+	if ((media_status & (IFM_ACTIVE | IFM_AVALID)) !=
+	    (IFM_ACTIVE | IFM_AVALID))
+		goto bce_miibus_statchg_exit;
+
 	val = REG_RD(sc, BCE_EMAC_MODE);
 	val &= ~(BCE_EMAC_MODE_PORT | BCE_EMAC_MODE_HALF_DUPLEX |
 	    BCE_EMAC_MODE_MAC_LOOP | BCE_EMAC_MODE_FORCE_LINK |
@@ -2131,6 +2136,7 @@ bce_miibus_statchg(device_t dev)
 
 	/* ToDo: Update watermarks in bce_init_rx_context(). */
 
+bce_miibus_statchg_exit:
 	DBEXIT(BCE_VERBOSE_PHY);
 }
 
@@ -4997,14 +5003,25 @@ bce_stop(struct bce_softc *sc)
 static int
 bce_reset(struct bce_softc *sc, u32 reset_code)
 {
-	u32 val;
+	u32 emac_mode_save, val;
 	int i, rc = 0;
+	static const u32 emac_mode_mask = BCE_EMAC_MODE_PORT |
+	    BCE_EMAC_MODE_HALF_DUPLEX | BCE_EMAC_MODE_25G;
 
 	DBENTER(BCE_VERBOSE_RESET);
 
 	DBPRINT(sc, BCE_VERBOSE_RESET, "%s(): reset_code = 0x%08X\n",
 	    __FUNCTION__, reset_code);
 
+	/*
+	 * If ASF/IPMI is operational, then the EMAC Mode register already
+	 * contains appropriate values for the link settings that have
+	 * been auto-negotiated.  Resetting the chip will clobber those
+	 * values.  Save the important bits so we can restore them after
+	 * the reset.
+	 */
+	emac_mode_save = REG_RD(sc, BCE_EMAC_MODE) & emac_mode_mask;
+
 	/* Wait for pending PCI transactions to complete. */
 	REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS,
 	    BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
@@ -5094,6 +5111,11 @@ bce_reset(struct bce_softc *sc, u32 rese
 	bce_fw_cap_init(sc);
 
 bce_reset_exit:
+	/* Restore EMAC Mode bits needed to keep ASF/IPMI running. */
+	val = REG_RD(sc, BCE_EMAC_MODE);
+	val = (val & ~emac_mode_mask) | emac_mode_save;
+	REG_WR(sc, BCE_EMAC_MODE, val);
+
 	DBEXIT(BCE_VERBOSE_RESET);
 	return (rc);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201205290432.q4T4WR85052571>