aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/mdio_10g.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-01-29 12:59:37 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-30 17:06:32 -0500
commitaf4ad9bca0c4039355b20d760b4fd39afa48c59d (patch)
tree720b182118bf2fcb5aa2fb34671d032cf75d0d43 /drivers/net/sfc/mdio_10g.c
parentc9d5a53f060bb9ac6cd20d9768b4b75e22bc8689 (diff)
sfc: SFX7101/SFT9001: Fix AN advertisements
All 10Xpress PHYs require autonegotiation all the time; enforce this in the set_settings() method and do not treat it as a workaround. Remove claimed support for 100M HD mode since it is not supported by current firmware. Do not set speed override bits when AN is enabled, and do not use register 1.49192 for AN configuration as it can override what we set elsewhere. Always set the AN selector bits to 1 (802.3). Fix confusion between Next Page and Extended Next Page. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/mdio_10g.c')
-rw-r--r--drivers/net/sfc/mdio_10g.c177
1 files changed, 79 insertions, 98 deletions
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) 453 if (required & ~prev.supported)
482 return -EINVAL; 454 return -EINVAL;
483 455
484 /* Set the basic control bits */ 456 if (ecmd->autoneg) {
485 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, 457 bool xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full
486 MDIO_MMDREG_CTRL1); 458 || EFX_WORKAROUND_13204(efx));
487 reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | 0x003c); 459
488 reg |= ctrl1_bits; 460 /* Set up the base page */
489 mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL1, 461 reg = ADVERTISE_CSMA;
490 reg); 462 if (ecmd->advertising & ADVERTISED_10baseT_Half)
491 463 reg |= ADVERTISE_10HALF;
492 /* Set the AN registers */ 464 if (ecmd->advertising & ADVERTISED_10baseT_Full)
493 if (ecmd->autoneg != prev.autoneg || 465 reg |= ADVERTISE_10FULL;
494 ecmd->advertising != prev.advertising) { 466 if (ecmd->advertising & ADVERTISED_100baseT_Half)
495 bool xnp = false; 467 reg |= ADVERTISE_100HALF;
496 468 if (ecmd->advertising & ADVERTISED_100baseT_Full)
497 if (efx->phy_op->set_xnp_advertise) 469 reg |= ADVERTISE_100FULL;
498 xnp = efx->phy_op->set_xnp_advertise(efx, 470 if (xnp)
499 ecmd->advertising); 471 reg |= ADVERTISE_RESV;
500 472 else if (ecmd->advertising & (ADVERTISED_1000baseT_Half |
501 if (ecmd->autoneg) { 473 ADVERTISED_1000baseT_Full))
502 reg = 0; 474 reg |= ADVERTISE_NPAGE;
503 if (ecmd->advertising & ADVERTISED_10baseT_Half) 475 reg |= efx_fc_advertise(efx->wanted_fc);
504 reg |= ADVERTISE_10HALF; 476 mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
505 if (ecmd->advertising & ADVERTISED_10baseT_Full) 477 MDIO_AN_ADVERTISE, reg);
506 reg |= ADVERTISE_10FULL; 478
507 if (ecmd->advertising & ADVERTISED_100baseT_Half) 479 /* Set up the (extended) next page if necessary */
508 reg |= ADVERTISE_100HALF; 480 if (efx->phy_op->set_npage_adv)
509 if (ecmd->advertising & ADVERTISED_100baseT_Full) 481 efx->phy_op->set_npage_adv(efx, ecmd->advertising);
510 reg |= ADVERTISE_100FULL;
511 if (xnp)
512 reg |= ADVERTISE_RESV;
513 mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
514 MDIO_AN_ADVERTISE, reg);
515 }
516 482
483 /* Enable and restart AN */
517 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, 484 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
518 MDIO_MMDREG_CTRL1); 485 MDIO_MMDREG_CTRL1);
519 if (ecmd->autoneg) 486 reg |= BMCR_ANENABLE;
520 reg |= BMCR_ANENABLE | BMCR_ANRESTART; 487 if (!(EFX_WORKAROUND_15195(efx) &&
521 else 488 LOOPBACK_MASK(efx) & efx->phy_op->loopbacks))
522 reg &= ~BMCR_ANENABLE; 489 reg |= BMCR_ANRESTART;
523 if (EFX_WORKAROUND_15195(efx)
524 && LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)
525 reg &= ~BMCR_ANRESTART;
526 if (xnp) 490 if (xnp)
527 reg |= 1 << MDIO_AN_CTRL_XNP_LBN; 491 reg |= 1 << MDIO_AN_CTRL_XNP_LBN;
528 else 492 else
529 reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); 493 reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN);
530 mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, 494 mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
531 MDIO_MMDREG_CTRL1, reg); 495 MDIO_MMDREG_CTRL1, reg);
496 } else {
497 /* Disable AN */
498 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
499 MDIO_MMDREG_CTRL1,
500 __ffs(BMCR_ANENABLE), false);
501
502 /* Set the basic control bits */
503 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
504 MDIO_MMDREG_CTRL1);
505 reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX |
506 0x003c);
507 if (ecmd->speed == SPEED_100)
508 reg |= BMCR_SPEED100;
509 if (ecmd->duplex)
510 reg |= BMCR_FULLDPLX;
511 mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
512 MDIO_MMDREG_CTRL1, reg);
532 } 513 }
533 514
534 return 0; 515 return 0;