diff options
| -rw-r--r-- | drivers/net/sfc/mdio_10g.c | 108 |
1 files changed, 39 insertions, 69 deletions
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 25fb20adf4b7..231e580acc9a 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c | |||
| @@ -248,7 +248,7 @@ void efx_mdio_set_mmds_lpower(struct efx_nic *efx, | |||
| 248 | int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 248 | int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) |
| 249 | { | 249 | { |
| 250 | struct ethtool_cmd prev; | 250 | struct ethtool_cmd prev; |
| 251 | u32 required; | 251 | bool xnp; |
| 252 | int reg; | 252 | int reg; |
| 253 | 253 | ||
| 254 | efx->phy_op->get_settings(efx, &prev); | 254 | efx->phy_op->get_settings(efx, &prev); |
| @@ -265,76 +265,46 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | |||
| 265 | return -EINVAL; | 265 | return -EINVAL; |
| 266 | 266 | ||
| 267 | /* Check that PHY supports these settings */ | 267 | /* Check that PHY supports these settings */ |
| 268 | if (ecmd->autoneg) { | 268 | if (!ecmd->autoneg || |
| 269 | required = SUPPORTED_Autoneg; | 269 | (ecmd->advertising | SUPPORTED_Autoneg) & ~prev.supported) |
| 270 | } else if (ecmd->duplex) { | ||
| 271 | switch (ecmd->speed) { | ||
| 272 | case SPEED_10: required = SUPPORTED_10baseT_Full; break; | ||
| 273 | case SPEED_100: required = SUPPORTED_100baseT_Full; break; | ||
| 274 | default: return -EINVAL; | ||
| 275 | } | ||
| 276 | } else { | ||
| 277 | switch (ecmd->speed) { | ||
| 278 | case SPEED_10: required = SUPPORTED_10baseT_Half; break; | ||
| 279 | case SPEED_100: required = SUPPORTED_100baseT_Half; break; | ||
| 280 | default: return -EINVAL; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | required |= ecmd->advertising; | ||
| 284 | if (required & ~prev.supported) | ||
| 285 | return -EINVAL; | 270 | return -EINVAL; |
| 286 | 271 | ||
| 287 | if (ecmd->autoneg) { | 272 | xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full |
| 288 | bool xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full | 273 | || EFX_WORKAROUND_13204(efx)); |
| 289 | || EFX_WORKAROUND_13204(efx)); | 274 | |
| 290 | 275 | /* Set up the base page */ | |
| 291 | /* Set up the base page */ | 276 | reg = ADVERTISE_CSMA; |
| 292 | reg = ADVERTISE_CSMA; | 277 | if (ecmd->advertising & ADVERTISED_10baseT_Half) |
| 293 | if (ecmd->advertising & ADVERTISED_10baseT_Half) | 278 | reg |= ADVERTISE_10HALF; |
| 294 | reg |= ADVERTISE_10HALF; | 279 | if (ecmd->advertising & ADVERTISED_10baseT_Full) |
| 295 | if (ecmd->advertising & ADVERTISED_10baseT_Full) | 280 | reg |= ADVERTISE_10FULL; |
| 296 | reg |= ADVERTISE_10FULL; | 281 | if (ecmd->advertising & ADVERTISED_100baseT_Half) |
| 297 | if (ecmd->advertising & ADVERTISED_100baseT_Half) | 282 | reg |= ADVERTISE_100HALF; |
| 298 | reg |= ADVERTISE_100HALF; | 283 | if (ecmd->advertising & ADVERTISED_100baseT_Full) |
| 299 | if (ecmd->advertising & ADVERTISED_100baseT_Full) | 284 | reg |= ADVERTISE_100FULL; |
| 300 | reg |= ADVERTISE_100FULL; | 285 | if (xnp) |
| 301 | if (xnp) | 286 | reg |= ADVERTISE_RESV; |
| 302 | reg |= ADVERTISE_RESV; | 287 | else if (ecmd->advertising & (ADVERTISED_1000baseT_Half | |
| 303 | else if (ecmd->advertising & (ADVERTISED_1000baseT_Half | | 288 | ADVERTISED_1000baseT_Full)) |
| 304 | ADVERTISED_1000baseT_Full)) | 289 | reg |= ADVERTISE_NPAGE; |
| 305 | reg |= ADVERTISE_NPAGE; | 290 | reg |= mii_advertise_flowctrl(efx->wanted_fc); |
| 306 | reg |= mii_advertise_flowctrl(efx->wanted_fc); | 291 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); |
| 307 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); | 292 | |
| 308 | 293 | /* Set up the (extended) next page if necessary */ | |
| 309 | /* Set up the (extended) next page if necessary */ | 294 | if (efx->phy_op->set_npage_adv) |
| 310 | if (efx->phy_op->set_npage_adv) | 295 | efx->phy_op->set_npage_adv(efx, ecmd->advertising); |
| 311 | efx->phy_op->set_npage_adv(efx, ecmd->advertising); | 296 | |
| 312 | 297 | /* Enable and restart AN */ | |
| 313 | /* Enable and restart AN */ | 298 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); |
| 314 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); | 299 | reg |= MDIO_AN_CTRL1_ENABLE; |
| 315 | reg |= MDIO_AN_CTRL1_ENABLE; | 300 | if (!(EFX_WORKAROUND_15195(efx) && |
| 316 | if (!(EFX_WORKAROUND_15195(efx) && | 301 | LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) |
| 317 | LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) | 302 | reg |= MDIO_AN_CTRL1_RESTART; |
| 318 | reg |= MDIO_AN_CTRL1_RESTART; | 303 | if (xnp) |
| 319 | if (xnp) | 304 | reg |= MDIO_AN_CTRL1_XNP; |
| 320 | reg |= MDIO_AN_CTRL1_XNP; | 305 | else |
| 321 | else | 306 | reg &= ~MDIO_AN_CTRL1_XNP; |
| 322 | reg &= ~MDIO_AN_CTRL1_XNP; | 307 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); |
| 323 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); | ||
| 324 | } else { | ||
| 325 | /* Disable AN */ | ||
| 326 | efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_CTRL1, | ||
| 327 | MDIO_AN_CTRL1_ENABLE, false); | ||
| 328 | |||
| 329 | /* Set the basic control bits */ | ||
| 330 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1); | ||
| 331 | reg &= ~(MDIO_CTRL1_SPEEDSEL | MDIO_CTRL1_FULLDPLX); | ||
| 332 | if (ecmd->speed == SPEED_100) | ||
| 333 | reg |= MDIO_PMA_CTRL1_SPEED100; | ||
| 334 | if (ecmd->duplex) | ||
| 335 | reg |= MDIO_CTRL1_FULLDPLX; | ||
| 336 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, reg); | ||
| 337 | } | ||
| 338 | 308 | ||
| 339 | return 0; | 309 | return 0; |
| 340 | } | 310 | } |
