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