aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/tenxpress.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-11-28 22:42:41 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-29 19:46:28 -0500
commitd3245b28ef2a45ec4e115062a38100bd06229289 (patch)
tree036133fdf01a20f36086d5eb8606728859c056de /drivers/net/sfc/tenxpress.c
parentef2b90ee4dba7a3d9001f1f0003b860b39a4aaae (diff)
sfc: Refactor link configuration
Refactor PHY, MAC and NIC configuration operations so that the existing link configuration can be re-pushed with: efx->phy_op->reconfigure(efx); efx->mac_op->reconfigure(efx); and a new configuration with: efx->nic_op->reconfigure_port(efx); (plus locking and error-checking). We have not held the link settings in software (aside from flow control), and have relied on asking the hardware what they are. This is a problem because in some cases the hardware may no longer be in a state to tell us. In particular, if an entire multi-port board is reset through one port, the driver bindings to other ports have no chance to save settings before recovering. We only actually need to keep track of the autonegotiation settings, so add an ethtool advertising mask to struct efx_nic, initialise it in PHY init and update it as necessary. Remove now-unneeded uses of efx_phy_op::{get,set}_settings() and struct ethtool_cmd. Much of this was done by Steve Hodgson <shodgson@solarflare.com>. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/tenxpress.c')
-rw-r--r--drivers/net/sfc/tenxpress.c66
1 files changed, 27 insertions, 39 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index 1bd79650a00f..c30185393cdc 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -199,15 +199,16 @@ static ssize_t set_phy_short_reach(struct device *dev,
199 const char *buf, size_t count) 199 const char *buf, size_t count)
200{ 200{
201 struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); 201 struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
202 int rc;
202 203
203 rtnl_lock(); 204 rtnl_lock();
204 efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, 205 efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
205 MDIO_PMA_10GBT_TXPWR_SHORT, 206 MDIO_PMA_10GBT_TXPWR_SHORT,
206 count != 0 && *buf != '0'); 207 count != 0 && *buf != '0');
207 efx_reconfigure_port(efx); 208 rc = efx_reconfigure_port(efx);
208 rtnl_unlock(); 209 rtnl_unlock();
209 210
210 return count; 211 return rc < 0 ? rc : (ssize_t)count;
211} 212}
212 213
213static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, 214static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach,
@@ -300,7 +301,6 @@ static int tenxpress_init(struct efx_nic *efx)
300static int tenxpress_phy_init(struct efx_nic *efx) 301static int tenxpress_phy_init(struct efx_nic *efx)
301{ 302{
302 struct tenxpress_phy_data *phy_data; 303 struct tenxpress_phy_data *phy_data;
303 u16 old_adv, adv;
304 int rc = 0; 304 int rc = 0;
305 305
306 falcon_board(efx)->type->init_phy(efx); 306 falcon_board(efx)->type->init_phy(efx);
@@ -335,14 +335,14 @@ static int tenxpress_phy_init(struct efx_nic *efx)
335 if (rc < 0) 335 if (rc < 0)
336 goto fail; 336 goto fail;
337 337
338 /* Set pause advertising */ 338 /* Initialise advertising flags */
339 old_adv = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE); 339 efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
340 adv = ((old_adv & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) | 340 ADVERTISED_10000baseT_Full);
341 mii_advertise_flowctrl(efx->wanted_fc)); 341 if (efx->phy_type != PHY_TYPE_SFX7101)
342 if (adv != old_adv) { 342 efx->link_advertising |= (ADVERTISED_1000baseT_Full |
343 efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, adv); 343 ADVERTISED_100baseT_Full);
344 mdio45_nway_restart(&efx->mdio); 344 efx_link_set_wanted_fc(efx, efx->wanted_fc);
345 } 345 efx_mdio_an_reconfigure(efx);
346 346
347 if (efx->phy_type == PHY_TYPE_SFT9001B) { 347 if (efx->phy_type == PHY_TYPE_SFT9001B) {
348 rc = device_create_file(&efx->pci_dev->dev, 348 rc = device_create_file(&efx->pci_dev->dev,
@@ -500,49 +500,41 @@ static void tenxpress_low_power(struct efx_nic *efx)
500 !!(efx->phy_mode & PHY_MODE_LOW_POWER)); 500 !!(efx->phy_mode & PHY_MODE_LOW_POWER));
501} 501}
502 502
503static void tenxpress_phy_reconfigure(struct efx_nic *efx) 503static int tenxpress_phy_reconfigure(struct efx_nic *efx)
504{ 504{
505 struct tenxpress_phy_data *phy_data = efx->phy_data; 505 struct tenxpress_phy_data *phy_data = efx->phy_data;
506 struct ethtool_cmd ecmd;
507 bool phy_mode_change, loop_reset; 506 bool phy_mode_change, loop_reset;
508 507
509 if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { 508 if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
510 phy_data->phy_mode = efx->phy_mode; 509 phy_data->phy_mode = efx->phy_mode;
511 return; 510 return 0;
512 } 511 }
513 512
514 tenxpress_low_power(efx);
515
516 phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL && 513 phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
517 phy_data->phy_mode != PHY_MODE_NORMAL); 514 phy_data->phy_mode != PHY_MODE_NORMAL);
518 loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) || 515 loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
519 LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); 516 LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));
520 517
521 if (loop_reset || phy_mode_change) { 518 if (loop_reset || phy_mode_change) {
522 int rc; 519 tenxpress_special_reset(efx);
523
524 efx->phy_op->get_settings(efx, &ecmd);
525 520
526 if (loop_reset || phy_mode_change) { 521 /* Reset XAUI if we were in 10G, and are staying
527 tenxpress_special_reset(efx); 522 * in 10G. If we're moving into and out of 10G
528 523 * then xaui will be reset anyway */
529 /* Reset XAUI if we were in 10G, and are staying 524 if (EFX_IS10G(efx))
530 * in 10G. If we're moving into and out of 10G 525 falcon_reset_xaui(efx);
531 * then xaui will be reset anyway */
532 if (EFX_IS10G(efx))
533 falcon_reset_xaui(efx);
534 }
535
536 rc = efx->phy_op->set_settings(efx, &ecmd);
537 WARN_ON(rc);
538 } 526 }
539 527
528 tenxpress_low_power(efx);
540 efx_mdio_transmit_disable(efx); 529 efx_mdio_transmit_disable(efx);
541 efx_mdio_phy_reconfigure(efx); 530 efx_mdio_phy_reconfigure(efx);
542 tenxpress_ext_loopback(efx); 531 tenxpress_ext_loopback(efx);
532 efx_mdio_an_reconfigure(efx);
543 533
544 phy_data->loopback_mode = efx->loopback_mode; 534 phy_data->loopback_mode = efx->loopback_mode;
545 phy_data->phy_mode = efx->phy_mode; 535 phy_data->phy_mode = efx->phy_mode;
536
537 return 0;
546} 538}
547 539
548static void 540static void
@@ -646,6 +638,9 @@ sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
646 /* BIST is automatically run after a special software reset */ 638 /* BIST is automatically run after a special software reset */
647 rc = tenxpress_special_reset(efx); 639 rc = tenxpress_special_reset(efx);
648 results[0] = rc ? -1 : 1; 640 results[0] = rc ? -1 : 1;
641
642 efx_mdio_an_reconfigure(efx);
643
649 return rc; 644 return rc;
650} 645}
651 646
@@ -663,12 +658,8 @@ static const char *const sft9001_test_names[] = {
663 658
664static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) 659static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
665{ 660{
666 struct ethtool_cmd ecmd;
667 int rc = 0, rc2, i, ctrl_reg, res_reg; 661 int rc = 0, rc2, i, ctrl_reg, res_reg;
668 662
669 if (flags & ETH_TEST_FL_OFFLINE)
670 efx->phy_op->get_settings(efx, &ecmd);
671
672 /* Initialise cable diagnostic results to unknown failure */ 663 /* Initialise cable diagnostic results to unknown failure */
673 for (i = 1; i < 9; ++i) 664 for (i = 1; i < 9; ++i)
674 results[i] = -1; 665 results[i] = -1;
@@ -720,9 +711,7 @@ out:
720 if (!rc) 711 if (!rc)
721 rc = rc2; 712 rc = rc2;
722 713
723 rc2 = efx->phy_op->set_settings(efx, &ecmd); 714 efx_mdio_an_reconfigure(efx);
724 if (!rc)
725 rc = rc2;
726 } 715 }
727 716
728 return rc; 717 return rc;
@@ -753,7 +742,6 @@ tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
753 742
754 mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa); 743 mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa);
755 744
756 ecmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
757 if (efx->phy_type != PHY_TYPE_SFX7101) { 745 if (efx->phy_type != PHY_TYPE_SFX7101) {
758 ecmd->supported |= (SUPPORTED_100baseT_Full | 746 ecmd->supported |= (SUPPORTED_100baseT_Full |
759 SUPPORTED_1000baseT_Full); 747 SUPPORTED_1000baseT_Full);