diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/sfc/efx.c | 132 | ||||
-rw-r--r-- | drivers/net/sfc/efx.h | 12 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 61 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 98 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.h | 3 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_boards.c | 3 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_gmac.c | 4 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_xmac.c | 8 | ||||
-rw-r--r-- | drivers/net/sfc/mac.h | 1 | ||||
-rw-r--r-- | drivers/net/sfc/mdio_10g.c | 41 | ||||
-rw-r--r-- | drivers/net/sfc/mdio_10g.h | 3 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 8 | ||||
-rw-r--r-- | drivers/net/sfc/qt202x_phy.c | 4 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 11 | ||||
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 66 |
15 files changed, 273 insertions, 182 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 73ab246d9f2a..4210121eeff9 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 | ||
623 | void 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 | |||
636 | void 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 | |||
623 | static void efx_fini_port(struct efx_nic *efx); | 651 | static 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 |
627 | void __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 | */ | ||
660 | int __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 | ||
661 | fail: | 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. */ |
669 | void efx_reconfigure_port(struct efx_nic *efx) | 690 | int 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. */ |
1685 | void efx_reset_down(struct efx_nic *efx, enum reset_type method, | 1717 | void 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. */ |
1707 | int efx_reset_up(struct efx_nic *efx, enum reset_type method, | 1736 | int 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 | */ |
1754 | static int efx_reset(struct efx_nic *efx) | 1783 | static 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 | ||
1797 | out_disable: | 1825 | out_disable: |
@@ -1895,7 +1923,7 @@ bool efx_port_dummy_op_poll(struct efx_nic *efx) | |||
1895 | 1923 | ||
1896 | static struct efx_phy_operations efx_dummy_phy_operations = { | 1924 | static 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 | }; |
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index 15edda2a2242..c78500321586 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h | |||
@@ -60,8 +60,8 @@ extern void efx_process_channel_now(struct efx_channel *channel); | |||
60 | #define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1) | 60 | #define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1) |
61 | 61 | ||
62 | /* Ports */ | 62 | /* Ports */ |
63 | extern void efx_reconfigure_port(struct efx_nic *efx); | 63 | extern int efx_reconfigure_port(struct efx_nic *efx); |
64 | extern void __efx_reconfigure_port(struct efx_nic *efx); | 64 | extern int __efx_reconfigure_port(struct efx_nic *efx); |
65 | 65 | ||
66 | /* Ethtool support */ | 66 | /* Ethtool support */ |
67 | extern int efx_ethtool_get_settings(struct net_device *net_dev, | 67 | extern int efx_ethtool_get_settings(struct net_device *net_dev, |
@@ -71,10 +71,8 @@ extern int efx_ethtool_set_settings(struct net_device *net_dev, | |||
71 | extern const struct ethtool_ops efx_ethtool_ops; | 71 | extern const struct ethtool_ops efx_ethtool_ops; |
72 | 72 | ||
73 | /* Reset handling */ | 73 | /* Reset handling */ |
74 | extern void efx_reset_down(struct efx_nic *efx, enum reset_type method, | 74 | extern void efx_reset_down(struct efx_nic *efx, enum reset_type method); |
75 | struct ethtool_cmd *ecmd); | 75 | extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok); |
76 | extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, | ||
77 | struct ethtool_cmd *ecmd, bool ok); | ||
78 | 76 | ||
79 | /* Global */ | 77 | /* Global */ |
80 | extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); | 78 | extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); |
@@ -115,5 +113,7 @@ static inline void efx_schedule_channel(struct efx_channel *channel) | |||
115 | } | 113 | } |
116 | 114 | ||
117 | extern void efx_link_status_changed(struct efx_nic *efx); | 115 | extern void efx_link_status_changed(struct efx_nic *efx); |
116 | extern void efx_link_set_advertising(struct efx_nic *efx, u32); | ||
117 | extern void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type); | ||
118 | 118 | ||
119 | #endif /* EFX_EFX_H */ | 119 | #endif /* EFX_EFX_H */ |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 49e0aed920d3..d95d0fa399ff 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -10,7 +10,6 @@ | |||
10 | 10 | ||
11 | #include <linux/netdevice.h> | 11 | #include <linux/netdevice.h> |
12 | #include <linux/ethtool.h> | 12 | #include <linux/ethtool.h> |
13 | #include <linux/mdio.h> | ||
14 | #include <linux/rtnetlink.h> | 13 | #include <linux/rtnetlink.h> |
15 | #include "net_driver.h" | 14 | #include "net_driver.h" |
16 | #include "workarounds.h" | 15 | #include "workarounds.h" |
@@ -191,6 +190,7 @@ int efx_ethtool_get_settings(struct net_device *net_dev, | |||
191 | struct ethtool_cmd *ecmd) | 190 | struct ethtool_cmd *ecmd) |
192 | { | 191 | { |
193 | struct efx_nic *efx = netdev_priv(net_dev); | 192 | struct efx_nic *efx = netdev_priv(net_dev); |
193 | struct efx_link_state *link_state = &efx->link_state; | ||
194 | 194 | ||
195 | mutex_lock(&efx->mac_lock); | 195 | mutex_lock(&efx->mac_lock); |
196 | efx->phy_op->get_settings(efx, ecmd); | 196 | efx->phy_op->get_settings(efx, ecmd); |
@@ -198,6 +198,13 @@ int efx_ethtool_get_settings(struct net_device *net_dev, | |||
198 | 198 | ||
199 | /* Falcon GMAC does not support 1000Mbps HD */ | 199 | /* Falcon GMAC does not support 1000Mbps HD */ |
200 | ecmd->supported &= ~SUPPORTED_1000baseT_Half; | 200 | ecmd->supported &= ~SUPPORTED_1000baseT_Half; |
201 | /* Both MACs support pause frames (bidirectional and respond-only) */ | ||
202 | ecmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; | ||
203 | |||
204 | if (LOOPBACK_INTERNAL(efx)) { | ||
205 | ecmd->speed = link_state->speed; | ||
206 | ecmd->duplex = link_state->fd ? DUPLEX_FULL : DUPLEX_HALF; | ||
207 | } | ||
201 | 208 | ||
202 | return 0; | 209 | return 0; |
203 | } | 210 | } |
@@ -219,9 +226,6 @@ int efx_ethtool_set_settings(struct net_device *net_dev, | |||
219 | mutex_lock(&efx->mac_lock); | 226 | mutex_lock(&efx->mac_lock); |
220 | rc = efx->phy_op->set_settings(efx, ecmd); | 227 | rc = efx->phy_op->set_settings(efx, ecmd); |
221 | mutex_unlock(&efx->mac_lock); | 228 | mutex_unlock(&efx->mac_lock); |
222 | if (!rc) | ||
223 | efx_reconfigure_port(efx); | ||
224 | |||
225 | return rc; | 229 | return rc; |
226 | } | 230 | } |
227 | 231 | ||
@@ -658,8 +662,12 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
658 | struct ethtool_pauseparam *pause) | 662 | struct ethtool_pauseparam *pause) |
659 | { | 663 | { |
660 | struct efx_nic *efx = netdev_priv(net_dev); | 664 | struct efx_nic *efx = netdev_priv(net_dev); |
661 | enum efx_fc_type wanted_fc; | 665 | enum efx_fc_type wanted_fc, old_fc; |
666 | u32 old_adv; | ||
662 | bool reset; | 667 | bool reset; |
668 | int rc = 0; | ||
669 | |||
670 | mutex_lock(&efx->mac_lock); | ||
663 | 671 | ||
664 | wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) | | 672 | wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) | |
665 | (pause->tx_pause ? EFX_FC_TX : 0) | | 673 | (pause->tx_pause ? EFX_FC_TX : 0) | |
@@ -667,14 +675,14 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
667 | 675 | ||
668 | if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) { | 676 | if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) { |
669 | EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n"); | 677 | EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n"); |
670 | return -EINVAL; | 678 | rc = -EINVAL; |
679 | goto out; | ||
671 | } | 680 | } |
672 | 681 | ||
673 | if (!(efx->phy_op->mmds & MDIO_DEVS_AN) && | 682 | if ((wanted_fc & EFX_FC_AUTO) && !efx->link_advertising) { |
674 | (wanted_fc & EFX_FC_AUTO)) { | 683 | EFX_LOG(efx, "Autonegotiation is disabled\n"); |
675 | EFX_LOG(efx, "PHY does not support flow control " | 684 | rc = -EINVAL; |
676 | "autonegotiation\n"); | 685 | goto out; |
677 | return -EINVAL; | ||
678 | } | 686 | } |
679 | 687 | ||
680 | /* TX flow control may automatically turn itself off if the | 688 | /* TX flow control may automatically turn itself off if the |
@@ -686,25 +694,38 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
686 | if (EFX_WORKAROUND_11482(efx) && reset) { | 694 | if (EFX_WORKAROUND_11482(efx) && reset) { |
687 | if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) { | 695 | if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) { |
688 | /* Recover by resetting the EM block */ | 696 | /* Recover by resetting the EM block */ |
689 | if (efx->link_state.up) | 697 | falcon_stop_nic_stats(efx); |
690 | falcon_drain_tx_fifo(efx); | 698 | falcon_drain_tx_fifo(efx); |
699 | efx->mac_op->reconfigure(efx); | ||
700 | falcon_start_nic_stats(efx); | ||
691 | } else { | 701 | } else { |
692 | /* Schedule a reset to recover */ | 702 | /* Schedule a reset to recover */ |
693 | efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); | 703 | efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); |
694 | } | 704 | } |
695 | } | 705 | } |
696 | 706 | ||
697 | /* Try to push the pause parameters */ | 707 | old_adv = efx->link_advertising; |
698 | mutex_lock(&efx->mac_lock); | 708 | old_fc = efx->wanted_fc; |
709 | efx_link_set_wanted_fc(efx, wanted_fc); | ||
710 | if (efx->link_advertising != old_adv || | ||
711 | (efx->wanted_fc ^ old_fc) & EFX_FC_AUTO) { | ||
712 | rc = efx->phy_op->reconfigure(efx); | ||
713 | if (rc) { | ||
714 | EFX_ERR(efx, "Unable to advertise requested flow " | ||
715 | "control setting\n"); | ||
716 | goto out; | ||
717 | } | ||
718 | } | ||
699 | 719 | ||
700 | efx->wanted_fc = wanted_fc; | 720 | /* Reconfigure the MAC. The PHY *may* generate a link state change event |
701 | if (efx->phy_op->mmds & MDIO_DEVS_AN) | 721 | * if the user just changed the advertised capabilities, but there's no |
702 | mdio45_ethtool_spauseparam_an(&efx->mdio, pause); | 722 | * harm doing this twice */ |
703 | __efx_reconfigure_port(efx); | 723 | efx->mac_op->reconfigure(efx); |
704 | 724 | ||
725 | out: | ||
705 | mutex_unlock(&efx->mac_lock); | 726 | mutex_unlock(&efx->mac_lock); |
706 | 727 | ||
707 | return 0; | 728 | return rc; |
708 | } | 729 | } |
709 | 730 | ||
710 | static void efx_ethtool_get_pauseparam(struct net_device *net_dev, | 731 | static void efx_ethtool_get_pauseparam(struct net_device *net_dev, |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index f6d10213d0b7..3466616c01c0 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -1193,6 +1193,8 @@ static void falcon_poll_flush_events(struct efx_nic *efx) | |||
1193 | channel->eventq_read_ptr = read_ptr; | 1193 | channel->eventq_read_ptr = read_ptr; |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | static void falcon_deconfigure_mac_wrapper(struct efx_nic *efx); | ||
1197 | |||
1196 | static void falcon_prepare_flush(struct efx_nic *efx) | 1198 | static void falcon_prepare_flush(struct efx_nic *efx) |
1197 | { | 1199 | { |
1198 | falcon_deconfigure_mac_wrapper(efx); | 1200 | falcon_deconfigure_mac_wrapper(efx); |
@@ -1836,9 +1838,10 @@ static void falcon_push_multicast_hash(struct efx_nic *efx) | |||
1836 | efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1); | 1838 | efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1); |
1837 | } | 1839 | } |
1838 | 1840 | ||
1839 | static int falcon_reset_macs(struct efx_nic *efx) | 1841 | static void falcon_reset_macs(struct efx_nic *efx) |
1840 | { | 1842 | { |
1841 | efx_oword_t reg; | 1843 | struct falcon_nic_data *nic_data = efx->nic_data; |
1844 | efx_oword_t reg, mac_ctrl; | ||
1842 | int count; | 1845 | int count; |
1843 | 1846 | ||
1844 | if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) { | 1847 | if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) { |
@@ -1853,7 +1856,7 @@ static int falcon_reset_macs(struct efx_nic *efx) | |||
1853 | EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0); | 1856 | EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0); |
1854 | efx_writeo(efx, ®, FR_AB_GM_CFG1); | 1857 | efx_writeo(efx, ®, FR_AB_GM_CFG1); |
1855 | udelay(1000); | 1858 | udelay(1000); |
1856 | return 0; | 1859 | return; |
1857 | } else { | 1860 | } else { |
1858 | EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1); | 1861 | EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1); |
1859 | efx_writeo(efx, ®, FR_AB_XM_GLB_CFG); | 1862 | efx_writeo(efx, ®, FR_AB_XM_GLB_CFG); |
@@ -1862,22 +1865,20 @@ static int falcon_reset_macs(struct efx_nic *efx) | |||
1862 | efx_reado(efx, ®, FR_AB_XM_GLB_CFG); | 1865 | efx_reado(efx, ®, FR_AB_XM_GLB_CFG); |
1863 | if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) == | 1866 | if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) == |
1864 | 0) | 1867 | 0) |
1865 | return 0; | 1868 | return; |
1866 | udelay(10); | 1869 | udelay(10); |
1867 | } | 1870 | } |
1868 | 1871 | ||
1869 | EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); | 1872 | EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); |
1870 | return -ETIMEDOUT; | ||
1871 | } | 1873 | } |
1872 | } | 1874 | } |
1873 | 1875 | ||
1874 | /* MAC stats will fail whilst the TX fifo is draining. Serialise | 1876 | /* Mac stats will fail whist the TX fifo is draining */ |
1875 | * the drain sequence with the statistics fetch */ | 1877 | WARN_ON(nic_data->stats_disable_count == 0); |
1876 | falcon_stop_nic_stats(efx); | ||
1877 | 1878 | ||
1878 | efx_reado(efx, ®, FR_AB_MAC_CTRL); | 1879 | efx_reado(efx, &mac_ctrl, FR_AB_MAC_CTRL); |
1879 | EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, 1); | 1880 | EFX_SET_OWORD_FIELD(mac_ctrl, FRF_BB_TXFIFO_DRAIN_EN, 1); |
1880 | efx_writeo(efx, ®, FR_AB_MAC_CTRL); | 1881 | efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL); |
1881 | 1882 | ||
1882 | efx_reado(efx, ®, FR_AB_GLB_CTL); | 1883 | efx_reado(efx, ®, FR_AB_GLB_CTL); |
1883 | EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_XGTX, 1); | 1884 | EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_XGTX, 1); |
@@ -1903,14 +1904,9 @@ static int falcon_reset_macs(struct efx_nic *efx) | |||
1903 | udelay(10); | 1904 | udelay(10); |
1904 | } | 1905 | } |
1905 | 1906 | ||
1906 | /* If we've reset the EM block and the link is up, then | 1907 | /* Ensure the correct MAC is selected before statistics |
1907 | * we'll have to kick the XAUI link so the PHY can recover */ | 1908 | * are re-enabled by the caller */ |
1908 | if (efx->link_state.up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx)) | 1909 | efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL); |
1909 | falcon_reset_xaui(efx); | ||
1910 | |||
1911 | falcon_start_nic_stats(efx); | ||
1912 | |||
1913 | return 0; | ||
1914 | } | 1910 | } |
1915 | 1911 | ||
1916 | void falcon_drain_tx_fifo(struct efx_nic *efx) | 1912 | void falcon_drain_tx_fifo(struct efx_nic *efx) |
@@ -1929,7 +1925,7 @@ void falcon_drain_tx_fifo(struct efx_nic *efx) | |||
1929 | falcon_reset_macs(efx); | 1925 | falcon_reset_macs(efx); |
1930 | } | 1926 | } |
1931 | 1927 | ||
1932 | void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) | 1928 | static void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) |
1933 | { | 1929 | { |
1934 | efx_oword_t reg; | 1930 | efx_oword_t reg; |
1935 | 1931 | ||
@@ -1941,8 +1937,8 @@ void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) | |||
1941 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 0); | 1937 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 0); |
1942 | efx_writeo(efx, ®, FR_AZ_RX_CFG); | 1938 | efx_writeo(efx, ®, FR_AZ_RX_CFG); |
1943 | 1939 | ||
1944 | if (!efx->link_state.up) | 1940 | /* Isolate TX -> MAC */ |
1945 | falcon_drain_tx_fifo(efx); | 1941 | falcon_drain_tx_fifo(efx); |
1946 | } | 1942 | } |
1947 | 1943 | ||
1948 | void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) | 1944 | void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) |
@@ -2044,6 +2040,8 @@ static void falcon_stats_timer_func(unsigned long context) | |||
2044 | spin_unlock(&efx->stats_lock); | 2040 | spin_unlock(&efx->stats_lock); |
2045 | } | 2041 | } |
2046 | 2042 | ||
2043 | static void falcon_switch_mac(struct efx_nic *efx); | ||
2044 | |||
2047 | static bool falcon_loopback_link_poll(struct efx_nic *efx) | 2045 | static bool falcon_loopback_link_poll(struct efx_nic *efx) |
2048 | { | 2046 | { |
2049 | struct efx_link_state old_state = efx->link_state; | 2047 | struct efx_link_state old_state = efx->link_state; |
@@ -2063,6 +2061,38 @@ static bool falcon_loopback_link_poll(struct efx_nic *efx) | |||
2063 | return !efx_link_state_equal(&efx->link_state, &old_state); | 2061 | return !efx_link_state_equal(&efx->link_state, &old_state); |
2064 | } | 2062 | } |
2065 | 2063 | ||
2064 | static int falcon_reconfigure_port(struct efx_nic *efx) | ||
2065 | { | ||
2066 | int rc; | ||
2067 | |||
2068 | WARN_ON(efx_nic_rev(efx) > EFX_REV_FALCON_B0); | ||
2069 | |||
2070 | /* Poll the PHY link state *before* reconfiguring it. This means we | ||
2071 | * will pick up the correct speed (in loopback) to select the correct | ||
2072 | * MAC. | ||
2073 | */ | ||
2074 | if (LOOPBACK_INTERNAL(efx)) | ||
2075 | falcon_loopback_link_poll(efx); | ||
2076 | else | ||
2077 | efx->phy_op->poll(efx); | ||
2078 | |||
2079 | falcon_stop_nic_stats(efx); | ||
2080 | falcon_deconfigure_mac_wrapper(efx); | ||
2081 | |||
2082 | falcon_switch_mac(efx); | ||
2083 | |||
2084 | efx->phy_op->reconfigure(efx); | ||
2085 | rc = efx->mac_op->reconfigure(efx); | ||
2086 | BUG_ON(rc); | ||
2087 | |||
2088 | falcon_start_nic_stats(efx); | ||
2089 | |||
2090 | /* Synchronise efx->link_state with the kernel */ | ||
2091 | efx_link_status_changed(efx); | ||
2092 | |||
2093 | return 0; | ||
2094 | } | ||
2095 | |||
2066 | /************************************************************************** | 2096 | /************************************************************************** |
2067 | * | 2097 | * |
2068 | * PHY access via GMII | 2098 | * PHY access via GMII |
@@ -2215,17 +2245,15 @@ static void falcon_clock_mac(struct efx_nic *efx) | |||
2215 | } | 2245 | } |
2216 | } | 2246 | } |
2217 | 2247 | ||
2218 | int falcon_switch_mac(struct efx_nic *efx) | 2248 | static void falcon_switch_mac(struct efx_nic *efx) |
2219 | { | 2249 | { |
2220 | struct efx_mac_operations *old_mac_op = efx->mac_op; | 2250 | struct efx_mac_operations *old_mac_op = efx->mac_op; |
2221 | struct falcon_nic_data *nic_data = efx->nic_data; | 2251 | struct falcon_nic_data *nic_data = efx->nic_data; |
2222 | unsigned int stats_done_offset; | 2252 | unsigned int stats_done_offset; |
2223 | int rc = 0; | ||
2224 | |||
2225 | /* Don't try to fetch MAC stats while we're switching MACs */ | ||
2226 | falcon_stop_nic_stats(efx); | ||
2227 | 2253 | ||
2228 | WARN_ON(!mutex_is_locked(&efx->mac_lock)); | 2254 | WARN_ON(!mutex_is_locked(&efx->mac_lock)); |
2255 | WARN_ON(nic_data->stats_disable_count == 0); | ||
2256 | |||
2229 | efx->mac_op = (EFX_IS10G(efx) ? | 2257 | efx->mac_op = (EFX_IS10G(efx) ? |
2230 | &falcon_xmac_operations : &falcon_gmac_operations); | 2258 | &falcon_xmac_operations : &falcon_gmac_operations); |
2231 | 2259 | ||
@@ -2236,18 +2264,14 @@ int falcon_switch_mac(struct efx_nic *efx) | |||
2236 | nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset; | 2264 | nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset; |
2237 | 2265 | ||
2238 | if (old_mac_op == efx->mac_op) | 2266 | if (old_mac_op == efx->mac_op) |
2239 | goto out; | 2267 | return; |
2240 | 2268 | ||
2241 | falcon_clock_mac(efx); | 2269 | falcon_clock_mac(efx); |
2242 | 2270 | ||
2243 | EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); | 2271 | EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); |
2244 | /* Not all macs support a mac-level link state */ | 2272 | /* Not all macs support a mac-level link state */ |
2245 | efx->xmac_poll_required = false; | 2273 | efx->xmac_poll_required = false; |
2246 | 2274 | falcon_reset_macs(efx); | |
2247 | rc = falcon_reset_macs(efx); | ||
2248 | out: | ||
2249 | falcon_start_nic_stats(efx); | ||
2250 | return rc; | ||
2251 | } | 2275 | } |
2252 | 2276 | ||
2253 | /* This call is responsible for hooking in the MAC and PHY operations */ | 2277 | /* This call is responsible for hooking in the MAC and PHY operations */ |
@@ -2597,7 +2621,8 @@ static void falcon_monitor(struct efx_nic *efx) | |||
2597 | EFX_ERR(efx, "Board sensor %s; shutting down PHY\n", | 2621 | EFX_ERR(efx, "Board sensor %s; shutting down PHY\n", |
2598 | (rc == -ERANGE) ? "reported fault" : "failed"); | 2622 | (rc == -ERANGE) ? "reported fault" : "failed"); |
2599 | efx->phy_mode |= PHY_MODE_LOW_POWER; | 2623 | efx->phy_mode |= PHY_MODE_LOW_POWER; |
2600 | __efx_reconfigure_port(efx); | 2624 | rc = __efx_reconfigure_port(efx); |
2625 | WARN_ON(rc); | ||
2601 | } | 2626 | } |
2602 | 2627 | ||
2603 | if (LOOPBACK_INTERNAL(efx)) | 2628 | if (LOOPBACK_INTERNAL(efx)) |
@@ -2610,7 +2635,8 @@ static void falcon_monitor(struct efx_nic *efx) | |||
2610 | falcon_deconfigure_mac_wrapper(efx); | 2635 | falcon_deconfigure_mac_wrapper(efx); |
2611 | 2636 | ||
2612 | falcon_switch_mac(efx); | 2637 | falcon_switch_mac(efx); |
2613 | efx->mac_op->reconfigure(efx); | 2638 | rc = efx->mac_op->reconfigure(efx); |
2639 | BUG_ON(rc); | ||
2614 | 2640 | ||
2615 | falcon_start_nic_stats(efx); | 2641 | falcon_start_nic_stats(efx); |
2616 | 2642 | ||
@@ -3239,6 +3265,7 @@ struct efx_nic_type falcon_a1_nic_type = { | |||
3239 | .stop_stats = falcon_stop_nic_stats, | 3265 | .stop_stats = falcon_stop_nic_stats, |
3240 | .push_irq_moderation = falcon_push_irq_moderation, | 3266 | .push_irq_moderation = falcon_push_irq_moderation, |
3241 | .push_multicast_hash = falcon_push_multicast_hash, | 3267 | .push_multicast_hash = falcon_push_multicast_hash, |
3268 | .reconfigure_port = falcon_reconfigure_port, | ||
3242 | .default_mac_ops = &falcon_xmac_operations, | 3269 | .default_mac_ops = &falcon_xmac_operations, |
3243 | 3270 | ||
3244 | .revision = EFX_REV_FALCON_A1, | 3271 | .revision = EFX_REV_FALCON_A1, |
@@ -3271,6 +3298,7 @@ struct efx_nic_type falcon_b0_nic_type = { | |||
3271 | .stop_stats = falcon_stop_nic_stats, | 3298 | .stop_stats = falcon_stop_nic_stats, |
3272 | .push_irq_moderation = falcon_push_irq_moderation, | 3299 | .push_irq_moderation = falcon_push_irq_moderation, |
3273 | .push_multicast_hash = falcon_push_multicast_hash, | 3300 | .push_multicast_hash = falcon_push_multicast_hash, |
3301 | .reconfigure_port = falcon_reconfigure_port, | ||
3274 | .default_mac_ops = &falcon_xmac_operations, | 3302 | .default_mac_ops = &falcon_xmac_operations, |
3275 | 3303 | ||
3276 | .revision = EFX_REV_FALCON_B0, | 3304 | .revision = EFX_REV_FALCON_B0, |
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h index 3fe64849c98d..560a3f9895a5 100644 --- a/drivers/net/sfc/falcon.h +++ b/drivers/net/sfc/falcon.h | |||
@@ -130,10 +130,7 @@ extern int falcon_process_eventq(struct efx_channel *channel, int rx_quota); | |||
130 | extern void falcon_eventq_read_ack(struct efx_channel *channel); | 130 | extern void falcon_eventq_read_ack(struct efx_channel *channel); |
131 | 131 | ||
132 | /* MAC/PHY */ | 132 | /* MAC/PHY */ |
133 | extern int falcon_switch_mac(struct efx_nic *efx); | ||
134 | extern bool falcon_xaui_link_ok(struct efx_nic *efx); | ||
135 | extern void falcon_drain_tx_fifo(struct efx_nic *efx); | 133 | extern void falcon_drain_tx_fifo(struct efx_nic *efx); |
136 | extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx); | ||
137 | extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx); | 134 | extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx); |
138 | 135 | ||
139 | /* Interrupts and test events */ | 136 | /* Interrupts and test events */ |
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c index da750959c61a..b92decc9521b 100644 --- a/drivers/net/sfc/falcon_boards.c +++ b/drivers/net/sfc/falcon_boards.c | |||
@@ -352,7 +352,8 @@ static ssize_t set_phy_flash_cfg(struct device *dev, | |||
352 | err = sfe4001_poweron(efx); | 352 | err = sfe4001_poweron(efx); |
353 | else | 353 | else |
354 | err = sfn4111t_reset(efx); | 354 | err = sfn4111t_reset(efx); |
355 | efx_reconfigure_port(efx); | 355 | if (!err) |
356 | err = efx_reconfigure_port(efx); | ||
356 | if (!(new_mode & PHY_MODE_SPECIAL)) | 357 | if (!(new_mode & PHY_MODE_SPECIAL)) |
357 | falcon_start_nic_stats(efx); | 358 | falcon_start_nic_stats(efx); |
358 | } | 359 | } |
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c index 66d499cc23f2..19dd3ac3d1c7 100644 --- a/drivers/net/sfc/falcon_gmac.c +++ b/drivers/net/sfc/falcon_gmac.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * | 22 | * |
23 | *************************************************************************/ | 23 | *************************************************************************/ |
24 | 24 | ||
25 | static void falcon_reconfigure_gmac(struct efx_nic *efx) | 25 | static int falcon_reconfigure_gmac(struct efx_nic *efx) |
26 | { | 26 | { |
27 | struct efx_link_state *link_state = &efx->link_state; | 27 | struct efx_link_state *link_state = &efx->link_state; |
28 | bool loopback, tx_fc, rx_fc, bytemode; | 28 | bool loopback, tx_fc, rx_fc, bytemode; |
@@ -123,6 +123,8 @@ static void falcon_reconfigure_gmac(struct efx_nic *efx) | |||
123 | udelay(10); | 123 | udelay(10); |
124 | 124 | ||
125 | falcon_reconfigure_mac_wrapper(efx); | 125 | falcon_reconfigure_mac_wrapper(efx); |
126 | |||
127 | return 0; | ||
126 | } | 128 | } |
127 | 129 | ||
128 | static void falcon_update_stats_gmac(struct efx_nic *efx) | 130 | static void falcon_update_stats_gmac(struct efx_nic *efx) |
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 60dc0975cfa4..898afc1b5ef1 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c | |||
@@ -112,7 +112,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) | |||
112 | } | 112 | } |
113 | 113 | ||
114 | /* Get status of XAUI link */ | 114 | /* Get status of XAUI link */ |
115 | bool falcon_xaui_link_ok(struct efx_nic *efx) | 115 | static bool falcon_xaui_link_ok(struct efx_nic *efx) |
116 | { | 116 | { |
117 | efx_oword_t reg; | 117 | efx_oword_t reg; |
118 | bool align_done, link_ok = false; | 118 | bool align_done, link_ok = false; |
@@ -143,7 +143,7 @@ bool falcon_xaui_link_ok(struct efx_nic *efx) | |||
143 | return link_ok; | 143 | return link_ok; |
144 | } | 144 | } |
145 | 145 | ||
146 | static void falcon_reconfigure_xmac_core(struct efx_nic *efx) | 146 | void falcon_reconfigure_xmac_core(struct efx_nic *efx) |
147 | { | 147 | { |
148 | unsigned int max_frame_len; | 148 | unsigned int max_frame_len; |
149 | efx_oword_t reg; | 149 | efx_oword_t reg; |
@@ -275,7 +275,7 @@ static bool falcon_xmac_check_fault(struct efx_nic *efx) | |||
275 | return !falcon_check_xaui_link_up(efx, 5); | 275 | return !falcon_check_xaui_link_up(efx, 5); |
276 | } | 276 | } |
277 | 277 | ||
278 | static void falcon_reconfigure_xmac(struct efx_nic *efx) | 278 | static int falcon_reconfigure_xmac(struct efx_nic *efx) |
279 | { | 279 | { |
280 | falcon_mask_status_intr(efx, false); | 280 | falcon_mask_status_intr(efx, false); |
281 | 281 | ||
@@ -286,6 +286,8 @@ static void falcon_reconfigure_xmac(struct efx_nic *efx) | |||
286 | 286 | ||
287 | efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5); | 287 | efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5); |
288 | falcon_mask_status_intr(efx, true); | 288 | falcon_mask_status_intr(efx, true); |
289 | |||
290 | return 0; | ||
289 | } | 291 | } |
290 | 292 | ||
291 | static void falcon_update_stats_xmac(struct efx_nic *efx) | 293 | static void falcon_update_stats_xmac(struct efx_nic *efx) |
diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h index 4e7074278fe1..d2af50f1747b 100644 --- a/drivers/net/sfc/mac.h +++ b/drivers/net/sfc/mac.h | |||
@@ -15,5 +15,6 @@ | |||
15 | 15 | ||
16 | extern struct efx_mac_operations falcon_gmac_operations; | 16 | extern struct efx_mac_operations falcon_gmac_operations; |
17 | extern struct efx_mac_operations falcon_xmac_operations; | 17 | extern struct efx_mac_operations falcon_xmac_operations; |
18 | extern void falcon_reconfigure_xmac_core(struct efx_nic *efx); | ||
18 | 19 | ||
19 | #endif | 20 | #endif |
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 231e580acc9a..1f62a5c002fd 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c | |||
@@ -248,8 +248,6 @@ void efx_mdio_set_mmds_lpower(struct efx_nic *efx, | |||
248 | int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 248 | int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) |
249 | { | 249 | { |
250 | struct ethtool_cmd prev; | 250 | struct ethtool_cmd prev; |
251 | bool xnp; | ||
252 | int reg; | ||
253 | 251 | ||
254 | efx->phy_op->get_settings(efx, &prev); | 252 | efx->phy_op->get_settings(efx, &prev); |
255 | 253 | ||
@@ -269,30 +267,47 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | |||
269 | (ecmd->advertising | SUPPORTED_Autoneg) & ~prev.supported) | 267 | (ecmd->advertising | SUPPORTED_Autoneg) & ~prev.supported) |
270 | return -EINVAL; | 268 | return -EINVAL; |
271 | 269 | ||
272 | xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full | 270 | efx_link_set_advertising(efx, ecmd->advertising | ADVERTISED_Autoneg); |
273 | || EFX_WORKAROUND_13204(efx)); | 271 | efx_mdio_an_reconfigure(efx); |
272 | return 0; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * efx_mdio_an_reconfigure - Push advertising flags and restart autonegotiation | ||
277 | * @efx: Efx NIC | ||
278 | */ | ||
279 | void efx_mdio_an_reconfigure(struct efx_nic *efx) | ||
280 | { | ||
281 | bool xnp = (efx->link_advertising & ADVERTISED_10000baseT_Full | ||
282 | || EFX_WORKAROUND_13204(efx)); | ||
283 | int reg; | ||
284 | |||
285 | WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN)); | ||
274 | 286 | ||
275 | /* Set up the base page */ | 287 | /* Set up the base page */ |
276 | reg = ADVERTISE_CSMA; | 288 | reg = ADVERTISE_CSMA; |
277 | if (ecmd->advertising & ADVERTISED_10baseT_Half) | 289 | if (efx->link_advertising & ADVERTISED_10baseT_Half) |
278 | reg |= ADVERTISE_10HALF; | 290 | reg |= ADVERTISE_10HALF; |
279 | if (ecmd->advertising & ADVERTISED_10baseT_Full) | 291 | if (efx->link_advertising & ADVERTISED_10baseT_Full) |
280 | reg |= ADVERTISE_10FULL; | 292 | reg |= ADVERTISE_10FULL; |
281 | if (ecmd->advertising & ADVERTISED_100baseT_Half) | 293 | if (efx->link_advertising & ADVERTISED_100baseT_Half) |
282 | reg |= ADVERTISE_100HALF; | 294 | reg |= ADVERTISE_100HALF; |
283 | if (ecmd->advertising & ADVERTISED_100baseT_Full) | 295 | if (efx->link_advertising & ADVERTISED_100baseT_Full) |
284 | reg |= ADVERTISE_100FULL; | 296 | reg |= ADVERTISE_100FULL; |
285 | if (xnp) | 297 | if (xnp) |
286 | reg |= ADVERTISE_RESV; | 298 | reg |= ADVERTISE_RESV; |
287 | else if (ecmd->advertising & (ADVERTISED_1000baseT_Half | | 299 | else if (efx->link_advertising & (ADVERTISED_1000baseT_Half | |
288 | ADVERTISED_1000baseT_Full)) | 300 | ADVERTISED_1000baseT_Full)) |
289 | reg |= ADVERTISE_NPAGE; | 301 | reg |= ADVERTISE_NPAGE; |
290 | reg |= mii_advertise_flowctrl(efx->wanted_fc); | 302 | if (efx->link_advertising & ADVERTISED_Pause) |
303 | reg |= ADVERTISE_PAUSE_CAP; | ||
304 | if (efx->link_advertising & ADVERTISED_Asym_Pause) | ||
305 | reg |= ADVERTISE_PAUSE_ASYM; | ||
291 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); | 306 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); |
292 | 307 | ||
293 | /* Set up the (extended) next page if necessary */ | 308 | /* Set up the (extended) next page if necessary */ |
294 | if (efx->phy_op->set_npage_adv) | 309 | if (efx->phy_op->set_npage_adv) |
295 | efx->phy_op->set_npage_adv(efx, ecmd->advertising); | 310 | efx->phy_op->set_npage_adv(efx, efx->link_advertising); |
296 | 311 | ||
297 | /* Enable and restart AN */ | 312 | /* Enable and restart AN */ |
298 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); | 313 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); |
@@ -305,8 +320,6 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | |||
305 | else | 320 | else |
306 | reg &= ~MDIO_AN_CTRL1_XNP; | 321 | reg &= ~MDIO_AN_CTRL1_XNP; |
307 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); | 322 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); |
308 | |||
309 | return 0; | ||
310 | } | 323 | } |
311 | 324 | ||
312 | enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) | 325 | enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) |
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index 75b37f101231..dbc8e7de2929 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h | |||
@@ -86,6 +86,9 @@ extern void efx_mdio_set_mmds_lpower(struct efx_nic *efx, | |||
86 | /* Set (some of) the PHY settings over MDIO */ | 86 | /* Set (some of) the PHY settings over MDIO */ |
87 | extern int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); | 87 | extern int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); |
88 | 88 | ||
89 | /* Push advertising flags and restart autonegotiation */ | ||
90 | extern void efx_mdio_an_reconfigure(struct efx_nic *efx); | ||
91 | |||
89 | /* Get pause parameters from AN if available (otherwise return | 92 | /* Get pause parameters from AN if available (otherwise return |
90 | * requested pause parameters) | 93 | * requested pause parameters) |
91 | */ | 94 | */ |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 32806f9a7e49..f63a05c4e38b 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -517,7 +517,7 @@ static inline bool efx_link_state_equal(const struct efx_link_state *left, | |||
517 | * @check_fault: Check fault state. True if fault present. | 517 | * @check_fault: Check fault state. True if fault present. |
518 | */ | 518 | */ |
519 | struct efx_mac_operations { | 519 | struct efx_mac_operations { |
520 | void (*reconfigure) (struct efx_nic *efx); | 520 | int (*reconfigure) (struct efx_nic *efx); |
521 | void (*update_stats) (struct efx_nic *efx); | 521 | void (*update_stats) (struct efx_nic *efx); |
522 | bool (*check_fault)(struct efx_nic *efx); | 522 | bool (*check_fault)(struct efx_nic *efx); |
523 | }; | 523 | }; |
@@ -544,7 +544,7 @@ struct efx_phy_operations { | |||
544 | enum efx_mac_type macs; | 544 | enum efx_mac_type macs; |
545 | int (*init) (struct efx_nic *efx); | 545 | int (*init) (struct efx_nic *efx); |
546 | void (*fini) (struct efx_nic *efx); | 546 | void (*fini) (struct efx_nic *efx); |
547 | void (*reconfigure) (struct efx_nic *efx); | 547 | int (*reconfigure) (struct efx_nic *efx); |
548 | bool (*poll) (struct efx_nic *efx); | 548 | bool (*poll) (struct efx_nic *efx); |
549 | void (*get_settings) (struct efx_nic *efx, | 549 | void (*get_settings) (struct efx_nic *efx, |
550 | struct ethtool_cmd *ecmd); | 550 | struct ethtool_cmd *ecmd); |
@@ -730,6 +730,7 @@ union efx_multicast_hash { | |||
730 | * @mdio: PHY MDIO interface | 730 | * @mdio: PHY MDIO interface |
731 | * @phy_mode: PHY operating mode. Serialised by @mac_lock. | 731 | * @phy_mode: PHY operating mode. Serialised by @mac_lock. |
732 | * @xmac_poll_required: XMAC link state needs polling | 732 | * @xmac_poll_required: XMAC link state needs polling |
733 | * @link_advertising: Autonegotiation advertising flags | ||
733 | * @link_state: Current state of the link | 734 | * @link_state: Current state of the link |
734 | * @n_link_state_changes: Number of times the link has changed state | 735 | * @n_link_state_changes: Number of times the link has changed state |
735 | * @promiscuous: Promiscuous flag. Protected by netif_tx_lock. | 736 | * @promiscuous: Promiscuous flag. Protected by netif_tx_lock. |
@@ -813,6 +814,7 @@ struct efx_nic { | |||
813 | enum efx_phy_mode phy_mode; | 814 | enum efx_phy_mode phy_mode; |
814 | 815 | ||
815 | bool xmac_poll_required; | 816 | bool xmac_poll_required; |
817 | u32 link_advertising; | ||
816 | struct efx_link_state link_state; | 818 | struct efx_link_state link_state; |
817 | unsigned int n_link_state_changes; | 819 | unsigned int n_link_state_changes; |
818 | 820 | ||
@@ -858,6 +860,7 @@ static inline const char *efx_dev_name(struct efx_nic *efx) | |||
858 | * @stop_stats: Stop the regular fetching of statistics | 860 | * @stop_stats: Stop the regular fetching of statistics |
859 | * @push_irq_moderation: Apply interrupt moderation value | 861 | * @push_irq_moderation: Apply interrupt moderation value |
860 | * @push_multicast_hash: Apply multicast hash table | 862 | * @push_multicast_hash: Apply multicast hash table |
863 | * @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY | ||
861 | * @default_mac_ops: efx_mac_operations to set at startup | 864 | * @default_mac_ops: efx_mac_operations to set at startup |
862 | * @revision: Hardware architecture revision | 865 | * @revision: Hardware architecture revision |
863 | * @mem_map_size: Memory BAR mapped size | 866 | * @mem_map_size: Memory BAR mapped size |
@@ -890,6 +893,7 @@ struct efx_nic_type { | |||
890 | void (*stop_stats)(struct efx_nic *efx); | 893 | void (*stop_stats)(struct efx_nic *efx); |
891 | void (*push_irq_moderation)(struct efx_channel *channel); | 894 | void (*push_irq_moderation)(struct efx_channel *channel); |
892 | void (*push_multicast_hash)(struct efx_nic *efx); | 895 | void (*push_multicast_hash)(struct efx_nic *efx); |
896 | int (*reconfigure_port)(struct efx_nic *efx); | ||
893 | struct efx_mac_operations *default_mac_ops; | 897 | struct efx_mac_operations *default_mac_ops; |
894 | 898 | ||
895 | int revision; | 899 | int revision; |
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index 3d7370e39787..4c38516a5525 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c | |||
@@ -178,7 +178,7 @@ static bool qt202x_phy_poll(struct efx_nic *efx) | |||
178 | return efx->link_state.up != was_up; | 178 | return efx->link_state.up != was_up; |
179 | } | 179 | } |
180 | 180 | ||
181 | static void qt202x_phy_reconfigure(struct efx_nic *efx) | 181 | static int qt202x_phy_reconfigure(struct efx_nic *efx) |
182 | { | 182 | { |
183 | struct qt202x_phy_data *phy_data = efx->phy_data; | 183 | struct qt202x_phy_data *phy_data = efx->phy_data; |
184 | 184 | ||
@@ -207,6 +207,8 @@ static void qt202x_phy_reconfigure(struct efx_nic *efx) | |||
207 | efx_mdio_phy_reconfigure(efx); | 207 | efx_mdio_phy_reconfigure(efx); |
208 | 208 | ||
209 | phy_data->phy_mode = efx->phy_mode; | 209 | phy_data->phy_mode = efx->phy_mode; |
210 | |||
211 | return 0; | ||
210 | } | 212 | } |
211 | 213 | ||
212 | static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 214 | static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) |
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 15d4d9c81362..dddeb9dfb373 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c | |||
@@ -659,7 +659,6 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
659 | enum efx_loopback_mode loopback_mode = efx->loopback_mode; | 659 | enum efx_loopback_mode loopback_mode = efx->loopback_mode; |
660 | int phy_mode = efx->phy_mode; | 660 | int phy_mode = efx->phy_mode; |
661 | enum reset_type reset_method = RESET_TYPE_INVISIBLE; | 661 | enum reset_type reset_method = RESET_TYPE_INVISIBLE; |
662 | struct ethtool_cmd ecmd; | ||
663 | struct efx_channel *channel; | 662 | struct efx_channel *channel; |
664 | int rc_test = 0, rc_reset = 0, rc; | 663 | int rc_test = 0, rc_reset = 0, rc; |
665 | 664 | ||
@@ -712,7 +711,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
712 | mutex_unlock(&efx->mac_lock); | 711 | mutex_unlock(&efx->mac_lock); |
713 | 712 | ||
714 | /* free up all consumers of SRAM (including all the queues) */ | 713 | /* free up all consumers of SRAM (including all the queues) */ |
715 | efx_reset_down(efx, reset_method, &ecmd); | 714 | efx_reset_down(efx, reset_method); |
716 | 715 | ||
717 | rc = efx_test_chip(efx, tests); | 716 | rc = efx_test_chip(efx, tests); |
718 | if (rc && !rc_test) | 717 | if (rc && !rc_test) |
@@ -726,7 +725,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
726 | efx->phy_mode &= ~PHY_MODE_LOW_POWER; | 725 | efx->phy_mode &= ~PHY_MODE_LOW_POWER; |
727 | efx->loopback_mode = LOOPBACK_NONE; | 726 | efx->loopback_mode = LOOPBACK_NONE; |
728 | 727 | ||
729 | rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0); | 728 | rc = efx_reset_up(efx, reset_method, rc_reset == 0); |
730 | if (rc && !rc_reset) | 729 | if (rc && !rc_reset) |
731 | rc_reset = rc; | 730 | rc_reset = rc; |
732 | 731 | ||
@@ -745,10 +744,12 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
745 | rc_test = rc; | 744 | rc_test = rc; |
746 | 745 | ||
747 | /* restore the PHY to the previous state */ | 746 | /* restore the PHY to the previous state */ |
748 | efx->loopback_mode = loopback_mode; | 747 | mutex_lock(&efx->mac_lock); |
749 | efx->phy_mode = phy_mode; | 748 | efx->phy_mode = phy_mode; |
750 | efx->port_inhibited = false; | 749 | efx->port_inhibited = false; |
751 | efx_ethtool_set_settings(efx->net_dev, &ecmd); | 750 | efx->loopback_mode = loopback_mode; |
751 | __efx_reconfigure_port(efx); | ||
752 | mutex_unlock(&efx->mac_lock); | ||
752 | 753 | ||
753 | return rc_test; | 754 | return rc_test; |
754 | } | 755 | } |
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 | ||
213 | static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, | 214 | static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, |
@@ -300,7 +301,6 @@ static int tenxpress_init(struct efx_nic *efx) | |||
300 | static int tenxpress_phy_init(struct efx_nic *efx) | 301 | static 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 | ||
503 | static void tenxpress_phy_reconfigure(struct efx_nic *efx) | 503 | static 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 | ||
548 | static void | 540 | static 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 | ||
664 | static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) | 659 | static 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); |