diff options
Diffstat (limited to 'drivers/net/sfc/tenxpress.c')
| -rw-r--r-- | drivers/net/sfc/tenxpress.c | 138 |
1 files changed, 77 insertions, 61 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index ca11572a49a9..3009c297c135 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c | |||
| @@ -202,10 +202,14 @@ static ssize_t set_phy_short_reach(struct device *dev, | |||
| 202 | int rc; | 202 | int rc; |
| 203 | 203 | ||
| 204 | rtnl_lock(); | 204 | rtnl_lock(); |
| 205 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, | 205 | if (efx->state != STATE_RUNNING) { |
| 206 | MDIO_PMA_10GBT_TXPWR_SHORT, | 206 | rc = -EBUSY; |
| 207 | count != 0 && *buf != '0'); | 207 | } else { |
| 208 | rc = efx_reconfigure_port(efx); | 208 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, |
| 209 | MDIO_PMA_10GBT_TXPWR_SHORT, | ||
| 210 | count != 0 && *buf != '0'); | ||
| 211 | rc = efx_reconfigure_port(efx); | ||
| 212 | } | ||
| 209 | rtnl_unlock(); | 213 | rtnl_unlock(); |
| 210 | 214 | ||
| 211 | return rc < 0 ? rc : (ssize_t)count; | 215 | return rc < 0 ? rc : (ssize_t)count; |
| @@ -298,36 +302,62 @@ static int tenxpress_init(struct efx_nic *efx) | |||
| 298 | return 0; | 302 | return 0; |
| 299 | } | 303 | } |
| 300 | 304 | ||
| 301 | static int sfx7101_phy_probe(struct efx_nic *efx) | 305 | static int tenxpress_phy_probe(struct efx_nic *efx) |
| 302 | { | 306 | { |
| 303 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | 307 | struct tenxpress_phy_data *phy_data; |
| 304 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | 308 | int rc; |
| 305 | efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; | 309 | |
| 306 | return 0; | 310 | /* Allocate phy private storage */ |
| 307 | } | 311 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); |
| 312 | if (!phy_data) | ||
| 313 | return -ENOMEM; | ||
| 314 | efx->phy_data = phy_data; | ||
| 315 | phy_data->phy_mode = efx->phy_mode; | ||
| 316 | |||
| 317 | /* Create any special files */ | ||
| 318 | if (efx->phy_type == PHY_TYPE_SFT9001B) { | ||
| 319 | rc = device_create_file(&efx->pci_dev->dev, | ||
| 320 | &dev_attr_phy_short_reach); | ||
| 321 | if (rc) | ||
| 322 | goto fail; | ||
| 323 | } | ||
| 324 | |||
| 325 | if (efx->phy_type == PHY_TYPE_SFX7101) { | ||
| 326 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
| 327 | efx->mdio.mode_support = MDIO_SUPPORTS_C45; | ||
| 328 | |||
| 329 | efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; | ||
| 330 | |||
| 331 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
| 332 | ADVERTISED_10000baseT_Full); | ||
| 333 | } else { | ||
| 334 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
| 335 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | ||
| 336 | |||
| 337 | efx->loopback_modes = (SFT9001_LOOPBACKS | | ||
| 338 | FALCON_XMAC_LOOPBACKS | | ||
| 339 | FALCON_GMAC_LOOPBACKS); | ||
| 340 | |||
| 341 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
| 342 | ADVERTISED_10000baseT_Full | | ||
| 343 | ADVERTISED_1000baseT_Full | | ||
| 344 | ADVERTISED_100baseT_Full); | ||
| 345 | } | ||
| 308 | 346 | ||
| 309 | static int sft9001_phy_probe(struct efx_nic *efx) | ||
| 310 | { | ||
| 311 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
| 312 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | ||
| 313 | efx->loopback_modes = (SFT9001_LOOPBACKS | FALCON_XMAC_LOOPBACKS | | ||
| 314 | FALCON_GMAC_LOOPBACKS); | ||
| 315 | return 0; | 347 | return 0; |
| 348 | |||
| 349 | fail: | ||
| 350 | kfree(efx->phy_data); | ||
| 351 | efx->phy_data = NULL; | ||
| 352 | return rc; | ||
| 316 | } | 353 | } |
| 317 | 354 | ||
| 318 | static int tenxpress_phy_init(struct efx_nic *efx) | 355 | static int tenxpress_phy_init(struct efx_nic *efx) |
| 319 | { | 356 | { |
| 320 | struct tenxpress_phy_data *phy_data; | 357 | int rc; |
| 321 | int rc = 0; | ||
| 322 | 358 | ||
| 323 | falcon_board(efx)->type->init_phy(efx); | 359 | falcon_board(efx)->type->init_phy(efx); |
| 324 | 360 | ||
| 325 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); | ||
| 326 | if (!phy_data) | ||
| 327 | return -ENOMEM; | ||
| 328 | efx->phy_data = phy_data; | ||
| 329 | phy_data->phy_mode = efx->phy_mode; | ||
| 330 | |||
| 331 | if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { | 361 | if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { |
| 332 | if (efx->phy_type == PHY_TYPE_SFT9001A) { | 362 | if (efx->phy_type == PHY_TYPE_SFT9001A) { |
| 333 | int reg; | 363 | int reg; |
| @@ -341,44 +371,27 @@ static int tenxpress_phy_init(struct efx_nic *efx) | |||
| 341 | 371 | ||
| 342 | rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); | 372 | rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); |
| 343 | if (rc < 0) | 373 | if (rc < 0) |
| 344 | goto fail; | 374 | return rc; |
| 345 | 375 | ||
| 346 | rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); | 376 | rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); |
| 347 | if (rc < 0) | 377 | if (rc < 0) |
| 348 | goto fail; | 378 | return rc; |
| 349 | } | 379 | } |
| 350 | 380 | ||
| 351 | rc = tenxpress_init(efx); | 381 | rc = tenxpress_init(efx); |
| 352 | if (rc < 0) | 382 | if (rc < 0) |
| 353 | goto fail; | 383 | return rc; |
| 354 | 384 | ||
| 355 | /* Initialise advertising flags */ | 385 | /* Reinitialise flow control settings */ |
| 356 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
| 357 | ADVERTISED_10000baseT_Full); | ||
| 358 | if (efx->phy_type != PHY_TYPE_SFX7101) | ||
| 359 | efx->link_advertising |= (ADVERTISED_1000baseT_Full | | ||
| 360 | ADVERTISED_100baseT_Full); | ||
| 361 | efx_link_set_wanted_fc(efx, efx->wanted_fc); | 386 | efx_link_set_wanted_fc(efx, efx->wanted_fc); |
| 362 | efx_mdio_an_reconfigure(efx); | 387 | efx_mdio_an_reconfigure(efx); |
| 363 | 388 | ||
| 364 | if (efx->phy_type == PHY_TYPE_SFT9001B) { | ||
| 365 | rc = device_create_file(&efx->pci_dev->dev, | ||
| 366 | &dev_attr_phy_short_reach); | ||
| 367 | if (rc) | ||
| 368 | goto fail; | ||
| 369 | } | ||
| 370 | |||
| 371 | schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ | 389 | schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ |
| 372 | 390 | ||
| 373 | /* Let XGXS and SerDes out of reset */ | 391 | /* Let XGXS and SerDes out of reset */ |
| 374 | falcon_reset_xaui(efx); | 392 | falcon_reset_xaui(efx); |
| 375 | 393 | ||
| 376 | return 0; | 394 | return 0; |
| 377 | |||
| 378 | fail: | ||
| 379 | kfree(efx->phy_data); | ||
| 380 | efx->phy_data = NULL; | ||
| 381 | return rc; | ||
| 382 | } | 395 | } |
| 383 | 396 | ||
| 384 | /* Perform a "special software reset" on the PHY. The caller is | 397 | /* Perform a "special software reset" on the PHY. The caller is |
| @@ -589,25 +602,26 @@ static bool tenxpress_phy_poll(struct efx_nic *efx) | |||
| 589 | return !efx_link_state_equal(&efx->link_state, &old_state); | 602 | return !efx_link_state_equal(&efx->link_state, &old_state); |
| 590 | } | 603 | } |
| 591 | 604 | ||
| 592 | static void tenxpress_phy_fini(struct efx_nic *efx) | 605 | static void sfx7101_phy_fini(struct efx_nic *efx) |
| 593 | { | 606 | { |
| 594 | int reg; | 607 | int reg; |
| 595 | 608 | ||
| 609 | /* Power down the LNPGA */ | ||
| 610 | reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); | ||
| 611 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); | ||
| 612 | |||
| 613 | /* Waiting here ensures that the board fini, which can turn | ||
| 614 | * off the power to the PHY, won't get run until the LNPGA | ||
| 615 | * powerdown has been given long enough to complete. */ | ||
| 616 | schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ | ||
| 617 | } | ||
| 618 | |||
| 619 | static void tenxpress_phy_remove(struct efx_nic *efx) | ||
| 620 | { | ||
| 596 | if (efx->phy_type == PHY_TYPE_SFT9001B) | 621 | if (efx->phy_type == PHY_TYPE_SFT9001B) |
| 597 | device_remove_file(&efx->pci_dev->dev, | 622 | device_remove_file(&efx->pci_dev->dev, |
| 598 | &dev_attr_phy_short_reach); | 623 | &dev_attr_phy_short_reach); |
| 599 | 624 | ||
| 600 | if (efx->phy_type == PHY_TYPE_SFX7101) { | ||
| 601 | /* Power down the LNPGA */ | ||
| 602 | reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); | ||
| 603 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); | ||
| 604 | |||
| 605 | /* Waiting here ensures that the board fini, which can turn | ||
| 606 | * off the power to the PHY, won't get run until the LNPGA | ||
| 607 | * powerdown has been given long enough to complete. */ | ||
| 608 | schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ | ||
| 609 | } | ||
| 610 | |||
| 611 | kfree(efx->phy_data); | 625 | kfree(efx->phy_data); |
| 612 | efx->phy_data = NULL; | 626 | efx->phy_data = NULL; |
| 613 | } | 627 | } |
| @@ -819,11 +833,12 @@ static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) | |||
| 819 | } | 833 | } |
| 820 | 834 | ||
| 821 | struct efx_phy_operations falcon_sfx7101_phy_ops = { | 835 | struct efx_phy_operations falcon_sfx7101_phy_ops = { |
| 822 | .probe = sfx7101_phy_probe, | 836 | .probe = tenxpress_phy_probe, |
| 823 | .init = tenxpress_phy_init, | 837 | .init = tenxpress_phy_init, |
| 824 | .reconfigure = tenxpress_phy_reconfigure, | 838 | .reconfigure = tenxpress_phy_reconfigure, |
| 825 | .poll = tenxpress_phy_poll, | 839 | .poll = tenxpress_phy_poll, |
| 826 | .fini = tenxpress_phy_fini, | 840 | .fini = sfx7101_phy_fini, |
| 841 | .remove = tenxpress_phy_remove, | ||
| 827 | .get_settings = tenxpress_get_settings, | 842 | .get_settings = tenxpress_get_settings, |
| 828 | .set_settings = tenxpress_set_settings, | 843 | .set_settings = tenxpress_set_settings, |
| 829 | .set_npage_adv = sfx7101_set_npage_adv, | 844 | .set_npage_adv = sfx7101_set_npage_adv, |
| @@ -832,11 +847,12 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { | |||
| 832 | }; | 847 | }; |
| 833 | 848 | ||
| 834 | struct efx_phy_operations falcon_sft9001_phy_ops = { | 849 | struct efx_phy_operations falcon_sft9001_phy_ops = { |
| 835 | .probe = sft9001_phy_probe, | 850 | .probe = tenxpress_phy_probe, |
| 836 | .init = tenxpress_phy_init, | 851 | .init = tenxpress_phy_init, |
| 837 | .reconfigure = tenxpress_phy_reconfigure, | 852 | .reconfigure = tenxpress_phy_reconfigure, |
| 838 | .poll = tenxpress_phy_poll, | 853 | .poll = tenxpress_phy_poll, |
| 839 | .fini = tenxpress_phy_fini, | 854 | .fini = efx_port_dummy_op_void, |
| 855 | .remove = tenxpress_phy_remove, | ||
| 840 | .get_settings = tenxpress_get_settings, | 856 | .get_settings = tenxpress_get_settings, |
| 841 | .set_settings = tenxpress_set_settings, | 857 | .set_settings = tenxpress_set_settings, |
| 842 | .set_npage_adv = sft9001_set_npage_adv, | 858 | .set_npage_adv = sft9001_set_npage_adv, |
