at v2.6.14-rc3 884 lines 20 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. We fall back to calling do_ioctl() 7 * for drivers which haven't been converted to ethtool_ops yet. 8 * 9 * It's GPL, stupid. 10 */ 11 12#include <linux/module.h> 13#include <linux/types.h> 14#include <linux/errno.h> 15#include <linux/ethtool.h> 16#include <linux/netdevice.h> 17#include <asm/uaccess.h> 18 19/* 20 * Some useful ethtool_ops methods that're device independent. 21 * If we find that all drivers want to do the same thing here, 22 * we can turn these into dev_() function calls. 23 */ 24 25u32 ethtool_op_get_link(struct net_device *dev) 26{ 27 return netif_carrier_ok(dev) ? 1 : 0; 28} 29 30u32 ethtool_op_get_tx_csum(struct net_device *dev) 31{ 32 return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0; 33} 34 35int ethtool_op_set_tx_csum(struct net_device *dev, u32 data) 36{ 37 if (data) 38 dev->features |= NETIF_F_IP_CSUM; 39 else 40 dev->features &= ~NETIF_F_IP_CSUM; 41 42 return 0; 43} 44 45int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data) 46{ 47 if (data) 48 dev->features |= NETIF_F_HW_CSUM; 49 else 50 dev->features &= ~NETIF_F_HW_CSUM; 51 52 return 0; 53} 54u32 ethtool_op_get_sg(struct net_device *dev) 55{ 56 return (dev->features & NETIF_F_SG) != 0; 57} 58 59int ethtool_op_set_sg(struct net_device *dev, u32 data) 60{ 61 if (data) 62 dev->features |= NETIF_F_SG; 63 else 64 dev->features &= ~NETIF_F_SG; 65 66 return 0; 67} 68 69u32 ethtool_op_get_tso(struct net_device *dev) 70{ 71 return (dev->features & NETIF_F_TSO) != 0; 72} 73 74int ethtool_op_set_tso(struct net_device *dev, u32 data) 75{ 76 if (data) 77 dev->features |= NETIF_F_TSO; 78 else 79 dev->features &= ~NETIF_F_TSO; 80 81 return 0; 82} 83 84int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *addr, u8 *data) 85{ 86 unsigned char len = dev->addr_len; 87 if ( addr->size < len ) 88 return -ETOOSMALL; 89 90 addr->size = len; 91 memcpy(data, dev->perm_addr, len); 92 return 0; 93} 94 95 96/* Handlers for each ethtool command */ 97 98static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) 99{ 100 struct ethtool_cmd cmd = { ETHTOOL_GSET }; 101 int err; 102 103 if (!dev->ethtool_ops->get_settings) 104 return -EOPNOTSUPP; 105 106 err = dev->ethtool_ops->get_settings(dev, &cmd); 107 if (err < 0) 108 return err; 109 110 if (copy_to_user(useraddr, &cmd, sizeof(cmd))) 111 return -EFAULT; 112 return 0; 113} 114 115static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) 116{ 117 struct ethtool_cmd cmd; 118 119 if (!dev->ethtool_ops->set_settings) 120 return -EOPNOTSUPP; 121 122 if (copy_from_user(&cmd, useraddr, sizeof(cmd))) 123 return -EFAULT; 124 125 return dev->ethtool_ops->set_settings(dev, &cmd); 126} 127 128static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) 129{ 130 struct ethtool_drvinfo info; 131 struct ethtool_ops *ops = dev->ethtool_ops; 132 133 if (!ops->get_drvinfo) 134 return -EOPNOTSUPP; 135 136 memset(&info, 0, sizeof(info)); 137 info.cmd = ETHTOOL_GDRVINFO; 138 ops->get_drvinfo(dev, &info); 139 140 if (ops->self_test_count) 141 info.testinfo_len = ops->self_test_count(dev); 142 if (ops->get_stats_count) 143 info.n_stats = ops->get_stats_count(dev); 144 if (ops->get_regs_len) 145 info.regdump_len = ops->get_regs_len(dev); 146 if (ops->get_eeprom_len) 147 info.eedump_len = ops->get_eeprom_len(dev); 148 149 if (copy_to_user(useraddr, &info, sizeof(info))) 150 return -EFAULT; 151 return 0; 152} 153 154static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) 155{ 156 struct ethtool_regs regs; 157 struct ethtool_ops *ops = dev->ethtool_ops; 158 void *regbuf; 159 int reglen, ret; 160 161 if (!ops->get_regs || !ops->get_regs_len) 162 return -EOPNOTSUPP; 163 164 if (copy_from_user(&regs, useraddr, sizeof(regs))) 165 return -EFAULT; 166 167 reglen = ops->get_regs_len(dev); 168 if (regs.len > reglen) 169 regs.len = reglen; 170 171 regbuf = kmalloc(reglen, GFP_USER); 172 if (!regbuf) 173 return -ENOMEM; 174 175 ops->get_regs(dev, &regs, regbuf); 176 177 ret = -EFAULT; 178 if (copy_to_user(useraddr, &regs, sizeof(regs))) 179 goto out; 180 useraddr += offsetof(struct ethtool_regs, data); 181 if (copy_to_user(useraddr, regbuf, regs.len)) 182 goto out; 183 ret = 0; 184 185 out: 186 kfree(regbuf); 187 return ret; 188} 189 190static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) 191{ 192 struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; 193 194 if (!dev->ethtool_ops->get_wol) 195 return -EOPNOTSUPP; 196 197 dev->ethtool_ops->get_wol(dev, &wol); 198 199 if (copy_to_user(useraddr, &wol, sizeof(wol))) 200 return -EFAULT; 201 return 0; 202} 203 204static int ethtool_set_wol(struct net_device *dev, char __user *useraddr) 205{ 206 struct ethtool_wolinfo wol; 207 208 if (!dev->ethtool_ops->set_wol) 209 return -EOPNOTSUPP; 210 211 if (copy_from_user(&wol, useraddr, sizeof(wol))) 212 return -EFAULT; 213 214 return dev->ethtool_ops->set_wol(dev, &wol); 215} 216 217static int ethtool_get_msglevel(struct net_device *dev, char __user *useraddr) 218{ 219 struct ethtool_value edata = { ETHTOOL_GMSGLVL }; 220 221 if (!dev->ethtool_ops->get_msglevel) 222 return -EOPNOTSUPP; 223 224 edata.data = dev->ethtool_ops->get_msglevel(dev); 225 226 if (copy_to_user(useraddr, &edata, sizeof(edata))) 227 return -EFAULT; 228 return 0; 229} 230 231static int ethtool_set_msglevel(struct net_device *dev, char __user *useraddr) 232{ 233 struct ethtool_value edata; 234 235 if (!dev->ethtool_ops->set_msglevel) 236 return -EOPNOTSUPP; 237 238 if (copy_from_user(&edata, useraddr, sizeof(edata))) 239 return -EFAULT; 240 241 dev->ethtool_ops->set_msglevel(dev, edata.data); 242 return 0; 243} 244 245static int ethtool_nway_reset(struct net_device *dev) 246{ 247 if (!dev->ethtool_ops->nway_reset) 248 return -EOPNOTSUPP; 249 250 return dev->ethtool_ops->nway_reset(dev); 251} 252 253static int ethtool_get_link(struct net_device *dev, void __user *useraddr) 254{ 255 struct ethtool_value edata = { ETHTOOL_GLINK }; 256 257 if (!dev->ethtool_ops->get_link) 258 return -EOPNOTSUPP; 259 260 edata.data = dev->ethtool_ops->get_link(dev); 261 262 if (copy_to_user(useraddr, &edata, sizeof(edata))) 263 return -EFAULT; 264 return 0; 265} 266 267static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) 268{ 269 struct ethtool_eeprom eeprom; 270 struct ethtool_ops *ops = dev->ethtool_ops; 271 u8 *data; 272 int ret; 273 274 if (!ops->get_eeprom || !ops->get_eeprom_len) 275 return -EOPNOTSUPP; 276 277 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) 278 return -EFAULT; 279 280 /* Check for wrap and zero */ 281 if (eeprom.offset + eeprom.len <= eeprom.offset) 282 return -EINVAL; 283 284 /* Check for exceeding total eeprom len */ 285 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) 286 return -EINVAL; 287 288 data = kmalloc(eeprom.len, GFP_USER); 289 if (!data) 290 return -ENOMEM; 291 292 ret = -EFAULT; 293 if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) 294 goto out; 295 296 ret = ops->get_eeprom(dev, &eeprom, data); 297 if (ret) 298 goto out; 299 300 ret = -EFAULT; 301 if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) 302 goto out; 303 if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) 304 goto out; 305 ret = 0; 306 307 out: 308 kfree(data); 309 return ret; 310} 311 312static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) 313{ 314 struct ethtool_eeprom eeprom; 315 struct ethtool_ops *ops = dev->ethtool_ops; 316 u8 *data; 317 int ret; 318 319 if (!ops->set_eeprom || !ops->get_eeprom_len) 320 return -EOPNOTSUPP; 321 322 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) 323 return -EFAULT; 324 325 /* Check for wrap and zero */ 326 if (eeprom.offset + eeprom.len <= eeprom.offset) 327 return -EINVAL; 328 329 /* Check for exceeding total eeprom len */ 330 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) 331 return -EINVAL; 332 333 data = kmalloc(eeprom.len, GFP_USER); 334 if (!data) 335 return -ENOMEM; 336 337 ret = -EFAULT; 338 if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) 339 goto out; 340 341 ret = ops->set_eeprom(dev, &eeprom, data); 342 if (ret) 343 goto out; 344 345 if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) 346 ret = -EFAULT; 347 348 out: 349 kfree(data); 350 return ret; 351} 352 353static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) 354{ 355 struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; 356 357 if (!dev->ethtool_ops->get_coalesce) 358 return -EOPNOTSUPP; 359 360 dev->ethtool_ops->get_coalesce(dev, &coalesce); 361 362 if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) 363 return -EFAULT; 364 return 0; 365} 366 367static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) 368{ 369 struct ethtool_coalesce coalesce; 370 371 if (!dev->ethtool_ops->set_coalesce) 372 return -EOPNOTSUPP; 373 374 if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) 375 return -EFAULT; 376 377 return dev->ethtool_ops->set_coalesce(dev, &coalesce); 378} 379 380static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr) 381{ 382 struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; 383 384 if (!dev->ethtool_ops->get_ringparam) 385 return -EOPNOTSUPP; 386 387 dev->ethtool_ops->get_ringparam(dev, &ringparam); 388 389 if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) 390 return -EFAULT; 391 return 0; 392} 393 394static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr) 395{ 396 struct ethtool_ringparam ringparam; 397 398 if (!dev->ethtool_ops->set_ringparam) 399 return -EOPNOTSUPP; 400 401 if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) 402 return -EFAULT; 403 404 return dev->ethtool_ops->set_ringparam(dev, &ringparam); 405} 406 407static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr) 408{ 409 struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; 410 411 if (!dev->ethtool_ops->get_pauseparam) 412 return -EOPNOTSUPP; 413 414 dev->ethtool_ops->get_pauseparam(dev, &pauseparam); 415 416 if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) 417 return -EFAULT; 418 return 0; 419} 420 421static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr) 422{ 423 struct ethtool_pauseparam pauseparam; 424 425 if (!dev->ethtool_ops->get_pauseparam) 426 return -EOPNOTSUPP; 427 428 if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) 429 return -EFAULT; 430 431 return dev->ethtool_ops->set_pauseparam(dev, &pauseparam); 432} 433 434static int ethtool_get_rx_csum(struct net_device *dev, char __user *useraddr) 435{ 436 struct ethtool_value edata = { ETHTOOL_GRXCSUM }; 437 438 if (!dev->ethtool_ops->get_rx_csum) 439 return -EOPNOTSUPP; 440 441 edata.data = dev->ethtool_ops->get_rx_csum(dev); 442 443 if (copy_to_user(useraddr, &edata, sizeof(edata))) 444 return -EFAULT; 445 return 0; 446} 447 448static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr) 449{ 450 struct ethtool_value edata; 451 452 if (!dev->ethtool_ops->set_rx_csum) 453 return -EOPNOTSUPP; 454 455 if (copy_from_user(&edata, useraddr, sizeof(edata))) 456 return -EFAULT; 457 458 dev->ethtool_ops->set_rx_csum(dev, edata.data); 459 return 0; 460} 461 462static int ethtool_get_tx_csum(struct net_device *dev, char __user *useraddr) 463{ 464 struct ethtool_value edata = { ETHTOOL_GTXCSUM }; 465 466 if (!dev->ethtool_ops->get_tx_csum) 467 return -EOPNOTSUPP; 468 469 edata.data = dev->ethtool_ops->get_tx_csum(dev); 470 471 if (copy_to_user(useraddr, &edata, sizeof(edata))) 472 return -EFAULT; 473 return 0; 474} 475 476static int __ethtool_set_sg(struct net_device *dev, u32 data) 477{ 478 int err; 479 480 if (!data && dev->ethtool_ops->set_tso) { 481 err = dev->ethtool_ops->set_tso(dev, 0); 482 if (err) 483 return err; 484 } 485 486 return dev->ethtool_ops->set_sg(dev, data); 487} 488 489static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr) 490{ 491 struct ethtool_value edata; 492 int err; 493 494 if (!dev->ethtool_ops->set_tx_csum) 495 return -EOPNOTSUPP; 496 497 if (copy_from_user(&edata, useraddr, sizeof(edata))) 498 return -EFAULT; 499 500 if (!edata.data && dev->ethtool_ops->set_sg) { 501 err = __ethtool_set_sg(dev, 0); 502 if (err) 503 return err; 504 } 505 506 return dev->ethtool_ops->set_tx_csum(dev, edata.data); 507} 508 509static int ethtool_get_sg(struct net_device *dev, char __user *useraddr) 510{ 511 struct ethtool_value edata = { ETHTOOL_GSG }; 512 513 if (!dev->ethtool_ops->get_sg) 514 return -EOPNOTSUPP; 515 516 edata.data = dev->ethtool_ops->get_sg(dev); 517 518 if (copy_to_user(useraddr, &edata, sizeof(edata))) 519 return -EFAULT; 520 return 0; 521} 522 523static int ethtool_set_sg(struct net_device *dev, char __user *useraddr) 524{ 525 struct ethtool_value edata; 526 527 if (!dev->ethtool_ops->set_sg) 528 return -EOPNOTSUPP; 529 530 if (copy_from_user(&edata, useraddr, sizeof(edata))) 531 return -EFAULT; 532 533 if (edata.data && 534 !(dev->features & (NETIF_F_IP_CSUM | 535 NETIF_F_NO_CSUM | 536 NETIF_F_HW_CSUM))) 537 return -EINVAL; 538 539 return __ethtool_set_sg(dev, edata.data); 540} 541 542static int ethtool_get_tso(struct net_device *dev, char __user *useraddr) 543{ 544 struct ethtool_value edata = { ETHTOOL_GTSO }; 545 546 if (!dev->ethtool_ops->get_tso) 547 return -EOPNOTSUPP; 548 549 edata.data = dev->ethtool_ops->get_tso(dev); 550 551 if (copy_to_user(useraddr, &edata, sizeof(edata))) 552 return -EFAULT; 553 return 0; 554} 555 556static int ethtool_set_tso(struct net_device *dev, char __user *useraddr) 557{ 558 struct ethtool_value edata; 559 560 if (!dev->ethtool_ops->set_tso) 561 return -EOPNOTSUPP; 562 563 if (copy_from_user(&edata, useraddr, sizeof(edata))) 564 return -EFAULT; 565 566 if (edata.data && !(dev->features & NETIF_F_SG)) 567 return -EINVAL; 568 569 return dev->ethtool_ops->set_tso(dev, edata.data); 570} 571 572static int ethtool_self_test(struct net_device *dev, char __user *useraddr) 573{ 574 struct ethtool_test test; 575 struct ethtool_ops *ops = dev->ethtool_ops; 576 u64 *data; 577 int ret; 578 579 if (!ops->self_test || !ops->self_test_count) 580 return -EOPNOTSUPP; 581 582 if (copy_from_user(&test, useraddr, sizeof(test))) 583 return -EFAULT; 584 585 test.len = ops->self_test_count(dev); 586 data = kmalloc(test.len * sizeof(u64), GFP_USER); 587 if (!data) 588 return -ENOMEM; 589 590 ops->self_test(dev, &test, data); 591 592 ret = -EFAULT; 593 if (copy_to_user(useraddr, &test, sizeof(test))) 594 goto out; 595 useraddr += sizeof(test); 596 if (copy_to_user(useraddr, data, test.len * sizeof(u64))) 597 goto out; 598 ret = 0; 599 600 out: 601 kfree(data); 602 return ret; 603} 604 605static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) 606{ 607 struct ethtool_gstrings gstrings; 608 struct ethtool_ops *ops = dev->ethtool_ops; 609 u8 *data; 610 int ret; 611 612 if (!ops->get_strings) 613 return -EOPNOTSUPP; 614 615 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) 616 return -EFAULT; 617 618 switch (gstrings.string_set) { 619 case ETH_SS_TEST: 620 if (!ops->self_test_count) 621 return -EOPNOTSUPP; 622 gstrings.len = ops->self_test_count(dev); 623 break; 624 case ETH_SS_STATS: 625 if (!ops->get_stats_count) 626 return -EOPNOTSUPP; 627 gstrings.len = ops->get_stats_count(dev); 628 break; 629 default: 630 return -EINVAL; 631 } 632 633 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); 634 if (!data) 635 return -ENOMEM; 636 637 ops->get_strings(dev, gstrings.string_set, data); 638 639 ret = -EFAULT; 640 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) 641 goto out; 642 useraddr += sizeof(gstrings); 643 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) 644 goto out; 645 ret = 0; 646 647 out: 648 kfree(data); 649 return ret; 650} 651 652static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) 653{ 654 struct ethtool_value id; 655 656 if (!dev->ethtool_ops->phys_id) 657 return -EOPNOTSUPP; 658 659 if (copy_from_user(&id, useraddr, sizeof(id))) 660 return -EFAULT; 661 662 return dev->ethtool_ops->phys_id(dev, id.data); 663} 664 665static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) 666{ 667 struct ethtool_stats stats; 668 struct ethtool_ops *ops = dev->ethtool_ops; 669 u64 *data; 670 int ret; 671 672 if (!ops->get_ethtool_stats || !ops->get_stats_count) 673 return -EOPNOTSUPP; 674 675 if (copy_from_user(&stats, useraddr, sizeof(stats))) 676 return -EFAULT; 677 678 stats.n_stats = ops->get_stats_count(dev); 679 data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); 680 if (!data) 681 return -ENOMEM; 682 683 ops->get_ethtool_stats(dev, &stats, data); 684 685 ret = -EFAULT; 686 if (copy_to_user(useraddr, &stats, sizeof(stats))) 687 goto out; 688 useraddr += sizeof(stats); 689 if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) 690 goto out; 691 ret = 0; 692 693 out: 694 kfree(data); 695 return ret; 696} 697 698static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr) 699{ 700 struct ethtool_perm_addr epaddr; 701 u8 *data; 702 int ret; 703 704 if (!dev->ethtool_ops->get_perm_addr) 705 return -EOPNOTSUPP; 706 707 if (copy_from_user(&epaddr,useraddr,sizeof(epaddr))) 708 return -EFAULT; 709 710 data = kmalloc(epaddr.size, GFP_USER); 711 if (!data) 712 return -ENOMEM; 713 714 ret = dev->ethtool_ops->get_perm_addr(dev,&epaddr,data); 715 if (ret) 716 return ret; 717 718 ret = -EFAULT; 719 if (copy_to_user(useraddr, &epaddr, sizeof(epaddr))) 720 goto out; 721 useraddr += sizeof(epaddr); 722 if (copy_to_user(useraddr, data, epaddr.size)) 723 goto out; 724 ret = 0; 725 726 out: 727 kfree(data); 728 return ret; 729} 730 731/* The main entry point in this file. Called from net/core/dev.c */ 732 733int dev_ethtool(struct ifreq *ifr) 734{ 735 struct net_device *dev = __dev_get_by_name(ifr->ifr_name); 736 void __user *useraddr = ifr->ifr_data; 737 u32 ethcmd; 738 int rc; 739 unsigned long old_features; 740 741 /* 742 * XXX: This can be pushed down into the ethtool_* handlers that 743 * need it. Keep existing behaviour for the moment. 744 */ 745 if (!capable(CAP_NET_ADMIN)) 746 return -EPERM; 747 748 if (!dev || !netif_device_present(dev)) 749 return -ENODEV; 750 751 if (!dev->ethtool_ops) 752 goto ioctl; 753 754 if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd))) 755 return -EFAULT; 756 757 if(dev->ethtool_ops->begin) 758 if ((rc = dev->ethtool_ops->begin(dev)) < 0) 759 return rc; 760 761 old_features = dev->features; 762 763 switch (ethcmd) { 764 case ETHTOOL_GSET: 765 rc = ethtool_get_settings(dev, useraddr); 766 break; 767 case ETHTOOL_SSET: 768 rc = ethtool_set_settings(dev, useraddr); 769 break; 770 case ETHTOOL_GDRVINFO: 771 rc = ethtool_get_drvinfo(dev, useraddr); 772 break; 773 case ETHTOOL_GREGS: 774 rc = ethtool_get_regs(dev, useraddr); 775 break; 776 case ETHTOOL_GWOL: 777 rc = ethtool_get_wol(dev, useraddr); 778 break; 779 case ETHTOOL_SWOL: 780 rc = ethtool_set_wol(dev, useraddr); 781 break; 782 case ETHTOOL_GMSGLVL: 783 rc = ethtool_get_msglevel(dev, useraddr); 784 break; 785 case ETHTOOL_SMSGLVL: 786 rc = ethtool_set_msglevel(dev, useraddr); 787 break; 788 case ETHTOOL_NWAY_RST: 789 rc = ethtool_nway_reset(dev); 790 break; 791 case ETHTOOL_GLINK: 792 rc = ethtool_get_link(dev, useraddr); 793 break; 794 case ETHTOOL_GEEPROM: 795 rc = ethtool_get_eeprom(dev, useraddr); 796 break; 797 case ETHTOOL_SEEPROM: 798 rc = ethtool_set_eeprom(dev, useraddr); 799 break; 800 case ETHTOOL_GCOALESCE: 801 rc = ethtool_get_coalesce(dev, useraddr); 802 break; 803 case ETHTOOL_SCOALESCE: 804 rc = ethtool_set_coalesce(dev, useraddr); 805 break; 806 case ETHTOOL_GRINGPARAM: 807 rc = ethtool_get_ringparam(dev, useraddr); 808 break; 809 case ETHTOOL_SRINGPARAM: 810 rc = ethtool_set_ringparam(dev, useraddr); 811 break; 812 case ETHTOOL_GPAUSEPARAM: 813 rc = ethtool_get_pauseparam(dev, useraddr); 814 break; 815 case ETHTOOL_SPAUSEPARAM: 816 rc = ethtool_set_pauseparam(dev, useraddr); 817 break; 818 case ETHTOOL_GRXCSUM: 819 rc = ethtool_get_rx_csum(dev, useraddr); 820 break; 821 case ETHTOOL_SRXCSUM: 822 rc = ethtool_set_rx_csum(dev, useraddr); 823 break; 824 case ETHTOOL_GTXCSUM: 825 rc = ethtool_get_tx_csum(dev, useraddr); 826 break; 827 case ETHTOOL_STXCSUM: 828 rc = ethtool_set_tx_csum(dev, useraddr); 829 break; 830 case ETHTOOL_GSG: 831 rc = ethtool_get_sg(dev, useraddr); 832 break; 833 case ETHTOOL_SSG: 834 rc = ethtool_set_sg(dev, useraddr); 835 break; 836 case ETHTOOL_GTSO: 837 rc = ethtool_get_tso(dev, useraddr); 838 break; 839 case ETHTOOL_STSO: 840 rc = ethtool_set_tso(dev, useraddr); 841 break; 842 case ETHTOOL_TEST: 843 rc = ethtool_self_test(dev, useraddr); 844 break; 845 case ETHTOOL_GSTRINGS: 846 rc = ethtool_get_strings(dev, useraddr); 847 break; 848 case ETHTOOL_PHYS_ID: 849 rc = ethtool_phys_id(dev, useraddr); 850 break; 851 case ETHTOOL_GSTATS: 852 rc = ethtool_get_stats(dev, useraddr); 853 break; 854 case ETHTOOL_GPERMADDR: 855 rc = ethtool_get_perm_addr(dev, useraddr); 856 break; 857 default: 858 rc = -EOPNOTSUPP; 859 } 860 861 if(dev->ethtool_ops->complete) 862 dev->ethtool_ops->complete(dev); 863 864 if (old_features != dev->features) 865 netdev_features_change(dev); 866 867 return rc; 868 869 ioctl: 870 if (dev->do_ioctl) 871 return dev->do_ioctl(dev, ifr, SIOCETHTOOL); 872 return -EOPNOTSUPP; 873} 874 875EXPORT_SYMBOL(dev_ethtool); 876EXPORT_SYMBOL(ethtool_op_get_link); 877EXPORT_SYMBOL_GPL(ethtool_op_get_perm_addr); 878EXPORT_SYMBOL(ethtool_op_get_sg); 879EXPORT_SYMBOL(ethtool_op_get_tso); 880EXPORT_SYMBOL(ethtool_op_get_tx_csum); 881EXPORT_SYMBOL(ethtool_op_set_sg); 882EXPORT_SYMBOL(ethtool_op_set_tso); 883EXPORT_SYMBOL(ethtool_op_set_tx_csum); 884EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);