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, |