diff options
| -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); |
