diff options
Diffstat (limited to 'drivers/net/sfc/ethtool.c')
-rw-r--r-- | drivers/net/sfc/ethtool.c | 222 |
1 files changed, 163 insertions, 59 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 45018f283ffa..6c0bbed8c477 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2005-2006 Fen Systems Ltd. | 3 | * Copyright 2005-2006 Fen Systems Ltd. |
4 | * Copyright 2006-2008 Solarflare Communications Inc. | 4 | * Copyright 2006-2009 Solarflare Communications Inc. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published | 7 | * under the terms of the GNU General Public License version 2 as published |
@@ -10,30 +10,15 @@ | |||
10 | 10 | ||
11 | #include <linux/netdevice.h> | 11 | #include <linux/netdevice.h> |
12 | #include <linux/ethtool.h> | 12 | #include <linux/ethtool.h> |
13 | #include <linux/mdio.h> | ||
14 | #include <linux/rtnetlink.h> | 13 | #include <linux/rtnetlink.h> |
15 | #include "net_driver.h" | 14 | #include "net_driver.h" |
16 | #include "workarounds.h" | 15 | #include "workarounds.h" |
17 | #include "selftest.h" | 16 | #include "selftest.h" |
18 | #include "efx.h" | 17 | #include "efx.h" |
19 | #include "ethtool.h" | 18 | #include "nic.h" |
20 | #include "falcon.h" | ||
21 | #include "spi.h" | 19 | #include "spi.h" |
22 | #include "mdio_10g.h" | 20 | #include "mdio_10g.h" |
23 | 21 | ||
24 | const char *efx_loopback_mode_names[] = { | ||
25 | [LOOPBACK_NONE] = "NONE", | ||
26 | [LOOPBACK_GMAC] = "GMAC", | ||
27 | [LOOPBACK_XGMII] = "XGMII", | ||
28 | [LOOPBACK_XGXS] = "XGXS", | ||
29 | [LOOPBACK_XAUI] = "XAUI", | ||
30 | [LOOPBACK_GPHY] = "GPHY", | ||
31 | [LOOPBACK_PHYXS] = "PHYXS", | ||
32 | [LOOPBACK_PCS] = "PCS", | ||
33 | [LOOPBACK_PMAPMD] = "PMA/PMD", | ||
34 | [LOOPBACK_NETWORK] = "NETWORK", | ||
35 | }; | ||
36 | |||
37 | struct ethtool_string { | 22 | struct ethtool_string { |
38 | char name[ETH_GSTRING_LEN]; | 23 | char name[ETH_GSTRING_LEN]; |
39 | }; | 24 | }; |
@@ -167,6 +152,7 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = { | |||
167 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), | 152 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), |
168 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err), | 153 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err), |
169 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err), | 154 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err), |
155 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch), | ||
170 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc), | 156 | EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc), |
171 | }; | 157 | }; |
172 | 158 | ||
@@ -187,13 +173,15 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count) | |||
187 | { | 173 | { |
188 | struct efx_nic *efx = netdev_priv(net_dev); | 174 | struct efx_nic *efx = netdev_priv(net_dev); |
189 | 175 | ||
190 | efx->board_info.blink(efx, 1); | 176 | do { |
191 | set_current_state(TASK_INTERRUPTIBLE); | 177 | efx->type->set_id_led(efx, EFX_LED_ON); |
192 | if (count) | 178 | schedule_timeout_interruptible(HZ / 2); |
193 | schedule_timeout(count * HZ); | 179 | |
194 | else | 180 | efx->type->set_id_led(efx, EFX_LED_OFF); |
195 | schedule(); | 181 | schedule_timeout_interruptible(HZ / 2); |
196 | efx->board_info.blink(efx, 0); | 182 | } while (!signal_pending(current) && --count != 0); |
183 | |||
184 | efx->type->set_id_led(efx, EFX_LED_DEFAULT); | ||
197 | return 0; | 185 | return 0; |
198 | } | 186 | } |
199 | 187 | ||
@@ -202,6 +190,7 @@ int efx_ethtool_get_settings(struct net_device *net_dev, | |||
202 | struct ethtool_cmd *ecmd) | 190 | struct ethtool_cmd *ecmd) |
203 | { | 191 | { |
204 | struct efx_nic *efx = netdev_priv(net_dev); | 192 | struct efx_nic *efx = netdev_priv(net_dev); |
193 | struct efx_link_state *link_state = &efx->link_state; | ||
205 | 194 | ||
206 | mutex_lock(&efx->mac_lock); | 195 | mutex_lock(&efx->mac_lock); |
207 | efx->phy_op->get_settings(efx, ecmd); | 196 | efx->phy_op->get_settings(efx, ecmd); |
@@ -209,6 +198,13 @@ int efx_ethtool_get_settings(struct net_device *net_dev, | |||
209 | 198 | ||
210 | /* Falcon GMAC does not support 1000Mbps HD */ | 199 | /* Falcon GMAC does not support 1000Mbps HD */ |
211 | ecmd->supported &= ~SUPPORTED_1000baseT_Half; | 200 | ecmd->supported &= ~SUPPORTED_1000baseT_Half; |
201 | /* Both MACs support pause frames (bidirectional and respond-only) */ | ||
202 | ecmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; | ||
203 | |||
204 | if (LOOPBACK_INTERNAL(efx)) { | ||
205 | ecmd->speed = link_state->speed; | ||
206 | ecmd->duplex = link_state->fd ? DUPLEX_FULL : DUPLEX_HALF; | ||
207 | } | ||
212 | 208 | ||
213 | return 0; | 209 | return 0; |
214 | } | 210 | } |
@@ -230,9 +226,6 @@ int efx_ethtool_set_settings(struct net_device *net_dev, | |||
230 | mutex_lock(&efx->mac_lock); | 226 | mutex_lock(&efx->mac_lock); |
231 | rc = efx->phy_op->set_settings(efx, ecmd); | 227 | rc = efx->phy_op->set_settings(efx, ecmd); |
232 | mutex_unlock(&efx->mac_lock); | 228 | mutex_unlock(&efx->mac_lock); |
233 | if (!rc) | ||
234 | efx_reconfigure_port(efx); | ||
235 | |||
236 | return rc; | 229 | return rc; |
237 | } | 230 | } |
238 | 231 | ||
@@ -243,6 +236,9 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev, | |||
243 | 236 | ||
244 | strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver)); | 237 | strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver)); |
245 | strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version)); | 238 | strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version)); |
239 | if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) | ||
240 | siena_print_fwver(efx, info->fw_version, | ||
241 | sizeof(info->fw_version)); | ||
246 | strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info)); | 242 | strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info)); |
247 | } | 243 | } |
248 | 244 | ||
@@ -289,7 +285,7 @@ static void efx_fill_test(unsigned int test_index, | |||
289 | #define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue | 285 | #define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue |
290 | #define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue | 286 | #define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue |
291 | #define EFX_LOOPBACK_NAME(_mode, _counter) \ | 287 | #define EFX_LOOPBACK_NAME(_mode, _counter) \ |
292 | "loopback.%s." _counter, LOOPBACK_MODE_NAME(mode) | 288 | "loopback.%s." _counter, STRING_TABLE_LOOKUP(_mode, efx_loopback_mode) |
293 | 289 | ||
294 | /** | 290 | /** |
295 | * efx_fill_loopback_test - fill in a block of loopback self-test entries | 291 | * efx_fill_loopback_test - fill in a block of loopback self-test entries |
@@ -372,9 +368,21 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, | |||
372 | efx_fill_test(n++, strings, data, &tests->registers, | 368 | efx_fill_test(n++, strings, data, &tests->registers, |
373 | "core", 0, "registers", NULL); | 369 | "core", 0, "registers", NULL); |
374 | 370 | ||
375 | for (i = 0; i < efx->phy_op->num_tests; i++) | 371 | if (efx->phy_op->run_tests != NULL) { |
376 | efx_fill_test(n++, strings, data, &tests->phy[i], | 372 | EFX_BUG_ON_PARANOID(efx->phy_op->test_name == NULL); |
377 | "phy", 0, efx->phy_op->test_names[i], NULL); | 373 | |
374 | for (i = 0; true; ++i) { | ||
375 | const char *name; | ||
376 | |||
377 | EFX_BUG_ON_PARANOID(i >= EFX_MAX_PHY_TESTS); | ||
378 | name = efx->phy_op->test_name(efx, i); | ||
379 | if (name == NULL) | ||
380 | break; | ||
381 | |||
382 | efx_fill_test(n++, strings, data, &tests->phy[i], | ||
383 | "phy", 0, name, NULL); | ||
384 | } | ||
385 | } | ||
378 | 386 | ||
379 | /* Loopback tests */ | 387 | /* Loopback tests */ |
380 | for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { | 388 | for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { |
@@ -463,6 +471,36 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, | |||
463 | } | 471 | } |
464 | } | 472 | } |
465 | 473 | ||
474 | static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable) | ||
475 | { | ||
476 | struct efx_nic *efx __attribute__ ((unused)) = netdev_priv(net_dev); | ||
477 | unsigned long features; | ||
478 | |||
479 | features = NETIF_F_TSO; | ||
480 | if (efx->type->offload_features & NETIF_F_V6_CSUM) | ||
481 | features |= NETIF_F_TSO6; | ||
482 | |||
483 | if (enable) | ||
484 | net_dev->features |= features; | ||
485 | else | ||
486 | net_dev->features &= ~features; | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable) | ||
492 | { | ||
493 | struct efx_nic *efx = netdev_priv(net_dev); | ||
494 | unsigned long features = efx->type->offload_features & NETIF_F_ALL_CSUM; | ||
495 | |||
496 | if (enable) | ||
497 | net_dev->features |= features; | ||
498 | else | ||
499 | net_dev->features &= ~features; | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
466 | static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable) | 504 | static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable) |
467 | { | 505 | { |
468 | struct efx_nic *efx = netdev_priv(net_dev); | 506 | struct efx_nic *efx = netdev_priv(net_dev); |
@@ -537,7 +575,7 @@ static u32 efx_ethtool_get_link(struct net_device *net_dev) | |||
537 | { | 575 | { |
538 | struct efx_nic *efx = netdev_priv(net_dev); | 576 | struct efx_nic *efx = netdev_priv(net_dev); |
539 | 577 | ||
540 | return efx->link_up; | 578 | return efx->link_state.up; |
541 | } | 579 | } |
542 | 580 | ||
543 | static int efx_ethtool_get_eeprom_len(struct net_device *net_dev) | 581 | static int efx_ethtool_get_eeprom_len(struct net_device *net_dev) |
@@ -562,7 +600,8 @@ static int efx_ethtool_get_eeprom(struct net_device *net_dev, | |||
562 | rc = mutex_lock_interruptible(&efx->spi_lock); | 600 | rc = mutex_lock_interruptible(&efx->spi_lock); |
563 | if (rc) | 601 | if (rc) |
564 | return rc; | 602 | return rc; |
565 | rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, | 603 | rc = falcon_spi_read(efx, spi, |
604 | eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, | ||
566 | eeprom->len, &len, buf); | 605 | eeprom->len, &len, buf); |
567 | mutex_unlock(&efx->spi_lock); | 606 | mutex_unlock(&efx->spi_lock); |
568 | 607 | ||
@@ -585,7 +624,8 @@ static int efx_ethtool_set_eeprom(struct net_device *net_dev, | |||
585 | rc = mutex_lock_interruptible(&efx->spi_lock); | 624 | rc = mutex_lock_interruptible(&efx->spi_lock); |
586 | if (rc) | 625 | if (rc) |
587 | return rc; | 626 | return rc; |
588 | rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, | 627 | rc = falcon_spi_write(efx, spi, |
628 | eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, | ||
589 | eeprom->len, &len, buf); | 629 | eeprom->len, &len, buf); |
590 | mutex_unlock(&efx->spi_lock); | 630 | mutex_unlock(&efx->spi_lock); |
591 | 631 | ||
@@ -618,6 +658,9 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev, | |||
618 | coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive; | 658 | coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive; |
619 | coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation; | 659 | coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation; |
620 | 660 | ||
661 | coalesce->tx_coalesce_usecs_irq *= EFX_IRQ_MOD_RESOLUTION; | ||
662 | coalesce->rx_coalesce_usecs_irq *= EFX_IRQ_MOD_RESOLUTION; | ||
663 | |||
621 | return 0; | 664 | return 0; |
622 | } | 665 | } |
623 | 666 | ||
@@ -656,13 +699,8 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, | |||
656 | } | 699 | } |
657 | 700 | ||
658 | efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive); | 701 | efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive); |
659 | |||
660 | /* Reset channel to pick up new moderation value. Note that | ||
661 | * this may change the value of the irq_moderation field | ||
662 | * (e.g. to allow for hardware timer granularity). | ||
663 | */ | ||
664 | efx_for_each_channel(channel, efx) | 702 | efx_for_each_channel(channel, efx) |
665 | falcon_set_int_moderation(channel); | 703 | efx->type->push_irq_moderation(channel); |
666 | 704 | ||
667 | return 0; | 705 | return 0; |
668 | } | 706 | } |
@@ -671,8 +709,12 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
671 | struct ethtool_pauseparam *pause) | 709 | struct ethtool_pauseparam *pause) |
672 | { | 710 | { |
673 | struct efx_nic *efx = netdev_priv(net_dev); | 711 | struct efx_nic *efx = netdev_priv(net_dev); |
674 | enum efx_fc_type wanted_fc; | 712 | enum efx_fc_type wanted_fc, old_fc; |
713 | u32 old_adv; | ||
675 | bool reset; | 714 | bool reset; |
715 | int rc = 0; | ||
716 | |||
717 | mutex_lock(&efx->mac_lock); | ||
676 | 718 | ||
677 | wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) | | 719 | wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) | |
678 | (pause->tx_pause ? EFX_FC_TX : 0) | | 720 | (pause->tx_pause ? EFX_FC_TX : 0) | |
@@ -680,14 +722,14 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
680 | 722 | ||
681 | if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) { | 723 | if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) { |
682 | EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n"); | 724 | EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n"); |
683 | return -EINVAL; | 725 | rc = -EINVAL; |
726 | goto out; | ||
684 | } | 727 | } |
685 | 728 | ||
686 | if (!(efx->phy_op->mmds & MDIO_DEVS_AN) && | 729 | if ((wanted_fc & EFX_FC_AUTO) && !efx->link_advertising) { |
687 | (wanted_fc & EFX_FC_AUTO)) { | 730 | EFX_LOG(efx, "Autonegotiation is disabled\n"); |
688 | EFX_LOG(efx, "PHY does not support flow control " | 731 | rc = -EINVAL; |
689 | "autonegotiation\n"); | 732 | goto out; |
690 | return -EINVAL; | ||
691 | } | 733 | } |
692 | 734 | ||
693 | /* TX flow control may automatically turn itself off if the | 735 | /* TX flow control may automatically turn itself off if the |
@@ -697,27 +739,40 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, | |||
697 | * and fix it be cycling transmit flow control on this end. */ | 739 | * and fix it be cycling transmit flow control on this end. */ |
698 | reset = (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX); | 740 | reset = (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX); |
699 | if (EFX_WORKAROUND_11482(efx) && reset) { | 741 | if (EFX_WORKAROUND_11482(efx) && reset) { |
700 | if (falcon_rev(efx) >= FALCON_REV_B0) { | 742 | if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) { |
701 | /* Recover by resetting the EM block */ | 743 | /* Recover by resetting the EM block */ |
702 | if (efx->link_up) | 744 | falcon_stop_nic_stats(efx); |
703 | falcon_drain_tx_fifo(efx); | 745 | falcon_drain_tx_fifo(efx); |
746 | efx->mac_op->reconfigure(efx); | ||
747 | falcon_start_nic_stats(efx); | ||
704 | } else { | 748 | } else { |
705 | /* Schedule a reset to recover */ | 749 | /* Schedule a reset to recover */ |
706 | efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); | 750 | efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); |
707 | } | 751 | } |
708 | } | 752 | } |
709 | 753 | ||
710 | /* Try to push the pause parameters */ | 754 | old_adv = efx->link_advertising; |
711 | mutex_lock(&efx->mac_lock); | 755 | old_fc = efx->wanted_fc; |
756 | efx_link_set_wanted_fc(efx, wanted_fc); | ||
757 | if (efx->link_advertising != old_adv || | ||
758 | (efx->wanted_fc ^ old_fc) & EFX_FC_AUTO) { | ||
759 | rc = efx->phy_op->reconfigure(efx); | ||
760 | if (rc) { | ||
761 | EFX_ERR(efx, "Unable to advertise requested flow " | ||
762 | "control setting\n"); | ||
763 | goto out; | ||
764 | } | ||
765 | } | ||
712 | 766 | ||
713 | efx->wanted_fc = wanted_fc; | 767 | /* Reconfigure the MAC. The PHY *may* generate a link state change event |
714 | if (efx->phy_op->mmds & MDIO_DEVS_AN) | 768 | * if the user just changed the advertised capabilities, but there's no |
715 | mdio45_ethtool_spauseparam_an(&efx->mdio, pause); | 769 | * harm doing this twice */ |
716 | __efx_reconfigure_port(efx); | 770 | efx->mac_op->reconfigure(efx); |
717 | 771 | ||
772 | out: | ||
718 | mutex_unlock(&efx->mac_lock); | 773 | mutex_unlock(&efx->mac_lock); |
719 | 774 | ||
720 | return 0; | 775 | return rc; |
721 | } | 776 | } |
722 | 777 | ||
723 | static void efx_ethtool_get_pauseparam(struct net_device *net_dev, | 778 | static void efx_ethtool_get_pauseparam(struct net_device *net_dev, |
@@ -731,6 +786,50 @@ static void efx_ethtool_get_pauseparam(struct net_device *net_dev, | |||
731 | } | 786 | } |
732 | 787 | ||
733 | 788 | ||
789 | static void efx_ethtool_get_wol(struct net_device *net_dev, | ||
790 | struct ethtool_wolinfo *wol) | ||
791 | { | ||
792 | struct efx_nic *efx = netdev_priv(net_dev); | ||
793 | return efx->type->get_wol(efx, wol); | ||
794 | } | ||
795 | |||
796 | |||
797 | static int efx_ethtool_set_wol(struct net_device *net_dev, | ||
798 | struct ethtool_wolinfo *wol) | ||
799 | { | ||
800 | struct efx_nic *efx = netdev_priv(net_dev); | ||
801 | return efx->type->set_wol(efx, wol->wolopts); | ||
802 | } | ||
803 | |||
804 | extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) | ||
805 | { | ||
806 | struct efx_nic *efx = netdev_priv(net_dev); | ||
807 | enum reset_type method; | ||
808 | enum { | ||
809 | ETH_RESET_EFX_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER | | ||
810 | ETH_RESET_OFFLOAD | ETH_RESET_MAC) | ||
811 | }; | ||
812 | |||
813 | /* Check for minimal reset flags */ | ||
814 | if ((*flags & ETH_RESET_EFX_INVISIBLE) != ETH_RESET_EFX_INVISIBLE) | ||
815 | return -EINVAL; | ||
816 | *flags ^= ETH_RESET_EFX_INVISIBLE; | ||
817 | method = RESET_TYPE_INVISIBLE; | ||
818 | |||
819 | if (*flags & ETH_RESET_PHY) { | ||
820 | *flags ^= ETH_RESET_PHY; | ||
821 | method = RESET_TYPE_ALL; | ||
822 | } | ||
823 | |||
824 | if ((*flags & efx->type->reset_world_flags) == | ||
825 | efx->type->reset_world_flags) { | ||
826 | *flags ^= efx->type->reset_world_flags; | ||
827 | method = RESET_TYPE_WORLD; | ||
828 | } | ||
829 | |||
830 | return efx_reset(efx, method); | ||
831 | } | ||
832 | |||
734 | const struct ethtool_ops efx_ethtool_ops = { | 833 | const struct ethtool_ops efx_ethtool_ops = { |
735 | .get_settings = efx_ethtool_get_settings, | 834 | .get_settings = efx_ethtool_get_settings, |
736 | .set_settings = efx_ethtool_set_settings, | 835 | .set_settings = efx_ethtool_set_settings, |
@@ -747,11 +846,13 @@ const struct ethtool_ops efx_ethtool_ops = { | |||
747 | .get_rx_csum = efx_ethtool_get_rx_csum, | 846 | .get_rx_csum = efx_ethtool_get_rx_csum, |
748 | .set_rx_csum = efx_ethtool_set_rx_csum, | 847 | .set_rx_csum = efx_ethtool_set_rx_csum, |
749 | .get_tx_csum = ethtool_op_get_tx_csum, | 848 | .get_tx_csum = ethtool_op_get_tx_csum, |
750 | .set_tx_csum = ethtool_op_set_tx_csum, | 849 | /* Need to enable/disable IPv6 too */ |
850 | .set_tx_csum = efx_ethtool_set_tx_csum, | ||
751 | .get_sg = ethtool_op_get_sg, | 851 | .get_sg = ethtool_op_get_sg, |
752 | .set_sg = ethtool_op_set_sg, | 852 | .set_sg = ethtool_op_set_sg, |
753 | .get_tso = ethtool_op_get_tso, | 853 | .get_tso = ethtool_op_get_tso, |
754 | .set_tso = ethtool_op_set_tso, | 854 | /* Need to enable/disable TSO-IPv6 too */ |
855 | .set_tso = efx_ethtool_set_tso, | ||
755 | .get_flags = ethtool_op_get_flags, | 856 | .get_flags = ethtool_op_get_flags, |
756 | .set_flags = ethtool_op_set_flags, | 857 | .set_flags = ethtool_op_set_flags, |
757 | .get_sset_count = efx_ethtool_get_sset_count, | 858 | .get_sset_count = efx_ethtool_get_sset_count, |
@@ -759,4 +860,7 @@ const struct ethtool_ops efx_ethtool_ops = { | |||
759 | .get_strings = efx_ethtool_get_strings, | 860 | .get_strings = efx_ethtool_get_strings, |
760 | .phys_id = efx_ethtool_phys_id, | 861 | .phys_id = efx_ethtool_phys_id, |
761 | .get_ethtool_stats = efx_ethtool_get_stats, | 862 | .get_ethtool_stats = efx_ethtool_get_stats, |
863 | .get_wol = efx_ethtool_get_wol, | ||
864 | .set_wol = efx_ethtool_set_wol, | ||
865 | .reset = efx_ethtool_reset, | ||
762 | }; | 866 | }; |