aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sfc/ethtool.c3
-rw-r--r--drivers/net/sfc/mdio_10g.c177
-rw-r--r--drivers/net/sfc/mdio_10g.h3
-rw-r--r--drivers/net/sfc/net_driver.h4
-rw-r--r--drivers/net/sfc/tenxpress.c151
-rw-r--r--drivers/net/sfc/workarounds.h4
6 files changed, 141 insertions, 201 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 53d259e90187..7b5924c039b3 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -219,9 +219,6 @@ int efx_ethtool_set_settings(struct net_device *net_dev,
219 struct efx_nic *efx = netdev_priv(net_dev); 219 struct efx_nic *efx = netdev_priv(net_dev);
220 int rc; 220 int rc;
221 221
222 if (EFX_WORKAROUND_13963(efx) && !ecmd->autoneg)
223 return -EINVAL;
224
225 /* Falcon GMAC does not support 1000Mbps HD */ 222 /* Falcon GMAC does not support 1000Mbps HD */
226 if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { 223 if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) {
227 EFX_LOG(efx, "rejecting unsupported 1000Mbps HD" 224 EFX_LOG(efx, "rejecting unsupported 1000Mbps HD"
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index 16bc5853d0ea..f9e2f95c3b48 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -266,7 +266,7 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
266 } 266 }
267} 267}
268 268
269static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp) 269static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr)
270{ 270{
271 int phy_id = efx->mii.phy_id; 271 int phy_id = efx->mii.phy_id;
272 u32 result = 0; 272 u32 result = 0;
@@ -281,9 +281,6 @@ static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp)
281 result |= ADVERTISED_100baseT_Half; 281 result |= ADVERTISED_100baseT_Half;
282 if (reg & ADVERTISE_100FULL) 282 if (reg & ADVERTISE_100FULL)
283 result |= ADVERTISED_100baseT_Full; 283 result |= ADVERTISED_100baseT_Full;
284 if (reg & LPA_RESV)
285 result |= xnp;
286
287 return result; 284 return result;
288} 285}
289 286
@@ -313,7 +310,7 @@ void mdio_clause45_get_settings(struct efx_nic *efx,
313 */ 310 */
314void mdio_clause45_get_settings_ext(struct efx_nic *efx, 311void mdio_clause45_get_settings_ext(struct efx_nic *efx,
315 struct ethtool_cmd *ecmd, 312 struct ethtool_cmd *ecmd,
316 u32 xnp, u32 xnp_lpa) 313 u32 npage_adv, u32 npage_lpa)
317{ 314{
318 int phy_id = efx->mii.phy_id; 315 int phy_id = efx->mii.phy_id;
319 int reg; 316 int reg;
@@ -364,8 +361,8 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx,
364 ecmd->autoneg = AUTONEG_ENABLE; 361 ecmd->autoneg = AUTONEG_ENABLE;
365 ecmd->advertising |= 362 ecmd->advertising |=
366 ADVERTISED_Autoneg | 363 ADVERTISED_Autoneg |
367 mdio_clause45_get_an(efx, 364 mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) |
368 MDIO_AN_ADVERTISE, xnp); 365 npage_adv;
369 } else 366 } else
370 ecmd->autoneg = AUTONEG_DISABLE; 367 ecmd->autoneg = AUTONEG_DISABLE;
371 } else 368 } else
@@ -374,27 +371,30 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx,
374 if (ecmd->autoneg) { 371 if (ecmd->autoneg) {
375 /* If AN is complete, report best common mode, 372 /* If AN is complete, report best common mode,
376 * otherwise report best advertised mode. */ 373 * otherwise report best advertised mode. */
377 u32 common = ecmd->advertising; 374 u32 modes = 0;
378 if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, 375 if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
379 MDIO_MMDREG_STAT1) & 376 MDIO_MMDREG_STAT1) &
380 (1 << MDIO_AN_STATUS_AN_DONE_LBN)) { 377 (1 << MDIO_AN_STATUS_AN_DONE_LBN))
381 common &= mdio_clause45_get_an(efx, MDIO_AN_LPA, 378 modes = (ecmd->advertising &
382 xnp_lpa); 379 (mdio_clause45_get_an(efx, MDIO_AN_LPA) |
383 } 380 npage_lpa));
384 if (common & ADVERTISED_10000baseT_Full) { 381 if (modes == 0)
382 modes = ecmd->advertising;
383
384 if (modes & ADVERTISED_10000baseT_Full) {
385 ecmd->speed = SPEED_10000; 385 ecmd->speed = SPEED_10000;
386 ecmd->duplex = DUPLEX_FULL; 386 ecmd->duplex = DUPLEX_FULL;
387 } else if (common & (ADVERTISED_1000baseT_Full | 387 } else if (modes & (ADVERTISED_1000baseT_Full |
388 ADVERTISED_1000baseT_Half)) { 388 ADVERTISED_1000baseT_Half)) {
389 ecmd->speed = SPEED_1000; 389 ecmd->speed = SPEED_1000;
390 ecmd->duplex = !!(common & ADVERTISED_1000baseT_Full); 390 ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full);
391 } else if (common & (ADVERTISED_100baseT_Full | 391 } else if (modes & (ADVERTISED_100baseT_Full |
392 ADVERTISED_100baseT_Half)) { 392 ADVERTISED_100baseT_Half)) {
393 ecmd->speed = SPEED_100; 393 ecmd->speed = SPEED_100;
394 ecmd->duplex = !!(common & ADVERTISED_100baseT_Full); 394 ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
395 } else { 395 } else {
396 ecmd->speed = SPEED_10; 396 ecmd->speed = SPEED_10;
397 ecmd->duplex = !!(common & ADVERTISED_10baseT_Full); 397 ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
398 } 398 }
399 } else { 399 } else {
400 /* Report forced settings */ 400 /* Report forced settings */
@@ -418,7 +418,7 @@ int mdio_clause45_set_settings(struct efx_nic *efx,
418 int phy_id = efx->mii.phy_id; 418 int phy_id = efx->mii.phy_id;
419 struct ethtool_cmd prev; 419 struct ethtool_cmd prev;
420 u32 required; 420 u32 required;
421 int ctrl1_bits, reg; 421 int reg;
422 422
423 efx->phy_op->get_settings(efx, &prev); 423 efx->phy_op->get_settings(efx, &prev);
424 424
@@ -433,102 +433,83 @@ int mdio_clause45_set_settings(struct efx_nic *efx,
433 if (prev.port != PORT_TP || ecmd->port != PORT_TP) 433 if (prev.port != PORT_TP || ecmd->port != PORT_TP)
434 return -EINVAL; 434 return -EINVAL;
435 435
436 /* Check that PHY supports these settings and work out the 436 /* Check that PHY supports these settings */
437 * basic control bits */ 437 if (ecmd->autoneg) {
438 if (ecmd->duplex) { 438 required = SUPPORTED_Autoneg;
439 } else if (ecmd->duplex) {
439 switch (ecmd->speed) { 440 switch (ecmd->speed) {
440 case SPEED_10: 441 case SPEED_10: required = SUPPORTED_10baseT_Full; break;
441 ctrl1_bits = BMCR_FULLDPLX; 442 case SPEED_100: required = SUPPORTED_100baseT_Full; break;
442 required = SUPPORTED_10baseT_Full; 443 default: return -EINVAL;
443 break;
444 case SPEED_100:
445 ctrl1_bits = BMCR_SPEED100 | BMCR_FULLDPLX;
446 required = SUPPORTED_100baseT_Full;
447 break;
448 case SPEED_1000:
449 ctrl1_bits = BMCR_SPEED1000 | BMCR_FULLDPLX;
450 required = SUPPORTED_1000baseT_Full;
451 break;
452 case SPEED_10000:
453 ctrl1_bits = (BMCR_SPEED1000 | BMCR_SPEED100 |
454 BMCR_FULLDPLX);
455 required = SUPPORTED_10000baseT_Full;
456 break;
457 default:
458 return -EINVAL;
459 } 444 }
460 } else { 445 } else {
461 switch (ecmd->speed) { 446 switch (ecmd->speed) {
462 case SPEED_10: 447 case SPEED_10: required = SUPPORTED_10baseT_Half; break;
463 ctrl1_bits = 0; 448 case SPEED_100: required = SUPPORTED_100baseT_Half; break;
464 required = SUPPORTED_10baseT_Half; 449 default: return -EINVAL;
465 break;
466 case SPEED_100:
467 ctrl1_bits = BMCR_SPEED100;
468 required = SUPPORTED_100baseT_Half;
469 break;
470 case SPEED_1000:
471 ctrl1_bits = BMCR_SPEED1000;
472 required = SUPPORTED_1000baseT_Half;
473 break;
474 default:
475 return -EINVAL;
476 } 450 }
477 } 451 }
478 if (ecmd->autoneg)
479 required |= SUPPORTED_Autoneg;
480 required |= ecmd->advertising; 452 required |= ecmd->advertising;
481 if (required & ~prev.supported)