mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
axgbe: apply RRC to miibus attached PHYs and add support for variable bitrate 25G SFP+ DACs
This commit is contained in:
parent
bf084b8bac
commit
d35993f92b
1 changed files with 43 additions and 16 deletions
|
|
@ -212,6 +212,7 @@ enum xgbe_sfp_speed {
|
|||
XGBE_SFP_SPEED_100_1000,
|
||||
XGBE_SFP_SPEED_1000,
|
||||
XGBE_SFP_SPEED_10000,
|
||||
XGBE_SFP_SPEED_25000,
|
||||
};
|
||||
|
||||
/* SFP Serial ID Base ID values relative to an offset of 0 */
|
||||
|
|
@ -251,6 +252,7 @@ enum xgbe_sfp_speed {
|
|||
#define XGBE_SFP_BASE_BR_1GBE_MAX 0x0d
|
||||
#define XGBE_SFP_BASE_BR_10GBE_MIN 0x64
|
||||
#define XGBE_SFP_BASE_BR_10GBE_MAX 0x68
|
||||
#define XGBE_SFP_BASE_BR_25GBE 0xFF
|
||||
|
||||
/* Single mode, length of fiber in units of km */
|
||||
#define XGBE_SFP_BASE_SM_LEN_KM 14
|
||||
|
|
@ -912,6 +914,10 @@ xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom,
|
|||
min = XGBE_SFP_BASE_BR_10GBE_MIN;
|
||||
max = XGBE_SFP_BASE_BR_10GBE_MAX;
|
||||
break;
|
||||
case XGBE_SFP_SPEED_25000:
|
||||
min = XGBE_SFP_BASE_BR_25GBE;
|
||||
max = XGBE_SFP_BASE_BR_25GBE;
|
||||
break;
|
||||
default:
|
||||
return (false);
|
||||
}
|
||||
|
|
@ -1294,10 +1300,13 @@ xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
|
|||
* 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 it's greater than 10G, we assume the DAC is capable
|
||||
* of multiple bitrates, set the MAC to 10G and hope for the best.
|
||||
*/
|
||||
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_cable == XGBE_SFP_CABLE_PASSIVE)) &&
|
||||
(xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000) ||
|
||||
xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_25000)))
|
||||
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;
|
||||
|
|
@ -2989,6 +2998,7 @@ xgbe_upd_link(struct xgbe_prv_data *pdata)
|
|||
|
||||
axgbe_printf(2, "%s: Link %d\n", __func__, pdata->phy.link);
|
||||
reg = xgbe_phy_mii_read(pdata, pdata->mdio_addr, MII_BMSR);
|
||||
reg = xgbe_phy_mii_read(pdata, pdata->mdio_addr, MII_BMSR);
|
||||
if (reg < 0)
|
||||
return (reg);
|
||||
|
||||
|
|
@ -3114,6 +3124,25 @@ xgbe_phy_read_status(struct xgbe_prv_data *pdata)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
xgbe_rrc(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_phy_data *phy_data = pdata->phy_data;
|
||||
int ret;
|
||||
|
||||
if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) {
|
||||
axgbe_printf(1, "ENTERED RRC: rrc_count: %d\n",
|
||||
phy_data->rrc_count);
|
||||
phy_data->rrc_count = 0;
|
||||
if (pdata->link_workaround) {
|
||||
ret = xgbe_phy_reset(pdata);
|
||||
if (ret)
|
||||
axgbe_error("Error resetting phy\n");
|
||||
} else
|
||||
xgbe_phy_rrc(pdata);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
|
||||
{
|
||||
|
|
@ -3139,6 +3168,11 @@ xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
|
|||
axgbe_printf(1, "%s: SFP absent 0x%x & sfp_rx_los 0x%x\n",
|
||||
__func__, phy_data->sfp_mod_absent,
|
||||
phy_data->sfp_rx_los);
|
||||
|
||||
if (!phy_data->sfp_mod_absent) {
|
||||
xgbe_rrc(pdata);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
|
@ -3149,8 +3183,8 @@ xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
|
|||
|
||||
ret = xgbe_phy_read_status(pdata);
|
||||
if (ret) {
|
||||
axgbe_printf(2, "Link: Read status returned %d\n", ret);
|
||||
return (ret);
|
||||
axgbe_error("Link: Read status returned %d\n", ret);
|
||||
return (0);
|
||||
}
|
||||
|
||||
axgbe_printf(2, "%s: link speed %#x duplex %#x media %#x "
|
||||
|
|
@ -3162,7 +3196,10 @@ xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
|
|||
if ((pdata->phy.autoneg == AUTONEG_ENABLE) && !ret)
|
||||
return (0);
|
||||
|
||||
return (pdata->phy.link);
|
||||
if (pdata->phy.link)
|
||||
return (1);
|
||||
|
||||
xgbe_rrc(pdata);
|
||||
}
|
||||
|
||||
/* Link status is latched low, so read once to clear
|
||||
|
|
@ -3175,17 +3212,7 @@ xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
|
|||
return (1);
|
||||
|
||||
/* No link, attempt a receiver reset cycle */
|
||||
if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) {
|
||||
axgbe_printf(1, "ENTERED RRC: rrc_count: %d\n",
|
||||
phy_data->rrc_count);
|
||||
phy_data->rrc_count = 0;
|
||||
if (pdata->link_workaround) {
|
||||
ret = xgbe_phy_reset(pdata);
|
||||
if (ret)
|
||||
axgbe_error("Error resetting phy\n");
|
||||
} else
|
||||
xgbe_phy_rrc(pdata);
|
||||
}
|
||||
xgbe_rrc(pdata);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue