diff options
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r-- | drivers/net/sfc/efx.c | 132 |
1 files changed, 80 insertions, 52 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 | }; |