Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 31 Jan 2021 08:47:48 GMT
From:      Vincenzo Maffione <vmaffione@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 7754ef5a3724 - stable/13 - axgbe: fix some link related issues
Message-ID:  <202101310847.10V8lmfW004713@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by vmaffione:

URL: https://cgit.FreeBSD.org/src/commit/?id=7754ef5a37245271c2a6832ad0a1289e25abff09

commit 7754ef5a37245271c2a6832ad0a1289e25abff09
Author:     Vincenzo Maffione <vmaffione@FreeBSD.org>
AuthorDate: 2021-01-23 13:44:24 +0000
Commit:     Vincenzo Maffione <vmaffione@FreeBSD.org>
CommitDate: 2021-01-31 08:47:36 +0000

    axgbe: fix some link related issues
    
    By default, axgbe driver does a receiver reset after predefined number
    of retries for the link to come up. However, this receiver reset
    doesn't always suffice, due to an hardware issue.
    In that case, as a workaround, a complete phy reset is necessary.
    This patch introduces a sysctl that can be set to 1 to let the driver
    reset the phy completely, rather than just doing receiver reset.
    The workaround will be removed once the issue is fixed by means
    of firmware update.
    
    This patch also fixes the handling of the direct attach cables
    properly.
    
    Submitted by:   rajesh1.kumar_amd.com
    Differential Revision:  https://reviews.freebsd.org/D28266
    
    (cherry picked from commit bfd75d45571958398a043517060d8c3d352e7dbd)
---
 sys/dev/axgbe/xgbe-phy-v2.c | 26 ++++++++++++++++++++------
 sys/dev/axgbe/xgbe-sysctl.c |  4 ++++
 sys/dev/axgbe/xgbe.h        |  1 +
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/sys/dev/axgbe/xgbe-phy-v2.c b/sys/dev/axgbe/xgbe-phy-v2.c
index 5fb6e960eab5..df8a75a145b9 100644
--- a/sys/dev/axgbe/xgbe-phy-v2.c
+++ b/sys/dev/axgbe/xgbe-phy-v2.c
@@ -213,6 +213,9 @@ enum xgbe_sfp_speed {
 #define XGBE_SFP_BASE_EXT_ID			1
 #define XGBE_SFP_EXT_ID_SFP			0x04
 
+#define XGBE_SFP_BASE_CV			2
+#define XGBE_SFP_BASE_CV_CP			0x21
+
 #define XGBE_SFP_BASE_10GBE_CC			3
 #define XGBE_SFP_BASE_10GBE_CC_SR		BIT(4)
 #define XGBE_SFP_BASE_10GBE_CC_LR		BIT(5)
@@ -380,6 +383,7 @@ struct xgbe_phy_data {
 };
 
 static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata);
+static int xgbe_phy_reset(struct xgbe_prv_data *pdata);
 
 static int
 xgbe_phy_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *i2c_op)
@@ -1209,8 +1213,16 @@ xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
 	} else
 		phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
 
-	/* Determine the type of SFP */
-	if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR)
+	/*
+	 * Determine the type of SFP. Certain 10G SFP+ modules read as
+	 * 1000BASE-CX. To prevent 10G DAC cables to be recognized as
+	 * 1G, we first check if it is a DAC and the bitrate is 10G.
+	 */
+	if (((sfp_base[XGBE_SFP_BASE_CV] & XGBE_SFP_BASE_CV_CP) ||
+	    (phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE)) &&
+	    xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000))
+		phy_data->sfp_base = XGBE_SFP_BASE_10000_CR;
+	else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR)
 		phy_data->sfp_base = XGBE_SFP_BASE_10000_SR;
 	else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_LR)
 		phy_data->sfp_base = XGBE_SFP_BASE_10000_LR;
@@ -1226,9 +1238,6 @@ xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
 		phy_data->sfp_base = XGBE_SFP_BASE_1000_CX;
 	else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_T)
 		phy_data->sfp_base = XGBE_SFP_BASE_1000_T;
-	else if ((phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE) &&
-		 xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000))
-		phy_data->sfp_base = XGBE_SFP_BASE_10000_CR;
 
 	switch (phy_data->sfp_base) {
 	case XGBE_SFP_BASE_1000_T:
@@ -2879,7 +2888,12 @@ xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
 		axgbe_printf(1, "ENTERED RRC: rrc_count: %d\n",
 		    phy_data->rrc_count);
 		phy_data->rrc_count = 0;
-		xgbe_phy_rrc(pdata);
+		if (pdata->link_workaround) {
+			ret = xgbe_phy_reset(pdata);
+			if (ret)
+				axgbe_error("Error resetting phy\n");
+		} else
+			xgbe_phy_rrc(pdata);
 	}
 
 	return (0);
diff --git a/sys/dev/axgbe/xgbe-sysctl.c b/sys/dev/axgbe/xgbe-sysctl.c
index a3e777e0ca26..f7998b943b16 100644
--- a/sys/dev/axgbe/xgbe-sysctl.c
+++ b/sys/dev/axgbe/xgbe-sysctl.c
@@ -1618,6 +1618,10 @@ axgbe_sysctl_init(struct xgbe_prv_data *pdata)
 	    CTLFLAG_RDTUN, &pdata->sph_enable, 1,
 	    "shows the split header feature state (1 - enable, 0 - disable");
 
+	SYSCTL_ADD_UINT(clist, top, OID_AUTO, "link_workaround",
+	    CTLFLAG_RWTUN, &pdata->link_workaround, 0,
+	    "enable the workaround for link issue in coming up");
+
 	SYSCTL_ADD_PROC(clist, top, OID_AUTO, "xgmac_register",
 	    CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
 	    pdata, 0, sysctl_xgmac_reg_addr_handler, "IU",
diff --git a/sys/dev/axgbe/xgbe.h b/sys/dev/axgbe/xgbe.h
index 766c0c6f551a..85b4c0c5c5d0 100644
--- a/sys/dev/axgbe/xgbe.h
+++ b/sys/dev/axgbe/xgbe.h
@@ -1302,6 +1302,7 @@ struct xgbe_prv_data {
 	 * This requires a complete restart.
 	 */
 	unsigned int sph_enable;
+	unsigned int link_workaround;
 };
 
 struct axgbe_if_softc {



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