aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSteve Hodgson <shodgson@solarflare.com>2009-01-29 12:50:51 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-30 17:06:30 -0500
commit4b988280be13a1b4c17f51cc66948aef467e7601 (patch)
treeb8a0bd4e96520461caeaeeea2f91aa64d6c32bdd /drivers/net
parent0cc128387969753ae037401eb49e4bbb474186ea (diff)
sfc: Reinitialise the PHY completely in case of a PHY or NIC reset
In particular, set pause advertising bits properly. A PHY reset is not necessary to recover from the register self-test, so use a "invisible" reset there instead. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/sfc/efx.c26
-rw-r--r--drivers/net/sfc/efx.h7
-rw-r--r--drivers/net/sfc/selftest.c7
-rw-r--r--drivers/net/sfc/tenxpress.c1
4 files changed, 28 insertions, 13 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7673fd92eaf5..b0e53087bda0 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -676,9 +676,8 @@ static int efx_init_port(struct efx_nic *efx)
676 rc = efx->phy_op->init(efx); 676 rc = efx->phy_op->init(efx);
677 if (rc) 677 if (rc)
678 return rc; 678 return rc;
679 efx->phy_op->reconfigure(efx);
680
681 mutex_lock(&efx->mac_lock); 679 mutex_lock(&efx->mac_lock);
680 efx->phy_op->reconfigure(efx);
682 rc = falcon_switch_mac(efx); 681 rc = falcon_switch_mac(efx);
683 mutex_unlock(&efx->mac_lock); 682 mutex_unlock(&efx->mac_lock);
684 if (rc) 683 if (rc)
@@ -1622,7 +1621,8 @@ static void efx_unregister_netdev(struct efx_nic *efx)
1622 1621
1623/* Tears down the entire software state and most of the hardware state 1622/* Tears down the entire software state and most of the hardware state
1624 * before reset. */ 1623 * before reset. */
1625void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) 1624void efx_reset_down(struct efx_nic *efx, enum reset_type method,
1625 struct ethtool_cmd *ecmd)
1626{ 1626{
1627 EFX_ASSERT_RESET_SERIALISED(efx); 1627 EFX_ASSERT_RESET_SERIALISED(efx);
1628 1628
@@ -1639,6 +1639,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
1639 efx->phy_op->get_settings(efx, ecmd); 1639 efx->phy_op->get_settings(efx, ecmd);
1640 1640
1641 efx_fini_channels(efx); 1641 efx_fini_channels(efx);
1642 if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
1643 efx->phy_op->fini(efx);
1642} 1644}
1643 1645
1644/* This function will always ensure that the locks acquired in 1646/* This function will always ensure that the locks acquired in
@@ -1646,7 +1648,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
1646 * that we were unable to reinitialise the hardware, and the 1648 * that we were unable to reinitialise the hardware, and the
1647 * driver should be disabled. If ok is false, then the rx and tx 1649 * driver should be disabled. If ok is false, then the rx and tx
1648 * engines are not restarted, pending a RESET_DISABLE. */ 1650 * engines are not restarted, pending a RESET_DISABLE. */
1649int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) 1651int efx_reset_up(struct efx_nic *efx, enum reset_type method,
1652 struct ethtool_cmd *ecmd, bool ok)
1650{ 1653{
1651 int rc; 1654 int rc;
1652 1655
@@ -1658,6 +1661,15 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
1658 ok = false; 1661 ok = false;
1659 } 1662 }
1660 1663
1664 if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) {
1665 if (ok) {
1666 rc = efx->phy_op->init(efx);
1667 if (rc)
1668 ok = false;
1669 } else
1670 efx->port_initialized = false;
1671 }
1672
1661 if (ok) { 1673 if (ok) {
1662 efx_init_channels(efx); 1674 efx_init_channels(efx);
1663 1675
@@ -1702,7 +1714,7 @@ static int efx_reset(struct efx_nic *efx)
1702 1714
1703 EFX_INFO(efx, "resetting (%d)\n", method); 1715 EFX_INFO(efx, "resetting (%d)\n", method);
1704 1716
1705 efx_reset_down(efx, &ecmd); 1717 efx_reset_down(efx, method, &ecmd);
1706 1718
1707 rc = falcon_reset_hw(efx, method); 1719 rc = falcon_reset_hw(efx, method);
1708 if (rc) { 1720 if (rc) {
@@ -1721,10 +1733,10 @@ static int efx_reset(struct efx_nic *efx)
1721 1733
1722 /* Leave device stopped if necessary */ 1734 /* Leave device stopped if necessary */
1723 if (method == RESET_TYPE_DISABLE) { 1735 if (method == RESET_TYPE_DISABLE) {
1724 efx_reset_up(efx, &ecmd, false); 1736 efx_reset_up(efx, method, &ecmd, false);
1725 rc = -EIO; 1737 rc = -EIO;
1726 } else { 1738 } else {
1727 rc = efx_reset_up(efx, &ecmd, true); 1739 rc = efx_reset_up(efx, method, &ecmd, true);
1728 } 1740 }
1729 1741
1730out_disable: 1742out_disable:
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 0dd7a532c78a..ac201587a163 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -40,9 +40,10 @@ extern void efx_reconfigure_port(struct efx_nic *efx);
40extern void __efx_reconfigure_port(struct efx_nic *efx); 40extern void __efx_reconfigure_port(struct efx_nic *efx);
41 41
42/* Reset handling */ 42/* Reset handling */
43extern void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd); 43extern void efx_reset_down(struct efx_nic *efx, enum reset_type method,
44extern int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, 44 struct ethtool_cmd *ecmd);
45 bool ok); 45extern int efx_reset_up(struct efx_nic *efx, enum reset_type method,
46 struct ethtool_cmd *ecmd, bool ok);
46 47
47/* Global */ 48/* Global */
48extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); 49extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index dba0d64d50cd..0a598084c513 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -665,6 +665,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
665{ 665{
666 enum efx_loopback_mode loopback_mode = efx->loopback_mode; 666 enum efx_loopback_mode loopback_mode = efx->loopback_mode;
667 int phy_mode = efx->phy_mode; 667 int phy_mode = efx->phy_mode;
668 enum reset_type reset_method = RESET_TYPE_INVISIBLE;
668 struct ethtool_cmd ecmd; 669 struct ethtool_cmd ecmd;
669 struct efx_channel *channel; 670 struct efx_channel *channel;
670 int rc_test = 0, rc_reset = 0, rc; 671 int rc_test = 0, rc_reset = 0, rc;
@@ -718,21 +719,21 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
718 mutex_unlock(&efx->mac_lock); 719 mutex_unlock(&efx->mac_lock);
719 720
720 /* free up all consumers of SRAM (including all the queues) */ 721 /* free up all consumers of SRAM (including all the queues) */
721 efx_reset_down(efx, &ecmd); 722 efx_reset_down(efx, reset_method, &ecmd);
722 723
723 rc = efx_test_chip(efx, tests); 724 rc = efx_test_chip(efx, tests);
724 if (rc && !rc_test) 725 if (rc && !rc_test)
725 rc_test = rc; 726 rc_test = rc;
726 727
727 /* reset the chip to recover from the register test */ 728 /* reset the chip to recover from the register test */
728 rc_reset = falcon_reset_hw(efx, RESET_TYPE_ALL); 729 rc_reset = falcon_reset_hw(efx, reset_method);
729 730
730 /* Ensure that the phy is powered and out of loopback 731 /* Ensure that the phy is powered and out of loopback
731 * for the bist and loopback tests */ 732 * for the bist and loopback tests */
732 efx->phy_mode &= ~PHY_MODE_LOW_POWER; 733 efx->phy_mode &= ~PHY_MODE_LOW_POWER;
733 efx->loopback_mode = LOOPBACK_NONE; 734 efx->loopback_mode = LOOPBACK_NONE;
734 735
735 rc = efx_reset_up(efx, &ecmd, rc_reset == 0); 736 rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0);
736 if (rc && !rc_reset) 737 if (rc && !rc_reset)
737 rc_reset = rc; 738 rc_reset = rc;
738 739
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index bc2833f9cbe4..c9584619322a 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -337,6 +337,7 @@ static int tenxpress_phy_init(struct efx_nic *efx)
337 rc = tenxpress_init(efx); 337 rc = tenxpress_init(efx);
338 if (rc < 0) 338 if (rc < 0)
339 goto fail; 339 goto fail;
340 mdio_clause45_set_pause(efx);
340 341
341 if (efx->phy_type == PHY_TYPE_SFT9001B) { 342 if (efx->phy_type == PHY_TYPE_SFT9001B) {
342 rc = device_create_file(&efx->pci_dev->dev, 343 rc = device_create_file(&efx->pci_dev->dev,