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 | |
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')
-rw-r--r-- | drivers/net/sfc/Makefile | 4 | ||||
-rw-r--r-- | drivers/net/sfc/efx.c | 62 | ||||
-rw-r--r-- | drivers/net/sfc/enum.h | 29 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 38 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 179 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.h | 3 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_gmac.c | 233 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_hwdefs.h | 156 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_xmac.c | 222 | ||||
-rw-r--r-- | drivers/net/sfc/mac.h | 16 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 31 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 26 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.h | 2 | ||||
-rw-r--r-- | drivers/net/sfc/sfe4001.c | 2 | ||||
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 10 | ||||
-rw-r--r-- | drivers/net/sfc/xfp_phy.c | 7 |
16 files changed, 699 insertions, 321 deletions
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile index e507daa4f0e8..b89f9be3cb13 100644 --- a/drivers/net/sfc/Makefile +++ b/drivers/net/sfc/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \ | 1 | sfc-y += efx.o falcon.o tx.o rx.o falcon_gmac.o \ |
2 | selftest.o ethtool.o xfp_phy.o \ | 2 | falcon_xmac.o selftest.o ethtool.o xfp_phy.o \ |
3 | mdio_10g.o tenxpress.o boards.o sfe4001.o | 3 | mdio_10g.o tenxpress.o boards.o sfe4001.o |
4 | sfc-$(CONFIG_SFC_MTD) += mtd.o | 4 | sfc-$(CONFIG_SFC_MTD) += mtd.o |
5 | 5 | ||
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); |
diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h index 41e758e8fdb1..0c2e41ce8b4a 100644 --- a/drivers/net/sfc/enum.h +++ b/drivers/net/sfc/enum.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2007 Solarflare Communications Inc. | 3 | * Copyright 2007-2008 Solarflare Communications Inc. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published | 6 | * under the terms of the GNU General Public License version 2 as published |
@@ -13,22 +13,24 @@ | |||
13 | /** | 13 | /** |
14 | * enum efx_loopback_mode - loopback modes | 14 | * enum efx_loopback_mode - loopback modes |
15 | * @LOOPBACK_NONE: no loopback | 15 | * @LOOPBACK_NONE: no loopback |
16 | * @LOOPBACK_XGMII: loopback within MAC at XGMII level | 16 | * @LOOPBACK_GMAC: loopback within GMAC at unspecified level |
17 | * @LOOPBACK_XGXS: loopback within MAC at XGXS level | 17 | * @LOOPBACK_XGMII: loopback within XMAC at XGMII level |
18 | * @LOOPBACK_XAUI: loopback within MAC at XAUI level | 18 | * @LOOPBACK_XGXS: loopback within XMAC at XGXS level |
19 | * @LOOPBACK_PHYXS: loopback within PHY at PHYXS level | 19 | * @LOOPBACK_XAUI: loopback within XMAC at XAUI level |
20 | * @LOOPBACK_PCS: loopback within PHY at PCS level | 20 | * @LOOPBACK_GPHY: loopback within 1G PHY at unspecified level |
21 | * @LOOPBACK_PMAPMD: loopback within PHY at PMAPMD level | 21 | * @LOOPBACK_PHYXS: loopback within 10G PHY at PHYXS level |
22 | * @LOOPBACK_PCS: loopback within 10G PHY at PCS level | ||
23 | * @LOOPBACK_PMAPMD: loopback within 10G PHY at PMAPMD level | ||
22 | * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!) | 24 | * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!) |
23 | */ | 25 | */ |
24 | /* Please keep in order and up-to-date w.r.t the following two #defines */ | 26 | /* Please keep in order and up-to-date w.r.t the following two #defines */ |
25 | enum efx_loopback_mode { | 27 | enum efx_loopback_mode { |
26 | LOOPBACK_NONE = 0, | 28 | LOOPBACK_NONE = 0, |
27 | LOOPBACK_MAC = 1, | 29 | LOOPBACK_GMAC = 1, |
28 | LOOPBACK_XGMII = 2, | 30 | LOOPBACK_XGMII = 2, |
29 | LOOPBACK_XGXS = 3, | 31 | LOOPBACK_XGXS = 3, |
30 | LOOPBACK_XAUI = 4, | 32 | LOOPBACK_XAUI = 4, |
31 | LOOPBACK_PHY = 5, | 33 | LOOPBACK_GPHY = 5, |
32 | LOOPBACK_PHYXS = 6, | 34 | LOOPBACK_PHYXS = 6, |
33 | LOOPBACK_PCS = 7, | 35 | LOOPBACK_PCS = 7, |
34 | LOOPBACK_PMAPMD = 8, | 36 | LOOPBACK_PMAPMD = 8, |
@@ -45,15 +47,16 @@ extern const char *efx_loopback_mode_names[]; | |||
45 | LOOPBACK_MODE_NAME(efx->loopback_mode) | 47 | LOOPBACK_MODE_NAME(efx->loopback_mode) |
46 | 48 | ||
47 | /* These loopbacks occur within the controller */ | 49 | /* These loopbacks occur within the controller */ |
48 | #define LOOPBACKS_10G_INTERNAL ((1 << LOOPBACK_XGMII)| \ | 50 | #define LOOPBACKS_INTERNAL ((1 << LOOPBACK_GMAC) | \ |
49 | (1 << LOOPBACK_XGXS) | \ | 51 | (1 << LOOPBACK_XGMII)| \ |
50 | (1 << LOOPBACK_XAUI)) | 52 | (1 << LOOPBACK_XGXS) | \ |
53 | (1 << LOOPBACK_XAUI)) | ||
51 | 54 | ||
52 | #define LOOPBACK_MASK(_efx) \ | 55 | #define LOOPBACK_MASK(_efx) \ |
53 | (1 << (_efx)->loopback_mode) | 56 | (1 << (_efx)->loopback_mode) |
54 | 57 | ||
55 | #define LOOPBACK_INTERNAL(_efx) \ | 58 | #define LOOPBACK_INTERNAL(_efx) \ |
56 | (!!(LOOPBACKS_10G_INTERNAL & LOOPBACK_MASK(_efx))) | 59 | (!!(LOOPBACKS_INTERNAL & LOOPBACK_MASK(_efx))) |
57 | 60 | ||
58 | #define LOOPBACK_OUT_OF(_from, _to, _mask) \ | 61 | #define LOOPBACK_OUT_OF(_from, _to, _mask) \ |
59 | ((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask))) | 62 | ((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask))) |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 43d6d8b4429a..1b33f89df4d5 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -17,15 +17,14 @@ | |||
17 | #include "ethtool.h" | 17 | #include "ethtool.h" |
18 | #include "falcon.h" | 18 | #include "falcon.h" |
19 | #include "spi.h" | 19 | #include "spi.h" |
20 | #include "mac.h" | ||
21 | 20 | ||
22 | const char *efx_loopback_mode_names[] = { | 21 | const char *efx_loopback_mode_names[] = { |
23 | [LOOPBACK_NONE] = "NONE", | 22 | [LOOPBACK_NONE] = "NONE", |
24 | [LOOPBACK_MAC] = "MAC", | 23 | [LOOPBACK_GMAC] = "GMAC", |
25 | [LOOPBACK_XGMII] = "XGMII", | 24 | [LOOPBACK_XGMII] = "XGMII", |
26 | [LOOPBACK_XGXS] = "XGXS", | 25 | [LOOPBACK_XGXS] = "XGXS", |
27 | [LOOPBACK_XAUI] = "XAUI", | 26 | [LOOPBACK_XAUI] = "XAUI", |
28 | [LOOPBACK_PHY] = "PHY", | 27 | [LOOPBACK_GPHY] = "GPHY", |
29 | [LOOPBACK_PHYXS] = "PHYXS", | 28 | [LOOPBACK_PHYXS] = "PHYXS", |
30 | [LOOPBACK_PCS] = "PCS", | 29 | [LOOPBACK_PCS] = "PCS", |
31 | [LOOPBACK_PMAPMD] = "PMA/PMD", | 30 | [LOOPBACK_PMAPMD] = "PMA/PMD", |
@@ -200,13 +199,15 @@ int efx_ethtool_get_settings(struct net_device *net_dev, | |||
200 | struct ethtool_cmd *ecmd) | 199 | struct ethtool_cmd *ecmd) |
201 | { | 200 | { |
202 | struct efx_nic *efx = netdev_priv(net_dev); | 201 | struct efx_nic *efx = netdev_priv(net_dev); |
203 | int rc; | ||
204 | 202 | ||
205 | mutex_lock(&efx->mac_lock); | 203 | mutex_lock(&efx->mac_lock); |
206 | rc = falcon_xmac_get_settings(efx, ecmd); | 204 | efx->phy_op->get_settings(efx, ecmd); |
207 | mutex_unlock(&efx->mac_lock); | 205 | mutex_unlock(&efx->mac_lock); |
208 | 206 | ||
209 | return rc; | 207 | /* Falcon GMAC does not support 1000Mbps HD */ |
208 | ecmd->supported &= ~SUPPORTED_1000baseT_Half; | ||
209 | |||
210 | return 0; | ||
210 | } | 211 | } |
211 | 212 | ||
212 | /* This must be called with rtnl_lock held. */ | 213 | /* This must be called with rtnl_lock held. */ |
@@ -216,8 +217,15 @@ int efx_ethtool_set_settings(struct net_device *net_dev, | |||
216 | struct efx_nic *efx = netdev_priv(net_dev); | 217 | struct efx_nic *efx = netdev_priv(net_dev); |
217 | int rc; | 218 | int rc; |
218 | 219 | ||
220 | /* Falcon GMAC does not support 1000Mbps HD */ | ||
221 | if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { | ||
222 | EFX_LOG(efx, "rejecting unsupported 1000Mbps HD" | ||
223 | " setting\n"); | ||
224 | return -EINVAL; | ||
225 | } | ||
226 | |||
219 | mutex_lock(&efx->mac_lock); | 227 | mutex_lock(&efx->mac_lock); |
220 | rc = falcon_xmac_set_settings(efx, ecmd); | 228 | rc = efx->phy_op->set_settings(efx, ecmd); |
221 | mutex_unlock(&efx->mac_lock); | 229 | mutex_unlock(&efx->mac_lock); |
222 | if (!rc) | 230 | if (!rc) |
223 | efx_reconfigure_port(efx); | 231 | efx_reconfigure_port(efx); |
@@ -362,10 +370,6 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, | |||
362 | EFX_PORT_NAME, "phy", NULL); | 370 | EFX_PORT_NAME, "phy", NULL); |
363 | 371 | ||
364 | /* Loopback tests */ | 372 | /* Loopback tests */ |
365 | efx_fill_test(n++, strings, data, &tests->loopback_speed, | ||
366 | EFX_PORT_NAME, "loopback.speed", NULL); | ||
367 | efx_fill_test(n++, strings, data, &tests->loopback_full_duplex, | ||
368 | EFX_PORT_NAME, "loopback.full_duplex", NULL); | ||
369 | for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { | 373 | for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { |
370 | if (!(efx->loopback_modes & (1 << mode))) | 374 | if (!(efx->loopback_modes & (1 << mode))) |
371 | continue; | 375 | continue; |
@@ -671,22 +675,14 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
671 | { | 675 | { |
672 | struct efx_nic *efx = netdev_priv(net_dev); | 676 | struct efx_nic *efx = netdev_priv(net_dev); |
673 | enum efx_fc_type flow_control = efx->flow_control; | 677 | enum efx_fc_type flow_control = efx->flow_control; |
674 | int rc; | ||
675 | 678 | ||
676 | flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO); | 679 | flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO); |
677 | flow_control |= pause->rx_pause ? EFX_FC_RX : 0; | 680 | flow_control |= pause->rx_pause ? EFX_FC_RX : 0; |
678 | flow_control |= pause->tx_pause ? EFX_FC_TX : 0; | 681 | flow_control |= pause->tx_pause ? EFX_FC_TX : 0; |
679 | flow_control |= pause->autoneg ? EFX_FC_AUTO : 0; | 682 | flow_control |= pause->autoneg ? EFX_FC_AUTO : 0; |
680 | 683 | ||
681 | /* Try to push the pause parameters */ | 684 | efx_reconfigure_port(efx); |
682 | mutex_lock(&efx->mac_lock); | 685 | return 0; |
683 | rc = falcon_xmac_set_pause(efx, flow_control); | ||
684 | mutex_unlock(&efx->mac_lock); | ||
685 | |||
686 | if (!rc) | ||
687 | efx_reconfigure_port(efx); | ||
688 | |||
689 | return rc; | ||
690 | } | 686 | } |
691 | 687 | ||
692 | static void efx_ethtool_get_pauseparam(struct net_device *net_dev, | 688 | 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 448bba9eed09..f09eded40fba 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -1168,6 +1168,19 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic) | |||
1168 | falcon_generate_event(channel, &test_event); | 1168 | falcon_generate_event(channel, &test_event); |
1169 | } | 1169 | } |
1170 | 1170 | ||
1171 | void falcon_sim_phy_event(struct efx_nic *efx) | ||
1172 | { | ||
1173 | efx_qword_t phy_event; | ||
1174 | |||
1175 | EFX_POPULATE_QWORD_1(phy_event, EV_CODE, GLOBAL_EV_DECODE); | ||
1176 | if (EFX_IS10G(efx)) | ||
1177 | EFX_SET_OWORD_FIELD(phy_event, XG_PHY_INTR, 1); | ||
1178 | else | ||
1179 | EFX_SET_OWORD_FIELD(phy_event, G_PHY0_INTR, 1); | ||
1180 | |||
1181 | falcon_generate_event(&efx->channel[0], &phy_event); | ||
1182 | } | ||
1183 | |||
1171 | /************************************************************************** | 1184 | /************************************************************************** |
1172 | * | 1185 | * |
1173 | * Flush handling | 1186 | * Flush handling |
@@ -1839,40 +1852,61 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, | |||
1839 | * | 1852 | * |
1840 | ************************************************************************** | 1853 | ************************************************************************** |
1841 | */ | 1854 | */ |
1842 | void falcon_drain_tx_fifo(struct efx_nic *efx) | 1855 | |
1856 | static int falcon_reset_macs(struct efx_nic *efx) | ||
1843 | { | 1857 | { |
1844 | efx_oword_t temp; | 1858 | efx_oword_t reg; |
1845 | int count; | 1859 | int count; |
1846 | 1860 | ||
1847 | if ((falcon_rev(efx) < FALCON_REV_B0) || | 1861 | if (falcon_rev(efx) < FALCON_REV_B0) { |
1848 | (efx->loopback_mode != LOOPBACK_NONE)) | 1862 | /* It's not safe to use GLB_CTL_REG to reset the |
1849 | return; | 1863 | * macs, so instead use the internal MAC resets |
1864 | */ | ||
1865 | if (!EFX_IS10G(efx)) { | ||
1866 | EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 1); | ||
1867 | falcon_write(efx, ®, GM_CFG1_REG); | ||
1868 | udelay(1000); | ||
1869 | |||
1870 | EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 0); | ||
1871 | falcon_write(efx, ®, GM_CFG1_REG); | ||
1872 | udelay(1000); | ||
1873 | return 0; | ||
1874 | } else { | ||
1875 | EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1); | ||
1876 | falcon_write(efx, ®, XM_GLB_CFG_REG); | ||
1877 | |||
1878 | for (count = 0; count < 10000; count++) { | ||
1879 | falcon_read(efx, ®, XM_GLB_CFG_REG); | ||
1880 | if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0) | ||
1881 | return 0; | ||
1882 | udelay(10); | ||
1883 | } | ||
1850 | 1884 | ||
1851 | falcon_read(efx, &temp, MAC0_CTRL_REG_KER); | 1885 | EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); |
1852 | /* There is no point in draining more than once */ | 1886 | return -ETIMEDOUT; |
1853 | if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0)) | 1887 | } |
1854 | return; | 1888 | } |
1855 | 1889 | ||
1856 | /* MAC stats will fail whilst the TX fifo is draining. Serialise | 1890 | /* MAC stats will fail whilst the TX fifo is draining. Serialise |
1857 | * the drain sequence with the statistics fetch */ | 1891 | * the drain sequence with the statistics fetch */ |
1858 | spin_lock(&efx->stats_lock); | 1892 | spin_lock(&efx->stats_lock); |
1859 | 1893 | ||
1860 | EFX_SET_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0, 1); | 1894 | falcon_read(efx, ®, MAC0_CTRL_REG_KER); |
1861 | falcon_write(efx, &temp, MAC0_CTRL_REG_KER); | 1895 | EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1); |
1896 | falcon_write(efx, ®, MAC0_CTRL_REG_KER); | ||
1862 | 1897 | ||
1863 | /* Reset the MAC and EM block. */ | 1898 | falcon_read(efx, ®, GLB_CTL_REG_KER); |
1864 | falcon_read(efx, &temp, GLB_CTL_REG_KER); | 1899 | EFX_SET_OWORD_FIELD(reg, RST_XGTX, 1); |
1865 | EFX_SET_OWORD_FIELD(temp, RST_XGTX, 1); | 1900 | EFX_SET_OWORD_FIELD(reg, RST_XGRX, 1); |
1866 | EFX_SET_OWORD_FIELD(temp, RST_XGRX, 1); | 1901 | EFX_SET_OWORD_FIELD(reg, RST_EM, 1); |
1867 | EFX_SET_OWORD_FIELD(temp, RST_EM, 1); | 1902 | falcon_write(efx, ®, GLB_CTL_REG_KER); |
1868 | falcon_write(efx, &temp, GLB_CTL_REG_KER); | ||
1869 | 1903 | ||
1870 | count = 0; | 1904 | count = 0; |
1871 | while (1) { | 1905 | while (1) { |
1872 | falcon_read(efx, &temp, GLB_CTL_REG_KER); | 1906 | falcon_read(efx, ®, GLB_CTL_REG_KER); |
1873 | if (!EFX_OWORD_FIELD(temp, RST_XGTX) && | 1907 | if (!EFX_OWORD_FIELD(reg, RST_XGTX) && |
1874 | !EFX_OWORD_FIELD(temp, RST_XGRX) && | 1908 | !EFX_OWORD_FIELD(reg, RST_XGRX) && |
1875 | !EFX_OWORD_FIELD(temp, RST_EM)) { | 1909 | !EFX_OWORD_FIELD(reg, RST_EM)) { |
1876 | EFX_LOG(efx, "Completed MAC reset after %d loops\n", | 1910 | EFX_LOG(efx, "Completed MAC reset after %d loops\n", |
1877 | count); | 1911 | count); |
1878 | break; | 1912 | break; |
@@ -1889,21 +1923,39 @@ void falcon_drain_tx_fifo(struct efx_nic *efx) | |||
1889 | 1923 | ||
1890 | /* If we've reset the EM block and the link is up, then | 1924 | /* If we've reset the EM block and the link is up, then |
1891 | * we'll have to kick the XAUI link so the PHY can recover */ | 1925 | * we'll have to kick the XAUI link so the PHY can recover */ |
1892 | if (efx->link_up && EFX_WORKAROUND_5147(efx)) | 1926 | if (efx->link_up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx)) |
1893 | falcon_reset_xaui(efx); | 1927 | falcon_reset_xaui(efx); |
1928 | |||
1929 | return 0; | ||
1930 | } | ||
1931 | |||
1932 | void falcon_drain_tx_fifo(struct efx_nic *efx) | ||
1933 | { | ||
1934 | efx_oword_t reg; | ||
1935 | |||
1936 | if ((falcon_rev(efx) < FALCON_REV_B0) || | ||
1937 | (efx->loopback_mode != LOOPBACK_NONE)) | ||
1938 | return; | ||
1939 | |||
1940 | falcon_read(efx, ®, MAC0_CTRL_REG_KER); | ||
1941 | /* There is no point in draining more than once */ | ||
1942 | if (EFX_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0)) | ||
1943 | return; | ||
1944 | |||
1945 | falcon_reset_macs(efx); | ||
1894 | } | 1946 | } |
1895 | 1947 | ||
1896 | void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) | 1948 | void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) |
1897 | { | 1949 | { |
1898 | efx_oword_t temp; | 1950 | efx_oword_t reg; |
1899 | 1951 | ||
1900 | if (falcon_rev(efx) < FALCON_REV_B0) | 1952 | if (falcon_rev(efx) < FALCON_REV_B0) |
1901 | return; | 1953 | return; |
1902 | 1954 | ||
1903 | /* Isolate the MAC -> RX */ | 1955 | /* Isolate the MAC -> RX */ |
1904 | falcon_read(efx, &temp, RX_CFG_REG_KER); | 1956 | falcon_read(efx, ®, RX_CFG_REG_KER); |
1905 | EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 0); | 1957 | EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 0); |
1906 | falcon_write(efx, &temp, RX_CFG_REG_KER); | 1958 | falcon_write(efx, ®, RX_CFG_REG_KER); |
1907 | 1959 | ||
1908 | if (!efx->link_up) | 1960 | if (!efx->link_up) |
1909 | falcon_drain_tx_fifo(efx); | 1961 | falcon_drain_tx_fifo(efx); |
@@ -2030,7 +2082,8 @@ static int falcon_gmii_wait(struct efx_nic *efx) | |||
2030 | efx_dword_t md_stat; | 2082 | efx_dword_t md_stat; |
2031 | int count; | 2083 | int count; |
2032 | 2084 | ||
2033 | for (count = 0; count < 1000; count++) { /* wait upto 10ms */ | 2085 | /* wait upto 50ms - taken max from datasheet */ |
2086 | for (count = 0; count < 5000; count++) { | ||
2034 | falcon_readl(efx, &md_stat, MD_STAT_REG_KER); | 2087 | falcon_readl(efx, &md_stat, MD_STAT_REG_KER); |
2035 | if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) { | 2088 | if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) { |
2036 | if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 || | 2089 | if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 || |
@@ -2206,10 +2259,59 @@ static int falcon_probe_phy(struct efx_nic *efx) | |||
2206 | return -1; | 2259 | return -1; |
2207 | } | 2260 | } |
2208 | 2261 | ||
2209 | efx->loopback_modes = LOOPBACKS_10G_INTERNAL | efx->phy_op->loopbacks; | 2262 | if (efx->phy_op->macs & EFX_XMAC) |
2263 | efx->loopback_modes |= ((1 << LOOPBACK_XGMII) | | ||
2264 | (1 << LOOPBACK_XGXS) | | ||
2265 | (1 << LOOPBACK_XAUI)); | ||
2266 | if (efx->phy_op->macs & EFX_GMAC) | ||
2267 | efx->loopback_modes |= (1 << LOOPBACK_GMAC); | ||
2268 | efx->loopback_modes |= efx->phy_op->loopbacks; | ||
2269 | |||
2210 | return 0; | 2270 | return 0; |
2211 | } | 2271 | } |
2212 | 2272 | ||
2273 | int falcon_switch_mac(struct efx_nic *efx) | ||
2274 | { | ||
2275 | struct efx_mac_operations *old_mac_op = efx->mac_op; | ||
2276 | efx_oword_t nic_stat; | ||
2277 | unsigned strap_val; | ||
2278 | |||
2279 | /* Internal loopbacks override the phy speed setting */ | ||
2280 | if (efx->loopback_mode == LOOPBACK_GMAC) { | ||
2281 | efx->link_speed = 1000; | ||
2282 | efx->link_fd = true; | ||
2283 | } else if (LOOPBACK_INTERNAL(efx)) { | ||
2284 | efx->link_speed = 10000; | ||
2285 | efx->link_fd = true; | ||
2286 | } | ||
2287 | |||
2288 | efx->mac_op = (EFX_IS10G(efx) ? | ||
2289 | &falcon_xmac_operations : &falcon_gmac_operations); | ||
2290 | if (old_mac_op == efx->mac_op) | ||
2291 | return 0; | ||
2292 | |||
2293 | WARN_ON(!mutex_is_locked(&efx->mac_lock)); | ||
2294 | |||
2295 | /* Not all macs support a mac-level link state */ | ||
2296 | efx->mac_up = true; | ||
2297 | |||
2298 | falcon_read(efx, &nic_stat, NIC_STAT_REG); | ||
2299 | strap_val = EFX_IS10G(efx) ? 5 : 3; | ||
2300 | if (falcon_rev(efx) >= FALCON_REV_B0) { | ||
2301 | EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_EN, 1); | ||
2302 | EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_OVR, strap_val); | ||
2303 | falcon_write(efx, &nic_stat, NIC_STAT_REG); | ||
2304 | } else { | ||
2305 | /* Falcon A1 does not support 1G/10G speed switching | ||
2306 | * and must not be used with a PHY that does. */ | ||
2307 | BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val); | ||
2308 | } | ||
2309 | |||
2310 | |||
2311 | EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); | ||
2312 | return falcon_reset_macs(efx); | ||
2313 | } | ||
2314 | |||
2213 | /* This call is responsible for hooking in the MAC and PHY operations */ | 2315 | /* This call is responsible for hooking in the MAC and PHY operations */ |
2214 | int falcon_probe_port(struct efx_nic *efx) | 2316 | int falcon_probe_port(struct efx_nic *efx) |
2215 | { | 2317 | { |
@@ -2362,6 +2464,10 @@ static struct { | |||
2362 | EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) }, | 2464 | EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) }, |
2363 | { DP_CTRL_REG, | 2465 | { DP_CTRL_REG, |
2364 | EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) }, | 2466 | EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) }, |
2467 | { GM_CFG2_REG, | ||
2468 | EFX_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) }, | ||
2469 | { GMF_CFG0_REG, | ||
2470 | EFX_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) }, | ||
2365 | { XM_GLB_CFG_REG, | 2471 | { XM_GLB_CFG_REG, |
2366 | EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) }, | 2472 | EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) }, |
2367 | { XM_TX_CFG_REG, | 2473 | { XM_TX_CFG_REG, |
@@ -2687,6 +2793,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) | |||
2687 | static int falcon_probe_nic_variant(struct efx_nic *efx) | 2793 | static int falcon_probe_nic_variant(struct efx_nic *efx) |
2688 | { | 2794 | { |
2689 | efx_oword_t altera_build; | 2795 | efx_oword_t altera_build; |
2796 | efx_oword_t nic_stat; | ||
2690 | 2797 | ||
2691 | falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER); | 2798 | falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER); |
2692 | if (EFX_OWORD_FIELD(altera_build, VER_ALL)) { | 2799 | if (EFX_OWORD_FIELD(altera_build, VER_ALL)) { |
@@ -2694,27 +2801,20 @@ static int falcon_probe_nic_variant(struct efx_nic *efx) | |||
2694 | return -ENODEV; | 2801 | return -ENODEV; |
2695 | } | 2802 | } |
2696 | 2803 | ||
2804 | falcon_read(efx, &nic_stat, NIC_STAT_REG); | ||
2805 | |||
2697 | switch (falcon_rev(efx)) { | 2806 | switch (falcon_rev(efx)) { |
2698 | case FALCON_REV_A0: | 2807 | case FALCON_REV_A0: |
2699 | case 0xff: | 2808 | case 0xff: |
2700 | EFX_ERR(efx, "Falcon rev A0 not supported\n"); | 2809 | EFX_ERR(efx, "Falcon rev A0 not supported\n"); |
2701 | return -ENODEV; | 2810 | return -ENODEV; |
2702 | 2811 | ||
2703 | case FALCON_REV_A1:{ | 2812 | case FALCON_REV_A1: |
2704 | efx_oword_t nic_stat; | ||
2705 | |||
2706 | falcon_read(efx, &nic_stat, NIC_STAT_REG); | ||
2707 | |||
2708 | if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) { | 2813 | if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) { |
2709 | EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n"); | 2814 | EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n"); |
2710 | return -ENODEV; | 2815 | return -ENODEV; |
2711 | } | 2816 | } |
2712 | if (!EFX_OWORD_FIELD(nic_stat, STRAP_10G)) { | ||
2713 | EFX_ERR(efx, "1G mode not supported\n"); | ||
2714 | return -ENODEV; | ||
2715 | } | ||
2716 | break; | 2817 | break; |
2717 | } | ||
2718 | 2818 | ||
2719 | case FALCON_REV_B0: | 2819 | case FALCON_REV_B0: |
2720 | break; | 2820 | break; |
@@ -2724,6 +2824,9 @@ static int falcon_probe_nic_variant(struct efx_nic *efx) | |||
2724 | return -ENODEV; | 2824 | return -ENODEV; |
2725 | } | 2825 | } |
2726 | 2826 | ||
2827 | /* Initial assumed speed */ | ||
2828 | efx->link_speed = EFX_OWORD_FIELD(nic_stat, STRAP_10G) ? 10000 : 1000; | ||
2829 | |||
2727 | return 0; | 2830 | return 0; |
2728 | } | 2831 | } |
2729 | 2832 | ||
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h index be025ba7a6c6..7869c3d74383 100644 --- a/drivers/net/sfc/falcon.h +++ b/drivers/net/sfc/falcon.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #define EFX_FALCON_H | 12 | #define EFX_FALCON_H |
13 | 13 | ||
14 | #include "net_driver.h" | 14 | #include "net_driver.h" |
15 | #include "efx.h" | ||
15 | 16 | ||
16 | /* | 17 | /* |
17 | * Falcon hardware control | 18 | * Falcon hardware control |
@@ -65,6 +66,7 @@ extern int falcon_probe_port(struct efx_nic *efx); | |||
65 | extern void falcon_remove_port(struct efx_nic *efx); | 66 | extern void falcon_remove_port(struct efx_nic *efx); |
66 | 67 | ||
67 | /* MAC/PHY */ | 68 | /* MAC/PHY */ |
69 | extern int falcon_switch_mac(struct efx_nic *efx); | ||
68 | extern bool falcon_xaui_link_ok(struct efx_nic *efx); | 70 | extern bool falcon_xaui_link_ok(struct efx_nic *efx); |
69 | extern int falcon_dma_stats(struct efx_nic *efx, | 71 | extern int falcon_dma_stats(struct efx_nic *efx, |
70 | unsigned int done_offset); | 72 | unsigned int done_offset); |
@@ -77,6 +79,7 @@ extern int falcon_init_interrupt(struct efx_nic *efx); | |||
77 | extern void falcon_enable_interrupts(struct efx_nic *efx); | 79 | extern void falcon_enable_interrupts(struct efx_nic *efx); |
78 | extern void falcon_generate_test_event(struct efx_channel *channel, | 80 | extern void falcon_generate_test_event(struct efx_channel *channel, |
79 | unsigned int magic); | 81 | unsigned int magic); |
82 | extern void falcon_sim_phy_event(struct efx_nic *efx); | ||
80 | extern void falcon_generate_interrupt(struct efx_nic *efx); | 83 | extern void falcon_generate_interrupt(struct efx_nic *efx); |
81 | extern void falcon_set_int_moderation(struct efx_channel *channel); | 84 | extern void falcon_set_int_moderation(struct efx_channel *channel); |
82 | extern void falcon_disable_interrupts(struct efx_nic *efx); | 85 | extern void falcon_disable_interrupts(struct efx_nic *efx); |
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c new file mode 100644 index 000000000000..247f8025ef00 --- /dev/null +++ b/drivers/net/sfc/falcon_gmac.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /**************************************************************************** | ||
2 | * Driver for Solarflare Solarstorm network controllers and boards | ||
3 | * Copyright 2005-2006 Fen Systems Ltd. | ||
4 | * Copyright 2006-2008 Solarflare Communications Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published | ||
8 | * by the Free Software Foundation, incorporated herein by reference. | ||
9 | */ | ||
10 | |||
11 | #include <linux/delay.h> | ||
12 | #include "net_driver.h" | ||
13 | #include "efx.h" | ||
14 | #include "falcon.h" | ||
15 | #include "mac.h" | ||
16 | #include "falcon_hwdefs.h" | ||
17 | #include "falcon_io.h" | ||
18 | #include "gmii.h" | ||
19 | |||
20 | /************************************************************************** | ||
21 | * | ||
22 | * MAC operations | ||
23 | * | ||
24 | *************************************************************************/ | ||
25 | |||
26 | static void falcon_reconfigure_gmac(struct efx_nic *efx) | ||
27 | { | ||
28 | bool loopback, tx_fc, rx_fc, bytemode; | ||
29 | int if_mode; | ||
30 | unsigned int max_frame_len; | ||
31 | efx_oword_t reg; | ||
32 | |||
33 | /* Configuration register 1 */ | ||
34 | tx_fc = (efx->flow_control & EFX_FC_TX) || !efx->link_fd; | ||
35 | rx_fc = !!(efx->flow_control & EFX_FC_RX); | ||
36 | loopback = (efx->loopback_mode == LOOPBACK_GMAC); | ||
37 | bytemode = (efx->link_speed == 1000); | ||
38 | |||
39 | EFX_POPULATE_OWORD_5(reg, | ||
40 | GM_LOOP, loopback, | ||
41 | GM_TX_EN, 1, | ||
42 | GM_TX_FC_EN, tx_fc, | ||
43 | GM_RX_EN, 1, | ||
44 | GM_RX_FC_EN, rx_fc); | ||
45 | falcon_write(efx, ®, GM_CFG1_REG); | ||
46 | udelay(10); | ||
47 | |||
48 | /* Configuration register 2 */ | ||
49 | if_mode = (bytemode) ? 2 : 1; | ||
50 | EFX_POPULATE_OWORD_5(reg, | ||
51 | GM_IF_MODE, if_mode, | ||
52 | GM_PAD_CRC_EN, 1, | ||
53 | GM_LEN_CHK, 1, | ||
54 | GM_FD, efx->link_fd, | ||
55 | GM_PAMBL_LEN, 0x7/*datasheet recommended */); | ||
56 | |||
57 | falcon_write(efx, ®, GM_CFG2_REG); | ||
58 | udelay(10); | ||
59 | |||
60 | /* Max frame len register */ | ||
61 | max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); | ||
62 | EFX_POPULATE_OWORD_1(reg, GM_MAX_FLEN, max_frame_len); | ||
63 | falcon_write(efx, ®, GM_MAX_FLEN_REG); | ||
64 | udelay(10); | ||
65 | |||
66 | /* FIFO configuration register 0 */ | ||
67 | EFX_POPULATE_OWORD_5(reg, | ||
68 | GMF_FTFENREQ, 1, | ||
69 | GMF_STFENREQ, 1, | ||
70 | GMF_FRFENREQ, 1, | ||
71 | GMF_SRFENREQ, 1, | ||
72 | GMF_WTMENREQ, 1); | ||
73 | falcon_write(efx, ®, GMF_CFG0_REG); | ||
74 | udelay(10); | ||
75 | |||
76 | /* FIFO configuration register 1 */ | ||
77 | EFX_POPULATE_OWORD_2(reg, | ||
78 | GMF_CFGFRTH, 0x12, | ||
79 | GMF_CFGXOFFRTX, 0xffff); | ||
80 | falcon_write(efx, ®, GMF_CFG1_REG); | ||
81 | udelay(10); | ||
82 | |||
83 | /* FIFO configuration register 2 */ | ||
84 | EFX_POPULATE_OWORD_2(reg, | ||
85 | GMF_CFGHWM, 0x3f, | ||
86 | GMF_CFGLWM, 0xa); | ||
87 | falcon_write(efx, ®, GMF_CFG2_REG); | ||
88 | udelay(10); | ||
89 | |||
90 | /* FIFO configuration register 3 */ | ||
91 | EFX_POPULATE_OWORD_2(reg, | ||
92 | GMF_CFGHWMFT, 0x1c, | ||
93 | GMF_CFGFTTH, 0x08); | ||
94 | falcon_write(efx, ®, GMF_CFG3_REG); | ||
95 | udelay(10); | ||
96 | |||
97 | /* FIFO configuration register 4 */ | ||
98 | EFX_POPULATE_OWORD_1(reg, GMF_HSTFLTRFRM_PAUSE, 1); | ||
99 | falcon_write(efx, ®, GMF_CFG4_REG); | ||
100 | udelay(10); | ||
101 | |||
102 | /* FIFO configuration register 5 */ | ||
103 | falcon_read(efx, ®, GMF_CFG5_REG); | ||
104 | EFX_SET_OWORD_FIELD(reg, GMF_CFGBYTMODE, bytemode); | ||
105 | EFX_SET_OWORD_FIELD(reg, GMF_CFGHDPLX, !efx->link_fd); | ||
106 | EFX_SET_OWORD_FIELD(reg, GMF_HSTDRPLT64, !efx->link_fd); | ||
107 | EFX_SET_OWORD_FIELD(reg, GMF_HSTFLTRFRMDC_PAUSE, 0); | ||
108 | falcon_write(efx, ®, GMF_CFG5_REG); | ||
109 | udelay(10); | ||
110 | |||
111 | /* MAC address */ | ||
112 | EFX_POPULATE_OWORD_4(reg, | ||
113 | GM_HWADDR_5, efx->net_dev->dev_addr[5], | ||
114 | GM_HWADDR_4, efx->net_dev->dev_addr[4], | ||
115 | GM_HWADDR_3, efx->net_dev->dev_addr[3], | ||
116 | GM_HWADDR_2, efx->net_dev->dev_addr[2]); | ||
117 | falcon_write(efx, ®, GM_ADR1_REG); | ||
118 | udelay(10); | ||
119 | EFX_POPULATE_OWORD_2(reg, | ||
120 | GM_HWADDR_1, efx->net_dev->dev_addr[1], | ||
121 | GM_HWADDR_0, efx->net_dev->dev_addr[0]); | ||
122 | falcon_write(efx, ®, GM_ADR2_REG); | ||
123 | udelay(10); | ||
124 | |||
125 | falcon_reconfigure_mac_wrapper(efx); | ||
126 | } | ||
127 | |||
128 | static void falcon_update_stats_gmac(struct efx_nic *efx) | ||
129 | { | ||
130 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | ||
131 | unsigned long old_rx_pause, old_tx_pause; | ||
132 | unsigned long new_rx_pause, new_tx_pause; | ||
133 | int rc; | ||
134 | |||
135 | rc = falcon_dma_stats(efx, GDmaDone_offset); | ||
136 | if (rc) | ||
137 | return; | ||
138 | |||
139 | /* Pause frames are erroneously counted as errors (SFC bug 3269) */ | ||
140 | old_rx_pause = mac_stats->rx_pause; | ||
141 | old_tx_pause = mac_stats->tx_pause; | ||
142 | |||
143 | /* Update MAC stats from DMAed values */ | ||
144 | FALCON_STAT(efx, GRxGoodOct, rx_good_bytes); | ||
145 | FALCON_STAT(efx, GRxBadOct, rx_bad_bytes); | ||
146 | FALCON_STAT(efx, GRxMissPkt, rx_missed); | ||
147 | FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier); | ||
148 | FALCON_STAT(efx, GRxPausePkt, rx_pause); | ||
149 | FALCON_STAT(efx, GRxBadPkt, rx_bad); | ||
150 | FALCON_STAT(efx, GRxUcastPkt, rx_unicast); | ||
151 | FALCON_STAT(efx, GRxMcastPkt, rx_multicast); | ||
152 | FALCON_STAT(efx, GRxBcastPkt, rx_broadcast); | ||
153 | FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64); | ||
154 | FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64); | ||
155 | FALCON_STAT(efx, GRx64Pkt, rx_64); | ||
156 | FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127); | ||
157 | FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255); | ||
158 | FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511); | ||
159 | FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023); | ||
160 | FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx); | ||
161 | FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo); | ||
162 | FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo); | ||
163 | FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx); | ||
164 | FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo); | ||
165 | FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo); | ||
166 | FALCON_STAT(efx, GTxGoodBadOct, tx_bytes); | ||
167 | FALCON_STAT(efx, GTxGoodOct, tx_good_bytes); | ||
168 | FALCON_STAT(efx, GTxSglColPkt, tx_single_collision); | ||
169 | FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision); | ||
170 | FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision); | ||
171 | FALCON_STAT(efx, GTxDefPkt, tx_deferred); | ||
172 | FALCON_STAT(efx, GTxLateCol, tx_late_collision); | ||
173 | FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred); | ||
174 | FALCON_STAT(efx, GTxPausePkt, tx_pause); | ||
175 | FALCON_STAT(efx, GTxBadPkt, tx_bad); | ||
176 | FALCON_STAT(efx, GTxUcastPkt, tx_unicast); | ||
177 | FALCON_STAT(efx, GTxMcastPkt, tx_multicast); | ||
178 | FALCON_STAT(efx, GTxBcastPkt, tx_broadcast); | ||
179 | FALCON_STAT(efx, GTxLt64Pkt, tx_lt64); | ||
180 | FALCON_STAT(efx, GTx64Pkt, tx_64); | ||
181 | FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127); | ||
182 | FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255); | ||
183 | FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511); | ||
184 | FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023); | ||
185 | FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx); | ||
186 | FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo); | ||
187 | FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo); | ||
188 | FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp); | ||
189 | FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error); | ||
190 | FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error); | ||
191 | |||
192 | /* Pause frames are erroneously counted as errors (SFC bug 3269) */ | ||
193 | new_rx_pause = mac_stats->rx_pause; | ||
194 | new_tx_pause = mac_stats->tx_pause; | ||
195 | mac_stats->rx_bad -= (new_rx_pause - old_rx_pause); | ||
196 | mac_stats->tx_bad -= (new_tx_pause - old_tx_pause); | ||
197 | |||
198 | /* Derive stats that the MAC doesn't provide directly */ | ||
199 | mac_stats->tx_bad_bytes = | ||
200 | mac_stats->tx_bytes - mac_stats->tx_good_bytes; | ||
201 | mac_stats->tx_packets = | ||
202 | mac_stats->tx_lt64 + mac_stats->tx_64 + | ||
203 | mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 + | ||
204 | mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 + | ||
205 | mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo + | ||
206 | mac_stats->tx_gtjumbo; | ||
207 | mac_stats->tx_collision = | ||
208 | mac_stats->tx_single_collision + | ||
209 | mac_stats->tx_multiple_collision + | ||
210 | mac_stats->tx_excessive_collision + | ||
211 | mac_stats->tx_late_collision; | ||
212 | mac_stats->rx_bytes = | ||
213 | mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes; | ||
214 | mac_stats->rx_packets = | ||
215 | mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 + | ||
216 | mac_stats->rx_64 + mac_stats->rx_65_to_127 + | ||
217 | mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 + | ||
218 | mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx + | ||
219 | mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo; | ||
220 | mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad; | ||
221 | mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64; | ||
222 | } | ||
223 | |||
224 | static int falcon_check_gmac(struct efx_nic *efx) | ||
225 | { | ||
226 | return efx->phy_op->check_hw(efx); | ||
227 | } | ||
228 | |||
229 | struct efx_mac_operations falcon_gmac_operations = { | ||
230 | .reconfigure = falcon_reconfigure_gmac, | ||
231 | .update_stats = falcon_update_stats_gmac, | ||
232 | .check_hw = falcon_check_gmac, | ||
233 | }; | ||
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h index 040e70ed4ec7..5553df888b84 100644 --- a/drivers/net/sfc/falcon_hwdefs.h +++ b/drivers/net/sfc/falcon_hwdefs.h | |||
@@ -111,12 +111,18 @@ | |||
111 | 111 | ||
112 | /* NIC status register */ | 112 | /* NIC status register */ |
113 | #define NIC_STAT_REG 0x0200 | 113 | #define NIC_STAT_REG 0x0200 |
114 | #define EE_STRAP_EN_LBN 31 | ||
115 | #define EE_STRAP_EN_WIDTH 1 | ||
116 | #define EE_STRAP_OVR_LBN 24 | ||
117 | #define EE_STRAP_OVR_WIDTH 4 | ||
114 | #define ONCHIP_SRAM_LBN 16 | 118 | #define ONCHIP_SRAM_LBN 16 |
115 | #define ONCHIP_SRAM_WIDTH 1 | 119 | #define ONCHIP_SRAM_WIDTH 1 |
116 | #define SF_PRST_LBN 9 | 120 | #define SF_PRST_LBN 9 |
117 | #define SF_PRST_WIDTH 1 | 121 | #define SF_PRST_WIDTH 1 |
118 | #define EE_PRST_LBN 8 | 122 | #define EE_PRST_LBN 8 |
119 | #define EE_PRST_WIDTH 1 | 123 | #define EE_PRST_WIDTH 1 |
124 | #define STRAP_PINS_LBN 0 | ||
125 | #define STRAP_PINS_WIDTH 3 | ||
120 | /* These bit definitions are extrapolated from the list of numerical | 126 | /* These bit definitions are extrapolated from the list of numerical |
121 | * values for STRAP_PINS. | 127 | * values for STRAP_PINS. |
122 | */ | 128 | */ |
@@ -492,6 +498,107 @@ | |||
492 | #define MAC_MCAST_HASH_REG0_KER 0xca0 | 498 | #define MAC_MCAST_HASH_REG0_KER 0xca0 |
493 | #define MAC_MCAST_HASH_REG1_KER 0xcb0 | 499 | #define MAC_MCAST_HASH_REG1_KER 0xcb0 |
494 | 500 | ||
501 | /* GMAC configuration register 1 */ | ||
502 | #define GM_CFG1_REG 0xe00 | ||
503 | #define GM_SW_RST_LBN 31 | ||
504 | #define GM_SW_RST_WIDTH 1 | ||
505 | #define GM_LOOP_LBN 8 | ||
506 | #define GM_LOOP_WIDTH 1 | ||
507 | #define GM_RX_FC_EN_LBN 5 | ||
508 | #define GM_RX_FC_EN_WIDTH 1 | ||
509 | #define GM_TX_FC_EN_LBN 4 | ||
510 | #define GM_TX_FC_EN_WIDTH 1 | ||
511 | #define GM_RX_EN_LBN 2 | ||
512 | #define GM_RX_EN_WIDTH 1 | ||
513 | #define GM_TX_EN_LBN 0 | ||
514 | #define GM_TX_EN_WIDTH 1 | ||
515 | |||
516 | /* GMAC configuration register 2 */ | ||
517 | #define GM_CFG2_REG 0xe10 | ||
518 | #define GM_PAMBL_LEN_LBN 12 | ||
519 | #define GM_PAMBL_LEN_WIDTH 4 | ||
520 | #define GM_IF_MODE_LBN 8 | ||
521 | #define GM_IF_MODE_WIDTH 2 | ||
522 | #define GM_LEN_CHK_LBN 4 | ||
523 | #define GM_LEN_CHK_WIDTH 1 | ||
524 | #define GM_PAD_CRC_EN_LBN 2 | ||
525 | #define GM_PAD_CRC_EN_WIDTH 1 | ||
526 | #define GM_FD_LBN 0 | ||
527 | #define GM_FD_WIDTH 1 | ||
528 | |||
529 | /* GMAC maximum frame length register */ | ||
530 | #define GM_MAX_FLEN_REG 0xe40 | ||
531 | #define GM_MAX_FLEN_LBN 0 | ||
532 | #define GM_MAX_FLEN_WIDTH 16 | ||
533 | |||
534 | /* GMAC station address register 1 */ | ||
535 | #define GM_ADR1_REG 0xf00 | ||
536 | #define GM_HWADDR_5_LBN 24 | ||
537 | #define GM_HWADDR_5_WIDTH 8 | ||
538 | #define GM_HWADDR_4_LBN 16 | ||
539 | #define GM_HWADDR_4_WIDTH 8 | ||
540 | #define GM_HWADDR_3_LBN 8 | ||
541 | #define GM_HWADDR_3_WIDTH 8 | ||
542 | #define GM_HWADDR_2_LBN 0 | ||
543 | #define GM_HWADDR_2_WIDTH 8 | ||
544 | |||
545 | /* GMAC station address register 2 */ | ||
546 | #define GM_ADR2_REG 0xf10 | ||
547 | #define GM_HWADDR_1_LBN 24 | ||
548 | #define GM_HWADDR_1_WIDTH 8 | ||
549 | #define GM_HWADDR_0_LBN 16 | ||
550 | #define GM_HWADDR_0_WIDTH 8 | ||
551 | |||
552 | /* GMAC FIFO configuration register 0 */ | ||
553 | #define GMF_CFG0_REG 0xf20 | ||
554 | #define GMF_FTFENREQ_LBN 12 | ||
555 | #define GMF_FTFENREQ_WIDTH 1 | ||
556 | #define GMF_STFENREQ_LBN 11 | ||
557 | #define GMF_STFENREQ_WIDTH 1 | ||
558 | #define GMF_FRFENREQ_LBN 10 | ||
559 | #define GMF_FRFENREQ_WIDTH 1 | ||
560 | #define GMF_SRFENREQ_LBN 9 | ||
561 | #define GMF_SRFENREQ_WIDTH 1 | ||
562 | #define GMF_WTMENREQ_LBN 8 | ||
563 | #define GMF_WTMENREQ_WIDTH 1 | ||
564 | |||
565 | /* GMAC FIFO configuration register 1 */ | ||
566 | #define GMF_CFG1_REG 0xf30 | ||
567 | #define GMF_CFGFRTH_LBN 16 | ||
568 | #define GMF_CFGFRTH_WIDTH 5 | ||
569 | #define GMF_CFGXOFFRTX_LBN 0 | ||
570 | #define GMF_CFGXOFFRTX_WIDTH 16 | ||
571 | |||
572 | /* GMAC FIFO configuration register 2 */ | ||
573 | #define GMF_CFG2_REG 0xf40 | ||
574 | #define GMF_CFGHWM_LBN 16 | ||
575 | #define GMF_CFGHWM_WIDTH 6 | ||
576 | #define GMF_CFGLWM_LBN 0 | ||
577 | #define GMF_CFGLWM_WIDTH 6 | ||
578 | |||
579 | /* GMAC FIFO configuration register 3 */ | ||
580 | #define GMF_CFG3_REG 0xf50 | ||
581 | #define GMF_CFGHWMFT_LBN 16 | ||
582 | #define GMF_CFGHWMFT_WIDTH 6 | ||
583 | #define GMF_CFGFTTH_LBN 0 | ||
584 | #define GMF_CFGFTTH_WIDTH 6 | ||
585 | |||
586 | /* GMAC FIFO configuration register 4 */ | ||
587 | #define GMF_CFG4_REG 0xf60 | ||
588 | #define GMF_HSTFLTRFRM_PAUSE_LBN 12 | ||
589 | #define GMF_HSTFLTRFRM_PAUSE_WIDTH 12 | ||
590 | |||
591 | /* GMAC FIFO configuration register 5 */ | ||
592 | #define GMF_CFG5_REG 0xf70 | ||
593 | #define GMF_CFGHDPLX_LBN 22 | ||
594 | #define GMF_CFGHDPLX_WIDTH 1 | ||
595 | #define GMF_CFGBYTMODE_LBN 19 | ||
596 | #define GMF_CFGBYTMODE_WIDTH 1 | ||
597 | #define GMF_HSTDRPLT64_LBN 18 | ||
598 | #define GMF_HSTDRPLT64_WIDTH 1 | ||
599 | #define GMF_HSTFLTRFRMDC_PAUSE_LBN 12 | ||
600 | #define GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1 | ||
601 | |||
495 | /* XGMAC address register low */ | 602 | /* XGMAC address register low */ |
496 | #define XM_ADR_LO_REG 0x1200 | 603 | #define XM_ADR_LO_REG 0x1200 |
497 | #define XM_ADR_3_LBN 24 | 604 | #define XM_ADR_3_LBN 24 |
@@ -962,54 +1069,103 @@ | |||
962 | ************************************************************************** | 1069 | ************************************************************************** |
963 | * | 1070 | * |
964 | */ | 1071 | */ |
1072 | |||
965 | #define GRxGoodOct_offset 0x0 | 1073 | #define GRxGoodOct_offset 0x0 |
1074 | #define GRxGoodOct_WIDTH 48 | ||
966 | #define GRxBadOct_offset 0x8 | 1075 | #define GRxBadOct_offset 0x8 |
1076 | #define GRxBadOct_WIDTH 48 | ||
967 | #define GRxMissPkt_offset 0x10 | 1077 | #define GRxMissPkt_offset 0x10 |
1078 | #define GRxMissPkt_WIDTH 32 | ||
968 | #define GRxFalseCRS_offset 0x14 | 1079 | #define GRxFalseCRS_offset 0x14 |
1080 | #define GRxFalseCRS_WIDTH 32 | ||
969 | #define GRxPausePkt_offset 0x18 | 1081 | #define GRxPausePkt_offset 0x18 |
1082 | #define GRxPausePkt_WIDTH 32 | ||
970 | #define GRxBadPkt_offset 0x1C | 1083 | #define GRxBadPkt_offset 0x1C |
1084 | #define GRxBadPkt_WIDTH 32 | ||
971 | #define GRxUcastPkt_offset 0x20 | 1085 | #define GRxUcastPkt_offset 0x20 |
1086 | #define GRxUcastPkt_WIDTH 32 | ||
972 | #define GRxMcastPkt_offset 0x24 | 1087 | #define GRxMcastPkt_offset 0x24 |
1088 | #define GRxMcastPkt_WIDTH 32 | ||
973 | #define GRxBcastPkt_offset 0x28 | 1089 | #define GRxBcastPkt_offset 0x28 |
1090 | #define GRxBcastPkt_WIDTH 32 | ||
974 | #define GRxGoodLt64Pkt_offset 0x2C | 1091 | #define GRxGoodLt64Pkt_offset 0x2C |
1092 | #define GRxGoodLt64Pkt_WIDTH 32 | ||
975 | #define GRxBadLt64Pkt_offset 0x30 | 1093 | #define GRxBadLt64Pkt_offset 0x30 |
1094 | #define GRxBadLt64Pkt_WIDTH 32 | ||
976 | #define GRx64Pkt_offset 0x34 | 1095 | #define GRx64Pkt_offset 0x34 |
1096 | #define GRx64Pkt_WIDTH 32 | ||
977 | #define GRx65to127Pkt_offset 0x38 | 1097 | #define GRx65to127Pkt_offset 0x38 |
1098 | #define GRx65to127Pkt_WIDTH 32 | ||
978 | #define GRx128to255Pkt_offset 0x3C | 1099 | #define GRx128to255Pkt_offset 0x3C |
1100 | #define GRx128to255Pkt_WIDTH 32 | ||
979 | #define GRx256to511Pkt_offset 0x40 | 1101 | #define GRx256to511Pkt_offset 0x40 |
1102 | #define GRx256to511Pkt_WIDTH 32 | ||
980 | #define GRx512to1023Pkt_offset 0x44 | 1103 | #define GRx512to1023Pkt_offset 0x44 |
1104 | #define GRx512to1023Pkt_WIDTH 32 | ||
981 | #define GRx1024to15xxPkt_offset 0x48 | 1105 | #define GRx1024to15xxPkt_offset 0x48 |
1106 | #define GRx1024to15xxPkt_WIDTH 32 | ||
982 | #define GRx15xxtoJumboPkt_offset 0x4C | 1107 | #define GRx15xxtoJumboPkt_offset 0x4C |
1108 | #define GRx15xxtoJumboPkt_WIDTH 32 | ||
983 | #define GRxGtJumboPkt_offset 0x50 | 1109 | #define GRxGtJumboPkt_offset 0x50 |
1110 | #define GRxGtJumboPkt_WIDTH 32 | ||
984 | #define GRxFcsErr64to15xxPkt_offset 0x54 | 1111 | #define GRxFcsErr64to15xxPkt_offset 0x54 |
1112 | #define GRxFcsErr64to15xxPkt_WIDTH 32 | ||
985 | #define GRxFcsErr15xxtoJumboPkt_offset 0x58 | 1113 | #define GRxFcsErr15xxtoJumboPkt_offset 0x58 |
1114 | #define GRxFcsErr15xxtoJumboPkt_WIDTH 32 | ||
986 | #define GRxFcsErrGtJumboPkt_offset 0x5C | 1115 | #define GRxFcsErrGtJumboPkt_offset 0x5C |
1116 | #define GRxFcsErrGtJumboPkt_WIDTH 32 | ||
987 | #define GTxGoodBadOct_offset 0x80 | 1117 | #define GTxGoodBadOct_offset 0x80 |
1118 | #define GTxGoodBadOct_WIDTH 48 | ||
988 | #define GTxGoodOct_offset 0x88 | 1119 | #define GTxGoodOct_offset 0x88 |
1120 | #define GTxGoodOct_WIDTH 48 | ||
989 | #define GTxSglColPkt_offset 0x90 | 1121 | #define GTxSglColPkt_offset 0x90 |
1122 | #define GTxSglColPkt_WIDTH 32 | ||
990 | #define GTxMultColPkt_offset 0x94 | 1123 | #define GTxMultColPkt_offset 0x94 |
1124 | #define GTxMultColPkt_WIDTH 32 | ||
991 | #define GTxExColPkt_offset 0x98 | 1125 | #define GTxExColPkt_offset 0x98 |
1126 | #define GTxExColPkt_WIDTH 32 | ||
992 | #define GTxDefPkt_offset 0x9C | 1127 | #define GTxDefPkt_offset 0x9C |
1128 | #define GTxDefPkt_WIDTH 32 | ||
993 | #define GTxLateCol_offset 0xA0 | 1129 | #define GTxLateCol_offset 0xA0 |
1130 | #define GTxLateCol_WIDTH 32 | ||
994 | #define GTxExDefPkt_offset 0xA4 | 1131 | #define GTxExDefPkt_offset 0xA4 |
1132 | #define GTxExDefPkt_WIDTH 32 | ||
995 | #define GTxPausePkt_offset 0xA8 | 1133 | #define GTxPausePkt_offset 0xA8 |
1134 | #define GTxPausePkt_WIDTH 32 | ||
996 | #define GTxBadPkt_offset 0xAC | 1135 | #define GTxBadPkt_offset 0xAC |
1136 | #define GTxBadPkt_WIDTH 32 | ||
997 | #define GTxUcastPkt_offset 0xB0 | 1137 | #define GTxUcastPkt_offset 0xB0 |
1138 | #define GTxUcastPkt_WIDTH 32 | ||
998 | #define GTxMcastPkt_offset 0xB4 | 1139 | #define GTxMcastPkt_offset 0xB4 |
1140 | #define GTxMcastPkt_WIDTH 32 | ||
999 | #define GTxBcastPkt_offset 0xB8 | 1141 | #define GTxBcastPkt_offset 0xB8 |
1142 | #define GTxBcastPkt_WIDTH 32 | ||
1000 | #define GTxLt64Pkt_offset 0xBC | 1143 | #define GTxLt64Pkt_offset 0xBC |
1144 | #define GTxLt64Pkt_WIDTH 32 | ||
1001 | #define GTx64Pkt_offset 0xC0 | 1145 | #define GTx64Pkt_offset 0xC0 |
1146 | #define GTx64Pkt_WIDTH 32 | ||
1002 | #define GTx65to127Pkt_offset 0xC4 | 1147 | #define GTx65to127Pkt_offset 0xC4 |
1148 | #define GTx65to127Pkt_WIDTH 32 | ||
1003 | #define GTx128to255Pkt_offset 0xC8 | 1149 | #define GTx128to255Pkt_offset 0xC8 |
1150 | #define GTx128to255Pkt_WIDTH 32 | ||
1004 | #define GTx256to511Pkt_offset 0xCC | 1151 | #define GTx256to511Pkt_offset 0xCC |
1152 | #define GTx256to511Pkt_WIDTH 32 | ||
1005 | #define GTx512to1023Pkt_offset 0xD0 | 1153 | #define GTx512to1023Pkt_offset 0xD0 |
1154 | #define GTx512to1023Pkt_WIDTH 32 | ||
1006 | #define GTx1024to15xxPkt_offset 0xD4 | 1155 | #define GTx1024to15xxPkt_offset 0xD4 |
1156 | #define GTx1024to15xxPkt_WIDTH 32 | ||
1007 | #define GTx15xxtoJumboPkt_offset 0xD8 | 1157 | #define GTx15xxtoJumboPkt_offset 0xD8 |
1158 | #define GTx15xxtoJumboPkt_WIDTH 32 | ||
1008 | #define GTxGtJumboPkt_offset 0xDC | 1159 | #define GTxGtJumboPkt_offset 0xDC |
1160 | #define GTxGtJumboPkt_WIDTH 32 | ||
1009 | #define GTxNonTcpUdpPkt_offset 0xE0 | 1161 | #define GTxNonTcpUdpPkt_offset 0xE0 |
1162 | #define GTxNonTcpUdpPkt_WIDTH 16 | ||
1010 | #define GTxMacSrcErrPkt_offset 0xE4 | 1163 | #define GTxMacSrcErrPkt_offset 0xE4 |
1164 | #define GTxMacSrcErrPkt_WIDTH 16 | ||
1011 | #define GTxIpSrcErrPkt_offset 0xE8 | 1165 | #define GTxIpSrcErrPkt_offset 0xE8 |
1166 | #define GTxIpSrcErrPkt_WIDTH 16 | ||
1012 | #define GDmaDone_offset 0xEC | 1167 | #define GDmaDone_offset 0xEC |
1168 | #define GDmaDone_WIDTH 32 | ||
1013 | 1169 | ||
1014 | #define XgRxOctets_offset 0x0 | 1170 | #define XgRxOctets_offset 0x0 |
1015 | #define XgRxOctets_WIDTH 48 | 1171 | #define XgRxOctets_WIDTH 48 |
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 4a54d0933e72..2206eada3463 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c | |||
@@ -25,24 +25,6 @@ | |||
25 | * MAC operations | 25 | * MAC operations |
26 | * | 26 | * |
27 | *************************************************************************/ | 27 | *************************************************************************/ |
28 | static int falcon_reset_xmac(struct efx_nic *efx) | ||
29 | { | ||
30 | efx_oword_t reg; | ||
31 | int count; | ||
32 | |||
33 | EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1); | ||
34 | falcon_write(efx, ®, XM_GLB_CFG_REG); | ||
35 | |||
36 | for (count = 0; count < 10000; count++) { /* wait upto 100ms */ | ||
37 | falcon_read(efx, ®, XM_GLB_CFG_REG); | ||
38 | if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0) | ||
39 | return 0; | ||
40 | udelay(10); | ||
41 | } | ||
42 | |||
43 | EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); | ||
44 | return -ETIMEDOUT; | ||
45 | } | ||
46 | 28 | ||
47 | /* Configure the XAUI driver that is an output from Falcon */ | 29 | /* Configure the XAUI driver that is an output from Falcon */ |
48 | static void falcon_setup_xaui(struct efx_nic *efx) | 30 | static void falcon_setup_xaui(struct efx_nic *efx) |
@@ -98,31 +80,20 @@ int falcon_reset_xaui(struct efx_nic *efx) | |||
98 | return -ETIMEDOUT; | 80 | return -ETIMEDOUT; |
99 | } | 81 | } |
100 | 82 | ||
101 | static bool falcon_xgmii_status(struct efx_nic *efx) | 83 | static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) |
102 | { | 84 | { |
103 | efx_oword_t reg; | 85 | efx_oword_t reg; |
104 | 86 | ||
105 | if (falcon_rev(efx) < FALCON_REV_B0) | 87 | if ((falcon_rev(efx) != FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) |
106 | return true; | 88 | return; |
107 | |||
108 | /* The ISR latches, so clear it and re-read */ | ||
109 | falcon_read(efx, ®, XM_MGT_INT_REG_B0); | ||
110 | falcon_read(efx, ®, XM_MGT_INT_REG_B0); | ||
111 | |||
112 | if (EFX_OWORD_FIELD(reg, XM_LCLFLT) || | ||
113 | EFX_OWORD_FIELD(reg, XM_RMTFLT)) { | ||
114 | EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg)); | ||
115 | return false; | ||
116 | } | ||
117 | |||
118 | return true; | ||
119 | } | ||
120 | 89 | ||
121 | static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) | 90 | /* We expect xgmii faults if the wireside link is up */ |
122 | { | 91 | if (!EFX_WORKAROUND_5147(efx) || !efx->link_up) |
123 | efx_oword_t reg; | 92 | return; |
124 | 93 | ||
125 | if ((falcon_rev(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) | 94 | /* We can only use this interrupt to signal the negative edge of |
95 | * xaui_align [we have to poll the positive edge]. */ | ||
96 | if (!efx->mac_up) | ||
126 | return; | 97 | return; |
127 | 98 | ||
128 | /* Flush the ISR */ | 99 | /* Flush the ISR */ |
@@ -135,35 +106,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) | |||
135 | falcon_write(efx, ®, XM_MGT_INT_MSK_REG_B0); | 106 | falcon_write(efx, ®, XM_MGT_INT_MSK_REG_B0); |
136 | } | 107 | } |
137 | 108 | ||
138 | int falcon_init_xmac(struct efx_nic *efx) | 109 | /* Get status of XAUI link */ |
139 | { | ||
140 | int rc; | ||
141 | |||
142 | /* Initialize the PHY first so the clock is around */ | ||
143 | rc = efx->phy_op->init(efx); | ||
144 | if (rc) | ||
145 | goto fail1; | ||
146 | |||
147 | rc = falcon_reset_xaui(efx); | ||
148 | if (rc) | ||
149 | goto fail2; | ||
150 | |||
151 | /* Wait again. Give the PHY and MAC time to come back */ | ||
152 | schedule_timeout_uninterruptible(HZ / 10); | ||
153 | |||
154 | rc = falcon_reset_xmac(efx); | ||
155 | if (rc) | ||
156 | goto fail2; | ||
157 | |||
158 | falcon_mask_status_intr(efx, true); | ||
159 | return 0; | ||
160 | |||
161 | fail2: | ||
162 | efx->phy_op->fini(efx); | ||
163 | fail1: | ||
164 | return rc; | ||
165 | } | ||
166 | |||
167 | bool falcon_xaui_link_ok(struct efx_nic *efx) | 110 | bool falcon_xaui_link_ok(struct efx_nic *efx) |
168 | { | 111 | { |
169 | efx_oword_t reg; | 112 | efx_oword_t reg; |
@@ -187,18 +130,10 @@ bool falcon_xaui_link_ok(struct efx_nic *efx) | |||
187 | EFX_SET_OWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET); | 130 | EFX_SET_OWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET); |
188 | falcon_write(efx, ®, XX_CORE_STAT_REG); | 131 | falcon_write(efx, ®, XX_CORE_STAT_REG); |
189 | 132 | ||
190 | /* If the link is up, then check the phy side of the xaui link | 133 | /* If the link is up, then check the phy side of the xaui link */ |
191 | * (error conditions from the wire side propoagate back through | 134 | if (efx->link_up && link_ok) |
192 | * the phy to the xaui side). */ | ||
193 | if (efx->link_up && link_ok) { | ||
194 | if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS)) | 135 | if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS)) |
195 | link_ok = mdio_clause45_phyxgxs_lane_sync(efx); | 136 | link_ok = mdio_clause45_phyxgxs_lane_sync(efx); |
196 | } | ||
197 | |||
198 | /* If the PHY and XAUI links are up, then check the mac's xgmii | ||
199 | * fault state */ | ||
200 | if (efx->link_up && link_ok) | ||
201 | link_ok = falcon_xgmii_status(efx); | ||
202 | 137 | ||
203 | return link_ok; | 138 | return link_ok; |
204 | } | 139 | } |
@@ -310,70 +245,39 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) | |||
310 | 245 | ||
311 | /* Try and bring the Falcon side of the Falcon-Phy XAUI link fails | 246 | /* Try and bring the Falcon side of the Falcon-Phy XAUI link fails |
312 | * to come back up. Bash it until it comes back up */ | 247 | * to come back up. Bash it until it comes back up */ |
313 | static bool falcon_check_xaui_link_up(struct efx_nic *efx) | 248 | static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries) |
314 | { | 249 | { |
315 | int max_tries, tries; | 250 | efx->mac_up = falcon_xaui_link_ok(efx); |
316 | tries = EFX_WORKAROUND_5147(efx) ? 5 : 1; | ||
317 | max_tries = tries; | ||
318 | 251 | ||
319 | if ((efx->loopback_mode == LOOPBACK_NETWORK) || | 252 | if ((efx->loopback_mode == LOOPBACK_NETWORK) || |
320 | (efx->phy_type == PHY_TYPE_NONE) || | ||
321 | efx_phy_mode_disabled(efx->phy_mode)) | 253 | efx_phy_mode_disabled(efx->phy_mode)) |
322 | return false; | 254 | /* XAUI link is expected to be down */ |
323 | 255 | return; | |
324 | while (tries) { | ||
325 | if (falcon_xaui_link_ok(efx)) | ||
326 | return true; | ||
327 | 256 | ||
328 | EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n", | 257 | while (!efx->mac_up && tries) { |
329 | __func__, tries); | 258 | EFX_LOG(efx, "bashing xaui\n"); |
330 | falcon_reset_xaui(efx); | 259 | falcon_reset_xaui(efx); |
331 | udelay(200); | 260 | udelay(200); |
332 | tries--; | ||
333 | } | ||
334 | 261 | ||
335 | EFX_LOG(efx, "Failed to bring XAUI link back up in %d tries!\n", | 262 | efx->mac_up = falcon_xaui_link_ok(efx); |
336 | max_tries); | 263 | --tries; |
337 | return false; | 264 | } |
338 | } | 265 | } |
339 | 266 | ||
340 | void falcon_reconfigure_xmac(struct efx_nic *efx) | 267 | static void falcon_reconfigure_xmac(struct efx_nic *efx) |
341 | { | 268 | { |
342 | bool xaui_link_ok; | ||
343 | |||
344 | falcon_mask_status_intr(efx, false); | 269 | falcon_mask_status_intr(efx, false); |
345 | 270 | ||
346 | falcon_deconfigure_mac_wrapper(efx); | ||
347 | |||
348 | /* Reconfigure the PHY, disabling transmit in mac level loopback. */ | ||
349 | if (LOOPBACK_INTERNAL(efx)) | ||
350 | efx->phy_mode |= PHY_MODE_TX_DISABLED; | ||
351 | else | ||
352 | efx->phy_mode &= ~PHY_MODE_TX_DISABLED; | ||
353 | efx->phy_op->reconfigure(efx); | ||
354 | |||
355 | falcon_reconfigure_xgxs_core(efx); | 271 | falcon_reconfigure_xgxs_core(efx); |
356 | falcon_reconfigure_xmac_core(efx); | 272 | falcon_reconfigure_xmac_core(efx); |
357 | 273 | ||
358 | falcon_reconfigure_mac_wrapper(efx); | 274 | falcon_reconfigure_mac_wrapper(efx); |
359 | 275 | ||
360 | /* Ensure XAUI link is up */ | 276 | falcon_check_xaui_link_up(efx, 5); |
361 | xaui_link_ok = falcon_check_xaui_link_up(efx); | 277 | falcon_mask_status_intr(efx, true); |
362 | |||
363 | if (xaui_link_ok && efx->link_up) | ||
364 | falcon_mask_status_intr(efx, true); | ||
365 | } | ||
366 | |||
367 | void falcon_fini_xmac(struct efx_nic *efx) | ||
368 | { | ||
369 | /* Isolate the MAC - PHY */ | ||
370 | falcon_deconfigure_mac_wrapper(efx); | ||
371 | |||
372 | /* Potentially power down the PHY */ | ||
373 | efx->phy_op->fini(efx); | ||
374 | } | 278 | } |
375 | 279 | ||
376 | void falcon_update_stats_xmac(struct efx_nic *efx) | 280 | static void falcon_update_stats_xmac(struct efx_nic *efx) |
377 | { | 281 | { |
378 | struct efx_mac_stats *mac_stats = &efx->mac_stats; | 282 | struct efx_mac_stats *mac_stats = &efx->mac_stats; |
379 | int rc; | 283 | int rc; |
@@ -438,7 +342,7 @@ void falcon_update_stats_xmac(struct efx_nic *efx) | |||
438 | mac_stats->rx_control * 64); | 342 | mac_stats->rx_control * 64); |
439 | } | 343 | } |
440 | 344 | ||
441 | int falcon_check_xmac(struct efx_nic *efx) | 345 | static int falcon_check_xmac(struct efx_nic *efx) |
442 | { | 346 | { |
443 | bool xaui_link_ok; | 347 | bool xaui_link_ok; |
444 | int rc; | 348 | int rc; |
@@ -463,72 +367,8 @@ int falcon_check_xmac(struct efx_nic *efx) | |||
463 | return rc; | 367 | return rc; |
464 | } | 368 | } |
465 | 369 | ||
466 | /* Simulate a PHY event */ | 370 | struct efx_mac_operations falcon_xmac_operations = { |
467 | void falcon_xmac_sim_phy_event(struct efx_nic *efx) | 371 | .reconfigure = falcon_reconfigure_xmac, |
468 | { | 372 | .update_stats = falcon_update_stats_xmac, |
469 | efx_qword_t phy_event; | 373 | .check_hw = falcon_check_xmac, |
470 | 374 | }; | |
471 | EFX_POPULATE_QWORD_2(phy_event, | ||
472 | EV_CODE, GLOBAL_EV_DECODE, | ||
473 | XG_PHY_INTR, 1); | ||
474 | falcon_generate_event(&efx->channel[0], &phy_event); | ||
475 | } | ||
476 | |||
477 | int falcon_xmac_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | ||
478 | { | ||
479 | mdio_clause45_get_settings(efx, ecmd); | ||
480 | ecmd->transceiver = XCVR_INTERNAL; | ||
481 | ecmd->phy_address = efx->mii.phy_id; | ||
482 | ecmd->autoneg = AUTONEG_DISABLE; | ||
483 | ecmd->duplex = DUPLEX_FULL; | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | int falcon_xmac_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | ||
488 | { | ||
489 | if (ecmd->transceiver != XCVR_INTERNAL) | ||
490 | return -EINVAL; | ||
491 | if (ecmd->autoneg != AUTONEG_DISABLE) | ||
492 | return -EINVAL; | ||
493 | if (ecmd->duplex != DUPLEX_FULL) | ||
494 | return -EINVAL; | ||
495 | |||
496 | return mdio_clause45_set_settings(efx, ecmd); | ||
497 | } | ||
498 | |||
499 | |||
500 | int falcon_xmac_set_pause(struct efx_nic *efx, enum efx_fc_type flow_control) | ||
501 | { | ||
502 | bool reset; | ||
503 | |||
504 | if (flow_control & EFX_FC_AUTO) { | ||
505 | EFX_LOG(efx, "10G does not support flow control " | ||
506 | "autonegotiation\n"); | ||
507 | return -EINVAL; | ||
508 | } | ||
509 | |||
510 | if ((flow_control & EFX_FC_TX) && !(flow_control & EFX_FC_RX)) | ||
511 | return -EINVAL; | ||
512 | |||
513 | /* TX flow control may automatically turn itself off if the | ||
514 | * link partner (intermittently) stops responding to pause | ||
515 | * frames. There isn't any indication that this has happened, | ||
516 | * so the best we do is leave it up to the user to spot this | ||
517 | * and fix it be cycling transmit flow control on this end. */ | ||
518 | reset = ((flow_control & EFX_FC_TX) && | ||
519 | !(efx->flow_control & EFX_FC_TX)); | ||
520 | if (EFX_WORKAROUND_11482(efx) && reset) { | ||
521 | if (falcon_rev(efx) >= FALCON_REV_B0) { | ||
522 | /* Recover by resetting the EM block */ | ||
523 | if (efx->link_up) | ||
524 | falcon_drain_tx_fifo(efx); | ||
525 | } else { | ||
526 | /* Schedule a reset to recover */ | ||
527 | efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); | ||
528 | } | ||
529 | } | ||
530 | |||
531 | efx->flow_control = flow_control; | ||
532 | |||
533 | return 0; | ||
534 | } | ||
diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h index a31571c69137..4e7074278fe1 100644 --- a/drivers/net/sfc/mac.h +++ b/drivers/net/sfc/mac.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2005-2006 Fen Systems Ltd. | 3 | * Copyright 2005-2006 Fen Systems Ltd. |
4 | * Copyright 2006-2007 Solarflare Communications Inc. | 4 | * Copyright 2006-2008 Solarflare Communications Inc. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published | 7 | * under the terms of the GNU General Public License version 2 as published |
@@ -13,17 +13,7 @@ | |||
13 | 13 | ||
14 | #include "net_driver.h" | 14 | #include "net_driver.h" |
15 | 15 | ||
16 | extern int falcon_init_xmac(struct efx_nic *efx); | 16 | extern struct efx_mac_operations falcon_gmac_operations; |
17 | extern void falcon_reconfigure_xmac(struct efx_nic *efx); | 17 | extern struct efx_mac_operations falcon_xmac_operations; |
18 | extern void falcon_update_stats_xmac(struct efx_nic *efx); | ||
19 | extern void falcon_fini_xmac(struct efx_nic *efx); | ||
20 | extern int falcon_check_xmac(struct efx_nic *efx); | ||
21 | extern void falcon_xmac_sim_phy_event(struct efx_nic *efx); | ||
22 | extern int falcon_xmac_get_settings(struct efx_nic *efx, | ||
23 | struct ethtool_cmd *ecmd); | ||
24 | extern int falcon_xmac_set_settings(struct efx_nic *efx, | ||
25 | struct ethtool_cmd *ecmd); | ||
26 | extern int falcon_xmac_set_pause(struct efx_nic *efx, | ||
27 | enum efx_fc_type pause_params); | ||
28 | 18 | ||
29 | #endif | 19 | #endif |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 6cac5ed427ba..883086e39455 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -463,6 +463,8 @@ enum phy_type { | |||
463 | 463 | ||
464 | #define PHY_ADDR_INVALID 0xff | 464 | #define PHY_ADDR_INVALID 0xff |
465 | 465 | ||
466 | #define EFX_IS10G(efx) ((efx)->link_speed == 10000) | ||
467 | |||
466 | enum nic_state { | 468 | enum nic_state { |
467 | STATE_INIT = 0, | 469 | STATE_INIT = 0, |
468 | STATE_RUNNING = 1, | 470 | STATE_RUNNING = 1, |
@@ -503,6 +505,24 @@ enum efx_fc_type { | |||
503 | EFX_FC_AUTO = 4, | 505 | EFX_FC_AUTO = 4, |
504 | }; | 506 | }; |
505 | 507 | ||
508 | /* Supported MAC bit-mask */ | ||
509 | enum efx_mac_type { | ||
510 | EFX_GMAC = 1, | ||
511 | EFX_XMAC = 2, | ||
512 | }; | ||
513 | |||
514 | /** | ||
515 | * struct efx_mac_operations - Efx MAC operations table | ||
516 | * @reconfigure: Reconfigure MAC. Serialised by the mac_lock | ||
517 | * @update_stats: Update statistics | ||
518 | * @check_hw: Check hardware. Serialised by the mac_lock | ||
519 | */ | ||
520 | struct efx_mac_operations { | ||
521 | void (*reconfigure) (struct efx_nic *efx); | ||
522 | void (*update_stats) (struct efx_nic *efx); | ||
523 | int (*check_hw) (struct efx_nic *efx); | ||
524 | }; | ||
525 | |||
506 | /** | 526 | /** |
507 | * struct efx_phy_operations - Efx PHY operations table | 527 | * struct efx_phy_operations - Efx PHY operations table |
508 | * @init: Initialise PHY | 528 | * @init: Initialise PHY |
@@ -511,16 +531,23 @@ enum efx_fc_type { | |||
511 | * @clear_interrupt: Clear down interrupt | 531 | * @clear_interrupt: Clear down interrupt |
512 | * @blink: Blink LEDs | 532 | * @blink: Blink LEDs |
513 | * @check_hw: Check hardware | 533 | * @check_hw: Check hardware |
534 | * @get_settings: Get ethtool settings. Serialised by the mac_lock. | ||
535 | * @set_settings: Set ethtool settings. Serialised by the mac_lock. | ||
514 | * @mmds: MMD presence mask | 536 | * @mmds: MMD presence mask |
515 | * @loopbacks: Supported loopback modes mask | 537 | * @loopbacks: Supported loopback modes mask |
516 | */ | 538 | */ |
517 | struct efx_phy_operations { | 539 | struct efx_phy_operations { |
540 | enum efx_mac_type macs; | ||
518 | int (*init) (struct efx_nic *efx); | 541 | int (*init) (struct efx_nic *efx); |
519 | void (*fini) (struct efx_nic *efx); | 542 | void (*fini) (struct efx_nic *efx); |
520 | void (*reconfigure) (struct efx_nic *efx); | 543 | void (*reconfigure) (struct efx_nic *efx); |
521 | void (*clear_interrupt) (struct efx_nic *efx); | 544 | void (*clear_interrupt) (struct efx_nic *efx); |
522 | int (*check_hw) (struct efx_nic *efx); | 545 | int (*check_hw) (struct efx_nic *efx); |
523 | int (*test) (struct efx_nic *efx); | 546 | int (*test) (struct efx_nic *efx); |
547 | void (*get_settings) (struct efx_nic *efx, | ||
548 | struct ethtool_cmd *ecmd); | ||
549 | int (*set_settings) (struct efx_nic *efx, | ||
550 | struct ethtool_cmd *ecmd); | ||
524 | int mmds; | 551 | int mmds; |
525 | unsigned loopbacks; | 552 | unsigned loopbacks; |
526 | }; | 553 | }; |
@@ -686,6 +713,7 @@ union efx_multicast_hash { | |||
686 | * @stats_lock: Statistics update lock. Serialises statistics fetches | 713 | * @stats_lock: Statistics update lock. Serialises statistics fetches |
687 | * @stats_enabled: Temporarily disable statistics fetches. | 714 | * @stats_enabled: Temporarily disable statistics fetches. |
688 | * Serialised by @stats_lock | 715 | * Serialised by @stats_lock |
716 | * @mac_op: MAC interface | ||
689 | * @mac_address: Permanent MAC address | 717 | * @mac_address: Permanent MAC address |
690 | * @phy_type: PHY type | 718 | * @phy_type: PHY type |
691 | * @phy_lock: PHY access lock | 719 | * @phy_lock: PHY access lock |
@@ -693,6 +721,7 @@ union efx_multicast_hash { | |||
693 | * @phy_data: PHY private data (including PHY-specific stats) | 721 | * @phy_data: PHY private data (including PHY-specific stats) |
694 | * @mii: PHY interface | 722 | * @mii: PHY interface |
695 | * @phy_mode: PHY operating mode. Serialised by @mac_lock. | 723 | * @phy_mode: PHY operating mode. Serialised by @mac_lock. |
724 | * @mac_up: MAC link state | ||
696 | * @link_up: Link status | 725 | * @link_up: Link status |
697 | * @link_fd: Link is full duplex | 726 | * @link_fd: Link is full duplex |
698 | * @link_speed: Link speed (Mbps) | 727 | * @link_speed: Link speed (Mbps) |
@@ -763,6 +792,7 @@ struct efx_nic { | |||
763 | spinlock_t stats_lock; | 792 | spinlock_t stats_lock; |
764 | bool stats_enabled; | 793 | bool stats_enabled; |
765 | 794 | ||
795 | struct efx_mac_operations *mac_op; | ||
766 | unsigned char mac_address[ETH_ALEN]; | 796 | unsigned char mac_address[ETH_ALEN]; |
767 | 797 | ||
768 | enum phy_type phy_type; | 798 | enum phy_type phy_type; |
@@ -772,6 +802,7 @@ struct efx_nic { | |||
772 | struct mii_if_info mii; | 802 | struct mii_if_info mii; |
773 | enum efx_phy_mode phy_mode; | 803 | enum efx_phy_mode phy_mode; |
774 | 804 | ||
805 | bool mac_up; | ||
775 | bool link_up; | 806 | bool link_up; |
776 | bool link_fd; | 807 | bool link_fd; |
777 | unsigned int link_speed; | 808 | unsigned int link_speed; |
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 362956e3fe17..8142e37a518f 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include "selftest.h" | 26 | #include "selftest.h" |
27 | #include "boards.h" | 27 | #include "boards.h" |
28 | #include "workarounds.h" | 28 | #include "workarounds.h" |
29 | #include "mac.h" | ||
30 | #include "spi.h" | 29 | #include "spi.h" |
31 | #include "falcon_io.h" | 30 | #include "falcon_io.h" |
32 | #include "mdio_10g.h" | 31 | #include "mdio_10g.h" |
@@ -105,9 +104,11 @@ static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests) | |||
105 | goto out; | 104 | goto out; |
106 | } | 105 | } |
107 | 106 | ||
108 | rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0); | 107 | if (EFX_IS10G(efx)) { |
109 | if (rc) | 108 | rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0); |
110 | goto out; | 109 | if (rc) |
110 | goto out; | ||
111 | } | ||
111 | 112 | ||
112 | out: | 113 | out: |
113 | mutex_unlock(&efx->mac_lock); | 114 | mutex_unlock(&efx->mac_lock); |
@@ -598,7 +599,7 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd, | |||
598 | do { | 599 | do { |
599 | struct efx_channel *channel = &efx->channel[0]; | 600 | struct efx_channel *channel = &efx->channel[0]; |
600 | 601 | ||
601 | falcon_check_xmac(efx); | 602 | efx->mac_op->check_hw(efx); |
602 | schedule_timeout_uninterruptible(HZ / 10); | 603 | schedule_timeout_uninterruptible(HZ / 10); |
603 | if (channel->work_pending) | 604 | if (channel->work_pending) |
604 | efx_process_channel_now(channel); | 605 | efx_process_channel_now(channel); |
@@ -606,13 +607,12 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd, | |||
606 | flush_workqueue(efx->workqueue); | 607 | flush_workqueue(efx->workqueue); |
607 | rmb(); | 608 | rmb(); |
608 | 609 | ||
609 | /* efx->link_up can be 1 even if the XAUI link is down, | 610 | /* We need both the phy and xaui links to be ok. |
610 | * (bug5762). Usually, it's not worth bothering with the | 611 | * rather than relying on the falcon_xmac irq/poll |
611 | * difference, but for selftests, we need that extra | 612 | * regime, just poll xaui directly */ |
612 | * guarantee that the link is really, really, up. | ||
613 | */ | ||
614 | link_up = efx->link_up; | 613 | link_up = efx->link_up; |
615 | if (!falcon_xaui_link_ok(efx)) | 614 | if (link_up && EFX_IS10G(efx) && |
615 | !falcon_xaui_link_ok(efx)) | ||
616 | link_up = false; | 616 | link_up = false; |
617 | 617 | ||
618 | } while ((++count < 20) && !link_up); | 618 | } while ((++count < 20) && !link_up); |
@@ -721,7 +721,6 @@ int efx_offline_test(struct efx_nic *efx, | |||
721 | if (ecmd_test.autoneg == AUTONEG_ENABLE) { | 721 | if (ecmd_test.autoneg == AUTONEG_ENABLE) { |
722 | ecmd_test.autoneg = AUTONEG_DISABLE; | 722 | ecmd_test.autoneg = AUTONEG_DISABLE; |
723 | ecmd_test.duplex = DUPLEX_FULL; | 723 | ecmd_test.duplex = DUPLEX_FULL; |
724 | ecmd_test.speed = SPEED_10000; | ||
725 | } | 724 | } |
726 | efx->loopback_mode = LOOPBACK_NONE; | 725 | efx->loopback_mode = LOOPBACK_NONE; |
727 | 726 | ||
@@ -732,9 +731,6 @@ int efx_offline_test(struct efx_nic *efx, | |||
732 | return rc; | 731 | return rc; |
733 | } | 732 | } |
734 | 733 | ||
735 | tests->loopback_speed = ecmd_test.speed; | ||
736 | tests->loopback_full_duplex = ecmd_test.duplex; | ||
737 | |||
738 | rc = efx_test_phy(efx, tests); | 734 | rc = efx_test_phy(efx, tests); |
739 | if (rc && !rc2) | 735 | if (rc && !rc2) |
740 | rc2 = rc; | 736 | rc2 = rc; |
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h index fc15df15d766..252f7d717242 100644 --- a/drivers/net/sfc/selftest.h +++ b/drivers/net/sfc/selftest.h | |||
@@ -39,8 +39,6 @@ struct efx_self_tests { | |||
39 | /* offline tests */ | 39 | /* offline tests */ |
40 | int registers; | 40 | int registers; |
41 | int phy; | 41 | int phy; |
42 | int loopback_speed; | ||
43 | int loopback_full_duplex; | ||
44 | struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; | 42 | struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; |
45 | }; | 43 | }; |
46 | 44 | ||
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index aa576c559ec8..af652844baee 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c | |||
@@ -176,7 +176,7 @@ static int sfe4001_check_hw(struct efx_nic *efx) | |||
176 | s32 status; | 176 | s32 status; |
177 | 177 | ||
178 | /* If XAUI link is up then do not monitor */ | 178 | /* If XAUI link is up then do not monitor */ |
179 | if (EFX_WORKAROUND_7884(efx) && falcon_xaui_link_ok(efx)) | 179 | if (EFX_WORKAROUND_7884(efx) && efx->mac_up) |
180 | return 0; | 180 | return 0; |
181 | 181 | ||
182 | /* Check the powered status of the PHY. Lack of power implies that | 182 | /* Check the powered status of the PHY. Lack of power implies that |
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 197b5449ab18..d60353bb40b6 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare 802.3an compliant PHY | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2007 Solarflare Communications Inc. | 3 | * Copyright 2007-2008 Solarflare Communications Inc. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published | 6 | * under the terms of the GNU General Public License version 2 as published |
@@ -15,7 +15,6 @@ | |||
15 | #include "phy.h" | 15 | #include "phy.h" |
16 | #include "falcon_hwdefs.h" | 16 | #include "falcon_hwdefs.h" |
17 | #include "boards.h" | 17 | #include "boards.h" |
18 | #include "mac.h" | ||
19 | 18 | ||
20 | /* We expect these MMDs to be in the package */ | 19 | /* We expect these MMDs to be in the package */ |
21 | /* AN not here as mdio_check_mmds() requires STAT2 support */ | 20 | /* AN not here as mdio_check_mmds() requires STAT2 support */ |
@@ -381,7 +380,7 @@ static int tenxpress_phy_check_hw(struct efx_nic *efx) | |||
381 | link_ok = tenxpress_link_ok(efx, true); | 380 | link_ok = tenxpress_link_ok(efx, true); |
382 | 381 | ||
383 | if (link_ok != efx->link_up) | 382 | if (link_ok != efx->link_up) |
384 | falcon_xmac_sim_phy_event(efx); | 383 | falcon_sim_phy_event(efx); |
385 | 384 | ||
386 | if (phy_data->phy_mode != PHY_MODE_NORMAL) | 385 | if (phy_data->phy_mode != PHY_MODE_NORMAL) |
387 | return 0; | 386 | return 0; |
@@ -453,12 +452,15 @@ static int tenxpress_phy_test(struct efx_nic *efx) | |||
453 | } | 452 | } |
454 | 453 | ||
455 | struct efx_phy_operations falcon_tenxpress_phy_ops = { | 454 | struct efx_phy_operations falcon_tenxpress_phy_ops = { |
455 | .macs = EFX_XMAC, | ||
456 | .init = tenxpress_phy_init, | 456 | .init = tenxpress_phy_init, |
457 | .reconfigure = tenxpress_phy_reconfigure, | 457 | .reconfigure = tenxpress_phy_reconfigure, |
458 | .check_hw = tenxpress_phy_check_hw, | 458 | .check_hw = tenxpress_phy_check_hw, |
459 | .fini = tenxpress_phy_fini, | 459 | .fini = tenxpress_phy_fini, |
460 | .clear_interrupt = tenxpress_phy_clear_interrupt, | 460 | .clear_interrupt = tenxpress_phy_clear_interrupt, |
461 | .test = tenxpress_phy_test, | 461 | .test = tenxpress_phy_test, |
462 | .get_settings = mdio_clause45_get_settings, | ||
463 | .set_settings = mdio_clause45_set_settings, | ||
462 | .mmds = TENXPRESS_REQUIRED_DEVS, | 464 | .mmds = TENXPRESS_REQUIRED_DEVS, |
463 | .loopbacks = TENXPRESS_LOOPBACKS, | 465 | .loopbacks = TENXPRESS_LOOPBACKS, |
464 | }; | 466 | }; |
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index 0413d135e4aa..d4e203ddcf1c 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include "mdio_10g.h" | 17 | #include "mdio_10g.h" |
18 | #include "xenpack.h" | 18 | #include "xenpack.h" |
19 | #include "phy.h" | 19 | #include "phy.h" |
20 | #include "mac.h" | 20 | #include "falcon.h" |
21 | 21 | ||
22 | #define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS | \ | 22 | #define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS | \ |
23 | MDIO_MMDREG_DEVS_PMAPMD | \ | 23 | MDIO_MMDREG_DEVS_PMAPMD | \ |
@@ -125,7 +125,7 @@ static int xfp_phy_check_hw(struct efx_nic *efx) | |||
125 | int link_up = xfp_link_ok(efx); | 125 | int link_up = xfp_link_ok(efx); |
126 | /* Simulate a PHY event if link state has changed */ | 126 | /* Simulate a PHY event if link state has changed */ |
127 | if (link_up != efx->link_up) | 127 | if (link_up != efx->link_up) |
128 | falcon_xmac_sim_phy_event(efx); | 128 | falcon_sim_phy_event(efx); |
129 | 129 | ||
130 | rc = efx->board_info.monitor(efx); | 130 | rc = efx->board_info.monitor(efx); |
131 | if (rc) { | 131 | if (rc) { |
@@ -169,11 +169,14 @@ static void xfp_phy_fini(struct efx_nic *efx) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | struct efx_phy_operations falcon_xfp_phy_ops = { | 171 | struct efx_phy_operations falcon_xfp_phy_ops = { |
172 | .macs = EFX_XMAC, | ||
172 | .init = xfp_phy_init, | 173 | .init = xfp_phy_init, |
173 | .reconfigure = xfp_phy_reconfigure, | 174 | .reconfigure = xfp_phy_reconfigure, |
174 | .check_hw = xfp_phy_check_hw, | 175 | .check_hw = xfp_phy_check_hw, |
175 | .fini = xfp_phy_fini, | 176 | .fini = xfp_phy_fini, |
176 | .clear_interrupt = xfp_phy_clear_interrupt, | 177 | .clear_interrupt = xfp_phy_clear_interrupt, |
178 | .get_settings = mdio_clause45_get_settings, | ||
179 | .set_settings = mdio_clause45_set_settings, | ||
177 | .mmds = XFP_REQUIRED_DEVS, | 180 | .mmds = XFP_REQUIRED_DEVS, |
178 | .loopbacks = XFP_LOOPBACKS, | 181 | .loopbacks = XFP_LOOPBACKS, |
179 | }; | 182 | }; |