diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-13 00:50:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-13 00:58:17 -0500 |
commit | 177dfcd80f28f8fbc3e22c2d8b24d21cb86f1d97 (patch) | |
tree | a6e5e9949f388d48ac20c4efbb2811762ac5f9d4 /drivers/net/sfc/efx.c | |
parent | 356eebb2b3af24cc701823f1e025f04eef333239 (diff) |
sfc: Add support for sub-10G speeds
The SFC4000 has a separate MAC for use at sub-10G speeds. Introduce
an efx_mac_operations structure with implementations for the two MACs.
Switch between the MACs as necessary.
PHY settings are independent of the MAC, so add get_settings() and
set_settings() to efx_phy_operations. Also add macs field to indicate
which MACs the PHY is connected to.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r-- | drivers/net/sfc/efx.c | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 90820d4046f8..7214ea6f7e1d 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include "efx.h" | 27 | #include "efx.h" |
28 | #include "mdio_10g.h" | 28 | #include "mdio_10g.h" |
29 | #include "falcon.h" | 29 | #include "falcon.h" |
30 | #include "mac.h" | ||
31 | 30 | ||
32 | #define EFX_MAX_MTU (9 * 1024) | 31 | #define EFX_MAX_MTU (9 * 1024) |
33 | 32 | ||
@@ -575,10 +574,28 @@ void __efx_reconfigure_port(struct efx_nic *efx) | |||
575 | netif_addr_unlock_bh(efx->net_dev); | 574 | netif_addr_unlock_bh(efx->net_dev); |
576 | } | 575 | } |
577 | 576 | ||
578 | falcon_reconfigure_xmac(efx); | 577 | falcon_deconfigure_mac_wrapper(efx); |
578 | |||
579 | /* Reconfigure the PHY, disabling transmit in mac level loopback. */ | ||
580 | if (LOOPBACK_INTERNAL(efx)) | ||
581 | efx->phy_mode |= PHY_MODE_TX_DISABLED; | ||
582 | else | ||
583 | efx->phy_mode &= ~PHY_MODE_TX_DISABLED; | ||
584 | efx->phy_op->reconfigure(efx); | ||
585 | |||
586 | if (falcon_switch_mac(efx)) | ||
587 | goto fail; | ||
588 | |||
589 | efx->mac_op->reconfigure(efx); | ||
579 | 590 | ||
580 | /* Inform kernel of loss/gain of carrier */ | 591 | /* Inform kernel of loss/gain of carrier */ |
581 | efx_link_status_changed(efx); | 592 | efx_link_status_changed(efx); |
593 | return; | ||
594 | |||
595 | fail: | ||
596 | EFX_ERR(efx, "failed to reconfigure MAC\n"); | ||
597 | efx->phy_op->fini(efx); | ||
598 | efx->port_initialized = false; | ||
582 | } | 599 | } |
583 | 600 | ||
584 | /* Reinitialise the MAC to pick up new PHY settings, even if the port is | 601 | /* Reinitialise the MAC to pick up new PHY settings, even if the port is |
@@ -648,18 +665,25 @@ static int efx_init_port(struct efx_nic *efx) | |||
648 | 665 | ||
649 | EFX_LOG(efx, "init port\n"); | 666 | EFX_LOG(efx, "init port\n"); |
650 | 667 | ||
651 | /* Initialise the MAC and PHY */ | 668 | rc = efx->phy_op->init(efx); |
652 | rc = falcon_init_xmac(efx); | ||
653 | if (rc) | 669 | if (rc) |
654 | return rc; | 670 | return rc; |
671 | efx->phy_op->reconfigure(efx); | ||
672 | |||
673 | mutex_lock(&efx->mac_lock); | ||
674 | rc = falcon_switch_mac(efx); | ||
675 | mutex_unlock(&efx->mac_lock); | ||
676 | if (rc) | ||
677 | goto fail; | ||
678 | efx->mac_op->reconfigure(efx); | ||
655 | 679 | ||
656 | efx->port_initialized = true; | 680 | efx->port_initialized = true; |
657 | efx->stats_enabled = true; | 681 | efx->stats_enabled = true; |
658 | |||
659 | /* Reconfigure port to program MAC registers */ | ||
660 | falcon_reconfigure_xmac(efx); | ||
661 | |||
662 | return 0; | 682 | return 0; |
683 | |||
684 | fail: | ||
685 | efx->phy_op->fini(efx); | ||
686 | return rc; | ||
663 | } | 687 | } |
664 | 688 | ||
665 | /* Allow efx_reconfigure_port() to be scheduled, and close the window | 689 | /* Allow efx_reconfigure_port() to be scheduled, and close the window |
@@ -702,7 +726,7 @@ static void efx_fini_port(struct efx_nic *efx) | |||
702 | if (!efx->port_initialized) | 726 | if (!efx->port_initialized) |
703 | return; | 727 | return; |
704 | 728 | ||
705 | falcon_fini_xmac(efx); | 729 | efx->phy_op->fini(efx); |
706 | efx->port_initialized = false; | 730 | efx->port_initialized = false; |
707 | 731 | ||
708 | efx->link_up = false; | 732 | efx->link_up = false; |
@@ -1179,7 +1203,6 @@ static void efx_monitor(struct work_struct *data) | |||
1179 | { | 1203 | { |
1180 | struct efx_nic *efx = container_of(data, struct efx_nic, | 1204 | struct efx_nic *efx = container_of(data, struct efx_nic, |
1181 | monitor_work.work); | 1205 | monitor_work.work); |
1182 | int rc = 0; | ||
1183 | 1206 | ||
1184 | EFX_TRACE(efx, "hardware monitor executing on CPU %d\n", | 1207 | EFX_TRACE(efx, "hardware monitor executing on CPU %d\n", |
1185 | raw_smp_processor_id()); | 1208 | raw_smp_processor_id()); |
@@ -1195,7 +1218,7 @@ static void efx_monitor(struct work_struct *data) | |||
1195 | } | 1218 | } |
1196 | 1219 | ||
1197 | if (efx->port_enabled) | 1220 | if (efx->port_enabled) |
1198 | rc = falcon_check_xmac(efx); | 1221 | efx->mac_op->check_hw(efx); |
1199 | mutex_unlock(&efx->mac_lock); | 1222 | mutex_unlock(&efx->mac_lock); |
1200 | 1223 | ||
1201 | queue_delayed_work(efx->workqueue, &efx->monitor_work, | 1224 | queue_delayed_work(efx->workqueue, &efx->monitor_work, |
@@ -1331,7 +1354,7 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) | |||
1331 | if (!spin_trylock(&efx->stats_lock)) | 1354 | if (!spin_trylock(&efx->stats_lock)) |
1332 | return stats; | 1355 | return stats; |
1333 | if (efx->stats_enabled) { | 1356 | if (efx->stats_enabled) { |
1334 | falcon_update_stats_xmac(efx); | 1357 | efx->mac_op->update_stats(efx); |
1335 | falcon_update_nic_stats(efx); | 1358 | falcon_update_nic_stats(efx); |
1336 | } | 1359 | } |
1337 | spin_unlock(&efx->stats_lock); | 1360 | spin_unlock(&efx->stats_lock); |
@@ -1519,7 +1542,7 @@ static int efx_register_netdev(struct efx_nic *efx) | |||
1519 | netif_carrier_off(efx->net_dev); | 1542 | netif_carrier_off(efx->net_dev); |
1520 | 1543 | ||
1521 | /* Clear MAC statistics */ | 1544 | /* Clear MAC statistics */ |
1522 | falcon_update_stats_xmac(efx); | 1545 | efx->mac_op->update_stats(efx); |
1523 | memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); | 1546 | memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); |
1524 | 1547 | ||
1525 | rc = register_netdev(net_dev); | 1548 | rc = register_netdev(net_dev); |
@@ -1575,8 +1598,6 @@ static void efx_unregister_netdev(struct efx_nic *efx) | |||
1575 | * before reset. */ | 1598 | * before reset. */ |
1576 | void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 1599 | void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) |
1577 | { | 1600 | { |
1578 | int rc; | ||
1579 | |||
1580 | EFX_ASSERT_RESET_SERIALISED(efx); | 1601 | EFX_ASSERT_RESET_SERIALISED(efx); |
1581 | 1602 | ||
1582 | /* The net_dev->get_stats handler is quite slow, and will fail | 1603 | /* The net_dev->get_stats handler is quite slow, and will fail |
@@ -1589,9 +1610,7 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) | |||
1589 | mutex_lock(&efx->mac_lock); | 1610 | mutex_lock(&efx->mac_lock); |
1590 | mutex_lock(&efx->spi_lock); | 1611 | mutex_lock(&efx->spi_lock); |
1591 | 1612 | ||
1592 | rc = falcon_xmac_get_settings(efx, ecmd); | 1613 | efx->phy_op->get_settings(efx, ecmd); |
1593 | if (rc) | ||
1594 | EFX_ERR(efx, "could not back up PHY settings\n"); | ||
1595 | 1614 | ||
1596 | efx_fini_channels(efx); | 1615 | efx_fini_channels(efx); |
1597 | } | 1616 | } |
@@ -1616,7 +1635,7 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) | |||
1616 | if (ok) { | 1635 | if (ok) { |
1617 | efx_init_channels(efx); | 1636 | efx_init_channels(efx); |
1618 | 1637 | ||
1619 | if (falcon_xmac_set_settings(efx, ecmd)) | 1638 | if (efx->phy_op->set_settings(efx, ecmd)) |
1620 | EFX_ERR(efx, "could not restore PHY settings\n"); | 1639 | EFX_ERR(efx, "could not restore PHY settings\n"); |
1621 | } | 1640 | } |
1622 | 1641 | ||
@@ -1779,6 +1798,10 @@ int efx_port_dummy_op_int(struct efx_nic *efx) | |||
1779 | void efx_port_dummy_op_void(struct efx_nic *efx) {} | 1798 | void efx_port_dummy_op_void(struct efx_nic *efx) {} |
1780 | void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {} | 1799 | void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {} |
1781 | 1800 | ||
1801 | static struct efx_mac_operations efx_dummy_mac_operations = { | ||
1802 | .reconfigure = efx_port_dummy_op_void, | ||
1803 | }; | ||
1804 | |||
1782 | static struct efx_phy_operations efx_dummy_phy_operations = { | 1805 | static struct efx_phy_operations efx_dummy_phy_operations = { |
1783 | .init = efx_port_dummy_op_int, | 1806 | .init = efx_port_dummy_op_int, |
1784 | .reconfigure = efx_port_dummy_op_void, | 1807 | .reconfigure = efx_port_dummy_op_void, |
@@ -1831,6 +1854,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, | |||
1831 | spin_lock_init(&efx->netif_stop_lock); | 1854 | spin_lock_init(&efx->netif_stop_lock); |
1832 | spin_lock_init(&efx->stats_lock); | 1855 | spin_lock_init(&efx->stats_lock); |
1833 | mutex_init(&efx->mac_lock); | 1856 | mutex_init(&efx->mac_lock); |
1857 | efx->mac_op = &efx_dummy_mac_operations; | ||
1834 | efx->phy_op = &efx_dummy_phy_operations; | 1858 | efx->phy_op = &efx_dummy_phy_operations; |
1835 | efx->mii.dev = net_dev; | 1859 | efx->mii.dev = net_dev; |
1836 | INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work); | 1860 | INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work); |