aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/phy/sfp-bus.c61
1 files changed, 38 insertions, 23 deletions
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 8961209ee949..15749428679e 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -180,10 +180,7 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
180 unsigned long *support) 180 unsigned long *support)
181{ 181{
182 unsigned int br_min, br_nom, br_max; 182 unsigned int br_min, br_nom, br_max;
183 183 __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
184 phylink_set(support, Autoneg);
185 phylink_set(support, Pause);
186 phylink_set(support, Asym_Pause);
187 184
188 /* Decode the bitrate information to MBd */ 185 /* Decode the bitrate information to MBd */
189 br_min = br_nom = br_max = 0; 186 br_min = br_nom = br_max = 0;
@@ -201,20 +198,20 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
201 198
202 /* Set ethtool support from the compliance fields. */ 199 /* Set ethtool support from the compliance fields. */
203 if (id->base.e10g_base_sr) 200 if (id->base.e10g_base_sr)
204 phylink_set(support, 10000baseSR_Full); 201 phylink_set(modes, 10000baseSR_Full);
205 if (id->base.e10g_base_lr) 202 if (id->base.e10g_base_lr)
206 phylink_set(support, 10000baseLR_Full); 203 phylink_set(modes, 10000baseLR_Full);
207 if (id->base.e10g_base_lrm) 204 if (id->base.e10g_base_lrm)
208 phylink_set(support, 10000baseLRM_Full); 205 phylink_set(modes, 10000baseLRM_Full);
209 if (id->base.e10g_base_er) 206 if (id->base.e10g_base_er)
210 phylink_set(support, 10000baseER_Full); 207 phylink_set(modes, 10000baseER_Full);
211 if (id->base.e1000_base_sx || 208 if (id->base.e1000_base_sx ||
212 id->base.e1000_base_lx || 209 id->base.e1000_base_lx ||
213 id->base.e1000_base_cx) 210 id->base.e1000_base_cx)
214 phylink_set(support, 1000baseX_Full); 211 phylink_set(modes, 1000baseX_Full);
215 if (id->base.e1000_base_t) { 212 if (id->base.e1000_base_t) {
216 phylink_set(support, 1000baseT_Half); 213 phylink_set(modes, 1000baseT_Half);
217 phylink_set(support, 1000baseT_Full); 214 phylink_set(modes, 1000baseT_Full);
218 } 215 }
219 216
220 /* 1000Base-PX or 1000Base-BX10 */ 217 /* 1000Base-PX or 1000Base-BX10 */
@@ -228,20 +225,20 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
228 if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) { 225 if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) {
229 /* This may look odd, but some manufacturers use 12000MBd */ 226 /* This may look odd, but some manufacturers use 12000MBd */
230 if (br_min <= 12000 && br_max >= 10300) 227 if (br_min <= 12000 && br_max >= 10300)
231 phylink_set(support, 10000baseCR_Full); 228 phylink_set(modes, 10000baseCR_Full);
232 if (br_min <= 3200 && br_max >= 3100) 229 if (br_min <= 3200 && br_max >= 3100)
233 phylink_set(support, 2500baseX_Full); 230 phylink_set(modes, 2500baseX_Full);
234 if (br_min <= 1300 && br_max >= 1200) 231 if (br_min <= 1300 && br_max >= 1200)
235 phylink_set(support, 1000baseX_Full); 232 phylink_set(modes, 1000baseX_Full);
236 } 233 }
237 if (id->base.sfp_ct_passive) { 234 if (id->base.sfp_ct_passive) {
238 if (id->base.passive.sff8431_app_e) 235 if (id->base.passive.sff8431_app_e)
239 phylink_set(support, 10000baseCR_Full); 236 phylink_set(modes, 10000baseCR_Full);
240 } 237 }
241 if (id->base.sfp_ct_active) { 238 if (id->base.sfp_ct_active) {
242 if (id->base.active.sff8431_app_e || 239 if (id->base.active.sff8431_app_e ||
243 id->base.active.sff8431_lim) { 240 id->base.active.sff8431_lim) {
244 phylink_set(support, 10000baseCR_Full); 241 phylink_set(modes, 10000baseCR_Full);
245 } 242 }
246 } 243 }
247 244
@@ -249,18 +246,18 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
249 case 0x00: /* Unspecified */ 246 case 0x00: /* Unspecified */
250 break; 247 break;
251 case 0x02: /* 100Gbase-SR4 or 25Gbase-SR */ 248 case 0x02: /* 100Gbase-SR4 or 25Gbase-SR */
252 phylink_set(support, 100000baseSR4_Full); 249 phylink_set(modes, 100000baseSR4_Full);
253 phylink_set(support, 25000baseSR_Full); 250 phylink_set(modes, 25000baseSR_Full);
254 break; 251 break;
255 case 0x03: /* 100Gbase-LR4 or 25Gbase-LR */ 252 case 0x03: /* 100Gbase-LR4 or 25Gbase-LR */
256 case 0x04: /* 100Gbase-ER4 or 25Gbase-ER */ 253 case 0x04: /* 100Gbase-ER4 or 25Gbase-ER */
257 phylink_set(support, 100000baseLR4_ER4_Full); 254 phylink_set(modes, 100000baseLR4_ER4_Full);
258 break; 255 break;
259 case 0x0b: /* 100Gbase-CR4 or 25Gbase-CR CA-L */ 256 case 0x0b: /* 100Gbase-CR4 or 25Gbase-CR CA-L */
260 case 0x0c: /* 25Gbase-CR CA-S */ 257 case 0x0c: /* 25Gbase-CR CA-S */
261 case 0x0d: /* 25Gbase-CR CA-N */ 258 case 0x0d: /* 25Gbase-CR CA-N */
262 phylink_set(support, 100000baseCR4_Full); 259 phylink_set(modes, 100000baseCR4_Full);
263 phylink_set(support, 25000baseCR_Full); 260 phylink_set(modes, 25000baseCR_Full);
264 break; 261 break;
265 default: 262 default:
266 dev_warn(bus->sfp_dev, 263 dev_warn(bus->sfp_dev,
@@ -274,10 +271,28 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
274 id->base.fc_speed_200 || 271 id->base.fc_speed_200 ||
275 id->base.fc_speed_400) { 272 id->base.fc_speed_400) {
276 if (id->base.br_nominal >= 31) 273 if (id->base.br_nominal >= 31)
277 phylink_set(support, 2500baseX_Full); 274 phylink_set(modes, 2500baseX_Full);
278 if (id->base.br_nominal >= 12) 275 if (id->base.br_nominal >= 12)
279 phylink_set(support, 1000baseX_Full); 276 phylink_set(modes, 1000baseX_Full);
280 } 277 }
278
279 /* If we haven't discovered any modes that this module supports, try
280 * the encoding and bitrate to determine supported modes. Some BiDi
281 * modules (eg, 1310nm/1550nm) are not 1000BASE-BX compliant due to
282 * the differing wavelengths, so do not set any transceiver bits.
283 */
284 if (bitmap_empty(modes, __ETHTOOL_LINK_MODE_MASK_NBITS)) {
285 /* If the encoding and bit rate allows 1000baseX */
286 if (id->base.encoding == SFP_ENCODING_8B10B && br_nom &&
287 br_min <= 1300 && br_max >= 1200)
288 phylink_set(modes, 1000baseX_Full);
289 }
290
291 bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
292
293 phylink_set(support, Autoneg);
294 phylink_set(support, Pause);
295 phylink_set(support, Asym_Pause);
281} 296}
282EXPORT_SYMBOL_GPL(sfp_parse_support); 297EXPORT_SYMBOL_GPL(sfp_parse_support);
283 298