aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/efx.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/efx.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/efx.c')
-rw-r--r--drivers/net/sfc/efx.c132
1 files changed, 80 insertions, 52 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 73ab246d9f2..4210121eeff 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -620,16 +620,49 @@ void efx_link_status_changed(struct efx_nic *efx)
620 620
621} 621}
622 622
623void efx_link_set_advertising(struct efx_nic *efx, u32 advertising)
624{
625 efx->link_advertising = advertising;
626 if (advertising) {
627 if (advertising & ADVERTISED_Pause)
628 efx->wanted_fc |= (EFX_FC_TX | EFX_FC_RX);
629 else
630 efx->wanted_fc &= ~(EFX_FC_TX | EFX_FC_RX);
631 if (advertising & ADVERTISED_Asym_Pause)
632 efx->wanted_fc ^= EFX_FC_TX;
633 }
634}
635
636void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type wanted_fc)
637{
638 efx->wanted_fc = wanted_fc;
639 if (efx->link_advertising) {
640 if (wanted_fc & EFX_FC_RX)
641 efx->link_advertising |= (ADVERTISED_Pause |
642 ADVERTISED_Asym_Pause);
643 else
644 efx->link_advertising &= ~(ADVERTISED_Pause |
645 ADVERTISED_Asym_Pause);
646 if (wanted_fc & EFX_FC_TX)
647 efx->link_advertising ^= ADVERTISED_Asym_Pause;
648 }
649}
650
623static void efx_fini_port(struct efx_nic *efx); 651static void efx_fini_port(struct efx_nic *efx);
624 652
625/* This call reinitialises the MAC to pick up new PHY settings. The 653/* Push loopback/power/transmit disable settings to the PHY, and reconfigure
626 * caller must hold the mac_lock */ 654 * the MAC appropriately. All other PHY configuration changes are pushed
627void __efx_reconfigure_port(struct efx_nic *efx) 655 * through phy_op->set_settings(), and pushed asynchronously to the MAC
656 * through efx_monitor().
657 *
658 * Callers must hold the mac_lock
659 */
660int __efx_reconfigure_port(struct efx_nic *efx)
628{ 661{
629 WARN_ON(!mutex_is_locked(&efx->mac_lock)); 662 enum efx_phy_mode phy_mode;
663 int rc;
630 664
631 EFX_LOG(efx, "reconfiguring MAC from PHY settings on CPU %d\n", 665 WARN_ON(!mutex_is_locked(&efx->mac_lock));
632 raw_smp_processor_id());
633 666
634 /* Serialise the promiscuous flag with efx_set_multicast_list. */ 667 /* Serialise the promiscuous flag with efx_set_multicast_list. */
635 if (efx_dev_registered(efx)) { 668 if (efx_dev_registered(efx)) {
@@ -637,42 +670,34 @@ void __efx_reconfigure_port(struct efx_nic *efx)
637 netif_addr_unlock_bh(efx->net_dev); 670 netif_addr_unlock_bh(efx->net_dev);
638 } 671 }
639 672
640 efx->type->stop_stats(efx); 673 /* Disable PHY transmit in mac level loopbacks */
641 falcon_deconfigure_mac_wrapper(efx); 674 phy_mode = efx->phy_mode;
642
643 /* Reconfigure the PHY, disabling transmit in mac level loopback. */
644 if (LOOPBACK_INTERNAL(efx)) 675 if (LOOPBACK_INTERNAL(efx))
645 efx->phy_mode |= PHY_MODE_TX_DISABLED; 676 efx->phy_mode |= PHY_MODE_TX_DISABLED;
646 else 677 else
647 efx->phy_mode &= ~PHY_MODE_TX_DISABLED; 678 efx->phy_mode &= ~PHY_MODE_TX_DISABLED;
648 efx->phy_op->reconfigure(efx);
649
650 if (falcon_switch_mac(efx))
651 goto fail;
652 679
653 efx->mac_op->reconfigure(efx); 680 rc = efx->type->reconfigure_port(efx);
654 681
655 efx->type->start_stats(efx); 682 if (rc)
656 683 efx->phy_mode = phy_mode;
657 /* Inform kernel of loss/gain of carrier */
658 efx_link_status_changed(efx);
659 return;
660 684
661fail: 685 return rc;
662 EFX_ERR(efx, "failed to reconfigure MAC\n");
663 efx->port_enabled = false;
664 efx_fini_port(efx);
665} 686}
666 687
667/* Reinitialise the MAC to pick up new PHY settings, even if the port is 688/* Reinitialise the MAC to pick up new PHY settings, even if the port is
668 * disabled. */ 689 * disabled. */
669void efx_reconfigure_port(struct efx_nic *efx) 690int efx_reconfigure_port(struct efx_nic *efx)
670{ 691{
692 int rc;
693
671 EFX_ASSERT_RESET_SERIALISED(efx); 694 EFX_ASSERT_RESET_SERIALISED(efx);
672 695
673 mutex_lock(&efx->mac_lock); 696 mutex_lock(&efx->mac_lock);
674 __efx_reconfigure_port(efx); 697 rc = __efx_reconfigure_port(efx);
675 mutex_unlock(&efx->mac_lock); 698 mutex_unlock(&efx->mac_lock);
699
700 return rc;
676} 701}
677 702
678/* Asynchronous work item for changing MAC promiscuity and multicast 703/* Asynchronous work item for changing MAC promiscuity and multicast
@@ -737,14 +762,18 @@ static int efx_init_port(struct efx_nic *efx)
737 rc = efx->phy_op->init(efx); 762 rc = efx->phy_op->init(efx);
738 if (rc) 763 if (rc)
739 goto fail1; 764 goto fail1;
740 efx->phy_op->reconfigure(efx);
741 rc = falcon_switch_mac(efx);
742 if (rc)
743 goto fail2;
744 efx->mac_op->reconfigure(efx);
745 765
746 efx->port_initialized = true; 766 efx->port_initialized = true;
747 767
768 /* Reconfigure the MAC before creating dma queues (required for
769 * Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */
770 efx->mac_op->reconfigure(efx);
771
772 /* Ensure the PHY advertises the correct flow control settings */
773 rc = efx->phy_op->reconfigure(efx);
774 if (rc)
775 goto fail2;
776
748 mutex_unlock(&efx->mac_lock); 777 mutex_unlock(&efx->mac_lock);
749 return 0; 778 return 0;
750 779
@@ -1209,12 +1238,6 @@ static void efx_stop_all(struct efx_nic *efx)
1209 /* Flush efx_mac_work(), refill_workqueue, monitor_work */ 1238 /* Flush efx_mac_work(), refill_workqueue, monitor_work */
1210 efx_flush_all(efx); 1239 efx_flush_all(efx);
1211 1240
1212 /* Isolate the MAC from the TX and RX engines, so that queue
1213 * flushes will complete in a timely fashion. */
1214 falcon_deconfigure_mac_wrapper(efx);
1215 msleep(10); /* Let the Rx FIFO drain */
1216 falcon_drain_tx_fifo(efx);
1217
1218 /* Stop the kernel transmit interface late, so the watchdog 1241 /* Stop the kernel transmit interface late, so the watchdog
1219 * timer isn't ticking over the flush */ 1242 * timer isn't ticking over the flush */
1220 if (efx_dev_registered(efx)) { 1243 if (efx_dev_registered(efx)) {
@@ -1491,7 +1514,14 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
1491 EFX_LOG(efx, "changing MTU to %d\n", new_mtu); 1514 EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
1492 1515
1493 efx_fini_channels(efx); 1516 efx_fini_channels(efx);
1517
1518 mutex_lock(&efx->mac_lock);
1519 /* Reconfigure the MAC before enabling the dma queues so that
1520 * the RX buffers don't overflow */
1494 net_dev->mtu = new_mtu; 1521 net_dev->mtu = new_mtu;
1522 efx->mac_op->reconfigure(efx);
1523 mutex_unlock(&efx->mac_lock);
1524
1495 efx_init_channels(efx); 1525 efx_init_channels(efx);
1496 1526
1497 efx_start_all(efx); 1527 efx_start_all(efx);
@@ -1515,7 +1545,9 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
1515 memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len); 1545 memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);
1516 1546
1517 /* Reconfigure the MAC */ 1547 /* Reconfigure the MAC */
1518 efx_reconfigure_port(efx); 1548 mutex_lock(&efx->mac_lock);
1549 efx->mac_op->reconfigure(efx);
1550 mutex_unlock(&efx->mac_lock);
1519 1551
1520 return 0; 1552 return 0;
1521} 1553}
@@ -1682,8 +1714,7 @@ static void efx_unregister_netdev(struct efx_nic *efx)
1682 1714
1683/* Tears down the entire software state and most of the hardware state 1715/* Tears down the entire software state and most of the hardware state
1684 * before reset. */ 1716 * before reset. */
1685void efx_reset_down(struct efx_nic *efx, enum reset_type method, 1717void efx_reset_down(struct efx_nic *efx, enum reset_type method)
1686 struct ethtool_cmd *ecmd)
1687{ 1718{
1688 EFX_ASSERT_RESET_SERIALISED(efx); 1719 EFX_ASSERT_RESET_SERIALISED(efx);
1689 1720
@@ -1691,8 +1722,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method,
1691 mutex_lock(&efx->mac_lock); 1722 mutex_lock(&efx->mac_lock);
1692 mutex_lock(&efx->spi_lock); 1723 mutex_lock(&efx->spi_lock);
1693 1724
1694 efx->phy_op->get_settings(efx, ecmd);
1695
1696 efx_fini_channels(efx); 1725 efx_fini_channels(efx);
1697 if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) 1726 if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
1698 efx->phy_op->fini(efx); 1727 efx->phy_op->fini(efx);
@@ -1704,8 +1733,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method,
1704 * that we were unable to reinitialise the hardware, and the 1733 * that we were unable to reinitialise the hardware, and the
1705 * driver should be disabled. If ok is false, then the rx and tx 1734 * driver should be disabled. If ok is false, then the rx and tx
1706 * engines are not restarted, pending a RESET_DISABLE. */ 1735 * engines are not restarted, pending a RESET_DISABLE. */
1707int efx_reset_up(struct efx_nic *efx, enum reset_type method, 1736int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
1708 struct ethtool_cmd *ecmd, bool ok)
1709{ 1737{
1710 int rc; 1738 int rc;
1711 1739
@@ -1722,16 +1750,17 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
1722 rc = efx->phy_op->init(efx); 1750 rc = efx->phy_op->init(efx);
1723 if (rc) 1751 if (rc)
1724 ok = false; 1752 ok = false;
1753 if (efx->phy_op->reconfigure(efx))
1754 EFX_ERR(efx, "could not restore PHY settings\n");
1725 } 1755 }
1726 if (!ok) 1756 if (!ok)
1727 efx->port_initialized = false; 1757 efx->port_initialized = false;
1728 } 1758 }
1729 1759
1730 if (ok) { 1760 if (ok) {
1731 efx_init_channels(efx); 1761 efx->mac_op->reconfigure(efx);
1732 1762
1733 if (efx->phy_op->set_settings(efx, ecmd)) 1763 efx_init_channels(efx);
1734 EFX_ERR(efx, "could not restore PHY settings\n");
1735 } 1764 }
1736 1765
1737 mutex_unlock(&efx->spi_lock); 1766 mutex_unlock(&efx->spi_lock);
@@ -1753,7 +1782,6 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
1753 */ 1782 */
1754static int efx_reset(struct efx_nic *efx) 1783static int efx_reset(struct efx_nic *efx)
1755{ 1784{
1756 struct ethtool_cmd ecmd;
1757 enum reset_type method = efx->reset_pending; 1785 enum reset_type method = efx->reset_pending;
1758 int rc = 0; 1786 int rc = 0;
1759 1787
@@ -1769,7 +1797,7 @@ static int efx_reset(struct efx_nic *efx)
1769 1797
1770 EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method)); 1798 EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method));
1771 1799
1772 efx_reset_down(efx, method, &ecmd); 1800 efx_reset_down(efx, method);
1773 1801
1774 rc = efx->type->reset(efx, method); 1802 rc = efx->type->reset(efx, method);
1775 if (rc) { 1803 if (rc) {
@@ -1788,10 +1816,10 @@ static int efx_reset(struct efx_nic *efx)
1788 1816
1789 /* Leave device stopped if necessary */ 1817 /* Leave device stopped if necessary */
1790 if (method == RESET_TYPE_DISABLE) { 1818 if (method == RESET_TYPE_DISABLE) {
1791 efx_reset_up(efx, method, &ecmd, false); 1819 efx_reset_up(efx, method, false);
1792 rc = -EIO; 1820 rc = -EIO;
1793 } else { 1821 } else {
1794 rc = efx_reset_up(efx, method, &ecmd, true); 1822 rc = efx_reset_up(efx, method, true);
1795 } 1823 }
1796 1824
1797out_disable: 1825out_disable:
@@ -1895,7 +1923,7 @@ bool efx_port_dummy_op_poll(struct efx_nic *efx)
1895 1923
1896static struct efx_phy_operations efx_dummy_phy_operations = { 1924static struct efx_phy_operations efx_dummy_phy_operations = {
1897 .init = efx_port_dummy_op_int, 1925 .init = efx_port_dummy_op_int,
1898 .reconfigure = efx_port_dummy_op_void, 1926 .reconfigure = efx_port_dummy_op_int,
1899 .poll = efx_port_dummy_op_poll, 1927 .poll = efx_port_dummy_op_poll,
1900 .fini = efx_port_dummy_op_void, 1928 .fini = efx_port_dummy_op_void,
1901}; 1929};