Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.28-rc1 727 lines 22 kB view raw
1/**************************************************************************** 2 * Driver for Solarflare Solarstorm network controllers and boards 3 * Copyright 2005-2006 Fen Systems Ltd. 4 * Copyright 2006-2008 Solarflare Communications Inc. 5 * 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 8 * by the Free Software Foundation, incorporated herein by reference. 9 */ 10 11#include <linux/netdevice.h> 12#include <linux/ethtool.h> 13#include <linux/rtnetlink.h> 14#include "net_driver.h" 15#include "selftest.h" 16#include "efx.h" 17#include "ethtool.h" 18#include "falcon.h" 19#include "gmii.h" 20#include "spi.h" 21#include "mac.h" 22 23const char *efx_loopback_mode_names[] = { 24 [LOOPBACK_NONE] = "NONE", 25 [LOOPBACK_MAC] = "MAC", 26 [LOOPBACK_XGMII] = "XGMII", 27 [LOOPBACK_XGXS] = "XGXS", 28 [LOOPBACK_XAUI] = "XAUI", 29 [LOOPBACK_PHY] = "PHY", 30 [LOOPBACK_PHYXS] = "PHY(XS)", 31 [LOOPBACK_PCS] = "PHY(PCS)", 32 [LOOPBACK_PMAPMD] = "PHY(PMAPMD)", 33 [LOOPBACK_NETWORK] = "NETWORK", 34}; 35 36struct ethtool_string { 37 char name[ETH_GSTRING_LEN]; 38}; 39 40struct efx_ethtool_stat { 41 const char *name; 42 enum { 43 EFX_ETHTOOL_STAT_SOURCE_mac_stats, 44 EFX_ETHTOOL_STAT_SOURCE_nic, 45 EFX_ETHTOOL_STAT_SOURCE_channel 46 } source; 47 unsigned offset; 48 u64(*get_stat) (void *field); /* Reader function */ 49}; 50 51/* Initialiser for a struct #efx_ethtool_stat with type-checking */ 52#define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \ 53 get_stat_function) { \ 54 .name = #stat_name, \ 55 .source = EFX_ETHTOOL_STAT_SOURCE_##source_name, \ 56 .offset = ((((field_type *) 0) == \ 57 &((struct efx_##source_name *)0)->field) ? \ 58 offsetof(struct efx_##source_name, field) : \ 59 offsetof(struct efx_##source_name, field)), \ 60 .get_stat = get_stat_function, \ 61} 62 63static u64 efx_get_uint_stat(void *field) 64{ 65 return *(unsigned int *)field; 66} 67 68static u64 efx_get_ulong_stat(void *field) 69{ 70 return *(unsigned long *)field; 71} 72 73static u64 efx_get_u64_stat(void *field) 74{ 75 return *(u64 *) field; 76} 77 78static u64 efx_get_atomic_stat(void *field) 79{ 80 return atomic_read((atomic_t *) field); 81} 82 83#define EFX_ETHTOOL_ULONG_MAC_STAT(field) \ 84 EFX_ETHTOOL_STAT(field, mac_stats, field, \ 85 unsigned long, efx_get_ulong_stat) 86 87#define EFX_ETHTOOL_U64_MAC_STAT(field) \ 88 EFX_ETHTOOL_STAT(field, mac_stats, field, \ 89 u64, efx_get_u64_stat) 90 91#define EFX_ETHTOOL_UINT_NIC_STAT(name) \ 92 EFX_ETHTOOL_STAT(name, nic, n_##name, \ 93 unsigned int, efx_get_uint_stat) 94 95#define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \ 96 EFX_ETHTOOL_STAT(field, nic, field, \ 97 atomic_t, efx_get_atomic_stat) 98 99#define EFX_ETHTOOL_UINT_CHANNEL_STAT(field) \ 100 EFX_ETHTOOL_STAT(field, channel, n_##field, \ 101 unsigned int, efx_get_uint_stat) 102 103static struct efx_ethtool_stat efx_ethtool_stats[] = { 104 EFX_ETHTOOL_U64_MAC_STAT(tx_bytes), 105 EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes), 106 EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes), 107 EFX_ETHTOOL_ULONG_MAC_STAT(tx_packets), 108 EFX_ETHTOOL_ULONG_MAC_STAT(tx_bad), 109 EFX_ETHTOOL_ULONG_MAC_STAT(tx_pause), 110 EFX_ETHTOOL_ULONG_MAC_STAT(tx_control), 111 EFX_ETHTOOL_ULONG_MAC_STAT(tx_unicast), 112 EFX_ETHTOOL_ULONG_MAC_STAT(tx_multicast), 113 EFX_ETHTOOL_ULONG_MAC_STAT(tx_broadcast), 114 EFX_ETHTOOL_ULONG_MAC_STAT(tx_lt64), 115 EFX_ETHTOOL_ULONG_MAC_STAT(tx_64), 116 EFX_ETHTOOL_ULONG_MAC_STAT(tx_65_to_127), 117 EFX_ETHTOOL_ULONG_MAC_STAT(tx_128_to_255), 118 EFX_ETHTOOL_ULONG_MAC_STAT(tx_256_to_511), 119 EFX_ETHTOOL_ULONG_MAC_STAT(tx_512_to_1023), 120 EFX_ETHTOOL_ULONG_MAC_STAT(tx_1024_to_15xx), 121 EFX_ETHTOOL_ULONG_MAC_STAT(tx_15xx_to_jumbo), 122 EFX_ETHTOOL_ULONG_MAC_STAT(tx_gtjumbo), 123 EFX_ETHTOOL_ULONG_MAC_STAT(tx_collision), 124 EFX_ETHTOOL_ULONG_MAC_STAT(tx_single_collision), 125 EFX_ETHTOOL_ULONG_MAC_STAT(tx_multiple_collision), 126 EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_collision), 127 EFX_ETHTOOL_ULONG_MAC_STAT(tx_deferred), 128 EFX_ETHTOOL_ULONG_MAC_STAT(tx_late_collision), 129 EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_deferred), 130 EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp), 131 EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error), 132 EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error), 133 EFX_ETHTOOL_U64_MAC_STAT(rx_bytes), 134 EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes), 135 EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes), 136 EFX_ETHTOOL_ULONG_MAC_STAT(rx_packets), 137 EFX_ETHTOOL_ULONG_MAC_STAT(rx_good), 138 EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad), 139 EFX_ETHTOOL_ULONG_MAC_STAT(rx_pause), 140 EFX_ETHTOOL_ULONG_MAC_STAT(rx_control), 141 EFX_ETHTOOL_ULONG_MAC_STAT(rx_unicast), 142 EFX_ETHTOOL_ULONG_MAC_STAT(rx_multicast), 143 EFX_ETHTOOL_ULONG_MAC_STAT(rx_broadcast), 144 EFX_ETHTOOL_ULONG_MAC_STAT(rx_lt64), 145 EFX_ETHTOOL_ULONG_MAC_STAT(rx_64), 146 EFX_ETHTOOL_ULONG_MAC_STAT(rx_65_to_127), 147 EFX_ETHTOOL_ULONG_MAC_STAT(rx_128_to_255), 148 EFX_ETHTOOL_ULONG_MAC_STAT(rx_256_to_511), 149 EFX_ETHTOOL_ULONG_MAC_STAT(rx_512_to_1023), 150 EFX_ETHTOOL_ULONG_MAC_STAT(rx_1024_to_15xx), 151 EFX_ETHTOOL_ULONG_MAC_STAT(rx_15xx_to_jumbo), 152 EFX_ETHTOOL_ULONG_MAC_STAT(rx_gtjumbo), 153 EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_lt64), 154 EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_64_to_15xx), 155 EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_15xx_to_jumbo), 156 EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_gtjumbo), 157 EFX_ETHTOOL_ULONG_MAC_STAT(rx_overflow), 158 EFX_ETHTOOL_ULONG_MAC_STAT(rx_missed), 159 EFX_ETHTOOL_ULONG_MAC_STAT(rx_false_carrier), 160 EFX_ETHTOOL_ULONG_MAC_STAT(rx_symbol_error), 161 EFX_ETHTOOL_ULONG_MAC_STAT(rx_align_error), 162 EFX_ETHTOOL_ULONG_MAC_STAT(rx_length_error), 163 EFX_ETHTOOL_ULONG_MAC_STAT(rx_internal_error), 164 EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt), 165 EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset), 166 EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), 167 EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err), 168 EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err), 169 EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc), 170}; 171 172/* Number of ethtool statistics */ 173#define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats) 174 175/* EEPROM range with gPXE configuration */ 176#define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB 177#define EFX_ETHTOOL_EEPROM_MIN 0x100U 178#define EFX_ETHTOOL_EEPROM_MAX 0x400U 179 180/************************************************************************** 181 * 182 * Ethtool operations 183 * 184 ************************************************************************** 185 */ 186 187/* Identify device by flashing LEDs */ 188static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds) 189{ 190 struct efx_nic *efx = netdev_priv(net_dev); 191 192 efx->board_info.blink(efx, 1); 193 schedule_timeout_interruptible(seconds * HZ); 194 efx->board_info.blink(efx, 0); 195 return 0; 196} 197 198/* This must be called with rtnl_lock held. */ 199int efx_ethtool_get_settings(struct net_device *net_dev, 200 struct ethtool_cmd *ecmd) 201{ 202 struct efx_nic *efx = netdev_priv(net_dev); 203 int rc; 204 205 mutex_lock(&efx->mac_lock); 206 rc = falcon_xmac_get_settings(efx, ecmd); 207 mutex_unlock(&efx->mac_lock); 208 209 return rc; 210} 211 212/* This must be called with rtnl_lock held. */ 213int efx_ethtool_set_settings(struct net_device *net_dev, 214 struct ethtool_cmd *ecmd) 215{ 216 struct efx_nic *efx = netdev_priv(net_dev); 217 int rc; 218 219 mutex_lock(&efx->mac_lock); 220 rc = falcon_xmac_set_settings(efx, ecmd); 221 mutex_unlock(&efx->mac_lock); 222 if (!rc) 223 efx_reconfigure_port(efx); 224 225 return rc; 226} 227 228static void efx_ethtool_get_drvinfo(struct net_device *net_dev, 229 struct ethtool_drvinfo *info) 230{ 231 struct efx_nic *efx = netdev_priv(net_dev); 232 233 strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver)); 234 strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version)); 235 strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info)); 236} 237 238/** 239 * efx_fill_test - fill in an individual self-test entry 240 * @test_index: Index of the test 241 * @strings: Ethtool strings, or %NULL 242 * @data: Ethtool test results, or %NULL 243 * @test: Pointer to test result (used only if data != %NULL) 244 * @unit_format: Unit name format (e.g. "channel\%d") 245 * @unit_id: Unit id (e.g. 0 for "channel0") 246 * @test_format: Test name format (e.g. "loopback.\%s.tx.sent") 247 * @test_id: Test id (e.g. "PHY" for "loopback.PHY.tx_sent") 248 * 249 * Fill in an individual self-test entry. 250 */ 251static void efx_fill_test(unsigned int test_index, 252 struct ethtool_string *strings, u64 *data, 253 int *test, const char *unit_format, int unit_id, 254 const char *test_format, const char *test_id) 255{ 256 struct ethtool_string unit_str, test_str; 257 258 /* Fill data value, if applicable */ 259 if (data) 260 data[test_index] = *test; 261 262 /* Fill string, if applicable */ 263 if (strings) { 264 snprintf(unit_str.name, sizeof(unit_str.name), 265 unit_format, unit_id); 266 snprintf(test_str.name, sizeof(test_str.name), 267 test_format, test_id); 268 snprintf(strings[test_index].name, 269 sizeof(strings[test_index].name), 270 "%-9s%-17s", unit_str.name, test_str.name); 271 } 272} 273 274#define EFX_PORT_NAME "port%d", 0 275#define EFX_CHANNEL_NAME(_channel) "channel%d", _channel->channel 276#define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue 277#define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue 278#define EFX_LOOPBACK_NAME(_mode, _counter) \ 279 "loopback.%s." _counter, LOOPBACK_MODE_NAME(mode) 280 281/** 282 * efx_fill_loopback_test - fill in a block of loopback self-test entries 283 * @efx: Efx NIC 284 * @lb_tests: Efx loopback self-test results structure 285 * @mode: Loopback test mode 286 * @test_index: Starting index of the test 287 * @strings: Ethtool strings, or %NULL 288 * @data: Ethtool test results, or %NULL 289 */ 290static int efx_fill_loopback_test(struct efx_nic *efx, 291 struct efx_loopback_self_tests *lb_tests, 292 enum efx_loopback_mode mode, 293 unsigned int test_index, 294 struct ethtool_string *strings, u64 *data) 295{ 296 struct efx_tx_queue *tx_queue; 297 298 efx_for_each_tx_queue(tx_queue, efx) { 299 efx_fill_test(test_index++, strings, data, 300 &lb_tests->tx_sent[tx_queue->queue], 301 EFX_TX_QUEUE_NAME(tx_queue), 302 EFX_LOOPBACK_NAME(mode, "tx_sent")); 303 efx_fill_test(test_index++, strings, data, 304 &lb_tests->tx_done[tx_queue->queue], 305 EFX_TX_QUEUE_NAME(tx_queue), 306 EFX_LOOPBACK_NAME(mode, "tx_done")); 307 } 308 efx_fill_test(test_index++, strings, data, 309 &lb_tests->rx_good, 310 EFX_PORT_NAME, 311 EFX_LOOPBACK_NAME(mode, "rx_good")); 312 efx_fill_test(test_index++, strings, data, 313 &lb_tests->rx_bad, 314 EFX_PORT_NAME, 315 EFX_LOOPBACK_NAME(mode, "rx_bad")); 316 317 return test_index; 318} 319 320/** 321 * efx_ethtool_fill_self_tests - get self-test details 322 * @efx: Efx NIC 323 * @tests: Efx self-test results structure, or %NULL 324 * @strings: Ethtool strings, or %NULL 325 * @data: Ethtool test results, or %NULL 326 */ 327static int efx_ethtool_fill_self_tests(struct efx_nic *efx, 328 struct efx_self_tests *tests, 329 struct ethtool_string *strings, 330 u64 *data) 331{ 332 struct efx_channel *channel; 333 unsigned int n = 0; 334 enum efx_loopback_mode mode; 335 336 efx_fill_test(n++, strings, data, &tests->mii, 337 "core", 0, "mii", NULL); 338 efx_fill_test(n++, strings, data, &tests->nvram, 339 "core", 0, "nvram", NULL); 340 efx_fill_test(n++, strings, data, &tests->interrupt, 341 "core", 0, "interrupt", NULL); 342 343 /* Event queues */ 344 efx_for_each_channel(channel, efx) { 345 efx_fill_test(n++, strings, data, 346 &tests->eventq_dma[channel->channel], 347 EFX_CHANNEL_NAME(channel), 348 "eventq.dma", NULL); 349 efx_fill_test(n++, strings, data, 350 &tests->eventq_int[channel->channel], 351 EFX_CHANNEL_NAME(channel), 352 "eventq.int", NULL); 353 efx_fill_test(n++, strings, data, 354 &tests->eventq_poll[channel->channel], 355 EFX_CHANNEL_NAME(channel), 356 "eventq.poll", NULL); 357 } 358 359 efx_fill_test(n++, strings, data, &tests->registers, 360 "core", 0, "registers", NULL); 361 efx_fill_test(n++, strings, data, &tests->phy, 362 EFX_PORT_NAME, "phy", NULL); 363 364 /* Loopback tests */ 365 efx_fill_test(n++, strings, data, &tests->loopback_speed, 366 EFX_PORT_NAME, "loopback.speed", NULL); 367 efx_fill_test(n++, strings, data, &tests->loopback_full_duplex, 368 EFX_PORT_NAME, "loopback.full_duplex", NULL); 369 for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { 370 if (!(efx->loopback_modes & (1 << mode))) 371 continue; 372 n = efx_fill_loopback_test(efx, 373 &tests->loopback[mode], mode, n, 374 strings, data); 375 } 376 377 return n; 378} 379 380static int efx_ethtool_get_sset_count(struct net_device *net_dev, 381 int string_set) 382{ 383 switch (string_set) { 384 case ETH_SS_STATS: 385 return EFX_ETHTOOL_NUM_STATS; 386 case ETH_SS_TEST: 387 return efx_ethtool_fill_self_tests(netdev_priv(net_dev), 388 NULL, NULL, NULL); 389 default: 390 return -EINVAL; 391 } 392} 393 394static void efx_ethtool_get_strings(struct net_device *net_dev, 395 u32 string_set, u8 *strings) 396{ 397 struct efx_nic *efx = netdev_priv(net_dev); 398 struct ethtool_string *ethtool_strings = 399 (struct ethtool_string *)strings; 400 int i; 401 402 switch (string_set) { 403 case ETH_SS_STATS: 404 for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) 405 strncpy(ethtool_strings[i].name, 406 efx_ethtool_stats[i].name, 407 sizeof(ethtool_strings[i].name)); 408 break; 409 case ETH_SS_TEST: 410 efx_ethtool_fill_self_tests(efx, NULL, 411 ethtool_strings, NULL); 412 break; 413 default: 414 /* No other string sets */ 415 break; 416 } 417} 418 419static void efx_ethtool_get_stats(struct net_device *net_dev, 420 struct ethtool_stats *stats, 421 u64 *data) 422{ 423 struct efx_nic *efx = netdev_priv(net_dev); 424 struct efx_mac_stats *mac_stats = &efx->mac_stats; 425 struct efx_ethtool_stat *stat; 426 struct efx_channel *channel; 427 int i; 428 429 EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS); 430 431 /* Update MAC and NIC statistics */ 432 net_dev->get_stats(net_dev); 433 434 /* Fill detailed statistics buffer */ 435 for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) { 436 stat = &efx_ethtool_stats[i]; 437 switch (stat->source) { 438 case EFX_ETHTOOL_STAT_SOURCE_mac_stats: 439 data[i] = stat->get_stat((void *)mac_stats + 440 stat->offset); 441 break; 442 case EFX_ETHTOOL_STAT_SOURCE_nic: 443 data[i] = stat->get_stat((void *)efx + stat->offset); 444 break; 445 case EFX_ETHTOOL_STAT_SOURCE_channel: 446 data[i] = 0; 447 efx_for_each_channel(channel, efx) 448 data[i] += stat->get_stat((void *)channel + 449 stat->offset); 450 break; 451 } 452 } 453} 454 455static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable) 456{ 457 struct efx_nic *efx = netdev_priv(net_dev); 458 459 /* No way to stop the hardware doing the checks; we just 460 * ignore the result. 461 */ 462 efx->rx_checksum_enabled = !!enable; 463 464 return 0; 465} 466 467static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev) 468{ 469 struct efx_nic *efx = netdev_priv(net_dev); 470 471 return efx->rx_checksum_enabled; 472} 473 474static void efx_ethtool_self_test(struct net_device *net_dev, 475 struct ethtool_test *test, u64 *data) 476{ 477 struct efx_nic *efx = netdev_priv(net_dev); 478 struct efx_self_tests efx_tests; 479 int offline, already_up; 480 int rc; 481 482 ASSERT_RTNL(); 483 if (efx->state != STATE_RUNNING) { 484 rc = -EIO; 485 goto fail1; 486 } 487 488 /* We need rx buffers and interrupts. */ 489 already_up = (efx->net_dev->flags & IFF_UP); 490 if (!already_up) { 491 rc = dev_open(efx->net_dev); 492 if (rc) { 493 EFX_ERR(efx, "failed opening device.\n"); 494 goto fail2; 495 } 496 } 497 498 memset(&efx_tests, 0, sizeof(efx_tests)); 499 offline = (test->flags & ETH_TEST_FL_OFFLINE); 500 501 /* Perform online self tests first */ 502 rc = efx_online_test(efx, &efx_tests); 503 if (rc) 504 goto out; 505 506 /* Perform offline tests only if online tests passed */ 507 if (offline) 508 rc = efx_offline_test(efx, &efx_tests, 509 efx->loopback_modes); 510 511 out: 512 if (!already_up) 513 dev_close(efx->net_dev); 514 515 EFX_LOG(efx, "%s all %sline self-tests\n", 516 rc == 0 ? "passed" : "failed", offline ? "off" : "on"); 517 518 fail2: 519 fail1: 520 /* Fill ethtool results structures */ 521 efx_ethtool_fill_self_tests(efx, &efx_tests, NULL, data); 522 if (rc) 523 test->flags |= ETH_TEST_FL_FAILED; 524} 525 526/* Restart autonegotiation */ 527static int efx_ethtool_nway_reset(struct net_device *net_dev) 528{ 529 struct efx_nic *efx = netdev_priv(net_dev); 530 531 return mii_nway_restart(&efx->mii); 532} 533 534static u32 efx_ethtool_get_link(struct net_device *net_dev) 535{ 536 struct efx_nic *efx = netdev_priv(net_dev); 537 538 return efx->link_up; 539} 540 541static int efx_ethtool_get_eeprom_len(struct net_device *net_dev) 542{ 543 struct efx_nic *efx = netdev_priv(net_dev); 544 struct efx_spi_device *spi = efx->spi_eeprom; 545 546 if (!spi) 547 return 0; 548 return min(spi->size, EFX_ETHTOOL_EEPROM_MAX) - 549 min(spi->size, EFX_ETHTOOL_EEPROM_MIN); 550} 551 552static int efx_ethtool_get_eeprom(struct net_device *net_dev, 553 struct ethtool_eeprom *eeprom, u8 *buf) 554{ 555 struct efx_nic *efx = netdev_priv(net_dev); 556 struct efx_spi_device *spi = efx->spi_eeprom; 557 size_t len; 558 int rc; 559 560 rc = falcon_spi_read(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN, 561 eeprom->len, &len, buf); 562 eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC; 563 eeprom->len = len; 564 return rc; 565} 566 567static int efx_ethtool_set_eeprom(struct net_device *net_dev, 568 struct ethtool_eeprom *eeprom, u8 *buf) 569{ 570 struct efx_nic *efx = netdev_priv(net_dev); 571 struct efx_spi_device *spi = efx->spi_eeprom; 572 size_t len; 573 int rc; 574 575 if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC) 576 return -EINVAL; 577 578 rc = falcon_spi_write(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN, 579 eeprom->len, &len, buf); 580 eeprom->len = len; 581 return rc; 582} 583 584static int efx_ethtool_get_coalesce(struct net_device *net_dev, 585 struct ethtool_coalesce *coalesce) 586{ 587 struct efx_nic *efx = netdev_priv(net_dev); 588 struct efx_tx_queue *tx_queue; 589 struct efx_rx_queue *rx_queue; 590 struct efx_channel *channel; 591 592 memset(coalesce, 0, sizeof(*coalesce)); 593 594 /* Find lowest IRQ moderation across all used TX queues */ 595 coalesce->tx_coalesce_usecs_irq = ~((u32) 0); 596 efx_for_each_tx_queue(tx_queue, efx) { 597 channel = tx_queue->channel; 598 if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) { 599 if (channel->used_flags != EFX_USED_BY_RX_TX) 600 coalesce->tx_coalesce_usecs_irq = 601 channel->irq_moderation; 602 else 603 coalesce->tx_coalesce_usecs_irq = 0; 604 } 605 } 606 607 /* Find lowest IRQ moderation across all used RX queues */ 608 coalesce->rx_coalesce_usecs_irq = ~((u32) 0); 609 efx_for_each_rx_queue(rx_queue, efx) { 610 channel = rx_queue->channel; 611 if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq) 612 coalesce->rx_coalesce_usecs_irq = 613 channel->irq_moderation; 614 } 615 616 return 0; 617} 618 619/* Set coalescing parameters 620 * The difficulties occur for shared channels 621 */ 622static int efx_ethtool_set_coalesce(struct net_device *net_dev, 623 struct ethtool_coalesce *coalesce) 624{ 625 struct efx_nic *efx = netdev_priv(net_dev); 626 struct efx_channel *channel; 627 struct efx_tx_queue *tx_queue; 628 unsigned tx_usecs, rx_usecs; 629 630 if (coalesce->use_adaptive_rx_coalesce || 631 coalesce->use_adaptive_tx_coalesce) 632 return -EOPNOTSUPP; 633 634 if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) { 635 EFX_ERR(efx, "invalid coalescing setting. " 636 "Only rx/tx_coalesce_usecs_irq are supported\n"); 637 return -EOPNOTSUPP; 638 } 639 640 rx_usecs = coalesce->rx_coalesce_usecs_irq; 641 tx_usecs = coalesce->tx_coalesce_usecs_irq; 642 643 /* If the channel is shared only allow RX parameters to be set */ 644 efx_for_each_tx_queue(tx_queue, efx) { 645 if ((tx_queue->channel->used_flags == EFX_USED_BY_RX_TX) && 646 tx_usecs) { 647 EFX_ERR(efx, "Channel is shared. " 648 "Only RX coalescing may be set\n"); 649 return -EOPNOTSUPP; 650 } 651 } 652 653 efx_init_irq_moderation(efx, tx_usecs, rx_usecs); 654 655 /* Reset channel to pick up new moderation value. Note that 656 * this may change the value of the irq_moderation field 657 * (e.g. to allow for hardware timer granularity). 658 */ 659 efx_for_each_channel(channel, efx) 660 falcon_set_int_moderation(channel); 661 662 return 0; 663} 664 665static int efx_ethtool_set_pauseparam(struct net_device *net_dev, 666 struct ethtool_pauseparam *pause) 667{ 668 struct efx_nic *efx = netdev_priv(net_dev); 669 enum efx_fc_type flow_control = efx->flow_control; 670 int rc; 671 672 flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO); 673 flow_control |= pause->rx_pause ? EFX_FC_RX : 0; 674 flow_control |= pause->tx_pause ? EFX_FC_TX : 0; 675 flow_control |= pause->autoneg ? EFX_FC_AUTO : 0; 676 677 /* Try to push the pause parameters */ 678 mutex_lock(&efx->mac_lock); 679 rc = falcon_xmac_set_pause(efx, flow_control); 680 mutex_unlock(&efx->mac_lock); 681 682 if (!rc) 683 efx_reconfigure_port(efx); 684 685 return rc; 686} 687 688static void efx_ethtool_get_pauseparam(struct net_device *net_dev, 689 struct ethtool_pauseparam *pause) 690{ 691 struct efx_nic *efx = netdev_priv(net_dev); 692 693 pause->rx_pause = !!(efx->flow_control & EFX_FC_RX); 694 pause->tx_pause = !!(efx->flow_control & EFX_FC_TX); 695 pause->autoneg = !!(efx->flow_control & EFX_FC_AUTO); 696} 697 698 699struct ethtool_ops efx_ethtool_ops = { 700 .get_settings = efx_ethtool_get_settings, 701 .set_settings = efx_ethtool_set_settings, 702 .get_drvinfo = efx_ethtool_get_drvinfo, 703 .nway_reset = efx_ethtool_nway_reset, 704 .get_link = efx_ethtool_get_link, 705 .get_eeprom_len = efx_ethtool_get_eeprom_len, 706 .get_eeprom = efx_ethtool_get_eeprom, 707 .set_eeprom = efx_ethtool_set_eeprom, 708 .get_coalesce = efx_ethtool_get_coalesce, 709 .set_coalesce = efx_ethtool_set_coalesce, 710 .get_pauseparam = efx_ethtool_get_pauseparam, 711 .set_pauseparam = efx_ethtool_set_pauseparam, 712 .get_rx_csum = efx_ethtool_get_rx_csum, 713 .set_rx_csum = efx_ethtool_set_rx_csum, 714 .get_tx_csum = ethtool_op_get_tx_csum, 715 .set_tx_csum = ethtool_op_set_tx_csum, 716 .get_sg = ethtool_op_get_sg, 717 .set_sg = ethtool_op_set_sg, 718 .get_tso = ethtool_op_get_tso, 719 .set_tso = ethtool_op_set_tso, 720 .get_flags = ethtool_op_get_flags, 721 .set_flags = ethtool_op_set_flags, 722 .get_sset_count = efx_ethtool_get_sset_count, 723 .self_test = efx_ethtool_self_test, 724 .get_strings = efx_ethtool_get_strings, 725 .phys_id = efx_ethtool_phys_id, 726 .get_ethtool_stats = efx_ethtool_get_stats, 727};