Commit f10fcbcf authored by Russell King's avatar Russell King Committed by David S. Miller

sfp: improve support for direct-attach copper cables

Improve the support for direct-attach copper so that we avoid kernel
warning messages, and report the appropriate PORT_DA type to userspace.
Direct Attach cables can use a number of protocols depending on their
range of speeds.
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9962acf7
...@@ -57,21 +57,19 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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");
...@@ -208,6 +222,29 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, ...@@ -208,6 +222,29 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
br_min <= 1300 && br_max >= 1200) br_min <= 1300 && br_max >= 1200)
phylink_set(support, 1000baseX_Full); 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;
......
...@@ -165,7 +165,41 @@ struct sfp_eeprom_base { ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment