Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.34-rc4 1546 lines 37 kB view raw
1/* 2 * net/core/ethtool.c - Ethtool ioctl handler 3 * Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx> 4 * 5 * This file is where we call all the ethtool_ops commands to get 6 * the information ethtool needs. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14#include <linux/module.h> 15#include <linux/types.h> 16#include <linux/capability.h> 17#include <linux/errno.h> 18#include <linux/ethtool.h> 19#include <linux/netdevice.h> 20#include <linux/bitops.h> 21#include <linux/slab.h> 22#include <asm/uaccess.h> 23 24/* 25 * Some useful ethtool_ops methods that're device independent. 26 * If we find that all drivers want to do the same thing here, 27 * we can turn these into dev_() function calls. 28 */ 29 30u32 ethtool_op_get_link(struct net_device *dev) 31{ 32 return netif_carrier_ok(dev) ? 1 : 0; 33} 34 35u32 ethtool_op_get_rx_csum(struct net_device *dev) 36{ 37 return (dev->features & NETIF_F_ALL_CSUM) != 0; 38} 39EXPORT_SYMBOL(ethtool_op_get_rx_csum); 40 41u32 ethtool_op_get_tx_csum(struct net_device *dev) 42{ 43 return (dev->features & NETIF_F_ALL_CSUM) != 0; 44} 45EXPORT_SYMBOL(ethtool_op_get_tx_csum); 46 47int ethtool_op_set_tx_csum(struct net_device *dev, u32 data) 48{ 49 if (data) 50 dev->features |= NETIF_F_IP_CSUM; 51 else 52 dev->features &= ~NETIF_F_IP_CSUM; 53 54 return 0; 55} 56 57int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data) 58{ 59 if (data) 60 dev->features |= NETIF_F_HW_CSUM; 61 else 62 dev->features &= ~NETIF_F_HW_CSUM; 63 64 return 0; 65} 66 67int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data) 68{ 69 if (data) 70 dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; 71 else 72 dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); 73 74 return 0; 75} 76 77u32 ethtool_op_get_sg(struct net_device *dev) 78{ 79 return (dev->features & NETIF_F_SG) != 0; 80} 81 82int ethtool_op_set_sg(struct net_device *dev, u32 data) 83{ 84 if (data) 85 dev->features |= NETIF_F_SG; 86 else 87 dev->features &= ~NETIF_F_SG; 88 89 return 0; 90} 91 92u32 ethtool_op_get_tso(struct net_device *dev) 93{ 94 return (dev->features & NETIF_F_TSO) != 0; 95} 96 97int ethtool_op_set_tso(struct net_device *dev, u32 data) 98{ 99 if (data) 100 dev->features |= NETIF_F_TSO; 101 else 102 dev->features &= ~NETIF_F_TSO; 103 104 return 0; 105} 106 107u32 ethtool_op_get_ufo(struct net_device *dev) 108{ 109 return (dev->features & NETIF_F_UFO) != 0; 110} 111 112int ethtool_op_set_ufo(struct net_device *dev, u32 data) 113{ 114 if (data) 115 dev->features |= NETIF_F_UFO; 116 else 117 dev->features &= ~NETIF_F_UFO; 118 return 0; 119} 120 121/* the following list of flags are the same as their associated 122 * NETIF_F_xxx values in include/linux/netdevice.h 123 */ 124static const u32 flags_dup_features = 125 (ETH_FLAG_LRO | ETH_FLAG_NTUPLE); 126 127u32 ethtool_op_get_flags(struct net_device *dev) 128{ 129 /* in the future, this function will probably contain additional 130 * handling for flags which are not so easily handled 131 * by a simple masking operation 132 */ 133 134 return dev->features & flags_dup_features; 135} 136 137int ethtool_op_set_flags(struct net_device *dev, u32 data) 138{ 139 const struct ethtool_ops *ops = dev->ethtool_ops; 140 unsigned long features = dev->features; 141 142 if (data & ETH_FLAG_LRO) 143 features |= NETIF_F_LRO; 144 else 145 features &= ~NETIF_F_LRO; 146 147 if (data & ETH_FLAG_NTUPLE) { 148 if (!ops->set_rx_ntuple) 149 return -EOPNOTSUPP; 150 features |= NETIF_F_NTUPLE; 151 } else { 152 /* safe to clear regardless */ 153 features &= ~NETIF_F_NTUPLE; 154 } 155 156 dev->features = features; 157 return 0; 158} 159 160void ethtool_ntuple_flush(struct net_device *dev) 161{ 162 struct ethtool_rx_ntuple_flow_spec_container *fsc, *f; 163 164 list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) { 165 list_del(&fsc->list); 166 kfree(fsc); 167 } 168 dev->ethtool_ntuple_list.count = 0; 169} 170EXPORT_SYMBOL(ethtool_ntuple_flush); 171 172/* Handlers for each ethtool command */ 173 174static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) 175{ 176 struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; 177 int err; 178 179 if (!dev->ethtool_ops->get_settings) 180 return -EOPNOTSUPP; 181 182 err = dev->ethtool_ops->get_settings(dev, &cmd); 183 if (err < 0) 184 return err; 185 186 if (copy_to_user(useraddr, &cmd, sizeof(cmd))) 187 return -EFAULT; 188 return 0; 189} 190 191static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) 192{ 193 struct ethtool_cmd cmd; 194 195 if (!dev->ethtool_ops->set_settings) 196 return -EOPNOTSUPP; 197 198 if (copy_from_user(&cmd, useraddr, sizeof(cmd))) 199 return -EFAULT; 200 201 return dev->ethtool_ops->set_settings(dev, &cmd); 202} 203 204static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) 205{ 206 struct ethtool_drvinfo info; 207 const struct ethtool_ops *ops = dev->ethtool_ops; 208 209 if (!ops->get_drvinfo) 210 return -EOPNOTSUPP; 211 212 memset(&info, 0, sizeof(info)); 213 info.cmd = ETHTOOL_GDRVINFO; 214 ops->get_drvinfo(dev, &info); 215 216 /* 217 * this method of obtaining string set info is deprecated; 218 * Use ETHTOOL_GSSET_INFO instead. 219 */ 220 if (ops->get_sset_count) { 221 int rc; 222 223 rc = ops->get_sset_count(dev, ETH_SS_TEST); 224 if (rc >= 0) 225 info.testinfo_len = rc; 226 rc = ops->get_sset_count(dev, ETH_SS_STATS); 227 if (rc >= 0) 228 info.n_stats = rc; 229 rc = ops->get_sset_count(dev, ETH_SS_PRIV_FLAGS); 230 if (rc >= 0) 231 info.n_priv_flags = rc; 232 } 233 if (ops->get_regs_len) 234 info.regdump_len = ops->get_regs_len(dev); 235 if (ops->get_eeprom_len) 236 info.eedump_len = ops->get_eeprom_len(dev); 237 238 if (copy_to_user(useraddr, &info, sizeof(info))) 239 return -EFAULT; 240 return 0; 241} 242 243static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev, 244 void __user *useraddr) 245{ 246 struct ethtool_sset_info info; 247 const struct ethtool_ops *ops = dev->ethtool_ops; 248 u64 sset_mask; 249 int i, idx = 0, n_bits = 0, ret, rc; 250 u32 *info_buf = NULL; 251 252 if (!ops->get_sset_count) 253 return -EOPNOTSUPP; 254 255 if (copy_from_user(&info, useraddr, sizeof(info))) 256 return -EFAULT; 257 258 /* store copy of mask, because we zero struct later on */ 259 sset_mask = info.sset_mask; 260 if (!sset_mask) 261 return 0; 262 263 /* calculate size of return buffer */ 264 n_bits = hweight64(sset_mask); 265 266 memset(&info, 0, sizeof(info)); 267 info.cmd = ETHTOOL_GSSET_INFO; 268 269 info_buf = kzalloc(n_bits * sizeof(u32), GFP_USER); 270 if (!info_buf) 271 return -ENOMEM; 272 273 /* 274 * fill return buffer based on input bitmask and successful 275 * get_sset_count return 276 */ 277 for (i = 0; i < 64; i++) { 278 if (!(sset_mask & (1ULL << i))) 279 continue; 280 281 rc = ops->get_sset_count(dev, i); 282 if (rc >= 0) { 283 info.sset_mask |= (1ULL << i); 284 info_buf[idx++] = rc; 285 } 286 } 287 288 ret = -EFAULT; 289 if (copy_to_user(useraddr, &info, sizeof(info))) 290 goto out; 291 292 useraddr += offsetof(struct ethtool_sset_info, data); 293 if (copy_to_user(useraddr, info_buf, idx * sizeof(u32))) 294 goto out; 295 296 ret = 0; 297 298out: 299 kfree(info_buf); 300 return ret; 301} 302 303static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) 304{ 305 struct ethtool_rxnfc cmd; 306 307 if (!dev->ethtool_ops->set_rxnfc) 308 return -EOPNOTSUPP; 309 310 if (copy_from_user(&cmd, useraddr, sizeof(cmd))) 311 return -EFAULT; 312 313 return dev->ethtool_ops->set_rxnfc(dev, &cmd); 314} 315 316static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) 317{ 318 struct ethtool_rxnfc info; 319 const struct ethtool_ops *ops = dev->ethtool_ops; 320 int ret; 321 void *rule_buf = NULL; 322 323 if (!ops->get_rxnfc) 324 return -EOPNOTSUPP; 325 326 if (copy_from_user(&info, useraddr, sizeof(info))) 327 return -EFAULT; 328 329 if (info.cmd == ETHTOOL_GRXCLSRLALL) { 330 if (info.rule_cnt > 0) { 331 rule_buf = kmalloc(info.rule_cnt * sizeof(u32), 332 GFP_USER); 333 if (!rule_buf) 334 return -ENOMEM; 335 } 336 } 337 338 ret = ops->get_rxnfc(dev, &info, rule_buf); 339 if (ret < 0) 340 goto err_out; 341 342 ret = -EFAULT; 343 if (copy_to_user(useraddr, &info, sizeof(info))) 344 goto err_out; 345 346 if (rule_buf) { 347 useraddr += offsetof(struct ethtool_rxnfc, rule_locs); 348 if (copy_to_user(useraddr, rule_buf, 349 info.rule_cnt * sizeof(u32))) 350 goto err_out; 351 } 352 ret = 0; 353 354err_out: 355 kfree(rule_buf); 356 357 return ret; 358} 359 360static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, 361 struct ethtool_rx_ntuple_flow_spec *spec, 362 struct ethtool_rx_ntuple_flow_spec_container *fsc) 363{ 364 365 /* don't add filters forever */ 366 if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) { 367 /* free the container */ 368 kfree(fsc); 369 return; 370 } 371 372 /* Copy the whole filter over */ 373 fsc->fs.flow_type = spec->flow_type; 374 memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u)); 375 memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u)); 376 377 fsc->fs.vlan_tag = spec->vlan_tag; 378 fsc->fs.vlan_tag_mask = spec->vlan_tag_mask; 379 fsc->fs.data = spec->data; 380 fsc->fs.data_mask = spec->data_mask; 381 fsc->fs.action = spec->action; 382 383 /* add to the list */ 384 list_add_tail_rcu(&fsc->list, &list->list); 385 list->count++; 386} 387 388static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) 389{ 390 struct ethtool_rx_ntuple cmd; 391 const struct ethtool_ops *ops = dev->ethtool_ops; 392 struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; 393 int ret; 394 395 if (!(dev->features & NETIF_F_NTUPLE)) 396 return -EINVAL; 397 398 if (copy_from_user(&cmd, useraddr, sizeof(cmd))) 399 return -EFAULT; 400 401 /* 402 * Cache filter in dev struct for GET operation only if 403 * the underlying driver doesn't have its own GET operation, and 404 * only if the filter was added successfully. First make sure we 405 * can allocate the filter, then continue if successful. 406 */ 407 if (!ops->get_rx_ntuple) { 408 fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); 409 if (!fsc) 410 return -ENOMEM; 411 } 412 413 ret = ops->set_rx_ntuple(dev, &cmd); 414 if (ret) { 415 kfree(fsc); 416 return ret; 417 } 418 419 if (!ops->get_rx_ntuple) 420 __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc); 421 422 return ret; 423} 424 425static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) 426{ 427 struct ethtool_gstrings gstrings; 428 const struct ethtool_ops *ops = dev->ethtool_ops; 429 struct ethtool_rx_ntuple_flow_spec_container *fsc; 430 u8 *data; 431 char *p; 432 int ret, i, num_strings = 0; 433 434 if (!ops->get_sset_count) 435 return -EOPNOTSUPP; 436 437 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) 438 return -EFAULT; 439 440 ret = ops->get_sset_count(dev, gstrings.string_set); 441 if (ret < 0) 442 return ret; 443 444 gstrings.len = ret; 445 446 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); 447 if (!data) 448 return -ENOMEM; 449 450 if (ops->get_rx_ntuple) { 451 /* driver-specific filter grab */ 452 ret = ops->get_rx_ntuple(dev, gstrings.string_set, data); 453 goto copy; 454 } 455 456 /* default ethtool filter grab */ 457 i = 0; 458 p = (char *)data; 459 list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) { 460 sprintf(p, "Filter %d:\n", i); 461 p += ETH_GSTRING_LEN; 462 num_strings++; 463 464 switch (fsc->fs.flow_type) { 465 case TCP_V4_FLOW: 466 sprintf(p, "\tFlow Type: TCP\n"); 467 p += ETH_GSTRING_LEN; 468 num_strings++; 469 break; 470 case UDP_V4_FLOW: 471 sprintf(p, "\tFlow Type: UDP\n"); 472 p += ETH_GSTRING_LEN; 473 num_strings++; 474 break; 475 case SCTP_V4_FLOW: 476 sprintf(p, "\tFlow Type: SCTP\n"); 477 p += ETH_GSTRING_LEN; 478 num_strings++; 479 break; 480 case AH_ESP_V4_FLOW: 481 sprintf(p, "\tFlow Type: AH ESP\n"); 482 p += ETH_GSTRING_LEN; 483 num_strings++; 484 break; 485 case ESP_V4_FLOW: 486 sprintf(p, "\tFlow Type: ESP\n"); 487 p += ETH_GSTRING_LEN; 488 num_strings++; 489 break; 490 case IP_USER_FLOW: 491 sprintf(p, "\tFlow Type: Raw IP\n"); 492 p += ETH_GSTRING_LEN; 493 num_strings++; 494 break; 495 case IPV4_FLOW: 496 sprintf(p, "\tFlow Type: IPv4\n"); 497 p += ETH_GSTRING_LEN; 498 num_strings++; 499 break; 500 default: 501 sprintf(p, "\tFlow Type: Unknown\n"); 502 p += ETH_GSTRING_LEN; 503 num_strings++; 504 goto unknown_filter; 505 }; 506 507 /* now the rest of the filters */ 508 switch (fsc->fs.flow_type) { 509 case TCP_V4_FLOW: 510 case UDP_V4_FLOW: 511 case SCTP_V4_FLOW: 512 sprintf(p, "\tSrc IP addr: 0x%x\n", 513 fsc->fs.h_u.tcp_ip4_spec.ip4src); 514 p += ETH_GSTRING_LEN; 515 num_strings++; 516 sprintf(p, "\tSrc IP mask: 0x%x\n", 517 fsc->fs.m_u.tcp_ip4_spec.ip4src); 518 p += ETH_GSTRING_LEN; 519 num_strings++; 520 sprintf(p, "\tDest IP addr: 0x%x\n", 521 fsc->fs.h_u.tcp_ip4_spec.ip4dst); 522 p += ETH_GSTRING_LEN; 523 num_strings++; 524 sprintf(p, "\tDest IP mask: 0x%x\n", 525 fsc->fs.m_u.tcp_ip4_spec.ip4dst); 526 p += ETH_GSTRING_LEN; 527 num_strings++; 528 sprintf(p, "\tSrc Port: %d, mask: 0x%x\n", 529 fsc->fs.h_u.tcp_ip4_spec.psrc, 530 fsc->fs.m_u.tcp_ip4_spec.psrc); 531 p += ETH_GSTRING_LEN; 532 num_strings++; 533 sprintf(p, "\tDest Port: %d, mask: 0x%x\n", 534 fsc->fs.h_u.tcp_ip4_spec.pdst, 535 fsc->fs.m_u.tcp_ip4_spec.pdst); 536 p += ETH_GSTRING_LEN; 537 num_strings++; 538 sprintf(p, "\tTOS: %d, mask: 0x%x\n", 539 fsc->fs.h_u.tcp_ip4_spec.tos, 540 fsc->fs.m_u.tcp_ip4_spec.tos); 541 p += ETH_GSTRING_LEN; 542 num_strings++; 543 break; 544 case AH_ESP_V4_FLOW: 545 case ESP_V4_FLOW: 546 sprintf(p, "\tSrc IP addr: 0x%x\n", 547 fsc->fs.h_u.ah_ip4_spec.ip4src); 548 p += ETH_GSTRING_LEN; 549 num_strings++; 550 sprintf(p, "\tSrc IP mask: 0x%x\n", 551 fsc->fs.m_u.ah_ip4_spec.ip4src); 552 p += ETH_GSTRING_LEN; 553 num_strings++; 554 sprintf(p, "\tDest IP addr: 0x%x\n", 555 fsc->fs.h_u.ah_ip4_spec.ip4dst); 556 p += ETH_GSTRING_LEN; 557 num_strings++; 558 sprintf(p, "\tDest IP mask: 0x%x\n", 559 fsc->fs.m_u.ah_ip4_spec.ip4dst); 560 p += ETH_GSTRING_LEN; 561 num_strings++; 562 sprintf(p, "\tSPI: %d, mask: 0x%x\n", 563 fsc->fs.h_u.ah_ip4_spec.spi, 564 fsc->fs.m_u.ah_ip4_spec.spi); 565 p += ETH_GSTRING_LEN; 566 num_strings++; 567 sprintf(p, "\tTOS: %d, mask: 0x%x\n", 568 fsc->fs.h_u.ah_ip4_spec.tos, 569 fsc->fs.m_u.ah_ip4_spec.tos); 570 p += ETH_GSTRING_LEN; 571 num_strings++; 572 break; 573 case IP_USER_FLOW: 574 sprintf(p, "\tSrc IP addr: 0x%x\n", 575 fsc->fs.h_u.raw_ip4_spec.ip4src); 576 p += ETH_GSTRING_LEN; 577 num_strings++; 578 sprintf(p, "\tSrc IP mask: 0x%x\n", 579 fsc->fs.m_u.raw_ip4_spec.ip4src); 580 p += ETH_GSTRING_LEN; 581 num_strings++; 582 sprintf(p, "\tDest IP addr: 0x%x\n", 583 fsc->fs.h_u.raw_ip4_spec.ip4dst); 584 p += ETH_GSTRING_LEN; 585 num_strings++; 586 sprintf(p, "\tDest IP mask: 0x%x\n", 587 fsc->fs.m_u.raw_ip4_spec.ip4dst); 588 p += ETH_GSTRING_LEN; 589 num_strings++; 590 break; 591 case IPV4_FLOW: 592 sprintf(p, "\tSrc IP addr: 0x%x\n", 593 fsc->fs.h_u.usr_ip4_spec.ip4src); 594 p += ETH_GSTRING_LEN; 595 num_strings++; 596 sprintf(p, "\tSrc IP mask: 0x%x\n", 597 fsc->fs.m_u.usr_ip4_spec.ip4src); 598 p += ETH_GSTRING_LEN; 599 num_strings++; 600 sprintf(p, "\tDest IP addr: 0x%x\n", 601 fsc->fs.h_u.usr_ip4_spec.ip4dst); 602 p += ETH_GSTRING_LEN; 603 num_strings++; 604 sprintf(p, "\tDest IP mask: 0x%x\n", 605 fsc->fs.m_u.usr_ip4_spec.ip4dst); 606 p += ETH_GSTRING_LEN; 607 num_strings++; 608 sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n", 609 fsc->fs.h_u.usr_ip4_spec.l4_4_bytes, 610 fsc->fs.m_u.usr_ip4_spec.l4_4_bytes); 611 p += ETH_GSTRING_LEN; 612 num_strings++; 613 sprintf(p, "\tTOS: %d, mask: 0x%x\n", 614 fsc->fs.h_u.usr_ip4_spec.tos, 615 fsc->fs.m_u.usr_ip4_spec.tos); 616 p += ETH_GSTRING_LEN; 617 num_strings++; 618 sprintf(p, "\tIP Version: %d, mask: 0x%x\n", 619 fsc->fs.h_u.usr_ip4_spec.ip_ver, 620 fsc->fs.m_u.usr_ip4_spec.ip_ver); 621 p += ETH_GSTRING_LEN; 622 num_strings++; 623 sprintf(p, "\tProtocol: %d, mask: 0x%x\n", 624 fsc->fs.h_u.usr_ip4_spec.proto, 625 fsc->fs.m_u.usr_ip4_spec.proto); 626 p += ETH_GSTRING_LEN; 627 num_strings++; 628 break; 629 }; 630 sprintf(p, "\tVLAN: %d, mask: 0x%x\n", 631 fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask); 632 p += ETH_GSTRING_LEN; 633 num_strings++; 634 sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data); 635 p += ETH_GSTRING_LEN; 636 num_strings++; 637 sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask); 638 p += ETH_GSTRING_LEN; 639 num_strings++; 640 if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) 641 sprintf(p, "\tAction: Drop\n"); 642 else 643 sprintf(p, "\tAction: Direct to queue %d\n", 644 fsc->fs.action); 645 p += ETH_GSTRING_LEN; 646 num_strings++; 647unknown_filter: 648 i++; 649 } 650copy: 651 /* indicate to userspace how many strings we actually have */ 652 gstrings.len = num_strings; 653 ret = -EFAULT; 654 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) 655 goto out; 656 useraddr += sizeof(gstrings); 657 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) 658 goto out; 659 ret = 0; 660 661out: 662 kfree(data); 663 return ret; 664} 665 666static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) 667{ 668 struct ethtool_regs regs; 669 const struct ethtool_ops *ops = dev->ethtool_ops; 670 void *regbuf; 671 int reglen, ret; 672 673 if (!ops->get_regs || !ops->get_regs_len) 674 return -EOPNOTSUPP; 675 676 if (copy_from_user(&regs, useraddr, sizeof(regs))) 677 return -EFAULT; 678 679 reglen = ops->get_regs_len(dev); 680 if (regs.len > reglen) 681 regs.len = reglen; 682 683 regbuf = kmalloc(reglen, GFP_USER); 684 if (!regbuf) 685 return -ENOMEM; 686 687 ops->get_regs(dev, &regs, regbuf); 688 689 ret = -EFAULT; 690 if (copy_to_user(useraddr, &regs, sizeof(regs))) 691 goto out; 692 useraddr += offsetof(struct ethtool_regs, data); 693 if (copy_to_user(useraddr, regbuf, regs.len)) 694 goto out; 695 ret = 0; 696 697 out: 698 kfree(regbuf); 699 return ret; 700} 701 702static int ethtool_reset(struct net_device *dev, char __user *useraddr) 703{ 704 struct ethtool_value reset; 705 int ret; 706 707 if (!dev->ethtool_ops->reset) 708 return -EOPNOTSUPP; 709 710 if (copy_from_user(&reset, useraddr, sizeof(reset))) 711 return -EFAULT; 712 713 ret = dev->ethtool_ops->reset(dev, &reset.data); 714 if (ret) 715 return ret; 716 717 if (copy_to_user(useraddr, &reset, sizeof(reset))) 718 return -EFAULT; 719 return 0; 720} 721 722static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) 723{ 724 struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; 725 726 if (!dev->ethtool_ops->get_wol) 727 return -EOPNOTSUPP; 728 729 dev->ethtool_ops->get_wol(dev, &wol); 730 731 if (copy_to_user(useraddr, &wol, sizeof(wol))) 732 return -EFAULT; 733 return 0; 734} 735 736static int ethtool_set_wol(struct net_device *dev, char __user *useraddr) 737{ 738 struct ethtool_wolinfo wol; 739 740 if (!dev->ethtool_ops->set_wol) 741 return -EOPNOTSUPP; 742 743 if (copy_from_user(&wol, useraddr, sizeof(wol))) 744 return -EFAULT; 745 746 return dev->ethtool_ops->set_wol(dev, &wol); 747} 748 749static int ethtool_nway_reset(struct net_device *dev) 750{ 751 if (!dev->ethtool_ops->nway_reset) 752 return -EOPNOTSUPP; 753 754 return dev->ethtool_ops->nway_reset(dev); 755} 756 757static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) 758{ 759 struct ethtool_eeprom eeprom; 760 const struct ethtool_ops *ops = dev->ethtool_ops; 761 void __user *userbuf = useraddr + sizeof(eeprom); 762 u32 bytes_remaining; 763 u8 *data; 764 int ret = 0; 765 766 if (!ops->get_eeprom || !ops->get_eeprom_len) 767 return -EOPNOTSUPP; 768 769 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) 770 return -EFAULT; 771 772 /* Check for wrap and zero */ 773 if (eeprom.offset + eeprom.len <= eeprom.offset) 774 return -EINVAL; 775 776 /* Check for exceeding total eeprom len */ 777 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) 778 return -EINVAL; 779 780 data = kmalloc(PAGE_SIZE, GFP_USER); 781 if (!data) 782 return -ENOMEM; 783 784 bytes_remaining = eeprom.len; 785 while (bytes_remaining > 0) { 786 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE); 787 788 ret = ops->get_eeprom(dev, &eeprom, data); 789 if (ret) 790 break; 791 if (copy_to_user(userbuf, data, eeprom.len)) { 792 ret = -EFAULT; 793 break; 794 } 795 userbuf += eeprom.len; 796 eeprom.offset += eeprom.len; 797 bytes_remaining -= eeprom.len; 798 } 799 800 eeprom.len = userbuf - (useraddr + sizeof(eeprom)); 801 eeprom.offset -= eeprom.len; 802 if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) 803 ret = -EFAULT; 804 805 kfree(data); 806 return ret; 807} 808 809static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) 810{ 811 struct ethtool_eeprom eeprom; 812 const struct ethtool_ops *ops = dev->ethtool_ops; 813 void __user *userbuf = useraddr + sizeof(eeprom); 814 u32 bytes_remaining; 815 u8 *data; 816 int ret = 0; 817 818 if (!ops->set_eeprom || !ops->get_eeprom_len) 819 return -EOPNOTSUPP; 820 821 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) 822 return -EFAULT; 823 824 /* Check for wrap and zero */ 825 if (eeprom.offset + eeprom.len <= eeprom.offset) 826 return -EINVAL; 827 828 /* Check for exceeding total eeprom len */ 829 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) 830 return -EINVAL; 831 832 data = kmalloc(PAGE_SIZE, GFP_USER); 833 if (!data) 834 return -ENOMEM; 835 836 bytes_remaining = eeprom.len; 837 while (bytes_remaining > 0) { 838 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE); 839 840 if (copy_from_user(data, userbuf, eeprom.len)) { 841 ret = -EFAULT; 842 break; 843 } 844 ret = ops->set_eeprom(dev, &eeprom, data); 845 if (ret) 846 break; 847 userbuf += eeprom.len; 848 eeprom.offset += eeprom.len; 849 bytes_remaining -= eeprom.len; 850 } 851 852 kfree(data); 853 return ret; 854} 855 856static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) 857{ 858 struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; 859 860 if (!dev->ethtool_ops->get_coalesce) 861 return -EOPNOTSUPP; 862 863 dev->ethtool_ops->get_coalesce(dev, &coalesce); 864 865 if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) 866 return -EFAULT; 867 return 0; 868} 869 870static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) 871{ 872 struct ethtool_coalesce coalesce; 873 874 if (!dev->ethtool_ops->set_coalesce) 875 return -EOPNOTSUPP; 876 877 if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) 878 return -EFAULT; 879 880 return dev->ethtool_ops->set_coalesce(dev, &coalesce); 881} 882 883static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr) 884{ 885 struct ethtool_ringparam ringparam = { .cmd = ETHTOOL_GRINGPARAM }; 886 887 if (!dev->ethtool_ops->get_ringparam) 888 return -EOPNOTSUPP; 889 890 dev->ethtool_ops->get_ringparam(dev, &ringparam); 891 892 if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) 893 return -EFAULT; 894 return 0; 895} 896 897static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr) 898{ 899 struct ethtool_ringparam ringparam; 900 901 if (!dev->ethtool_ops->set_ringparam) 902 return -EOPNOTSUPP; 903 904 if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) 905 return -EFAULT; 906 907 return dev->ethtool_ops->set_ringparam(dev, &ringparam); 908} 909 910static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr) 911{ 912 struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; 913 914 if (!dev->ethtool_ops->get_pauseparam) 915 return -EOPNOTSUPP; 916 917 dev->ethtool_ops->get_pauseparam(dev, &pauseparam); 918 919 if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) 920 return -EFAULT; 921 return 0; 922} 923 924static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr) 925{ 926 struct ethtool_pauseparam pauseparam; 927 928 if (!dev->ethtool_ops->set_pauseparam) 929 return -EOPNOTSUPP; 930 931 if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) 932 return -EFAULT; 933 934 return dev->ethtool_ops->set_pauseparam(dev, &pauseparam); 935} 936 937static int __ethtool_set_sg(struct net_device *dev, u32 data) 938{ 939 int err; 940 941 if (!data && dev->ethtool_ops->set_tso) { 942 err = dev->ethtool_ops->set_tso(dev, 0); 943 if (err) 944 return err; 945 } 946 947 if (!data && dev->ethtool_ops->set_ufo) { 948 err = dev->ethtool_ops->set_ufo(dev, 0); 949 if (err) 950 return err; 951 } 952 return dev->ethtool_ops->set_sg(dev, data); 953} 954 955static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr) 956{ 957 struct ethtool_value edata; 958 int err; 959 960 if (!dev->ethtool_ops->set_tx_csum) 961 return -EOPNOTSUPP; 962 963 if (copy_from_user(&edata, useraddr, sizeof(edata))) 964 return -EFAULT; 965 966 if (!edata.data && dev->ethtool_ops->set_sg) { 967 err = __ethtool_set_sg(dev, 0); 968 if (err) 969 return err; 970 } 971 972 return dev->ethtool_ops->set_tx_csum(dev, edata.data); 973} 974 975static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr) 976{ 977 struct ethtool_value edata; 978 979 if (!dev->ethtool_ops->set_rx_csum) 980 return -EOPNOTSUPP; 981 982 if (copy_from_user(&edata, useraddr, sizeof(edata))) 983 return -EFAULT; 984 985 if (!edata.data && dev->ethtool_ops->set_sg) 986 dev->features &= ~NETIF_F_GRO; 987 988 return dev->ethtool_ops->set_rx_csum(dev, edata.data); 989} 990 991static int ethtool_set_sg(struct net_device *dev, char __user *useraddr) 992{ 993 struct ethtool_value edata; 994 995 if (!dev->ethtool_ops->set_sg) 996 return -EOPNOTSUPP; 997 998 if (copy_from_user(&edata, useraddr, sizeof(edata))) 999 return -EFAULT; 1000 1001 if (edata.data && 1002 !(dev->features & NETIF_F_ALL_CSUM)) 1003 return -EINVAL; 1004 1005 return __ethtool_set_sg(dev, edata.data); 1006} 1007 1008static int ethtool_set_tso(struct net_device *dev, char __user *useraddr) 1009{ 1010 struct ethtool_value edata; 1011 1012 if (!dev->ethtool_ops->set_tso) 1013 return -EOPNOTSUPP; 1014 1015 if (copy_from_user(&edata, useraddr, sizeof(edata))) 1016 return -EFAULT; 1017 1018 if (edata.data && !(dev->features & NETIF_F_SG)) 1019 return -EINVAL; 1020 1021 return dev->ethtool_ops->set_tso(dev, edata.data); 1022} 1023 1024static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) 1025{ 1026 struct ethtool_value edata; 1027 1028 if (!dev->ethtool_ops->set_ufo) 1029 return -EOPNOTSUPP; 1030 if (copy_from_user(&edata, useraddr, sizeof(edata))) 1031 return -EFAULT; 1032 if (edata.data && !(dev->features & NETIF_F_SG)) 1033 return -EINVAL; 1034 if (edata.data && !(dev->features & NETIF_F_HW_CSUM)) 1035 return -EINVAL; 1036 return dev->ethtool_ops->set_ufo(dev, edata.data); 1037} 1038 1039static int ethtool_get_gso(struct net_device *dev, char __user *useraddr) 1040{ 1041 struct ethtool_value edata = { ETHTOOL_GGSO }; 1042 1043 edata.data = dev->features & NETIF_F_GSO; 1044 if (copy_to_user(useraddr, &edata, sizeof(edata))) 1045 return -EFAULT; 1046 return 0; 1047} 1048 1049static int ethtool_set_gso(struct net_device *dev, char __user *useraddr) 1050{ 1051 struct ethtool_value edata; 1052 1053 if (copy_from_user(&edata, useraddr, sizeof(edata))) 1054 return -EFAULT; 1055 if (edata.data) 1056 dev->features |= NETIF_F_GSO; 1057 else 1058 dev->features &= ~NETIF_F_GSO; 1059 return 0; 1060} 1061 1062static int ethtool_get_gro(struct net_device *dev, char __user *useraddr) 1063{ 1064 struct ethtool_value edata = { ETHTOOL_GGRO }; 1065 1066 edata.data = dev->features & NETIF_F_GRO; 1067 if (copy_to_user(useraddr, &edata, sizeof(edata))) 1068 return -EFAULT; 1069 return 0; 1070} 1071 1072static int ethtool_set_gro(struct net_device *dev, char __user *useraddr) 1073{ 1074 struct ethtool_value edata; 1075 1076 if (copy_from_user(&edata, useraddr, sizeof(edata))) 1077 return -EFAULT; 1078 1079 if (edata.data) { 1080 if (!dev->ethtool_ops->get_rx_csum || 1081 !dev->ethtool_ops->get_rx_csum(dev)) 1082 return -EINVAL; 1083 dev->features |= NETIF_F_GRO; 1084 } else 1085 dev->features &= ~NETIF_F_GRO; 1086 1087 return 0; 1088} 1089 1090static int ethtool_self_test(struct net_device *dev, char __user *useraddr) 1091{ 1092 struct ethtool_test test; 1093 const struct ethtool_ops *ops = dev->ethtool_ops; 1094 u64 *data; 1095 int ret, test_len; 1096 1097 if (!ops->self_test || !ops->get_sset_count) 1098 return -EOPNOTSUPP; 1099 1100 test_len = ops->get_sset_count(dev, ETH_SS_TEST); 1101 if (test_len < 0) 1102 return test_len; 1103 WARN_ON(test_len == 0); 1104 1105 if (copy_from_user(&test, useraddr, sizeof(test))) 1106 return -EFAULT; 1107 1108 test.len = test_len; 1109 data = kmalloc(test_len * sizeof(u64), GFP_USER); 1110 if (!data) 1111 return -ENOMEM; 1112 1113 ops->self_test(dev, &test, data); 1114 1115 ret = -EFAULT; 1116 if (copy_to_user(useraddr, &test, sizeof(test))) 1117 goto out; 1118 useraddr += sizeof(test); 1119 if (copy_to_user(useraddr, data, test.len * sizeof(u64))) 1120 goto out; 1121 ret = 0; 1122 1123 out: 1124 kfree(data); 1125 return ret; 1126} 1127 1128static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) 1129{ 1130 struct ethtool_gstrings gstrings; 1131 const struct ethtool_ops *ops = dev->ethtool_ops; 1132 u8 *data; 1133 int ret; 1134 1135 if (!ops->get_strings || !ops->get_sset_count) 1136 return -EOPNOTSUPP; 1137 1138 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) 1139 return -EFAULT; 1140 1141 ret = ops->get_sset_count(dev, gstrings.string_set); 1142 if (ret < 0) 1143 return ret; 1144 1145 gstrings.len = ret; 1146 1147 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); 1148 if (!data) 1149 return -ENOMEM; 1150 1151 ops->get_strings(dev, gstrings.string_set, data); 1152 1153 ret = -EFAULT; 1154 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) 1155 goto out; 1156 useraddr += sizeof(gstrings); 1157 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) 1158 goto out; 1159 ret = 0; 1160 1161 out: 1162 kfree(data); 1163 return ret; 1164} 1165 1166static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) 1167{ 1168 struct ethtool_value id; 1169 1170 if (!dev->ethtool_ops->phys_id) 1171 return -EOPNOTSUPP; 1172 1173 if (copy_from_user(&id, useraddr, sizeof(id))) 1174 return -EFAULT; 1175 1176 return dev->ethtool_ops->phys_id(dev, id.data); 1177} 1178 1179static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) 1180{ 1181 struct ethtool_stats stats; 1182 const struct ethtool_ops *ops = dev->ethtool_ops; 1183 u64 *data; 1184 int ret, n_stats; 1185 1186 if (!ops->get_ethtool_stats || !ops->get_sset_count) 1187 return -EOPNOTSUPP; 1188 1189 n_stats = ops->get_sset_count(dev, ETH_SS_STATS); 1190 if (n_stats < 0) 1191 return n_stats; 1192 WARN_ON(n_stats == 0); 1193 1194 if (copy_from_user(&stats, useraddr, sizeof(stats))) 1195 return -EFAULT; 1196 1197 stats.n_stats = n_stats; 1198 data = kmalloc(n_stats * sizeof(u64), GFP_USER); 1199 if (!data) 1200 return -ENOMEM; 1201 1202 ops->get_ethtool_stats(dev, &stats, data); 1203 1204 ret = -EFAULT; 1205 if (copy_to_user(useraddr, &stats, sizeof(stats))) 1206 goto out; 1207 useraddr += sizeof(stats); 1208 if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) 1209 goto out; 1210 ret = 0; 1211 1212 out: 1213 kfree(data); 1214 return ret; 1215} 1216 1217static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr) 1218{ 1219 struct ethtool_perm_addr epaddr; 1220 1221 if (copy_from_user(&epaddr, useraddr, sizeof(epaddr))) 1222 return -EFAULT; 1223 1224 if (epaddr.size < dev->addr_len) 1225 return -ETOOSMALL; 1226 epaddr.size = dev->addr_len; 1227 1228 if (copy_to_user(useraddr, &epaddr, sizeof(epaddr))) 1229 return -EFAULT; 1230 useraddr += sizeof(epaddr); 1231 if (copy_to_user(useraddr, dev->perm_addr, epaddr.size)) 1232 return -EFAULT; 1233 return 0; 1234} 1235 1236static int ethtool_get_value(struct net_device *dev, char __user *useraddr, 1237 u32 cmd, u32 (*actor)(struct net_device *)) 1238{ 1239 struct ethtool_value edata = { .cmd = cmd }; 1240 1241 if (!actor) 1242 return -EOPNOTSUPP; 1243 1244 edata.data = actor(dev); 1245 1246 if (copy_to_user(useraddr, &edata, sizeof(edata))) 1247 return -EFAULT; 1248 return 0; 1249} 1250 1251static int ethtool_set_value_void(struct net_device *dev, char __user *useraddr, 1252 void (*actor)(struct net_device *, u32)) 1253{ 1254 struct ethtool_value edata; 1255 1256 if (!actor) 1257 return -EOPNOTSUPP; 1258 1259 if (copy_from_user(&edata, useraddr, sizeof(edata))) 1260 return -EFAULT; 1261 1262 actor(dev, edata.data); 1263 return 0; 1264} 1265 1266static int ethtool_set_value(struct net_device *dev, char __user *useraddr, 1267 int (*actor)(struct net_device *, u32)) 1268{ 1269 struct ethtool_value edata; 1270 1271 if (!actor) 1272 return -EOPNOTSUPP; 1273 1274 if (copy_from_user(&edata, useraddr, sizeof(edata))) 1275 return -EFAULT; 1276 1277 return actor(dev, edata.data); 1278} 1279 1280static noinline_for_stack int ethtool_flash_device(struct net_device *dev, char __user *useraddr) 1281{ 1282 struct ethtool_flash efl; 1283 1284 if (copy_from_user(&efl, useraddr, sizeof(efl))) 1285 return -EFAULT; 1286 1287 if (!dev->ethtool_ops->flash_device) 1288 return -EOPNOTSUPP; 1289 1290 return dev->ethtool_ops->flash_device(dev, &efl); 1291} 1292 1293/* The main entry point in this file. Called from net/core/dev.c */ 1294 1295int dev_ethtool(struct net *net, struct ifreq *ifr) 1296{ 1297 struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); 1298 void __user *useraddr = ifr->ifr_data; 1299 u32 ethcmd; 1300 int rc; 1301 unsigned long old_features; 1302 1303 if (!dev || !netif_device_present(dev)) 1304 return -ENODEV; 1305 1306 if (!dev->ethtool_ops) 1307 return -EOPNOTSUPP; 1308 1309 if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd))) 1310 return -EFAULT; 1311 1312 /* Allow some commands to be done by anyone */ 1313 switch(ethcmd) { 1314 case ETHTOOL_GDRVINFO: 1315 case ETHTOOL_GMSGLVL: 1316 case ETHTOOL_GCOALESCE: 1317 case ETHTOOL_GRINGPARAM: 1318 case ETHTOOL_GPAUSEPARAM: 1319 case ETHTOOL_GRXCSUM: 1320 case ETHTOOL_GTXCSUM: 1321 case ETHTOOL_GSG: 1322 case ETHTOOL_GSTRINGS: 1323 case ETHTOOL_GTSO: 1324 case ETHTOOL_GPERMADDR: 1325 case ETHTOOL_GUFO: 1326 case ETHTOOL_GGSO: 1327 case ETHTOOL_GGRO: 1328 case ETHTOOL_GFLAGS: 1329 case ETHTOOL_GPFLAGS: 1330 case ETHTOOL_GRXFH: 1331 case ETHTOOL_GRXRINGS: 1332 case ETHTOOL_GRXCLSRLCNT: 1333 case ETHTOOL_GRXCLSRULE: 1334 case ETHTOOL_GRXCLSRLALL: 1335 break; 1336 default: 1337 if (!capable(CAP_NET_ADMIN)) 1338 return -EPERM; 1339 } 1340 1341 if (dev->ethtool_ops->begin) 1342 if ((rc = dev->ethtool_ops->begin(dev)) < 0) 1343 return rc; 1344 1345 old_features = dev->features; 1346 1347 switch (ethcmd) { 1348 case ETHTOOL_GSET: 1349 rc = ethtool_get_settings(dev, useraddr); 1350 break; 1351 case ETHTOOL_SSET: 1352 rc = ethtool_set_settings(dev, useraddr); 1353 break; 1354 case ETHTOOL_GDRVINFO: 1355 rc = ethtool_get_drvinfo(dev, useraddr); 1356 break; 1357 case ETHTOOL_GREGS: 1358 rc = ethtool_get_regs(dev, useraddr); 1359 break; 1360 case ETHTOOL_GWOL: 1361 rc = ethtool_get_wol(dev, useraddr); 1362 break; 1363 case ETHTOOL_SWOL: 1364 rc = ethtool_set_wol(dev, useraddr); 1365 break; 1366 case ETHTOOL_GMSGLVL: 1367 rc = ethtool_get_value(dev, useraddr, ethcmd, 1368 dev->ethtool_ops->get_msglevel); 1369 break; 1370 case ETHTOOL_SMSGLVL: 1371 rc = ethtool_set_value_void(dev, useraddr, 1372 dev->ethtool_ops->set_msglevel); 1373 break; 1374 case ETHTOOL_NWAY_RST: 1375 rc = ethtool_nway_reset(dev); 1376 break; 1377 case ETHTOOL_GLINK: 1378 rc = ethtool_get_value(dev, useraddr, ethcmd, 1379 dev->ethtool_ops->get_link); 1380 break; 1381 case ETHTOOL_GEEPROM: 1382 rc = ethtool_get_eeprom(dev, useraddr); 1383 break; 1384 case ETHTOOL_SEEPROM: 1385 rc = ethtool_set_eeprom(dev, useraddr); 1386 break; 1387 case ETHTOOL_GCOALESCE: 1388 rc = ethtool_get_coalesce(dev, useraddr); 1389 break; 1390 case ETHTOOL_SCOALESCE: 1391 rc = ethtool_set_coalesce(dev, useraddr); 1392 break; 1393 case ETHTOOL_GRINGPARAM: 1394 rc = ethtool_get_ringparam(dev, useraddr); 1395 break; 1396 case ETHTOOL_SRINGPARAM: 1397 rc = ethtool_set_ringparam(dev, useraddr); 1398 break; 1399 case ETHTOOL_GPAUSEPARAM: 1400 rc = ethtool_get_pauseparam(dev, useraddr); 1401 break; 1402 case ETHTOOL_SPAUSEPARAM: 1403 rc = ethtool_set_pauseparam(dev, useraddr); 1404 break; 1405 case ETHTOOL_GRXCSUM: 1406 rc = ethtool_get_value(dev, useraddr, ethcmd, 1407 (dev->ethtool_ops->get_rx_csum ? 1408 dev->ethtool_ops->get_rx_csum : 1409 ethtool_op_get_rx_csum)); 1410 break; 1411 case ETHTOOL_SRXCSUM: 1412 rc = ethtool_set_rx_csum(dev, useraddr); 1413 break; 1414 case ETHTOOL_GTXCSUM: 1415 rc = ethtool_get_value(dev, useraddr, ethcmd, 1416 (dev->ethtool_ops->get_tx_csum ? 1417 dev->ethtool_ops->get_tx_csum : 1418 ethtool_op_get_tx_csum)); 1419 break; 1420 case ETHTOOL_STXCSUM: 1421 rc = ethtool_set_tx_csum(dev, useraddr); 1422 break; 1423 case ETHTOOL_GSG: 1424 rc = ethtool_get_value(dev, useraddr, ethcmd, 1425 (dev->ethtool_ops->get_sg ? 1426 dev->ethtool_ops->get_sg : 1427 ethtool_op_get_sg)); 1428 break; 1429 case ETHTOOL_SSG: 1430 rc = ethtool_set_sg(dev, useraddr); 1431 break; 1432 case ETHTOOL_GTSO: 1433 rc = ethtool_get_value(dev, useraddr, ethcmd, 1434 (dev->ethtool_ops->get_tso ? 1435 dev->ethtool_ops->get_tso : 1436 ethtool_op_get_tso)); 1437 break; 1438 case ETHTOOL_STSO: 1439 rc = ethtool_set_tso(dev, useraddr); 1440 break; 1441 case ETHTOOL_TEST: 1442 rc = ethtool_self_test(dev, useraddr); 1443 break; 1444 case ETHTOOL_GSTRINGS: 1445 rc = ethtool_get_strings(dev, useraddr); 1446 break; 1447 case ETHTOOL_PHYS_ID: 1448 rc = ethtool_phys_id(dev, useraddr); 1449 break; 1450 case ETHTOOL_GSTATS: 1451 rc = ethtool_get_stats(dev, useraddr); 1452 break; 1453 case ETHTOOL_GPERMADDR: 1454 rc = ethtool_get_perm_addr(dev, useraddr); 1455 break; 1456 case ETHTOOL_GUFO: 1457 rc = ethtool_get_value(dev, useraddr, ethcmd, 1458 (dev->ethtool_ops->get_ufo ? 1459 dev->ethtool_ops->get_ufo : 1460 ethtool_op_get_ufo)); 1461 break; 1462 case ETHTOOL_SUFO: 1463 rc = ethtool_set_ufo(dev, useraddr); 1464 break; 1465 case ETHTOOL_GGSO: 1466 rc = ethtool_get_gso(dev, useraddr); 1467 break; 1468 case ETHTOOL_SGSO: 1469 rc = ethtool_set_gso(dev, useraddr); 1470 break; 1471 case ETHTOOL_GFLAGS: 1472 rc = ethtool_get_value(dev, useraddr, ethcmd, 1473 (dev->ethtool_ops->get_flags ? 1474 dev->ethtool_ops->get_flags : 1475 ethtool_op_get_flags)); 1476 break; 1477 case ETHTOOL_SFLAGS: 1478 rc = ethtool_set_value(dev, useraddr, 1479 dev->ethtool_ops->set_flags); 1480 break; 1481 case ETHTOOL_GPFLAGS: 1482 rc = ethtool_get_value(dev, useraddr, ethcmd, 1483 dev->ethtool_ops->get_priv_flags); 1484 break; 1485 case ETHTOOL_SPFLAGS: 1486 rc = ethtool_set_value(dev, useraddr, 1487 dev->ethtool_ops->set_priv_flags); 1488 break; 1489 case ETHTOOL_GRXFH: 1490 case ETHTOOL_GRXRINGS: 1491 case ETHTOOL_GRXCLSRLCNT: 1492 case ETHTOOL_GRXCLSRULE: 1493 case ETHTOOL_GRXCLSRLALL: 1494 rc = ethtool_get_rxnfc(dev, useraddr); 1495 break; 1496 case ETHTOOL_SRXFH: 1497 case ETHTOOL_SRXCLSRLDEL: 1498 case ETHTOOL_SRXCLSRLINS: 1499 rc = ethtool_set_rxnfc(dev, useraddr); 1500 break; 1501 case ETHTOOL_GGRO: 1502 rc = ethtool_get_gro(dev, useraddr); 1503 break; 1504 case ETHTOOL_SGRO: 1505 rc = ethtool_set_gro(dev, useraddr); 1506 break; 1507 case ETHTOOL_FLASHDEV: 1508 rc = ethtool_flash_device(dev, useraddr); 1509 break; 1510 case ETHTOOL_RESET: 1511 rc = ethtool_reset(dev, useraddr); 1512 break; 1513 case ETHTOOL_SRXNTUPLE: 1514 rc = ethtool_set_rx_ntuple(dev, useraddr); 1515 break; 1516 case ETHTOOL_GRXNTUPLE: 1517 rc = ethtool_get_rx_ntuple(dev, useraddr); 1518 break; 1519 case ETHTOOL_GSSET_INFO: 1520 rc = ethtool_get_sset_info(dev, useraddr); 1521 break; 1522 default: 1523 rc = -EOPNOTSUPP; 1524 } 1525 1526 if (dev->ethtool_ops->complete) 1527 dev->ethtool_ops->complete(dev); 1528 1529 if (old_features != dev->features) 1530 netdev_features_change(dev); 1531 1532 return rc; 1533} 1534 1535EXPORT_SYMBOL(ethtool_op_get_link); 1536EXPORT_SYMBOL(ethtool_op_get_sg); 1537EXPORT_SYMBOL(ethtool_op_get_tso); 1538EXPORT_SYMBOL(ethtool_op_set_sg); 1539EXPORT_SYMBOL(ethtool_op_set_tso); 1540EXPORT_SYMBOL(ethtool_op_set_tx_csum); 1541EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); 1542EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); 1543EXPORT_SYMBOL(ethtool_op_set_ufo); 1544EXPORT_SYMBOL(ethtool_op_get_ufo); 1545EXPORT_SYMBOL(ethtool_op_set_flags); 1546EXPORT_SYMBOL(ethtool_op_get_flags);