diff options
Diffstat (limited to 'drivers/net/sfc/tenxpress.c')
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 308 |
1 files changed, 175 insertions, 133 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index f4d509015f75..f21efe7bd316 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2007-2008 Solarflare Communications Inc. | 3 | * Copyright 2007-2009 Solarflare Communications Inc. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published | 6 | * under the terms of the GNU General Public License version 2 as published |
@@ -10,12 +10,12 @@ | |||
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/rtnetlink.h> | 11 | #include <linux/rtnetlink.h> |
12 | #include <linux/seq_file.h> | 12 | #include <linux/seq_file.h> |
13 | #include <linux/slab.h> | ||
13 | #include "efx.h" | 14 | #include "efx.h" |
14 | #include "mdio_10g.h" | 15 | #include "mdio_10g.h" |
15 | #include "falcon.h" | 16 | #include "nic.h" |
16 | #include "phy.h" | 17 | #include "phy.h" |
17 | #include "falcon_hwdefs.h" | 18 | #include "regs.h" |
18 | #include "boards.h" | ||
19 | #include "workarounds.h" | 19 | #include "workarounds.h" |
20 | #include "selftest.h" | 20 | #include "selftest.h" |
21 | 21 | ||
@@ -31,13 +31,13 @@ | |||
31 | #define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \ | 31 | #define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \ |
32 | (1 << LOOPBACK_PCS) | \ | 32 | (1 << LOOPBACK_PCS) | \ |
33 | (1 << LOOPBACK_PMAPMD) | \ | 33 | (1 << LOOPBACK_PMAPMD) | \ |
34 | (1 << LOOPBACK_NETWORK)) | 34 | (1 << LOOPBACK_PHYXS_WS)) |
35 | 35 | ||
36 | #define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \ | 36 | #define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \ |
37 | (1 << LOOPBACK_PHYXS) | \ | 37 | (1 << LOOPBACK_PHYXS) | \ |
38 | (1 << LOOPBACK_PCS) | \ | 38 | (1 << LOOPBACK_PCS) | \ |
39 | (1 << LOOPBACK_PMAPMD) | \ | 39 | (1 << LOOPBACK_PMAPMD) | \ |
40 | (1 << LOOPBACK_NETWORK)) | 40 | (1 << LOOPBACK_PHYXS_WS)) |
41 | 41 | ||
42 | /* We complain if we fail to see the link partner as 10G capable this many | 42 | /* We complain if we fail to see the link partner as 10G capable this many |
43 | * times in a row (must be > 1 as sampling the autoneg. registers is racy) | 43 | * times in a row (must be > 1 as sampling the autoneg. registers is racy) |
@@ -84,9 +84,9 @@ | |||
84 | #define PMA_PMD_LED_FLASH (3) | 84 | #define PMA_PMD_LED_FLASH (3) |
85 | #define PMA_PMD_LED_MASK 3 | 85 | #define PMA_PMD_LED_MASK 3 |
86 | /* All LEDs under hardware control */ | 86 | /* All LEDs under hardware control */ |
87 | #define PMA_PMD_LED_FULL_AUTO (0) | 87 | #define SFT9001_PMA_PMD_LED_DEFAULT 0 |
88 | /* Green and Amber under hardware control, Red off */ | 88 | /* Green and Amber under hardware control, Red off */ |
89 | #define PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) | 89 | #define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) |
90 | 90 | ||
91 | #define PMA_PMD_SPEED_ENABLE_REG 49192 | 91 | #define PMA_PMD_SPEED_ENABLE_REG 49192 |
92 | #define PMA_PMD_100TX_ADV_LBN 1 | 92 | #define PMA_PMD_100TX_ADV_LBN 1 |
@@ -200,15 +200,20 @@ static ssize_t set_phy_short_reach(struct device *dev, | |||
200 | const char *buf, size_t count) | 200 | const char *buf, size_t count) |
201 | { | 201 | { |
202 | struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); | 202 | struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); |
203 | int rc; | ||
203 | 204 | ||
204 | rtnl_lock(); | 205 | rtnl_lock(); |
205 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, | 206 | if (efx->state != STATE_RUNNING) { |
206 | MDIO_PMA_10GBT_TXPWR_SHORT, | 207 | rc = -EBUSY; |
207 | count != 0 && *buf != '0'); | 208 | } else { |
208 | efx_reconfigure_port(efx); | 209 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, |
210 | MDIO_PMA_10GBT_TXPWR_SHORT, | ||
211 | count != 0 && *buf != '0'); | ||
212 | rc = efx_reconfigure_port(efx); | ||
213 | } | ||
209 | rtnl_unlock(); | 214 | rtnl_unlock(); |
210 | 215 | ||
211 | return count; | 216 | return rc < 0 ? rc : (ssize_t)count; |
212 | } | 217 | } |
213 | 218 | ||
214 | static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, | 219 | static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, |
@@ -292,23 +297,68 @@ static int tenxpress_init(struct efx_nic *efx) | |||
292 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG, | 297 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG, |
293 | 1 << PMA_PMA_LED_ACTIVITY_LBN, true); | 298 | 1 << PMA_PMA_LED_ACTIVITY_LBN, true); |
294 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, | 299 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, |
295 | PMA_PMD_LED_DEFAULT); | 300 | SFX7101_PMA_PMD_LED_DEFAULT); |
296 | } | 301 | } |
297 | 302 | ||
298 | return 0; | 303 | return 0; |
299 | } | 304 | } |
300 | 305 | ||
301 | static int tenxpress_phy_init(struct efx_nic *efx) | 306 | static int tenxpress_phy_probe(struct efx_nic *efx) |
302 | { | 307 | { |
303 | struct tenxpress_phy_data *phy_data; | 308 | struct tenxpress_phy_data *phy_data; |
304 | int rc = 0; | 309 | int rc; |
305 | 310 | ||
311 | /* Allocate phy private storage */ | ||
306 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); | 312 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); |
307 | if (!phy_data) | 313 | if (!phy_data) |
308 | return -ENOMEM; | 314 | return -ENOMEM; |
309 | efx->phy_data = phy_data; | 315 | efx->phy_data = phy_data; |
310 | phy_data->phy_mode = efx->phy_mode; | 316 | phy_data->phy_mode = efx->phy_mode; |
311 | 317 | ||
318 | /* Create any special files */ | ||
319 | if (efx->phy_type == PHY_TYPE_SFT9001B) { | ||
320 | rc = device_create_file(&efx->pci_dev->dev, | ||
321 | &dev_attr_phy_short_reach); | ||
322 | if (rc) | ||
323 | goto fail; | ||
324 | } | ||
325 | |||
326 | if (efx->phy_type == PHY_TYPE_SFX7101) { | ||
327 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
328 | efx->mdio.mode_support = MDIO_SUPPORTS_C45; | ||
329 | |||
330 | efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; | ||
331 | |||
332 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
333 | ADVERTISED_10000baseT_Full); | ||
334 | } else { | ||
335 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
336 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | ||
337 | |||
338 | efx->loopback_modes = (SFT9001_LOOPBACKS | | ||
339 | FALCON_XMAC_LOOPBACKS | | ||
340 | FALCON_GMAC_LOOPBACKS); | ||
341 | |||
342 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
343 | ADVERTISED_10000baseT_Full | | ||
344 | ADVERTISED_1000baseT_Full | | ||
345 | ADVERTISED_100baseT_Full); | ||
346 | } | ||
347 | |||
348 | return 0; | ||
349 | |||
350 | fail: | ||
351 | kfree(efx->phy_data); | ||
352 | efx->phy_data = NULL; | ||
353 | return rc; | ||
354 | } | ||
355 | |||
356 | static int tenxpress_phy_init(struct efx_nic *efx) | ||
357 | { | ||
358 | int rc; | ||
359 | |||
360 | falcon_board(efx)->type->init_phy(efx); | ||
361 | |||
312 | if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { | 362 | if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { |
313 | if (efx->phy_type == PHY_TYPE_SFT9001A) { | 363 | if (efx->phy_type == PHY_TYPE_SFT9001A) { |
314 | int reg; | 364 | int reg; |
@@ -322,23 +372,20 @@ static int tenxpress_phy_init(struct efx_nic *efx) | |||
322 | 372 | ||
323 | rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); | 373 | rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); |
324 | if (rc < 0) | 374 | if (rc < 0) |
325 | goto fail; | 375 | return rc; |
326 | 376 | ||
327 | rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); | 377 | rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); |
328 | if (rc < 0) | 378 | if (rc < 0) |
329 | goto fail; | 379 | return rc; |
330 | } | 380 | } |
331 | 381 | ||
332 | rc = tenxpress_init(efx); | 382 | rc = tenxpress_init(efx); |
333 | if (rc < 0) | 383 | if (rc < 0) |
334 | goto fail; | 384 | return rc; |
335 | 385 | ||
336 | if (efx->phy_type == PHY_TYPE_SFT9001B) { | 386 | /* Reinitialise flow control settings */ |
337 | rc = device_create_file(&efx->pci_dev->dev, | 387 | efx_link_set_wanted_fc(efx, efx->wanted_fc); |
338 | &dev_attr_phy_short_reach); | 388 | efx_mdio_an_reconfigure(efx); |
339 | if (rc) | ||
340 | goto fail; | ||
341 | } | ||
342 | 389 | ||
343 | schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ | 390 | schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ |
344 | 391 | ||
@@ -346,11 +393,6 @@ static int tenxpress_phy_init(struct efx_nic *efx) | |||
346 | falcon_reset_xaui(efx); | 393 | falcon_reset_xaui(efx); |
347 | 394 | ||
348 | return 0; | 395 | return 0; |
349 | |||
350 | fail: | ||
351 | kfree(efx->phy_data); | ||
352 | efx->phy_data = NULL; | ||
353 | return rc; | ||
354 | } | 396 | } |
355 | 397 | ||
356 | /* Perform a "special software reset" on the PHY. The caller is | 398 | /* Perform a "special software reset" on the PHY. The caller is |
@@ -363,7 +405,7 @@ static int tenxpress_special_reset(struct efx_nic *efx) | |||
363 | /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so | 405 | /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so |
364 | * a special software reset can glitch the XGMAC sufficiently for stats | 406 | * a special software reset can glitch the XGMAC sufficiently for stats |
365 | * requests to fail. */ | 407 | * requests to fail. */ |
366 | efx_stats_disable(efx); | 408 | falcon_stop_nic_stats(efx); |
367 | 409 | ||
368 | /* Initiate reset */ | 410 | /* Initiate reset */ |
369 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); | 411 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); |
@@ -385,7 +427,7 @@ static int tenxpress_special_reset(struct efx_nic *efx) | |||
385 | /* Wait for the XGXS state machine to churn */ | 427 | /* Wait for the XGXS state machine to churn */ |
386 | mdelay(10); | 428 | mdelay(10); |
387 | out: | 429 | out: |
388 | efx_stats_enable(efx); | 430 | falcon_start_nic_stats(efx); |
389 | return rc; | 431 | return rc; |
390 | } | 432 | } |
391 | 433 | ||
@@ -489,133 +531,126 @@ static void tenxpress_low_power(struct efx_nic *efx) | |||
489 | !!(efx->phy_mode & PHY_MODE_LOW_POWER)); | 531 | !!(efx->phy_mode & PHY_MODE_LOW_POWER)); |
490 | } | 532 | } |
491 | 533 | ||
492 | static void tenxpress_phy_reconfigure(struct efx_nic *efx) | 534 | static int tenxpress_phy_reconfigure(struct efx_nic *efx) |
493 | { | 535 | { |
494 | struct tenxpress_phy_data *phy_data = efx->phy_data; | 536 | struct tenxpress_phy_data *phy_data = efx->phy_data; |
495 | struct ethtool_cmd ecmd; | ||
496 | bool phy_mode_change, loop_reset; | 537 | bool phy_mode_change, loop_reset; |
497 | 538 | ||
498 | if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { | 539 | if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { |
499 | phy_data->phy_mode = efx->phy_mode; | 540 | phy_data->phy_mode = efx->phy_mode; |
500 | return; | 541 | return 0; |
501 | } | 542 | } |
502 | 543 | ||
503 | tenxpress_low_power(efx); | ||
504 | |||
505 | phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL && | 544 | phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL && |
506 | phy_data->phy_mode != PHY_MODE_NORMAL); | 545 | phy_data->phy_mode != PHY_MODE_NORMAL); |
507 | loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) || | 546 | loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, LOOPBACKS_EXTERNAL(efx)) || |
508 | LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); | 547 | LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); |
509 | 548 | ||
510 | if (loop_reset || phy_mode_change) { | 549 | if (loop_reset || phy_mode_change) { |
511 | int rc; | 550 | tenxpress_special_reset(efx); |
512 | |||
513 | efx->phy_op->get_settings(efx, &ecmd); | ||
514 | |||
515 | if (loop_reset || phy_mode_change) { | ||
516 | tenxpress_special_reset(efx); | ||
517 | |||
518 | /* Reset XAUI if we were in 10G, and are staying | ||
519 | * in 10G. If we're moving into and out of 10G | ||
520 | * then xaui will be reset anyway */ | ||
521 | if (EFX_IS10G(efx)) | ||
522 | falcon_reset_xaui(efx); | ||
523 | } | ||
524 | 551 | ||
525 | rc = efx->phy_op->set_settings(efx, &ecmd); | 552 | /* Reset XAUI if we were in 10G, and are staying |
526 | WARN_ON(rc); | 553 | * in 10G. If we're moving into and out of 10G |
554 | * then xaui will be reset anyway */ | ||
555 | if (EFX_IS10G(efx)) | ||
556 | falcon_reset_xaui(efx); | ||
527 | } | 557 | } |
528 | 558 | ||
559 | tenxpress_low_power(efx); | ||
529 | efx_mdio_transmit_disable(efx); | 560 | efx_mdio_transmit_disable(efx); |
530 | efx_mdio_phy_reconfigure(efx); | 561 | efx_mdio_phy_reconfigure(efx); |
531 | tenxpress_ext_loopback(efx); | 562 | tenxpress_ext_loopback(efx); |
563 | efx_mdio_an_reconfigure(efx); | ||
532 | 564 | ||
533 | phy_data->loopback_mode = efx->loopback_mode; | 565 | phy_data->loopback_mode = efx->loopback_mode; |
534 | phy_data->phy_mode = efx->phy_mode; | 566 | phy_data->phy_mode = efx->phy_mode; |
535 | 567 | ||
536 | if (efx->phy_type == PHY_TYPE_SFX7101) { | 568 | return 0; |
537 | efx->link_speed = 10000; | ||
538 | efx->link_fd = true; | ||
539 | efx->link_up = sfx7101_link_ok(efx); | ||
540 | } else { | ||
541 | efx->phy_op->get_settings(efx, &ecmd); | ||
542 | efx->link_speed = ecmd.speed; | ||
543 | efx->link_fd = ecmd.duplex == DUPLEX_FULL; | ||
544 | efx->link_up = sft9001_link_ok(efx, &ecmd); | ||
545 | } | ||
546 | efx->link_fc = efx_mdio_get_pause(efx); | ||
547 | } | 569 | } |
548 | 570 | ||
549 | /* Poll PHY for interrupt */ | 571 | static void |
550 | static void tenxpress_phy_poll(struct efx_nic *efx) | 572 | tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); |
573 | |||
574 | /* Poll for link state changes */ | ||
575 | static bool tenxpress_phy_poll(struct efx_nic *efx) | ||
551 | { | 576 | { |
552 | struct tenxpress_phy_data *phy_data = efx->phy_data; | 577 | struct efx_link_state old_state = efx->link_state; |
553 | bool change = false; | ||
554 | 578 | ||
555 | if (efx->phy_type == PHY_TYPE_SFX7101) { | 579 | if (efx->phy_type == PHY_TYPE_SFX7101) { |
556 | bool link_ok = sfx7101_link_ok(efx); | 580 | efx->link_state.up = sfx7101_link_ok(efx); |
557 | if (link_ok != efx->link_up) { | 581 | efx->link_state.speed = 10000; |
558 | change = true; | 582 | efx->link_state.fd = true; |
559 | } else { | 583 | efx->link_state.fc = efx_mdio_get_pause(efx); |
560 | unsigned int link_fc = efx_mdio_get_pause(efx); | 584 | |
561 | if (link_fc != efx->link_fc) | 585 | sfx7101_check_bad_lp(efx, efx->link_state.up); |
562 | change = true; | ||
563 | } | ||
564 | sfx7101_check_bad_lp(efx, link_ok); | ||
565 | } else if (efx->loopback_mode) { | ||
566 | bool link_ok = sft9001_link_ok(efx, NULL); | ||
567 | if (link_ok != efx->link_up) | ||
568 | change = true; | ||
569 | } else { | 586 | } else { |
570 | int status = efx_mdio_read(efx, MDIO_MMD_PMAPMD, | 587 | struct ethtool_cmd ecmd; |
571 | MDIO_PMA_LASI_STAT); | ||
572 | if (status & MDIO_PMA_LASI_LSALARM) | ||
573 | change = true; | ||
574 | } | ||
575 | 588 | ||
576 | if (change) | 589 | /* Check the LASI alarm first */ |
577 | falcon_sim_phy_event(efx); | 590 | if (efx->loopback_mode == LOOPBACK_NONE && |
591 | !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) & | ||
592 | MDIO_PMA_LASI_LSALARM)) | ||
593 | return false; | ||
578 | 594 | ||
579 | if (phy_data->phy_mode != PHY_MODE_NORMAL) | 595 | tenxpress_get_settings(efx, &ecmd); |
580 | return; | 596 | |
597 | efx->link_state.up = sft9001_link_ok(efx, &ecmd); | ||
598 | efx->link_state.speed = ecmd.speed; | ||
599 | efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL); | ||
600 | efx->link_state.fc = efx_mdio_get_pause(efx); | ||
601 | } | ||
602 | |||
603 | return !efx_link_state_equal(&efx->link_state, &old_state); | ||
581 | } | 604 | } |
582 | 605 | ||
583 | static void tenxpress_phy_fini(struct efx_nic *efx) | 606 | static void sfx7101_phy_fini(struct efx_nic *efx) |
584 | { | 607 | { |
585 | int reg; | 608 | int reg; |
586 | 609 | ||
610 | /* Power down the LNPGA */ | ||
611 | reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); | ||
612 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); | ||
613 | |||
614 | /* Waiting here ensures that the board fini, which can turn | ||
615 | * off the power to the PHY, won't get run until the LNPGA | ||
616 | * powerdown has been given long enough to complete. */ | ||
617 | schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ | ||
618 | } | ||
619 | |||
620 | static void tenxpress_phy_remove(struct efx_nic *efx) | ||
621 | { | ||
587 | if (efx->phy_type == PHY_TYPE_SFT9001B) | 622 | if (efx->phy_type == PHY_TYPE_SFT9001B) |
588 | device_remove_file(&efx->pci_dev->dev, | 623 | device_remove_file(&efx->pci_dev->dev, |
589 | &dev_attr_phy_short_reach); | 624 | &dev_attr_phy_short_reach); |
590 | 625 | ||
591 | if (efx->phy_type == PHY_TYPE_SFX7101) { | ||
592 | /* Power down the LNPGA */ | ||
593 | reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); | ||
594 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); | ||
595 | |||
596 | /* Waiting here ensures that the board fini, which can turn | ||
597 | * off the power to the PHY, won't get run until the LNPGA | ||
598 | * powerdown has been given long enough to complete. */ | ||
599 | schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ | ||
600 | } | ||
601 | |||
602 | kfree(efx->phy_data); | 626 | kfree(efx->phy_data); |
603 | efx->phy_data = NULL; | 627 | efx->phy_data = NULL; |
604 | } | 628 | } |
605 | 629 | ||
606 | 630 | ||
607 | /* Set the RX and TX LEDs and Link LED flashing. The other LEDs | 631 | /* Override the RX, TX and link LEDs */ |
608 | * (which probably aren't wired anyway) are left in AUTO mode */ | 632 | void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) |
609 | void tenxpress_phy_blink(struct efx_nic *efx, bool blink) | ||
610 | { | 633 | { |
611 | int reg; | 634 | int reg; |
612 | 635 | ||
613 | if (blink) | 636 | switch (mode) { |
614 | reg = (PMA_PMD_LED_FLASH << PMA_PMD_LED_TX_LBN) | | 637 | case EFX_LED_OFF: |
615 | (PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN) | | 638 | reg = (PMA_PMD_LED_OFF << PMA_PMD_LED_TX_LBN) | |
616 | (PMA_PMD_LED_FLASH << PMA_PMD_LED_LINK_LBN); | 639 | (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) | |
617 | else | 640 | (PMA_PMD_LED_OFF << PMA_PMD_LED_LINK_LBN); |
618 | reg = PMA_PMD_LED_DEFAULT; | 641 | break; |
642 | case EFX_LED_ON: | ||
643 | reg = (PMA_PMD_LED_ON << PMA_PMD_LED_TX_LBN) | | ||
644 | (PMA_PMD_LED_ON << PMA_PMD_LED_RX_LBN) | | ||
645 | (PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN); | ||
646 | break; | ||
647 | default: | ||
648 | if (efx->phy_type == PHY_TYPE_SFX7101) | ||
649 | reg = SFX7101_PMA_PMD_LED_DEFAULT; | ||
650 | else | ||
651 | reg = SFT9001_PMA_PMD_LED_DEFAULT; | ||
652 | break; | ||
653 | } | ||
619 | 654 | ||
620 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg); | 655 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg); |
621 | } | 656 | } |
@@ -624,6 +659,13 @@ static const char *const sfx7101_test_names[] = { | |||
624 | "bist" | 659 | "bist" |
625 | }; | 660 | }; |
626 | 661 | ||
662 | static const char *sfx7101_test_name(struct efx_nic *efx, unsigned int index) | ||
663 | { | ||
664 | if (index < ARRAY_SIZE(sfx7101_test_names)) | ||
665 | return sfx7101_test_names[index]; | ||
666 | return NULL; | ||
667 | } | ||
668 | |||
627 | static int | 669 | static int |
628 | sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags) | 670 | sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags) |
629 | { | 671 | { |
@@ -635,6 +677,9 @@ sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags) | |||
635 | /* BIST is automatically run after a special software reset */ | 677 | /* BIST is automatically run after a special software reset */ |
636 | rc = tenxpress_special_reset(efx); | 678 | rc = tenxpress_special_reset(efx); |
637 | results[0] = rc ? -1 : 1; | 679 | results[0] = rc ? -1 : 1; |
680 | |||
681 | efx_mdio_an_reconfigure(efx); | ||
682 | |||
638 | return rc; | 683 | return rc; |
639 | } | 684 | } |
640 | 685 | ||
@@ -650,14 +695,17 @@ static const char *const sft9001_test_names[] = { | |||
650 | "cable.pairD.length", | 695 | "cable.pairD.length", |
651 | }; | 696 | }; |
652 | 697 | ||
698 | static const char *sft9001_test_name(struct efx_nic *efx, unsigned int index) | ||
699 | { | ||
700 | if (index < ARRAY_SIZE(sft9001_test_names)) | ||
701 | return sft9001_test_names[index]; | ||
702 | return NULL; | ||
703 | } | ||
704 | |||
653 | static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) | 705 | static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) |
654 | { | 706 | { |
655 | struct ethtool_cmd ecmd; | ||
656 | int rc = 0, rc2, i, ctrl_reg, res_reg; | 707 | int rc = 0, rc2, i, ctrl_reg, res_reg; |
657 | 708 | ||
658 | if (flags & ETH_TEST_FL_OFFLINE) | ||
659 | efx->phy_op->get_settings(efx, &ecmd); | ||
660 | |||
661 | /* Initialise cable diagnostic results to unknown failure */ | 709 | /* Initialise cable diagnostic results to unknown failure */ |
662 | for (i = 1; i < 9; ++i) | 710 | for (i = 1; i < 9; ++i) |
663 | results[i] = -1; | 711 | results[i] = -1; |
@@ -709,9 +757,7 @@ out: | |||
709 | if (!rc) | 757 | if (!rc) |
710 | rc = rc2; | 758 | rc = rc2; |
711 | 759 | ||
712 | rc2 = efx->phy_op->set_settings(efx, &ecmd); | 760 | efx_mdio_an_reconfigure(efx); |
713 | if (!rc) | ||
714 | rc = rc2; | ||
715 | } | 761 | } |
716 | 762 | ||
717 | return rc; | 763 | return rc; |
@@ -758,7 +804,7 @@ tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | |||
758 | * but doesn't advertise the correct speed. So override it */ | 804 | * but doesn't advertise the correct speed. So override it */ |
759 | if (efx->loopback_mode == LOOPBACK_GPHY) | 805 | if (efx->loopback_mode == LOOPBACK_GPHY) |
760 | ecmd->speed = SPEED_1000; | 806 | ecmd->speed = SPEED_1000; |
761 | else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks) | 807 | else if (LOOPBACK_EXTERNAL(efx)) |
762 | ecmd->speed = SPEED_10000; | 808 | ecmd->speed = SPEED_10000; |
763 | } | 809 | } |
764 | 810 | ||
@@ -788,35 +834,31 @@ static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) | |||
788 | } | 834 | } |
789 | 835 | ||
790 | struct efx_phy_operations falcon_sfx7101_phy_ops = { | 836 | struct efx_phy_operations falcon_sfx7101_phy_ops = { |
791 | .macs = EFX_XMAC, | 837 | .probe = tenxpress_phy_probe, |
792 | .init = tenxpress_phy_init, | 838 | .init = tenxpress_phy_init, |
793 | .reconfigure = tenxpress_phy_reconfigure, | 839 | .reconfigure = tenxpress_phy_reconfigure, |
794 | .poll = tenxpress_phy_poll, | 840 | .poll = tenxpress_phy_poll, |
795 | .fini = tenxpress_phy_fini, | 841 | .fini = sfx7101_phy_fini, |
796 | .clear_interrupt = efx_port_dummy_op_void, | 842 | .remove = tenxpress_phy_remove, |
797 | .get_settings = tenxpress_get_settings, | 843 | .get_settings = tenxpress_get_settings, |
798 | .set_settings = tenxpress_set_settings, | 844 | .set_settings = tenxpress_set_settings, |
799 | .set_npage_adv = sfx7101_set_npage_adv, | 845 | .set_npage_adv = sfx7101_set_npage_adv, |
800 | .num_tests = ARRAY_SIZE(sfx7101_test_names), | 846 | .test_alive = efx_mdio_test_alive, |
801 | .test_names = sfx7101_test_names, | 847 | .test_name = sfx7101_test_name, |
802 | .run_tests = sfx7101_run_tests, | 848 | .run_tests = sfx7101_run_tests, |
803 | .mmds = TENXPRESS_REQUIRED_DEVS, | ||
804 | .loopbacks = SFX7101_LOOPBACKS, | ||
805 | }; | 849 | }; |
806 | 850 | ||
807 | struct efx_phy_operations falcon_sft9001_phy_ops = { | 851 | struct efx_phy_operations falcon_sft9001_phy_ops = { |
808 | .macs = EFX_GMAC | EFX_XMAC, | 852 | .probe = tenxpress_phy_probe, |
809 | .init = tenxpress_phy_init, | 853 | .init = tenxpress_phy_init, |
810 | .reconfigure = tenxpress_phy_reconfigure, | 854 | .reconfigure = tenxpress_phy_reconfigure, |
811 | .poll = tenxpress_phy_poll, | 855 | .poll = tenxpress_phy_poll, |
812 | .fini = tenxpress_phy_fini, | 856 | .fini = efx_port_dummy_op_void, |
813 | .clear_interrupt = efx_port_dummy_op_void, | 857 | .remove = tenxpress_phy_remove, |
814 | .get_settings = tenxpress_get_settings, | 858 | .get_settings = tenxpress_get_settings, |
815 | .set_settings = tenxpress_set_settings, | 859 | .set_settings = tenxpress_set_settings, |
816 | .set_npage_adv = sft9001_set_npage_adv, | 860 | .set_npage_adv = sft9001_set_npage_adv, |
817 | .num_tests = ARRAY_SIZE(sft9001_test_names), | 861 | .test_alive = efx_mdio_test_alive, |
818 | .test_names = sft9001_test_names, | 862 | .test_name = sft9001_test_name, |
819 | .run_tests = sft9001_run_tests, | 863 | .run_tests = sft9001_run_tests, |
820 | .mmds = TENXPRESS_REQUIRED_DEVS, | ||
821 | .loopbacks = SFT9001_LOOPBACKS, | ||
822 | }; | 864 | }; |