Skip to content

Commit c06ca8c

Browse files
committed
Merge branch 'net-fix-optical-sfp-failures'
Russell King says: ==================== net: fix optical SFP failures A regression was reported back in April concerning pcs-lynx and 10G optical SFPs. This patch series addresses that regression, and likely similar unreported regressions. These patches: - Add phy_interface_weight() which will be used in the solution. - Split out the code that determines the inband "type" for an interface mode. - Clear the Autoneg bit in the advertising mask, or the Autoneg bit in the support mask and the entire advertising mask if the selected interface mode has no inband capabilties. Tested with the mvpp2 patch posted earlier today. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents fa39032 + a212027 commit c06ca8c

File tree

2 files changed

+67
-35
lines changed

2 files changed

+67
-35
lines changed

drivers/net/phy/phylink.c

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,42 @@ static void phylink_pcs_an_restart(struct phylink *pl)
10161016
pl->pcs->ops->pcs_an_restart(pl->pcs);
10171017
}
10181018

1019+
enum inband_type {
1020+
INBAND_NONE,
1021+
INBAND_CISCO_SGMII,
1022+
INBAND_BASEX,
1023+
};
1024+
1025+
static enum inband_type phylink_get_inband_type(phy_interface_t interface)
1026+
{
1027+
switch (interface) {
1028+
case PHY_INTERFACE_MODE_SGMII:
1029+
case PHY_INTERFACE_MODE_QSGMII:
1030+
case PHY_INTERFACE_MODE_QUSGMII:
1031+
case PHY_INTERFACE_MODE_USXGMII:
1032+
case PHY_INTERFACE_MODE_10G_QXGMII:
1033+
/* These protocols are designed for use with a PHY which
1034+
* communicates its negotiation result back to the MAC via
1035+
* inband communication. Note: there exist PHYs that run
1036+
* with SGMII but do not send the inband data.
1037+
*/
1038+
return INBAND_CISCO_SGMII;
1039+
1040+
case PHY_INTERFACE_MODE_1000BASEX:
1041+
case PHY_INTERFACE_MODE_2500BASEX:
1042+
/* 1000base-X is designed for use media-side for Fibre
1043+
* connections, and thus the Autoneg bit needs to be
1044+
* taken into account. We also do this for 2500base-X
1045+
* as well, but drivers may not support this, so may
1046+
* need to override this.
1047+
*/
1048+
return INBAND_BASEX;
1049+
1050+
default:
1051+
return INBAND_NONE;
1052+
}
1053+
}
1054+
10191055
/**
10201056
* phylink_pcs_neg_mode() - helper to determine PCS inband mode
10211057
* @pl: a pointer to a &struct phylink returned from phylink_create()
@@ -1043,46 +1079,19 @@ static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
10431079
unsigned int pcs_ib_caps = 0;
10441080
unsigned int phy_ib_caps = 0;
10451081
unsigned int neg_mode, mode;
1046-
enum {
1047-
INBAND_CISCO_SGMII,
1048-
INBAND_BASEX,
1049-
} type;
1050-
1051-
mode = pl->req_link_an_mode;
1052-
1053-
pl->phy_ib_mode = 0;
1082+
enum inband_type type;
10541083

1055-
switch (interface) {
1056-
case PHY_INTERFACE_MODE_SGMII:
1057-
case PHY_INTERFACE_MODE_QSGMII:
1058-
case PHY_INTERFACE_MODE_QUSGMII:
1059-
case PHY_INTERFACE_MODE_USXGMII:
1060-
case PHY_INTERFACE_MODE_10G_QXGMII:
1061-
/* These protocols are designed for use with a PHY which
1062-
* communicates its negotiation result back to the MAC via
1063-
* inband communication. Note: there exist PHYs that run
1064-
* with SGMII but do not send the inband data.
1065-
*/
1066-
type = INBAND_CISCO_SGMII;
1067-
break;
1068-
1069-
case PHY_INTERFACE_MODE_1000BASEX:
1070-
case PHY_INTERFACE_MODE_2500BASEX:
1071-
/* 1000base-X is designed for use media-side for Fibre
1072-
* connections, and thus the Autoneg bit needs to be
1073-
* taken into account. We also do this for 2500base-X
1074-
* as well, but drivers may not support this, so may
1075-
* need to override this.
1076-
*/
1077-
type = INBAND_BASEX;
1078-
break;
1079-
1080-
default:
1084+
type = phylink_get_inband_type(interface);
1085+
if (type == INBAND_NONE) {
10811086
pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
1082-
pl->act_link_an_mode = mode;
1087+
pl->act_link_an_mode = pl->req_link_an_mode;
10831088
return;
10841089
}
10851090

1091+
mode = pl->req_link_an_mode;
1092+
1093+
pl->phy_ib_mode = 0;
1094+
10861095
if (pcs)
10871096
pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface);
10881097

@@ -3625,6 +3634,7 @@ static int phylink_sfp_config_optical(struct phylink *pl)
36253634
{
36263635
__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
36273636
struct phylink_link_state config;
3637+
enum inband_type inband_type;
36283638
phy_interface_t interface;
36293639
int ret;
36303640

@@ -3671,6 +3681,23 @@ static int phylink_sfp_config_optical(struct phylink *pl)
36713681
phylink_dbg(pl, "optical SFP: chosen %s interface\n",
36723682
phy_modes(interface));
36733683

3684+
inband_type = phylink_get_inband_type(interface);
3685+
if (inband_type == INBAND_NONE) {
3686+
/* If this is the sole interface, and there is no inband
3687+
* support, clear the advertising mask and Autoneg bit in
3688+
* the support mask. Otherwise, just clear the Autoneg bit
3689+
* in the advertising mask.
3690+
*/
3691+
if (phy_interface_weight(pl->sfp_interfaces) == 1) {
3692+
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
3693+
pl->sfp_support);
3694+
linkmode_zero(config.advertising);
3695+
} else {
3696+
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
3697+
config.advertising);
3698+
}
3699+
}
3700+
36743701
if (!phylink_validate_pcs_inband_autoneg(pl, interface,
36753702
config.advertising)) {
36763703
phylink_err(pl, "autoneg setting not compatible with PCS");

include/linux/phy.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ static inline bool phy_interface_empty(const unsigned long *intf)
169169
return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX);
170170
}
171171

172+
static inline unsigned int phy_interface_weight(const unsigned long *intf)
173+
{
174+
return bitmap_weight(intf, PHY_INTERFACE_MODE_MAX);
175+
}
176+
172177
static inline void phy_interface_and(unsigned long *dst, const unsigned long *a,
173178
const unsigned long *b)
174179
{

0 commit comments

Comments
 (0)