diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index 508b6cc8eddc..15033cbf7068 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -516,6 +516,15 @@ static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id, { .vendor = _v, .part = _p, .support = _s, .fixup = _f, } #define SFP_QUIRK_S(_v, _p, _s) SFP_QUIRK(_v, _p, _s, NULL) #define SFP_QUIRK_F(_v, _p, _f) SFP_QUIRK(_v, _p, NULL, _f) +/* Like SFP_QUIRK_F, but matches the part as a prefix; the vendor name + * is still matched exactly. Use for modules whose EEPROM vendor PN + * field reads back with garbage past the legitimate characters instead + * of the SFF-8472-mandated space padding, so sfp_strlen can't trim the + * field down to the legitimate length. + */ +#define SFP_QUIRK_F_PREFIX(_v, _p, _f) \ + { .vendor = _v, .part = _p, .support = NULL, .fixup = _f, \ + .part_prefix_match = true } static const struct sfp_quirk sfp_quirks[] = { // Alcatel Lucent G-010S-P can operate at 2500base-X, but incorrectly @@ -629,13 +638,16 @@ static size_t sfp_strlen(const char *str, size_t maxlen) return size; } -static bool sfp_match(const char *qs, const char *str, size_t len) +static bool sfp_match(const char *qs, const char *str, size_t len, bool prefix) { + size_t qs_len; + if (!qs) return true; - if (strlen(qs) != len) + qs_len = strlen(qs); + if (prefix ? qs_len > len : qs_len != len) return false; - return !strncmp(qs, str, len); + return !strncmp(qs, str, qs_len); } static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id) @@ -648,8 +660,9 @@ static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id) ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn)); for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++) - if (sfp_match(q->vendor, id->base.vendor_name, vs) && - sfp_match(q->part, id->base.vendor_pn, ps)) + if (sfp_match(q->vendor, id->base.vendor_name, vs, false) && + sfp_match(q->part, id->base.vendor_pn, ps, + q->part_prefix_match)) return q; return NULL; diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h index 879dff7afe6a..19fe29d844a1 100644 --- a/drivers/net/phy/sfp.h +++ b/drivers/net/phy/sfp.h @@ -12,6 +12,7 @@ struct sfp_quirk { void (*support)(const struct sfp_eeprom_id *id, struct sfp_module_caps *caps); void (*fixup)(struct sfp *sfp); + bool part_prefix_match; }; struct sfp_socket_ops {