diff options
Diffstat (limited to 'drivers/net/sfc/falcon.c')
-rw-r--r-- | drivers/net/sfc/falcon.c | 137 |
1 files changed, 37 insertions, 100 deletions
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 466a8abb0053..c049364aec46 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -2063,26 +2063,6 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) | |||
2063 | ************************************************************************** | 2063 | ************************************************************************** |
2064 | */ | 2064 | */ |
2065 | 2065 | ||
2066 | /* Use the top bit of the MII PHY id to indicate the PHY type | ||
2067 | * (1G/10G), with the remaining bits as the actual PHY id. | ||
2068 | * | ||
2069 | * This allows us to avoid leaking information from the mii_if_info | ||
2070 | * structure into other data structures. | ||
2071 | */ | ||
2072 | #define FALCON_PHY_ID_ID_WIDTH EFX_WIDTH(MD_PRT_DEV_ADR) | ||
2073 | #define FALCON_PHY_ID_ID_MASK ((1 << FALCON_PHY_ID_ID_WIDTH) - 1) | ||
2074 | #define FALCON_PHY_ID_WIDTH (FALCON_PHY_ID_ID_WIDTH + 1) | ||
2075 | #define FALCON_PHY_ID_MASK ((1 << FALCON_PHY_ID_WIDTH) - 1) | ||
2076 | #define FALCON_PHY_ID_10G (1 << (FALCON_PHY_ID_WIDTH - 1)) | ||
2077 | |||
2078 | |||
2079 | /* Packing the clause 45 port and device fields into a single value */ | ||
2080 | #define MD_PRT_ADR_COMP_LBN (MD_PRT_ADR_LBN - MD_DEV_ADR_LBN) | ||
2081 | #define MD_PRT_ADR_COMP_WIDTH MD_PRT_ADR_WIDTH | ||
2082 | #define MD_DEV_ADR_COMP_LBN 0 | ||
2083 | #define MD_DEV_ADR_COMP_WIDTH MD_DEV_ADR_WIDTH | ||
2084 | |||
2085 | |||
2086 | /* Wait for GMII access to complete */ | 2066 | /* Wait for GMII access to complete */ |
2087 | static int falcon_gmii_wait(struct efx_nic *efx) | 2067 | static int falcon_gmii_wait(struct efx_nic *efx) |
2088 | { | 2068 | { |
@@ -2108,49 +2088,29 @@ static int falcon_gmii_wait(struct efx_nic *efx) | |||
2108 | return -ETIMEDOUT; | 2088 | return -ETIMEDOUT; |
2109 | } | 2089 | } |
2110 | 2090 | ||
2111 | /* Writes a GMII register of a PHY connected to Falcon using MDIO. */ | 2091 | /* Write an MDIO register of a PHY connected to Falcon. */ |
2112 | static void falcon_mdio_write(struct net_device *net_dev, int phy_id, | 2092 | static int falcon_mdio_write(struct net_device *net_dev, |
2113 | int addr, int value) | 2093 | int prtad, int devad, u16 addr, u16 value) |
2114 | { | 2094 | { |
2115 | struct efx_nic *efx = netdev_priv(net_dev); | 2095 | struct efx_nic *efx = netdev_priv(net_dev); |
2116 | unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK; | ||
2117 | efx_oword_t reg; | 2096 | efx_oword_t reg; |
2097 | int rc; | ||
2118 | 2098 | ||
2119 | /* The 'generic' prt/dev packing in mdio_10g.h is conveniently | 2099 | EFX_REGDUMP(efx, "writing MDIO %d register %d.%d with 0x%04x\n", |
2120 | * chosen so that the only current user, Falcon, can take the | 2100 | prtad, devad, addr, value); |
2121 | * packed value and use them directly. | ||
2122 | * Fail to build if this assumption is broken. | ||
2123 | */ | ||
2124 | BUILD_BUG_ON(FALCON_PHY_ID_10G != MDIO45_XPRT_ID_IS10G); | ||
2125 | BUILD_BUG_ON(FALCON_PHY_ID_ID_WIDTH != MDIO45_PRT_DEV_WIDTH); | ||
2126 | BUILD_BUG_ON(MD_PRT_ADR_COMP_LBN != MDIO45_PRT_ID_COMP_LBN); | ||
2127 | BUILD_BUG_ON(MD_DEV_ADR_COMP_LBN != MDIO45_DEV_ID_COMP_LBN); | ||
2128 | |||
2129 | if (phy_id2 == PHY_ADDR_INVALID) | ||
2130 | return; | ||
2131 | |||
2132 | /* See falcon_mdio_read for an explanation. */ | ||
2133 | if (!(phy_id & FALCON_PHY_ID_10G)) { | ||
2134 | int mmd = ffs(efx->phy_op->mmds) - 1; | ||
2135 | EFX_TRACE(efx, "Fixing erroneous clause22 write\n"); | ||
2136 | phy_id2 = mdio_clause45_pack(phy_id2, mmd) | ||
2137 | & FALCON_PHY_ID_ID_MASK; | ||
2138 | } | ||
2139 | |||
2140 | EFX_REGDUMP(efx, "writing GMII %d register %02x with %04x\n", phy_id, | ||
2141 | addr, value); | ||
2142 | 2101 | ||
2143 | spin_lock_bh(&efx->phy_lock); | 2102 | spin_lock_bh(&efx->phy_lock); |
2144 | 2103 | ||
2145 | /* Check MII not currently being accessed */ | 2104 | /* Check MDIO not currently being accessed */ |
2146 | if (falcon_gmii_wait(efx) != 0) | 2105 | rc = falcon_gmii_wait(efx); |
2106 | if (rc) | ||
2147 | goto out; | 2107 | goto out; |
2148 | 2108 | ||
2149 | /* Write the address/ID register */ | 2109 | /* Write the address/ID register */ |
2150 | EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); | 2110 | EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); |
2151 | falcon_write(efx, ®, MD_PHY_ADR_REG_KER); | 2111 | falcon_write(efx, ®, MD_PHY_ADR_REG_KER); |
2152 | 2112 | ||
2153 | EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_id2); | 2113 | EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad); |
2154 | falcon_write(efx, ®, MD_ID_REG_KER); | 2114 | falcon_write(efx, ®, MD_ID_REG_KER); |
2155 | 2115 | ||
2156 | /* Write data */ | 2116 | /* Write data */ |
@@ -2163,7 +2123,8 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, | |||
2163 | falcon_write(efx, ®, MD_CS_REG_KER); | 2123 | falcon_write(efx, ®, MD_CS_REG_KER); |
2164 | 2124 | ||
2165 | /* Wait for data to be written */ | 2125 | /* Wait for data to be written */ |
2166 | if (falcon_gmii_wait(efx) != 0) { | 2126 | rc = falcon_gmii_wait(efx); |
2127 | if (rc) { | ||
2167 | /* Abort the write operation */ | 2128 | /* Abort the write operation */ |
2168 | EFX_POPULATE_OWORD_2(reg, | 2129 | EFX_POPULATE_OWORD_2(reg, |
2169 | MD_WRC, 0, | 2130 | MD_WRC, 0, |
@@ -2174,45 +2135,28 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, | |||
2174 | 2135 | ||
2175 | out: | 2136 | out: |
2176 | spin_unlock_bh(&efx->phy_lock); | 2137 | spin_unlock_bh(&efx->phy_lock); |
2138 | return rc; | ||
2177 | } | 2139 | } |
2178 | 2140 | ||
2179 | /* Reads a GMII register from a PHY connected to Falcon. If no value | 2141 | /* Read an MDIO register of a PHY connected to Falcon. */ |
2180 | * could be read, -1 will be returned. */ | 2142 | static int falcon_mdio_read(struct net_device *net_dev, |
2181 | static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) | 2143 | int prtad, int devad, u16 addr) |
2182 | { | 2144 | { |
2183 | struct efx_nic *efx = netdev_priv(net_dev); | 2145 | struct efx_nic *efx = netdev_priv(net_dev); |
2184 | unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK; | ||
2185 | efx_oword_t reg; | 2146 | efx_oword_t reg; |
2186 | int value = -1; | 2147 | int rc; |
2187 | |||
2188 | if (phy_addr == PHY_ADDR_INVALID) | ||
2189 | return -1; | ||
2190 | |||
2191 | /* Our PHY code knows whether it needs to talk clause 22(1G) or 45(10G) | ||
2192 | * but the generic Linux code does not make any distinction or have | ||
2193 | * any state for this. | ||
2194 | * We spot the case where someone tried to talk 22 to a 45 PHY and | ||
2195 | * redirect the request to the lowest numbered MMD as a clause45 | ||
2196 | * request. This is enough to allow simple queries like id and link | ||
2197 | * state to succeed. TODO: We may need to do more in future. | ||
2198 | */ | ||
2199 | if (!(phy_id & FALCON_PHY_ID_10G)) { | ||
2200 | int mmd = ffs(efx->phy_op->mmds) - 1; | ||
2201 | EFX_TRACE(efx, "Fixing erroneous clause22 read\n"); | ||
2202 | phy_addr = mdio_clause45_pack(phy_addr, mmd) | ||
2203 | & FALCON_PHY_ID_ID_MASK; | ||
2204 | } | ||
2205 | 2148 | ||
2206 | spin_lock_bh(&efx->phy_lock); | 2149 | spin_lock_bh(&efx->phy_lock); |
2207 | 2150 | ||
2208 | /* Check MII not currently being accessed */ | 2151 | /* Check MDIO not currently being accessed */ |
2209 | if (falcon_gmii_wait(efx) != 0) | 2152 | rc = falcon_gmii_wait(efx); |
2153 | if (rc) | ||
2210 | goto out; | 2154 | goto out; |
2211 | 2155 | ||
2212 | EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); | 2156 | EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); |
2213 | falcon_write(efx, ®, MD_PHY_ADR_REG_KER); | 2157 | falcon_write(efx, ®, MD_PHY_ADR_REG_KER); |
2214 | 2158 | ||
2215 | EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_addr); | 2159 | EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad); |
2216 | falcon_write(efx, ®, MD_ID_REG_KER); | 2160 | falcon_write(efx, ®, MD_ID_REG_KER); |
2217 | 2161 | ||
2218 | /* Request data to be read */ | 2162 | /* Request data to be read */ |
@@ -2220,12 +2164,12 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) | |||
2220 | falcon_write(efx, ®, MD_CS_REG_KER); | 2164 | falcon_write(efx, ®, MD_CS_REG_KER); |
2221 | 2165 | ||
2222 | /* Wait for data to become available */ | 2166 | /* Wait for data to become available */ |
2223 | value = falcon_gmii_wait(efx); | 2167 | rc = falcon_gmii_wait(efx); |
2224 | if (value == 0) { | 2168 | if (rc == 0) { |
2225 | falcon_read(efx, ®, MD_RXD_REG_KER); | 2169 | falcon_read(efx, ®, MD_RXD_REG_KER); |
2226 | value = EFX_OWORD_FIELD(reg, MD_RXD); | 2170 | rc = EFX_OWORD_FIELD(reg, MD_RXD); |
2227 | EFX_REGDUMP(efx, "read from GMII %d register %02x, got %04x\n", | 2171 | EFX_REGDUMP(efx, "read from MDIO %d register %d.%d, got %04x\n", |
2228 | phy_id, addr, value); | 2172 | prtad, devad, addr, rc); |
2229 | } else { | 2173 | } else { |
2230 | /* Abort the read operation */ | 2174 | /* Abort the read operation */ |
2231 | EFX_POPULATE_OWORD_2(reg, | 2175 | EFX_POPULATE_OWORD_2(reg, |
@@ -2233,22 +2177,13 @@ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) | |||
2233 | MD_GC, 1); | 2177 | MD_GC, 1); |
2234 | falcon_write(efx, ®, MD_CS_REG_KER); | 2178 | falcon_write(efx, ®, MD_CS_REG_KER); |
2235 | 2179 | ||
2236 | EFX_LOG(efx, "read from GMII 0x%x register %02x, got " | 2180 | EFX_LOG(efx, "read from MDIO %d register %d.%d, got error %d\n", |
2237 | "error %d\n", phy_id, addr, value); | 2181 | prtad, devad, addr, rc); |
2238 | } | 2182 | } |
2239 | 2183 | ||
2240 | out: | 2184 | out: |
2241 | spin_unlock_bh(&efx->phy_lock); | 2185 | spin_unlock_bh(&efx->phy_lock); |
2242 | 2186 | return rc; | |
2243 | return value; | ||
2244 | } | ||
2245 | |||
2246 | static void falcon_init_mdio(struct mii_if_info *gmii) | ||
2247 | { | ||
2248 | gmii->mdio_read = falcon_mdio_read; | ||
2249 | gmii->mdio_write = falcon_mdio_write; | ||
2250 | gmii->phy_id_mask = FALCON_PHY_ID_MASK; | ||
2251 | gmii->reg_num_mask = ((1 << EFX_WIDTH(MD_PHY_ADR)) - 1); | ||
2252 | } | 2187 | } |
2253 | 2188 | ||
2254 | static int falcon_probe_phy(struct efx_nic *efx) | 2189 | static int falcon_probe_phy(struct efx_nic *efx) |
@@ -2342,9 +2277,11 @@ int falcon_probe_port(struct efx_nic *efx) | |||
2342 | if (rc) | 2277 | if (rc) |
2343 | return rc; | 2278 | return rc; |
2344 | 2279 | ||
2345 | /* Set up GMII structure for PHY */ | 2280 | /* Set up MDIO structure for PHY */ |
2346 | efx->mii.supports_gmii = true; | 2281 | efx->mdio.mmds = efx->phy_op->mmds; |
2347 | falcon_init_mdio(&efx->mii); | 2282 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; |
2283 | efx->mdio.mdio_read = falcon_mdio_read; | ||
2284 | efx->mdio.mdio_write = falcon_mdio_write; | ||
2348 | 2285 | ||
2349 | /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */ | 2286 | /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */ |
2350 | if (falcon_rev(efx) >= FALCON_REV_B0) | 2287 | if (falcon_rev(efx) >= FALCON_REV_B0) |
@@ -2761,7 +2698,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) | |||
2761 | if (rc == -EINVAL) { | 2698 | if (rc == -EINVAL) { |
2762 | EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n"); | 2699 | EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n"); |
2763 | efx->phy_type = PHY_TYPE_NONE; | 2700 | efx->phy_type = PHY_TYPE_NONE; |
2764 | efx->mii.phy_id = PHY_ADDR_INVALID; | 2701 | efx->mdio.prtad = MDIO_PRTAD_NONE; |
2765 | board_rev = 0; | 2702 | board_rev = 0; |
2766 | rc = 0; | 2703 | rc = 0; |
2767 | } else if (rc) { | 2704 | } else if (rc) { |
@@ -2771,7 +2708,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) | |||
2771 | struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3; | 2708 | struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3; |
2772 | 2709 | ||
2773 | efx->phy_type = v2->port0_phy_type; | 2710 | efx->phy_type = v2->port0_phy_type; |
2774 | efx->mii.phy_id = v2->port0_phy_addr; | 2711 | efx->mdio.prtad = v2->port0_phy_addr; |
2775 | board_rev = le16_to_cpu(v2->board_revision); | 2712 | board_rev = le16_to_cpu(v2->board_revision); |
2776 | 2713 | ||
2777 | if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { | 2714 | if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { |
@@ -2793,7 +2730,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) | |||
2793 | /* Read the MAC addresses */ | 2730 | /* Read the MAC addresses */ |
2794 | memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN); | 2731 | memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN); |
2795 | 2732 | ||
2796 | EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id); | 2733 | EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad); |
2797 | 2734 | ||
2798 | efx_set_board_info(efx, board_rev); | 2735 | efx_set_board_info(efx, board_rev); |
2799 | 2736 | ||