diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2008-12-13 00:50:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-13 00:58:17 -0500 |
commit | 177dfcd80f28f8fbc3e22c2d8b24d21cb86f1d97 (patch) | |
tree | a6e5e9949f388d48ac20c4efbb2811762ac5f9d4 /drivers/net/sfc/falcon.c | |
parent | 356eebb2b3af24cc701823f1e025f04eef333239 (diff) |
sfc: Add support for sub-10G speeds
The SFC4000 has a separate MAC for use at sub-10G speeds. Introduce
an efx_mac_operations structure with implementations for the two MACs.
Switch between the MACs as necessary.
PHY settings are independent of the MAC, so add get_settings() and
set_settings() to efx_phy_operations. Also add macs field to indicate
which MACs the PHY is connected to.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/falcon.c')
-rw-r--r-- | drivers/net/sfc/falcon.c | 179 |
1 files changed, 141 insertions, 38 deletions
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 | ||