aboutsummaryrefslogtreecommitdiffstats
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
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>
-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) 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;
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index 09bf801d0569..8ba49773ce7e 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -155,7 +155,8 @@
155#define MDIO_AN_XNP 22 155#define MDIO_AN_XNP 22
156#define MDIO_AN_LPA_XNP 25 156#define MDIO_AN_LPA_XNP 25
157 157
158#define MDIO_AN_10GBT_ADVERTISE 32 158#define MDIO_AN_10GBT_CTRL 32
159#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN 12
159#define MDIO_AN_10GBT_STATUS (33) 160#define MDIO_AN_10GBT_STATUS (33)
160#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */ 161#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */
161#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */ 162#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 5f255f75754e..8eb411a1c82e 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -566,7 +566,7 @@ struct efx_mac_operations {
566 * @poll: Poll for hardware state. Serialised by the mac_lock. 566 * @poll: Poll for hardware state. Serialised by the mac_lock.
567 * @get_settings: Get ethtool settings. Serialised by the mac_lock. 567 * @get_settings: Get ethtool settings. Serialised by the mac_lock.
568 * @set_settings: Set ethtool settings. Serialised by the mac_lock. 568 * @set_settings: Set ethtool settings. Serialised by the mac_lock.
569 * @set_xnp_advertise: Set abilities advertised in Extended Next Page 569 * @set_npage_adv: Set abilities advertised in (Extended) Next Page
570 * (only needed where AN bit is set in mmds) 570 * (only needed where AN bit is set in mmds)
571 * @num_tests: Number of PHY-specific tests/results 571 * @num_tests: Number of PHY-specific tests/results
572 * @test_names: Names of the tests/results 572 * @test_names: Names of the tests/results
@@ -586,7 +586,7 @@ struct efx_phy_operations {
586 struct ethtool_cmd *ecmd); 586 struct ethtool_cmd *ecmd);
587 int (*set_settings) (struct efx_nic *efx, 587 int (*set_settings) (struct efx_nic *efx,
588 struct ethtool_cmd *ecmd); 588 struct ethtool_cmd *ecmd);
589 bool (*set_xnp_advertise) (struct efx_nic *efx, u32); 589 void (*set_npage_adv) (struct efx_nic *efx, u32);
590 u32 num_tests; 590 u32 num_tests;
591 const char *const *test_names; 591 const char *const *test_names;
592 int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); 592 int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index c9584619322a..412d209d8313 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -179,11 +179,13 @@
179#define C22EXT_STATUS_LINK_LBN 2 179#define C22EXT_STATUS_LINK_LBN 2
180#define C22EXT_STATUS_LINK_WIDTH 1 180#define C22EXT_STATUS_LINK_WIDTH 1
181 181
182#define C22EXT_MSTSLV_REG 49162 182#define C22EXT_MSTSLV_CTRL 49161
183#define C22EXT_MSTSLV_1000_HD_LBN 10 183#define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8
184#define C22EXT_MSTSLV_1000_HD_WIDTH 1 184#define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9
185#define C22EXT_MSTSLV_1000_FD_LBN 11 185
186#define C22EXT_MSTSLV_1000_FD_WIDTH 1 186#define C22EXT_MSTSLV_STATUS 49162
187#define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN 10
188#define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN 11
187 189
188/* Time to wait between powering down the LNPGA and turning off the power 190/* Time to wait between powering down the LNPGA and turning off the power
189 * rails */ 191 * rails */
@@ -741,114 +743,76 @@ reset:
741 return rc; 743 return rc;
742} 744}
743 745
744static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) 746static void
747tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
745{ 748{
746 int phy = efx->mii.phy_id; 749 int phy_id = efx->mii.phy_id;
747 u32 lpa = 0; 750 u32 adv = 0, lpa = 0;
748 int reg; 751 int reg;
749 752
750 if (efx->phy_type != PHY_TYPE_SFX7101) { 753 if (efx->phy_type != PHY_TYPE_SFX7101) {
751 reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT, 754 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
752 C22EXT_MSTSLV_REG); 755 C22EXT_MSTSLV_CTRL);
753 if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN)) 756 if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
757 adv |= ADVERTISED_1000baseT_Full;
758 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
759 C22EXT_MSTSLV_STATUS);
760 if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
754 lpa |= ADVERTISED_1000baseT_Half; 761 lpa |= ADVERTISED_1000baseT_Half;
755 if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN)) 762 if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
756 lpa |= ADVERTISED_1000baseT_Full; 763 lpa |= ADVERTISED_1000baseT_Full;
757 } 764 }
758 reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS); 765 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
766 MDIO_AN_10GBT_CTRL);
767 if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN))
768 adv |= ADVERTISED_10000baseT_Full;
769 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
770 MDIO_AN_10GBT_STATUS);
759 if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) 771 if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN))
760 lpa |= ADVERTISED_10000baseT_Full; 772 lpa |= ADVERTISED_10000baseT_Full;
761 return lpa;
762}
763
764static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
765{
766 mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full,
767 tenxpress_get_xnp_lpa(efx));
768 ecmd->supported |= SUPPORTED_10000baseT_Full;
769 ecmd->advertising |= ADVERTISED_10000baseT_Full;
770}
771
772static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
773{
774 int phy_id = efx->mii.phy_id;
775 u32 xnp_adv = 0;
776 int reg;
777
778 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
779 PMA_PMD_SPEED_ENABLE_REG);
780 if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN)))
781 xnp_adv |= ADVERTISED_100baseT_Full;
782 if (reg & (1 << PMA_PMD_1000T_ADV_LBN))
783 xnp_adv |= ADVERTISED_1000baseT_Full;
784 if (reg & (1 << PMA_PMD_10000T_ADV_LBN))
785 xnp_adv |= ADVERTISED_10000baseT_Full;
786
787 mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv,
788 tenxpress_get_xnp_lpa(efx));
789 773
790 ecmd->supported |= (SUPPORTED_100baseT_Half | 774 mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa);
791 SUPPORTED_100baseT_Full |
792 SUPPORTED_1000baseT_Full);
793 775
794 /* Use the vendor defined C22ext register for duplex settings */ 776 if (efx->phy_type != PHY_TYPE_SFX7101)
795 if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) { 777 ecmd->supported |= (SUPPORTED_100baseT_Full |
796 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, 778 SUPPORTED_1000baseT_Full);
797 GPHY_XCONTROL_REG);
798 ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ?
799 DUPLEX_FULL : DUPLEX_HALF);
800 }
801 779
802 /* In loopback, the PHY automatically brings up the correct interface, 780 /* In loopback, the PHY automatically brings up the correct interface,
803 * but doesn't advertise the correct speed. So override it */ 781 * but doesn't advertise the correct speed. So override it */
804 if (efx->loopback_mode == LOOPBACK_GPHY) 782 if (efx->loopback_mode == LOOPBACK_GPHY)
805 ecmd->speed = SPEED_1000; 783 ecmd->speed = SPEED_1000;
806 else if (LOOPBACK_MASK(efx) & SFT9001_LOOPBACKS) 784 else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)
807 ecmd->speed = SPEED_10000; 785 ecmd->speed = SPEED_10000;
808} 786}
809 787
810static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) 788static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
811{ 789{
812 int phy_id = efx->mii.phy_id; 790 if (!ecmd->autoneg)
813 int rc; 791 return -EINVAL;
814
815 rc = mdio_clause45_set_settings(efx, ecmd);
816 if (rc)
817 return rc;
818 792
819 if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) 793 return mdio_clause45_set_settings(efx, ecmd);
820 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, 794}
821 GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN,
822 ecmd->duplex == DUPLEX_FULL);
823 795
824 return rc; 796static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
797{
798 mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
799 MDIO_AN_10GBT_CTRL,
800 MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
801 advertising & ADVERTISED_10000baseT_Full);
825} 802}
826 803
827static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising) 804static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
828{ 805{
829 int phy = efx->mii.phy_id; 806 int phy_id = efx->mii.phy_id;
830 int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD, 807
831 PMA_PMD_SPEED_ENABLE_REG); 808 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
832 bool enabled; 809 C22EXT_MSTSLV_CTRL,
833 810 C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
834 reg &= ~((1 << 2) | (1 << 3)); 811 advertising & ADVERTISED_1000baseT_Full);
835 if (EFX_WORKAROUND_13204(efx) && 812 mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
836 (advertising & ADVERTISED_100baseT_Full)) 813 MDIO_AN_10GBT_CTRL,
837 reg |= 1 << PMA_PMD_100TX_ADV_LBN; 814 MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
838 if (advertising & ADVERTISED_1000baseT_Full) 815 advertising & ADVERTISED_10000baseT_Full);
839 reg |= 1 << PMA_PMD_1000T_ADV_LBN;
840 if (advertising & ADVERTISED_10000baseT_Full)
841 reg |= 1 << PMA_PMD_10000T_ADV_LBN;
842 mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD,
843 PMA_PMD_SPEED_ENABLE_REG, reg);
844
845 enabled = (advertising &
846 (ADVERTISED_1000baseT_Half |
847 ADVERTISED_1000baseT_Full |
848 ADVERTISED_10000baseT_Full));
849 if (EFX_WORKAROUND_13204(efx))
850 enabled |= (advertising & ADVERTISED_100baseT_Full);
851 return enabled;
852} 816}
853 817
854struct efx_phy_operations falcon_sfx7101_phy_ops = { 818struct efx_phy_operations falcon_sfx7101_phy_ops = {
@@ -858,8 +822,9 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
858 .poll = tenxpress_phy_poll, 822 .poll = tenxpress_phy_poll,
859 .fini = tenxpress_phy_fini, 823 .fini = tenxpress_phy_fini,
860 .clear_interrupt = efx_port_dummy_op_void, 824 .clear_interrupt = efx_port_dummy_op_void,
861 .get_settings = sfx7101_get_settings, 825 .get_settings = tenxpress_get_settings,
862 .set_settings = mdio_clause45_set_settings, 826 .set_settings = tenxpress_set_settings,
827 .set_npage_adv = sfx7101_set_npage_adv,
863 .num_tests = ARRAY_SIZE(sfx7101_test_names), 828 .num_tests = ARRAY_SIZE(sfx7101_test_names),
864 .test_names = sfx7101_test_names, 829 .test_names = sfx7101_test_names,
865 .run_tests = sfx7101_run_tests, 830 .run_tests = sfx7101_run_tests,
@@ -874,9 +839,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
874 .poll = tenxpress_phy_poll, 839 .poll = tenxpress_phy_poll,
875 .fini = tenxpress_phy_fini, 840 .fini = tenxpress_phy_fini,
876 .clear_interrupt = efx_port_dummy_op_void, 841 .clear_interrupt = efx_port_dummy_op_void,
877 .get_settings = sft9001_get_settings, 842 .get_settings = tenxpress_get_settings,
878 .set_settings = sft9001_set_settings, 843 .set_settings = tenxpress_set_settings,
879 .set_xnp_advertise = sft9001_set_xnp_advertise, 844 .set_npage_adv = sft9001_set_npage_adv,
880 .num_tests = ARRAY_SIZE(sft9001_test_names), 845 .num_tests = ARRAY_SIZE(sft9001_test_names),
881 .test_names = sft9001_test_names, 846 .test_names = sft9001_test_names,
882 .run_tests = sft9001_run_tests, 847 .run_tests = sft9001_run_tests,
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index b810dcdf4681..78de68f4a95b 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -18,7 +18,6 @@
18#define EFX_WORKAROUND_ALWAYS(efx) 1 18#define EFX_WORKAROUND_ALWAYS(efx) 1
19#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) 19#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1)
20#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx) 20#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
21#define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A)
22#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \ 21#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \
23 (efx)->phy_type == PHY_TYPE_SFT9001B) 22 (efx)->phy_type == PHY_TYPE_SFT9001B)
24 23
@@ -55,9 +54,6 @@
55 54
56/* Need to send XNP pages for 100BaseT */ 55/* Need to send XNP pages for 100BaseT */
57#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001 56#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001
58/* Need to keep AN enabled */
59#define EFX_WORKAROUND_13963 EFX_WORKAROUND_SFT9001A
60
61/* Don't restart AN in near-side loopback */ 57/* Don't restart AN in near-side loopback */
62#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001 58#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001
63 59