aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/ethtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc/ethtool.c')
-rw-r--r--drivers/net/sfc/ethtool.c222
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
24const 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
37struct ethtool_string { 22struct 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
474static 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
491static 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
466static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable) 504static 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
543static int efx_ethtool_get_eeprom_len(struct net_device *net_dev) 581static 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
772out:
718 mutex_unlock(&efx->mac_lock); 773 mutex_unlock(&efx->mac_lock);
719 774
720 return 0; 775 return rc;
721} 776}
722 777
723static void efx_ethtool_get_pauseparam(struct net_device *net_dev, 778static 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
789static 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
797static 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
804extern 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
734const struct ethtool_ops efx_ethtool_ops = { 833const 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};