aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/falcon.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-11-28 22:42:41 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-29 19:46:28 -0500
commitd3245b28ef2a45ec4e115062a38100bd06229289 (patch)
tree036133fdf01a20f36086d5eb8606728859c056de /drivers/net/sfc/falcon.c
parentef2b90ee4dba7a3d9001f1f0003b860b39a4aaae (diff)
sfc: Refactor link configuration
Refactor PHY, MAC and NIC configuration operations so that the existing link configuration can be re-pushed with: efx->phy_op->reconfigure(efx); efx->mac_op->reconfigure(efx); and a new configuration with: efx->nic_op->reconfigure_port(efx); (plus locking and error-checking). We have not held the link settings in software (aside from flow control), and have relied on asking the hardware what they are. This is a problem because in some cases the hardware may no longer be in a state to tell us. In particular, if an entire multi-port board is reset through one port, the driver bindings to other ports have no chance to save settings before recovering. We only actually need to keep track of the autonegotiation settings, so add an ethtool advertising mask to struct efx_nic, initialise it in PHY init and update it as necessary. Remove now-unneeded uses of efx_phy_op::{get,set}_settings() and struct ethtool_cmd. Much of this was done by Steve Hodgson <shodgson@solarflare.com>. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/falcon.c')
-rw-r--r--drivers/net/sfc/falcon.c98
1 files changed, 63 insertions, 35 deletions
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index f6d10213d0b7..3466616c01c0 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1193,6 +1193,8 @@ static void falcon_poll_flush_events(struct efx_nic *efx)
1193 channel->eventq_read_ptr = read_ptr; 1193 channel->eventq_read_ptr = read_ptr;
1194} 1194}
1195 1195
1196static void falcon_deconfigure_mac_wrapper(struct efx_nic *efx);
1197
1196static void falcon_prepare_flush(struct efx_nic *efx) 1198static void falcon_prepare_flush(struct efx_nic *efx)
1197{ 1199{
1198 falcon_deconfigure_mac_wrapper(efx); 1200 falcon_deconfigure_mac_wrapper(efx);
@@ -1836,9 +1838,10 @@ static void falcon_push_multicast_hash(struct efx_nic *efx)
1836 efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1); 1838 efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1);
1837} 1839}
1838 1840
1839static int falcon_reset_macs(struct efx_nic *efx) 1841static void falcon_reset_macs(struct efx_nic *efx)
1840{ 1842{
1841 efx_oword_t reg; 1843 struct falcon_nic_data *nic_data = efx->nic_data;
1844 efx_oword_t reg, mac_ctrl;
1842 int count; 1845 int count;
1843 1846
1844 if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) { 1847 if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) {
@@ -1853,7 +1856,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
1853 EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0); 1856 EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0);
1854 efx_writeo(efx, &reg, FR_AB_GM_CFG1); 1857 efx_writeo(efx, &reg, FR_AB_GM_CFG1);
1855 udelay(1000); 1858 udelay(1000);
1856 return 0; 1859 return;
1857 } else { 1860 } else {
1858 EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1); 1861 EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
1859 efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG); 1862 efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
@@ -1862,22 +1865,20 @@ static int falcon_reset_macs(struct efx_nic *efx)
1862 efx_reado(efx, &reg, FR_AB_XM_GLB_CFG); 1865 efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
1863 if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) == 1866 if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
1864 0) 1867 0)
1865 return 0; 1868 return;
1866 udelay(10); 1869 udelay(10);
1867 } 1870 }
1868 1871
1869 EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); 1872 EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
1870 return -ETIMEDOUT;
1871 } 1873 }
1872 } 1874 }
1873 1875
1874 /* MAC stats will fail whilst the TX fifo is draining. Serialise 1876 /* Mac stats will fail whist the TX fifo is draining */
1875 * the drain sequence with the statistics fetch */ 1877 WARN_ON(nic_data->stats_disable_count == 0);
1876 falcon_stop_nic_stats(efx);
1877 1878
1878 efx_reado(efx, &reg, FR_AB_MAC_CTRL); 1879 efx_reado(efx, &mac_ctrl, FR_AB_MAC_CTRL);
1879 EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, 1); 1880 EFX_SET_OWORD_FIELD(mac_ctrl, FRF_BB_TXFIFO_DRAIN_EN, 1);
1880 efx_writeo(efx, &reg, FR_AB_MAC_CTRL); 1881 efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
1881 1882
1882 efx_reado(efx, &reg, FR_AB_GLB_CTL); 1883 efx_reado(efx, &reg, FR_AB_GLB_CTL);
1883 EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_XGTX, 1); 1884 EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_XGTX, 1);
@@ -1903,14 +1904,9 @@ static int falcon_reset_macs(struct efx_nic *efx)
1903 udelay(10); 1904 udelay(10);
1904 } 1905 }
1905 1906
1906 /* If we've reset the EM block and the link is up, then 1907 /* Ensure the correct MAC is selected before statistics
1907 * we'll have to kick the XAUI link so the PHY can recover */ 1908 * are re-enabled by the caller */
1908 if (efx->link_state.up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx)) 1909 efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
1909 falcon_reset_xaui(efx);
1910
1911 falcon_start_nic_stats(efx);
1912
1913 return 0;
1914} 1910}
1915 1911
1916void falcon_drain_tx_fifo(struct efx_nic *efx) 1912void falcon_drain_tx_fifo(struct efx_nic *efx)
@@ -1929,7 +1925,7 @@ void falcon_drain_tx_fifo(struct efx_nic *efx)
1929 falcon_reset_macs(efx); 1925 falcon_reset_macs(efx);
1930} 1926}
1931 1927
1932void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) 1928static void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
1933{ 1929{
1934 efx_oword_t reg; 1930 efx_oword_t reg;
1935 1931
@@ -1941,8 +1937,8 @@ void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
1941 EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 0); 1937 EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 0);
1942 efx_writeo(efx, &reg, FR_AZ_RX_CFG); 1938 efx_writeo(efx, &reg, FR_AZ_RX_CFG);
1943 1939
1944 if (!efx->link_state.up) 1940 /* Isolate TX -> MAC */
1945 falcon_drain_tx_fifo(efx); 1941 falcon_drain_tx_fifo(efx);
1946} 1942}
1947 1943
1948void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) 1944void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
@@ -2044,6 +2040,8 @@ static void falcon_stats_timer_func(unsigned long context)
2044 spin_unlock(&efx->stats_lock); 2040 spin_unlock(&efx->stats_lock);
2045} 2041}
2046 2042
2043static void falcon_switch_mac(struct efx_nic *efx);
2044
2047static bool falcon_loopback_link_poll(struct efx_nic *efx) 2045static bool falcon_loopback_link_poll(struct efx_nic *efx)
2048{ 2046{
2049 struct efx_link_state old_state = efx->link_state; 2047 struct efx_link_state old_state = efx->link_state;
@@ -2063,6 +2061,38 @@ static bool falcon_loopback_link_poll(struct efx_nic *efx)
2063 return !efx_link_state_equal(&efx->link_state, &old_state); 2061 return !efx_link_state_equal(&efx->link_state, &old_state);
2064} 2062}
2065 2063
2064static int falcon_reconfigure_port(struct efx_nic *efx)
2065{
2066 int rc;
2067
2068 WARN_ON(efx_nic_rev(efx) > EFX_REV_FALCON_B0);
2069
2070 /* Poll the PHY link state *before* reconfiguring it. This means we
2071 * will pick up the correct speed (in loopback) to select the correct
2072 * MAC.
2073 */
2074 if (LOOPBACK_INTERNAL(efx))
2075 falcon_loopback_link_poll(efx);
2076 else
2077 efx->phy_op->poll(efx);
2078
2079 falcon_stop_nic_stats(efx);
2080 falcon_deconfigure_mac_wrapper(efx);
2081
2082 falcon_switch_mac(efx);
2083
2084 efx->phy_op->reconfigure(efx);
2085 rc = efx->mac_op->reconfigure(efx);
2086 BUG_ON(rc);
2087
2088 falcon_start_nic_stats(efx);
2089
2090 /* Synchronise efx->link_state with the kernel */
2091 efx_link_status_changed(efx);
2092
2093 return 0;
2094}
2095
2066/************************************************************************** 2096/**************************************************************************
2067 * 2097 *
2068 * PHY access via GMII 2098 * PHY access via GMII
@@ -2215,17 +2245,15 @@ static void falcon_clock_mac(struct efx_nic *efx)
2215 } 2245 }
2216} 2246}
2217 2247
2218int falcon_switch_mac(struct efx_nic *efx) 2248static void falcon_switch_mac(struct efx_nic *efx)
2219{ 2249{
2220 struct efx_mac_operations *old_mac_op = efx->mac_op; 2250 struct efx_mac_operations *old_mac_op = efx->mac_op;
2221 struct falcon_nic_data *nic_data = efx->nic_data; 2251 struct falcon_nic_data *nic_data = efx->nic_data;
2222 unsigned int stats_done_offset; 2252 unsigned int stats_done_offset;
2223 int rc = 0;
2224
2225 /* Don't try to fetch MAC stats while we're switching MACs */
2226 falcon_stop_nic_stats(efx);
2227 2253
2228 WARN_ON(!mutex_is_locked(&efx->mac_lock)); 2254 WARN_ON(!mutex_is_locked(&efx->mac_lock));
2255 WARN_ON(nic_data->stats_disable_count == 0);
2256
2229 efx->mac_op = (EFX_IS10G(efx) ? 2257 efx->mac_op = (EFX_IS10G(efx) ?
2230 &falcon_xmac_operations : &falcon_gmac_operations); 2258 &falcon_xmac_operations : &falcon_gmac_operations);
2231 2259
@@ -2236,18 +2264,14 @@ int falcon_switch_mac(struct efx_nic *efx)
2236 nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset; 2264 nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset;
2237 2265
2238 if (old_mac_op == efx->mac_op) 2266 if (old_mac_op == efx->mac_op)
2239 goto out; 2267 return;
2240 2268
2241 falcon_clock_mac(efx); 2269 falcon_clock_mac(efx);
2242 2270
2243 EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); 2271 EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
2244 /* Not all macs support a mac-level link state */ 2272 /* Not all macs support a mac-level link state */
2245 efx->xmac_poll_required = false; 2273 efx->xmac_poll_required = false;
2246 2274 falcon_reset_macs(efx);
2247 rc = falcon_reset_macs(efx);
2248out:
2249 falcon_start_nic_stats(efx);
2250 return rc;
2251} 2275}
2252 2276
2253/* This call is responsible for hooking in the MAC and PHY operations */ 2277/* This call is responsible for hooking in the MAC and PHY operations */
@@ -2597,7 +2621,8 @@ static void falcon_monitor(struct efx_nic *efx)
2597 EFX_ERR(efx, "Board sensor %s; shutting down PHY\n", 2621 EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
2598 (rc == -ERANGE) ? "reported fault" : "failed"); 2622 (rc == -ERANGE) ? "reported fault" : "failed");
2599 efx->phy_mode |= PHY_MODE_LOW_POWER; 2623 efx->phy_mode |= PHY_MODE_LOW_POWER;
2600 __efx_reconfigure_port(efx); 2624 rc = __efx_reconfigure_port(efx);
2625 WARN_ON(rc);
2601 } 2626 }
2602 2627
2603 if (LOOPBACK_INTERNAL(efx)) 2628 if (LOOPBACK_INTERNAL(efx))
@@ -2610,7 +2635,8 @@ static void falcon_monitor(struct efx_nic *efx)
2610 falcon_deconfigure_mac_wrapper(efx); 2635 falcon_deconfigure_mac_wrapper(efx);
2611 2636
2612 falcon_switch_mac(efx); 2637 falcon_switch_mac(efx);
2613 efx->mac_op->reconfigure(efx); 2638 rc = efx->mac_op->reconfigure(efx);
2639 BUG_ON(rc);
2614 2640
2615 falcon_start_nic_stats(efx); 2641 falcon_start_nic_stats(efx);
2616 2642
@@ -3239,6 +3265,7 @@ struct efx_nic_type falcon_a1_nic_type = {
3239 .stop_stats = falcon_stop_nic_stats, 3265 .stop_stats = falcon_stop_nic_stats,
3240 .push_irq_moderation = falcon_push_irq_moderation, 3266 .push_irq_moderation = falcon_push_irq_moderation,
3241 .push_multicast_hash = falcon_push_multicast_hash, 3267 .push_multicast_hash = falcon_push_multicast_hash,
3268 .reconfigure_port = falcon_reconfigure_port,
3242 .default_mac_ops = &falcon_xmac_operations, 3269 .default_mac_ops = &falcon_xmac_operations,
3243 3270
3244 .revision = EFX_REV_FALCON_A1, 3271 .revision = EFX_REV_FALCON_A1,
@@ -3271,6 +3298,7 @@ struct efx_nic_type falcon_b0_nic_type = {
3271 .stop_stats = falcon_stop_nic_stats, 3298 .stop_stats = falcon_stop_nic_stats,
3272 .push_irq_moderation = falcon_push_irq_moderation, 3299 .push_irq_moderation = falcon_push_irq_moderation,
3273 .push_multicast_hash = falcon_push_multicast_hash, 3300 .push_multicast_hash = falcon_push_multicast_hash,
3301 .reconfigure_port = falcon_reconfigure_port,
3274 .default_mac_ops = &falcon_xmac_operations, 3302 .default_mac_ops = &falcon_xmac_operations,
3275 3303
3276 .revision = EFX_REV_FALCON_B0, 3304 .revision = EFX_REV_FALCON_B0,