Merge branch 'further-sfp-phylink-updates'
Russell King says: ==================== further sfp/phylink updates This series: - cleans up printing of module information - improves the transceiver capability decoding, getting rid of the guessing by connector type, improves direct-attach cable support and adds support for 1G Base-PX and Base-BX10 modules. - cleans up phylink_sfp_module_insert() ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
f619b00900
@ -1578,7 +1578,7 @@ static int phylink_sfp_module_insert(void *upstream,
|
|||||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
|
__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
|
||||||
struct phylink_link_state config;
|
struct phylink_link_state config;
|
||||||
phy_interface_t iface;
|
phy_interface_t iface;
|
||||||
int mode, ret = 0;
|
int ret = 0;
|
||||||
bool changed;
|
bool changed;
|
||||||
u8 port;
|
u8 port;
|
||||||
|
|
||||||
@ -1593,7 +1593,6 @@ static int phylink_sfp_module_insert(void *upstream,
|
|||||||
case PHY_INTERFACE_MODE_1000BASEX:
|
case PHY_INTERFACE_MODE_1000BASEX:
|
||||||
case PHY_INTERFACE_MODE_2500BASEX:
|
case PHY_INTERFACE_MODE_2500BASEX:
|
||||||
case PHY_INTERFACE_MODE_10GKR:
|
case PHY_INTERFACE_MODE_10GKR:
|
||||||
mode = MLO_AN_INBAND;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1611,13 +1610,15 @@ static int phylink_sfp_module_insert(void *upstream,
|
|||||||
ret = phylink_validate(pl, support, &config);
|
ret = phylink_validate(pl, support, &config);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
netdev_err(pl->netdev, "validation of %s/%s with support %*pb failed: %d\n",
|
netdev_err(pl->netdev, "validation of %s/%s with support %*pb failed: %d\n",
|
||||||
phylink_an_mode_str(mode), phy_modes(config.interface),
|
phylink_an_mode_str(MLO_AN_INBAND),
|
||||||
|
phy_modes(config.interface),
|
||||||
__ETHTOOL_LINK_MODE_MASK_NBITS, support, ret);
|
__ETHTOOL_LINK_MODE_MASK_NBITS, support, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev_dbg(pl->netdev, "requesting link mode %s/%s with support %*pb\n",
|
netdev_dbg(pl->netdev, "requesting link mode %s/%s with support %*pb\n",
|
||||||
phylink_an_mode_str(mode), phy_modes(config.interface),
|
phylink_an_mode_str(MLO_AN_INBAND),
|
||||||
|
phy_modes(config.interface),
|
||||||
__ETHTOOL_LINK_MODE_MASK_NBITS, support);
|
__ETHTOOL_LINK_MODE_MASK_NBITS, support);
|
||||||
|
|
||||||
if (phy_interface_mode_is_8023z(iface) && pl->phydev)
|
if (phy_interface_mode_is_8023z(iface) && pl->phydev)
|
||||||
@ -1630,15 +1631,15 @@ static int phylink_sfp_module_insert(void *upstream,
|
|||||||
linkmode_copy(pl->link_config.advertising, config.advertising);
|
linkmode_copy(pl->link_config.advertising, config.advertising);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pl->link_an_mode != mode ||
|
if (pl->link_an_mode != MLO_AN_INBAND ||
|
||||||
pl->link_config.interface != config.interface) {
|
pl->link_config.interface != config.interface) {
|
||||||
pl->link_config.interface = config.interface;
|
pl->link_config.interface = config.interface;
|
||||||
pl->link_an_mode = mode;
|
pl->link_an_mode = MLO_AN_INBAND;
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
netdev_info(pl->netdev, "switched to %s/%s link mode\n",
|
netdev_info(pl->netdev, "switched to %s/%s link mode\n",
|
||||||
phylink_an_mode_str(mode),
|
phylink_an_mode_str(MLO_AN_INBAND),
|
||||||
phy_modes(config.interface));
|
phy_modes(config.interface));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,21 +57,19 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
|||||||
case SFP_CONNECTOR_MT_RJ:
|
case SFP_CONNECTOR_MT_RJ:
|
||||||
case SFP_CONNECTOR_MU:
|
case SFP_CONNECTOR_MU:
|
||||||
case SFP_CONNECTOR_OPTICAL_PIGTAIL:
|
case SFP_CONNECTOR_OPTICAL_PIGTAIL:
|
||||||
if (support)
|
|
||||||
phylink_set(support, FIBRE);
|
|
||||||
port = PORT_FIBRE;
|
port = PORT_FIBRE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SFP_CONNECTOR_RJ45:
|
case SFP_CONNECTOR_RJ45:
|
||||||
if (support)
|
|
||||||
phylink_set(support, TP);
|
|
||||||
port = PORT_TP;
|
port = PORT_TP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SFP_CONNECTOR_COPPER_PIGTAIL:
|
||||||
|
port = PORT_DA;
|
||||||
|
break;
|
||||||
|
|
||||||
case SFP_CONNECTOR_UNSPEC:
|
case SFP_CONNECTOR_UNSPEC:
|
||||||
if (id->base.e1000_base_t) {
|
if (id->base.e1000_base_t) {
|
||||||
if (support)
|
|
||||||
phylink_set(support, TP);
|
|
||||||
port = PORT_TP;
|
port = PORT_TP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -80,7 +78,6 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
|||||||
case SFP_CONNECTOR_MPO_1X12:
|
case SFP_CONNECTOR_MPO_1X12:
|
||||||
case SFP_CONNECTOR_MPO_2X16:
|
case SFP_CONNECTOR_MPO_2X16:
|
||||||
case SFP_CONNECTOR_HSSDC_II:
|
case SFP_CONNECTOR_HSSDC_II:
|
||||||
case SFP_CONNECTOR_COPPER_PIGTAIL:
|
|
||||||
case SFP_CONNECTOR_NOSEPARATE:
|
case SFP_CONNECTOR_NOSEPARATE:
|
||||||
case SFP_CONNECTOR_MXC_2X16:
|
case SFP_CONNECTOR_MXC_2X16:
|
||||||
port = PORT_OTHER;
|
port = PORT_OTHER;
|
||||||
@ -92,6 +89,18 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (support) {
|
||||||
|
switch (port) {
|
||||||
|
case PORT_FIBRE:
|
||||||
|
phylink_set(support, FIBRE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PORT_TP:
|
||||||
|
phylink_set(support, TP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(sfp_parse_port);
|
EXPORT_SYMBOL_GPL(sfp_parse_port);
|
||||||
@ -143,6 +152,11 @@ phy_interface_t sfp_parse_interface(struct sfp_bus *bus,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (id->base.e1000_base_cx) {
|
||||||
|
iface = PHY_INTERFACE_MODE_1000BASEX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
iface = PHY_INTERFACE_MODE_NA;
|
iface = PHY_INTERFACE_MODE_NA;
|
||||||
dev_err(bus->sfp_dev,
|
dev_err(bus->sfp_dev,
|
||||||
"SFP module encoding does not support 8b10b nor 64b66b\n");
|
"SFP module encoding does not support 8b10b nor 64b66b\n");
|
||||||
@ -165,10 +179,26 @@ EXPORT_SYMBOL_GPL(sfp_parse_interface);
|
|||||||
void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
||||||
unsigned long *support)
|
unsigned long *support)
|
||||||
{
|
{
|
||||||
|
unsigned int br_min, br_nom, br_max;
|
||||||
|
|
||||||
phylink_set(support, Autoneg);
|
phylink_set(support, Autoneg);
|
||||||
phylink_set(support, Pause);
|
phylink_set(support, Pause);
|
||||||
phylink_set(support, Asym_Pause);
|
phylink_set(support, Asym_Pause);
|
||||||
|
|
||||||
|
/* Decode the bitrate information to MBd */
|
||||||
|
br_min = br_nom = br_max = 0;
|
||||||
|
if (id->base.br_nominal) {
|
||||||
|
if (id->base.br_nominal != 255) {
|
||||||
|
br_nom = id->base.br_nominal * 100;
|
||||||
|
br_min = br_nom + id->base.br_nominal * id->ext.br_min;
|
||||||
|
br_max = br_nom + id->base.br_nominal * id->ext.br_max;
|
||||||
|
} else if (id->ext.br_max) {
|
||||||
|
br_nom = 250 * id->ext.br_max;
|
||||||
|
br_max = br_nom + br_nom * id->ext.br_min / 100;
|
||||||
|
br_min = br_nom - br_nom * id->ext.br_min / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Set ethtool support from the compliance fields. */
|
/* Set ethtool support from the compliance fields. */
|
||||||
if (id->base.e10g_base_sr)
|
if (id->base.e10g_base_sr)
|
||||||
phylink_set(support, 10000baseSR_Full);
|
phylink_set(support, 10000baseSR_Full);
|
||||||
@ -187,6 +217,34 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
|||||||
phylink_set(support, 1000baseT_Full);
|
phylink_set(support, 1000baseT_Full);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 1000Base-PX or 1000Base-BX10 */
|
||||||
|
if ((id->base.e_base_px || id->base.e_base_bx10) &&
|
||||||
|
br_min <= 1300 && br_max >= 1200)
|
||||||
|
phylink_set(support, 1000baseX_Full);
|
||||||
|
|
||||||
|
/* For active or passive cables, select the link modes
|
||||||
|
* based on the bit rates and the cable compliance bytes.
|
||||||
|
*/
|
||||||
|
if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) {
|
||||||
|
/* This may look odd, but some manufacturers use 12000MBd */
|
||||||
|
if (br_min <= 12000 && br_max >= 10300)
|
||||||
|
phylink_set(support, 10000baseCR_Full);
|
||||||
|
if (br_min <= 3200 && br_max >= 3100)
|
||||||
|
phylink_set(support, 2500baseX_Full);
|
||||||
|
if (br_min <= 1300 && br_max >= 1200)
|
||||||
|
phylink_set(support, 1000baseX_Full);
|
||||||
|
}
|
||||||
|
if (id->base.sfp_ct_passive) {
|
||||||
|
if (id->base.passive.sff8431_app_e)
|
||||||
|
phylink_set(support, 10000baseCR_Full);
|
||||||
|
}
|
||||||
|
if (id->base.sfp_ct_active) {
|
||||||
|
if (id->base.active.sff8431_app_e ||
|
||||||
|
id->base.active.sff8431_lim) {
|
||||||
|
phylink_set(support, 10000baseCR_Full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (id->base.extended_cc) {
|
switch (id->base.extended_cc) {
|
||||||
case 0x00: /* Unspecified */
|
case 0x00: /* Unspecified */
|
||||||
break;
|
break;
|
||||||
@ -220,35 +278,6 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
|
|||||||
if (id->base.br_nominal >= 12)
|
if (id->base.br_nominal >= 12)
|
||||||
phylink_set(support, 1000baseX_Full);
|
phylink_set(support, 1000baseX_Full);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (id->base.connector) {
|
|
||||||
case SFP_CONNECTOR_SC:
|
|
||||||
case SFP_CONNECTOR_FIBERJACK:
|
|
||||||
case SFP_CONNECTOR_LC:
|
|
||||||
case SFP_CONNECTOR_MT_RJ:
|
|
||||||
case SFP_CONNECTOR_MU:
|
|
||||||
case SFP_CONNECTOR_OPTICAL_PIGTAIL:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SFP_CONNECTOR_UNSPEC:
|
|
||||||
if (id->base.e1000_base_t)
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SFP_CONNECTOR_SG: /* guess */
|
|
||||||
case SFP_CONNECTOR_MPO_1X12:
|
|
||||||
case SFP_CONNECTOR_MPO_2X16:
|
|
||||||
case SFP_CONNECTOR_HSSDC_II:
|
|
||||||
case SFP_CONNECTOR_COPPER_PIGTAIL:
|
|
||||||
case SFP_CONNECTOR_NOSEPARATE:
|
|
||||||
case SFP_CONNECTOR_MXC_2X16:
|
|
||||||
default:
|
|
||||||
/* a guess at the supported link modes */
|
|
||||||
dev_warn(bus->sfp_dev,
|
|
||||||
"Guessing link modes, please report...\n");
|
|
||||||
phylink_set(support, 1000baseT_Half);
|
|
||||||
phylink_set(support, 1000baseT_Full);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(sfp_parse_support);
|
EXPORT_SYMBOL_GPL(sfp_parse_support);
|
||||||
|
|
||||||
|
@ -466,11 +466,6 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
|
|||||||
{
|
{
|
||||||
/* SFP module inserted - read I2C data */
|
/* SFP module inserted - read I2C data */
|
||||||
struct sfp_eeprom_id id;
|
struct sfp_eeprom_id id;
|
||||||
char vendor[17];
|
|
||||||
char part[17];
|
|
||||||
char sn[17];
|
|
||||||
char date[9];
|
|
||||||
char rev[5];
|
|
||||||
u8 check;
|
u8 check;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -506,19 +501,12 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
|
|||||||
|
|
||||||
sfp->id = id;
|
sfp->id = id;
|
||||||
|
|
||||||
memcpy(vendor, sfp->id.base.vendor_name, 16);
|
dev_info(sfp->dev, "module %.*s %.*s rev %.*s sn %.*s dc %.*s\n",
|
||||||
vendor[16] = '\0';
|
(int)sizeof(id.base.vendor_name), id.base.vendor_name,
|
||||||
memcpy(part, sfp->id.base.vendor_pn, 16);
|
(int)sizeof(id.base.vendor_pn), id.base.vendor_pn,
|
||||||
part[16] = '\0';
|
(int)sizeof(id.base.vendor_rev), id.base.vendor_rev,
|
||||||
memcpy(rev, sfp->id.base.vendor_rev, 4);
|
(int)sizeof(id.ext.vendor_sn), id.ext.vendor_sn,
|
||||||
rev[4] = '\0';
|
(int)sizeof(id.ext.datecode), id.ext.datecode);
|
||||||
memcpy(sn, sfp->id.ext.vendor_sn, 16);
|
|
||||||
sn[16] = '\0';
|
|
||||||
memcpy(date, sfp->id.ext.datecode, 8);
|
|
||||||
date[8] = '\0';
|
|
||||||
|
|
||||||
dev_info(sfp->dev, "module %s %s rev %s sn %s dc %s\n",
|
|
||||||
vendor, part, rev, sn, date);
|
|
||||||
|
|
||||||
/* Check whether we support this module */
|
/* Check whether we support this module */
|
||||||
if (!sfp->type->module_supported(&sfp->id)) {
|
if (!sfp->type->module_supported(&sfp->id)) {
|
||||||
|
@ -165,7 +165,41 @@ struct sfp_eeprom_base {
|
|||||||
char vendor_rev[4];
|
char vendor_rev[4];
|
||||||
union {
|
union {
|
||||||
__be16 optical_wavelength;
|
__be16 optical_wavelength;
|
||||||
u8 cable_spec;
|
__be16 cable_compliance;
|
||||||
|
struct {
|
||||||
|
#if defined __BIG_ENDIAN_BITFIELD
|
||||||
|
u8 reserved60_2:6;
|
||||||
|
u8 fc_pi_4_app_h:1;
|
||||||
|
u8 sff8431_app_e:1;
|
||||||
|
u8 reserved61:8;
|
||||||
|
#elif defined __LITTLE_ENDIAN_BITFIELD
|
||||||
|
u8 sff8431_app_e:1;
|
||||||
|
u8 fc_pi_4_app_h:1;
|
||||||
|
u8 reserved60_2:6;
|
||||||
|
u8 reserved61:8;
|
||||||
|
#else
|
||||||
|
#error Unknown Endian
|
||||||
|
#endif
|
||||||
|
} __packed passive;
|
||||||
|
struct {
|
||||||
|
#if defined __BIG_ENDIAN_BITFIELD
|
||||||
|
u8 reserved60_4:4;
|
||||||
|
u8 fc_pi_4_lim:1;
|
||||||
|
u8 sff8431_lim:1;
|
||||||
|
u8 fc_pi_4_app_h:1;
|
||||||
|
u8 sff8431_app_e:1;
|
||||||
|
u8 reserved61:8;
|
||||||
|
#elif defined __LITTLE_ENDIAN_BITFIELD
|
||||||
|
u8 sff8431_app_e:1;
|
||||||
|
u8 fc_pi_4_app_h:1;
|
||||||
|
u8 sff8431_lim:1;
|
||||||
|
u8 fc_pi_4_lim:1;
|
||||||
|
u8 reserved60_4:4;
|
||||||
|
u8 reserved61:8;
|
||||||
|
#else
|
||||||
|
#error Unknown Endian
|
||||||
|
#endif
|
||||||
|
} __packed active;
|
||||||
} __packed;
|
} __packed;
|
||||||
u8 reserved62;
|
u8 reserved62;
|
||||||
u8 cc_base;
|
u8 cc_base;
|
||||||
|
Loading…
Reference in New Issue
Block a user