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