aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/axgbe/xgbe-phy-v2.c
diff options
context:
space:
mode:
authorVincenzo Maffione <vmaffione@FreeBSD.org>2021-01-23 13:44:24 +0000
committerVincenzo Maffione <vmaffione@FreeBSD.org>2021-01-23 13:51:29 +0000
commitbfd75d45571958398a043517060d8c3d352e7dbd (patch)
tree8515162fdbdd463954e8105913bc5ce525c86a87 /sys/dev/axgbe/xgbe-phy-v2.c
parent6c789c55c4ba11014bfd1b59942c204615412ba6 (diff)
downloadsrc-bfd75d45571958398a043517060d8c3d352e7dbd.tar.gz
src-bfd75d45571958398a043517060d8c3d352e7dbd.zip
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
Diffstat (limited to 'sys/dev/axgbe/xgbe-phy-v2.c')
-rw-r--r--sys/dev/axgbe/xgbe-phy-v2.c26
1 files changed, 20 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);