summaryrefslogtreecommitdiff
path: root/drivers/net/phy/sfp.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2018-03-28 11:18:25 +0100
committerDavid S. Miller <davem@davemloft.net>2018-03-29 14:30:41 -0400
commit981f1f803516666d3e02f1d707a7f4b0ebf41967 (patch)
treecfb398d457f839ce9ea7a9ab8f03024e49bf830e /drivers/net/phy/sfp.c
parent5593e3340f32f43eede742a96cbf9603fbe6003b (diff)
sfp: allow cotsworks modules
Cotsworks modules fail the checksums - it appears that Cotsworks reprograms the EEPROM at the end of production with the final product information (serial, date code, and exact part number for module options) and fails to update the checksum. Work around this by detecting the Cotsworks name in the manufacturer field, and reducing the checksum failures to warnings rather than a hard error. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/sfp.c')
-rw-r--r--drivers/net/phy/sfp.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 83bf4959b043..4ab6e9a50bbe 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -560,6 +560,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
{
/* SFP module inserted - read I2C data */
struct sfp_eeprom_id id;
+ bool cotsworks;
u8 check;
int ret;
@@ -574,23 +575,43 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
return -EAGAIN;
}
+ /* Cotsworks do not seem to update the checksums when they
+ * do the final programming with the final module part number,
+ * serial number and date code.
+ */
+ cotsworks = !memcmp(id.base.vendor_name, "COTSWORKS ", 16);
+
/* Validate the checksum over the base structure */
check = sfp_check(&id.base, sizeof(id.base) - 1);
if (check != id.base.cc_base) {
- dev_err(sfp->dev,
- "EEPROM base structure checksum failure: 0x%02x\n",
- check);
- print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
- 16, 1, &id, sizeof(id.base) - 1, true);
- return -EINVAL;
+ if (cotsworks) {
+ dev_warn(sfp->dev,
+ "EEPROM base structure checksum failure (0x%02x != 0x%02x)\n",
+ check, id.base.cc_base);
+ } else {
+ dev_err(sfp->dev,
+ "EEPROM base structure checksum failure: 0x%02x != 0x%02x\n",
+ check, id.base.cc_base);
+ print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
+ 16, 1, &id, sizeof(id), true);
+ return -EINVAL;
+ }
}
check = sfp_check(&id.ext, sizeof(id.ext) - 1);
if (check != id.ext.cc_ext) {
- dev_err(sfp->dev,
- "EEPROM extended structure checksum failure: 0x%02x\n",
- check);
- memset(&id.ext, 0, sizeof(id.ext));
+ if (cotsworks) {
+ dev_warn(sfp->dev,
+ "EEPROM extended structure checksum failure (0x%02x != 0x%02x)\n",
+ check, id.ext.cc_ext);
+ } else {
+ dev_err(sfp->dev,
+ "EEPROM extended structure checksum failure: 0x%02x != 0x%02x\n",
+ check, id.ext.cc_ext);
+ print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
+ 16, 1, &id, sizeof(id), true);
+ memset(&id.ext, 0, sizeof(id.ext));
+ }
}
sfp->id = id;