]> bbs.cooldavid.org Git - net-next-2.6.git/blob - net/core/ethtool.c
ethtool: device independent rx_csum and get_flags routines
[net-next-2.6.git] / net / core / ethtool.c
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 <asm/uaccess.h>
21
22 /*
23  * Some useful ethtool_ops methods that're device independent.
24  * If we find that all drivers want to do the same thing here,
25  * we can turn these into dev_() function calls.
26  */
27
28 u32 ethtool_op_get_link(struct net_device *dev)
29 {
30         return netif_carrier_ok(dev) ? 1 : 0;
31 }
32
33 u32 ethtool_op_get_rx_csum(struct net_device *dev)
34 {
35         return (dev->features & NETIF_F_ALL_CSUM) != 0;
36 }
37
38 u32 ethtool_op_get_tx_csum(struct net_device *dev)
39 {
40         return (dev->features & NETIF_F_ALL_CSUM) != 0;
41 }
42
43 int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
44 {
45         if (data)
46                 dev->features |= NETIF_F_IP_CSUM;
47         else
48                 dev->features &= ~NETIF_F_IP_CSUM;
49
50         return 0;
51 }
52
53 int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data)
54 {
55         if (data)
56                 dev->features |= NETIF_F_HW_CSUM;
57         else
58                 dev->features &= ~NETIF_F_HW_CSUM;
59
60         return 0;
61 }
62
63 int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data)
64 {
65         if (data)
66                 dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
67         else
68                 dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
69
70         return 0;
71 }
72
73 u32 ethtool_op_get_sg(struct net_device *dev)
74 {
75         return (dev->features & NETIF_F_SG) != 0;
76 }
77
78 int ethtool_op_set_sg(struct net_device *dev, u32 data)
79 {
80         if (data)
81                 dev->features |= NETIF_F_SG;
82         else
83                 dev->features &= ~NETIF_F_SG;
84
85         return 0;
86 }
87
88 u32 ethtool_op_get_tso(struct net_device *dev)
89 {
90         return (dev->features & NETIF_F_TSO) != 0;
91 }
92
93 int ethtool_op_set_tso(struct net_device *dev, u32 data)
94 {
95         if (data)
96                 dev->features |= NETIF_F_TSO;
97         else
98                 dev->features &= ~NETIF_F_TSO;
99
100         return 0;
101 }
102
103 u32 ethtool_op_get_ufo(struct net_device *dev)
104 {
105         return (dev->features & NETIF_F_UFO) != 0;
106 }
107
108 int ethtool_op_set_ufo(struct net_device *dev, u32 data)
109 {
110         if (data)
111                 dev->features |= NETIF_F_UFO;
112         else
113                 dev->features &= ~NETIF_F_UFO;
114         return 0;
115 }
116
117 /* the following list of flags are the same as their associated
118  * NETIF_F_xxx values in include/linux/netdevice.h
119  */
120 static const u32 flags_dup_features =
121         ETH_FLAG_LRO;
122
123 u32 ethtool_op_get_flags(struct net_device *dev)
124 {
125         /* in the future, this function will probably contain additional
126          * handling for flags which are not so easily handled
127          * by a simple masking operation
128          */
129
130         return dev->features & flags_dup_features;
131 }
132
133 int ethtool_op_set_flags(struct net_device *dev, u32 data)
134 {
135         if (data & ETH_FLAG_LRO)
136                 dev->features |= NETIF_F_LRO;
137         else
138                 dev->features &= ~NETIF_F_LRO;
139
140         return 0;
141 }
142
143 /* Handlers for each ethtool command */
144
145 static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
146 {
147         struct ethtool_cmd cmd = { ETHTOOL_GSET };
148         int err;
149
150         if (!dev->ethtool_ops->get_settings)
151                 return -EOPNOTSUPP;
152
153         err = dev->ethtool_ops->get_settings(dev, &cmd);
154         if (err < 0)
155                 return err;
156
157         if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
158                 return -EFAULT;
159         return 0;
160 }
161
162 static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
163 {
164         struct ethtool_cmd cmd;
165
166         if (!dev->ethtool_ops->set_settings)
167                 return -EOPNOTSUPP;
168
169         if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
170                 return -EFAULT;
171
172         return dev->ethtool_ops->set_settings(dev, &cmd);
173 }
174
175 static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr)
176 {
177         struct ethtool_drvinfo info;
178         const struct ethtool_ops *ops = dev->ethtool_ops;
179
180         if (!ops->get_drvinfo)
181                 return -EOPNOTSUPP;
182
183         memset(&info, 0, sizeof(info));
184         info.cmd = ETHTOOL_GDRVINFO;
185         ops->get_drvinfo(dev, &info);
186
187         if (ops->get_sset_count) {
188                 int rc;
189
190                 rc = ops->get_sset_count(dev, ETH_SS_TEST);
191                 if (rc >= 0)
192                         info.testinfo_len = rc;
193                 rc = ops->get_sset_count(dev, ETH_SS_STATS);
194                 if (rc >= 0)
195                         info.n_stats = rc;
196                 rc = ops->get_sset_count(dev, ETH_SS_PRIV_FLAGS);
197                 if (rc >= 0)
198                         info.n_priv_flags = rc;
199         } else {
200                 /* code path for obsolete hooks */
201
202                 if (ops->self_test_count)
203                         info.testinfo_len = ops->self_test_count(dev);
204                 if (ops->get_stats_count)
205                         info.n_stats = ops->get_stats_count(dev);
206         }
207         if (ops->get_regs_len)
208                 info.regdump_len = ops->get_regs_len(dev);
209         if (ops->get_eeprom_len)
210                 info.eedump_len = ops->get_eeprom_len(dev);
211
212         if (copy_to_user(useraddr, &info, sizeof(info)))
213                 return -EFAULT;
214         return 0;
215 }
216
217 static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr)
218 {
219         struct ethtool_rxnfc cmd;
220
221         if (!dev->ethtool_ops->set_rxnfc)
222                 return -EOPNOTSUPP;
223
224         if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
225                 return -EFAULT;
226
227         return dev->ethtool_ops->set_rxnfc(dev, &cmd);
228 }
229
230 static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr)
231 {
232         struct ethtool_rxnfc info;
233         const struct ethtool_ops *ops = dev->ethtool_ops;
234         int ret;
235         void *rule_buf = NULL;
236
237         if (!ops->get_rxnfc)
238                 return -EOPNOTSUPP;
239
240         if (copy_from_user(&info, useraddr, sizeof(info)))
241                 return -EFAULT;
242
243         if (info.cmd == ETHTOOL_GRXCLSRLALL) {
244                 if (info.rule_cnt > 0) {
245                         rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
246                                            GFP_USER);
247                         if (!rule_buf)
248                                 return -ENOMEM;
249                 }
250         }
251
252         ret = ops->get_rxnfc(dev, &info, rule_buf);
253         if (ret < 0)
254                 goto err_out;
255
256         ret = -EFAULT;
257         if (copy_to_user(useraddr, &info, sizeof(info)))
258                 goto err_out;
259
260         if (rule_buf) {
261                 useraddr += offsetof(struct ethtool_rxnfc, rule_locs);
262                 if (copy_to_user(useraddr, rule_buf,
263                                  info.rule_cnt * sizeof(u32)))
264                         goto err_out;
265         }
266         ret = 0;
267
268 err_out:
269         kfree(rule_buf);
270
271         return ret;
272 }
273
274 static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
275 {
276         struct ethtool_regs regs;
277         const struct ethtool_ops *ops = dev->ethtool_ops;
278         void *regbuf;
279         int reglen, ret;
280
281         if (!ops->get_regs || !ops->get_regs_len)
282                 return -EOPNOTSUPP;
283
284         if (copy_from_user(&regs, useraddr, sizeof(regs)))
285                 return -EFAULT;
286
287         reglen = ops->get_regs_len(dev);
288         if (regs.len > reglen)
289                 regs.len = reglen;
290
291         regbuf = kmalloc(reglen, GFP_USER);
292         if (!regbuf)
293                 return -ENOMEM;
294
295         ops->get_regs(dev, &regs, regbuf);
296
297         ret = -EFAULT;
298         if (copy_to_user(useraddr, &regs, sizeof(regs)))
299                 goto out;
300         useraddr += offsetof(struct ethtool_regs, data);
301         if (copy_to_user(useraddr, regbuf, regs.len))
302                 goto out;
303         ret = 0;
304
305  out:
306         kfree(regbuf);
307         return ret;
308 }
309
310 static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
311 {
312         struct ethtool_wolinfo wol = { ETHTOOL_GWOL };
313
314         if (!dev->ethtool_ops->get_wol)
315                 return -EOPNOTSUPP;
316
317         dev->ethtool_ops->get_wol(dev, &wol);
318
319         if (copy_to_user(useraddr, &wol, sizeof(wol)))
320                 return -EFAULT;
321         return 0;
322 }
323
324 static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
325 {
326         struct ethtool_wolinfo wol;
327
328         if (!dev->ethtool_ops->set_wol)
329                 return -EOPNOTSUPP;
330
331         if (copy_from_user(&wol, useraddr, sizeof(wol)))
332                 return -EFAULT;
333
334         return dev->ethtool_ops->set_wol(dev, &wol);
335 }
336
337 static int ethtool_nway_reset(struct net_device *dev)
338 {
339         if (!dev->ethtool_ops->nway_reset)
340                 return -EOPNOTSUPP;
341
342         return dev->ethtool_ops->nway_reset(dev);
343 }
344
345 static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
346 {
347         struct ethtool_eeprom eeprom;
348         const struct ethtool_ops *ops = dev->ethtool_ops;
349         void __user *userbuf = useraddr + sizeof(eeprom);
350         u32 bytes_remaining;
351         u8 *data;
352         int ret = 0;
353
354         if (!ops->get_eeprom || !ops->get_eeprom_len)
355                 return -EOPNOTSUPP;
356
357         if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
358                 return -EFAULT;
359
360         /* Check for wrap and zero */
361         if (eeprom.offset + eeprom.len <= eeprom.offset)
362                 return -EINVAL;
363
364         /* Check for exceeding total eeprom len */
365         if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
366                 return -EINVAL;
367
368         data = kmalloc(PAGE_SIZE, GFP_USER);
369         if (!data)
370                 return -ENOMEM;
371
372         bytes_remaining = eeprom.len;
373         while (bytes_remaining > 0) {
374                 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
375
376                 ret = ops->get_eeprom(dev, &eeprom, data);
377                 if (ret)
378                         break;
379                 if (copy_to_user(userbuf, data, eeprom.len)) {
380                         ret = -EFAULT;
381                         break;
382                 }
383                 userbuf += eeprom.len;
384                 eeprom.offset += eeprom.len;
385                 bytes_remaining -= eeprom.len;
386         }
387
388         eeprom.len = userbuf - (useraddr + sizeof(eeprom));
389         eeprom.offset -= eeprom.len;
390         if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
391                 ret = -EFAULT;
392
393         kfree(data);
394         return ret;
395 }
396
397 static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
398 {
399         struct ethtool_eeprom eeprom;
400         const struct ethtool_ops *ops = dev->ethtool_ops;
401         void __user *userbuf = useraddr + sizeof(eeprom);
402         u32 bytes_remaining;
403         u8 *data;
404         int ret = 0;
405
406         if (!ops->set_eeprom || !ops->get_eeprom_len)
407                 return -EOPNOTSUPP;
408
409         if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
410                 return -EFAULT;
411
412         /* Check for wrap and zero */
413         if (eeprom.offset + eeprom.len <= eeprom.offset)
414                 return -EINVAL;
415
416         /* Check for exceeding total eeprom len */
417         if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
418                 return -EINVAL;
419
420         data = kmalloc(PAGE_SIZE, GFP_USER);
421         if (!data)
422                 return -ENOMEM;
423
424         bytes_remaining = eeprom.len;
425         while (bytes_remaining > 0) {
426                 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
427
428                 if (copy_from_user(data, userbuf, eeprom.len)) {
429                         ret = -EFAULT;
430                         break;
431                 }
432                 ret = ops->set_eeprom(dev, &eeprom, data);
433                 if (ret)
434                         break;
435                 userbuf += eeprom.len;
436                 eeprom.offset += eeprom.len;
437                 bytes_remaining -= eeprom.len;
438         }
439
440         kfree(data);
441         return ret;
442 }
443
444 static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr)
445 {
446         struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE };
447
448         if (!dev->ethtool_ops->get_coalesce)
449                 return -EOPNOTSUPP;
450
451         dev->ethtool_ops->get_coalesce(dev, &coalesce);
452
453         if (copy_to_user(useraddr, &coalesce, sizeof(coalesce)))
454                 return -EFAULT;
455         return 0;
456 }
457
458 static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr)
459 {
460         struct ethtool_coalesce coalesce;
461
462         if (!dev->ethtool_ops->set_coalesce)
463                 return -EOPNOTSUPP;
464
465         if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
466                 return -EFAULT;
467
468         return dev->ethtool_ops->set_coalesce(dev, &coalesce);
469 }
470
471 static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr)
472 {
473         struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM };
474
475         if (!dev->ethtool_ops->get_ringparam)
476                 return -EOPNOTSUPP;
477
478         dev->ethtool_ops->get_ringparam(dev, &ringparam);
479
480         if (copy_to_user(useraddr, &ringparam, sizeof(ringparam)))
481                 return -EFAULT;
482         return 0;
483 }
484
485 static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr)
486 {
487         struct ethtool_ringparam ringparam;
488
489         if (!dev->ethtool_ops->set_ringparam)
490                 return -EOPNOTSUPP;
491
492         if (copy_from_user(&ringparam, useraddr, sizeof(ringparam)))
493                 return -EFAULT;
494
495         return dev->ethtool_ops->set_ringparam(dev, &ringparam);
496 }
497
498 static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr)
499 {
500         struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM };
501
502         if (!dev->ethtool_ops->get_pauseparam)
503                 return -EOPNOTSUPP;
504
505         dev->ethtool_ops->get_pauseparam(dev, &pauseparam);
506
507         if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam)))
508                 return -EFAULT;
509         return 0;
510 }
511
512 static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr)
513 {
514         struct ethtool_pauseparam pauseparam;
515
516         if (!dev->ethtool_ops->set_pauseparam)
517                 return -EOPNOTSUPP;
518
519         if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam)))
520                 return -EFAULT;
521
522         return dev->ethtool_ops->set_pauseparam(dev, &pauseparam);
523 }
524
525 static int __ethtool_set_sg(struct net_device *dev, u32 data)
526 {
527         int err;
528
529         if (!data && dev->ethtool_ops->set_tso) {
530                 err = dev->ethtool_ops->set_tso(dev, 0);
531                 if (err)
532                         return err;
533         }
534
535         if (!data && dev->ethtool_ops->set_ufo) {
536                 err = dev->ethtool_ops->set_ufo(dev, 0);
537                 if (err)
538                         return err;
539         }
540         return dev->ethtool_ops->set_sg(dev, data);
541 }
542
543 static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr)
544 {
545         struct ethtool_value edata;
546         int err;
547
548         if (!dev->ethtool_ops->set_tx_csum)
549                 return -EOPNOTSUPP;
550
551         if (copy_from_user(&edata, useraddr, sizeof(edata)))
552                 return -EFAULT;
553
554         if (!edata.data && dev->ethtool_ops->set_sg) {
555                 err = __ethtool_set_sg(dev, 0);
556                 if (err)
557                         return err;
558         }
559
560         return dev->ethtool_ops->set_tx_csum(dev, edata.data);
561 }
562
563 static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr)
564 {
565         struct ethtool_value edata;
566
567         if (!dev->ethtool_ops->set_rx_csum)
568                 return -EOPNOTSUPP;
569
570         if (copy_from_user(&edata, useraddr, sizeof(edata)))
571                 return -EFAULT;
572
573         if (!edata.data && dev->ethtool_ops->set_sg)
574                 dev->features &= ~NETIF_F_GRO;
575
576         return dev->ethtool_ops->set_rx_csum(dev, edata.data);
577 }
578
579 static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
580 {
581         struct ethtool_value edata;
582
583         if (!dev->ethtool_ops->set_sg)
584                 return -EOPNOTSUPP;
585
586         if (copy_from_user(&edata, useraddr, sizeof(edata)))
587                 return -EFAULT;
588
589         if (edata.data &&
590             !(dev->features & NETIF_F_ALL_CSUM))
591                 return -EINVAL;
592
593         return __ethtool_set_sg(dev, edata.data);
594 }
595
596 static int ethtool_set_tso(struct net_device *dev, char __user *useraddr)
597 {
598         struct ethtool_value edata;
599
600         if (!dev->ethtool_ops->set_tso)
601                 return -EOPNOTSUPP;
602
603         if (copy_from_user(&edata, useraddr, sizeof(edata)))
604                 return -EFAULT;
605
606         if (edata.data && !(dev->features & NETIF_F_SG))
607                 return -EINVAL;
608
609         return dev->ethtool_ops->set_tso(dev, edata.data);
610 }
611
612 static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
613 {
614         struct ethtool_value edata;
615
616         if (!dev->ethtool_ops->set_ufo)
617                 return -EOPNOTSUPP;
618         if (copy_from_user(&edata, useraddr, sizeof(edata)))
619                 return -EFAULT;
620         if (edata.data && !(dev->features & NETIF_F_SG))
621                 return -EINVAL;
622         if (edata.data && !(dev->features & NETIF_F_HW_CSUM))
623                 return -EINVAL;
624         return dev->ethtool_ops->set_ufo(dev, edata.data);
625 }
626
627 static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
628 {
629         struct ethtool_value edata = { ETHTOOL_GGSO };
630
631         edata.data = dev->features & NETIF_F_GSO;
632         if (copy_to_user(useraddr, &edata, sizeof(edata)))
633                  return -EFAULT;
634         return 0;
635 }
636
637 static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
638 {
639         struct ethtool_value edata;
640
641         if (copy_from_user(&edata, useraddr, sizeof(edata)))
642                 return -EFAULT;
643         if (edata.data)
644                 dev->features |= NETIF_F_GSO;
645         else
646                 dev->features &= ~NETIF_F_GSO;
647         return 0;
648 }
649
650 static int ethtool_get_gro(struct net_device *dev, char __user *useraddr)
651 {
652         struct ethtool_value edata = { ETHTOOL_GGRO };
653
654         edata.data = dev->features & NETIF_F_GRO;
655         if (copy_to_user(useraddr, &edata, sizeof(edata)))
656                  return -EFAULT;
657         return 0;
658 }
659
660 static int ethtool_set_gro(struct net_device *dev, char __user *useraddr)
661 {
662         struct ethtool_value edata;
663
664         if (copy_from_user(&edata, useraddr, sizeof(edata)))
665                 return -EFAULT;
666
667         if (edata.data) {
668                 if (!dev->ethtool_ops->get_rx_csum ||
669                     !dev->ethtool_ops->get_rx_csum(dev))
670                         return -EINVAL;
671                 dev->features |= NETIF_F_GRO;
672         } else
673                 dev->features &= ~NETIF_F_GRO;
674
675         return 0;
676 }
677
678 static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
679 {
680         struct ethtool_test test;
681         const struct ethtool_ops *ops = dev->ethtool_ops;
682         u64 *data;
683         int ret, test_len;
684
685         if (!ops->self_test)
686                 return -EOPNOTSUPP;
687         if (!ops->get_sset_count && !ops->self_test_count)
688                 return -EOPNOTSUPP;
689
690         if (ops->get_sset_count)
691                 test_len = ops->get_sset_count(dev, ETH_SS_TEST);
692         else
693                 /* code path for obsolete hook */
694                 test_len = ops->self_test_count(dev);
695         if (test_len < 0)
696                 return test_len;
697         WARN_ON(test_len == 0);
698
699         if (copy_from_user(&test, useraddr, sizeof(test)))
700                 return -EFAULT;
701
702         test.len = test_len;
703         data = kmalloc(test_len * sizeof(u64), GFP_USER);
704         if (!data)
705                 return -ENOMEM;
706
707         ops->self_test(dev, &test, data);
708
709         ret = -EFAULT;
710         if (copy_to_user(useraddr, &test, sizeof(test)))
711                 goto out;
712         useraddr += sizeof(test);
713         if (copy_to_user(useraddr, data, test.len * sizeof(u64)))
714                 goto out;
715         ret = 0;
716
717  out:
718         kfree(data);
719         return ret;
720 }
721
722 static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
723 {
724         struct ethtool_gstrings gstrings;
725         const struct ethtool_ops *ops = dev->ethtool_ops;
726         u8 *data;
727         int ret;
728
729         if (!ops->get_strings)
730                 return -EOPNOTSUPP;
731
732         if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
733                 return -EFAULT;
734
735         if (ops->get_sset_count) {
736                 ret = ops->get_sset_count(dev, gstrings.string_set);
737                 if (ret < 0)
738                         return ret;
739
740                 gstrings.len = ret;
741         } else {
742                 /* code path for obsolete hooks */
743
744                 switch (gstrings.string_set) {
745                 case ETH_SS_TEST:
746                         if (!ops->self_test_count)
747                                 return -EOPNOTSUPP;
748                         gstrings.len = ops->self_test_count(dev);
749                         break;
750                 case ETH_SS_STATS:
751                         if (!ops->get_stats_count)
752                                 return -EOPNOTSUPP;
753                         gstrings.len = ops->get_stats_count(dev);
754                         break;
755                 default:
756                         return -EINVAL;
757                 }
758         }
759
760         data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
761         if (!data)
762                 return -ENOMEM;
763
764         ops->get_strings(dev, gstrings.string_set, data);
765
766         ret = -EFAULT;
767         if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
768                 goto out;
769         useraddr += sizeof(gstrings);
770         if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
771                 goto out;
772         ret = 0;
773
774  out:
775         kfree(data);
776         return ret;
777 }
778
779 static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
780 {
781         struct ethtool_value id;
782
783         if (!dev->ethtool_ops->phys_id)
784                 return -EOPNOTSUPP;
785
786         if (copy_from_user(&id, useraddr, sizeof(id)))
787                 return -EFAULT;
788
789         return dev->ethtool_ops->phys_id(dev, id.data);
790 }
791
792 static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
793 {
794         struct ethtool_stats stats;
795         const struct ethtool_ops *ops = dev->ethtool_ops;
796         u64 *data;
797         int ret, n_stats;
798
799         if (!ops->get_ethtool_stats)
800                 return -EOPNOTSUPP;
801         if (!ops->get_sset_count && !ops->get_stats_count)
802                 return -EOPNOTSUPP;
803
804         if (ops->get_sset_count)
805                 n_stats = ops->get_sset_count(dev, ETH_SS_STATS);
806         else
807                 /* code path for obsolete hook */
808                 n_stats = ops->get_stats_count(dev);
809         if (n_stats < 0)
810                 return n_stats;
811         WARN_ON(n_stats == 0);
812
813         if (copy_from_user(&stats, useraddr, sizeof(stats)))
814                 return -EFAULT;
815
816         stats.n_stats = n_stats;
817         data = kmalloc(n_stats * sizeof(u64), GFP_USER);
818         if (!data)
819                 return -ENOMEM;
820
821         ops->get_ethtool_stats(dev, &stats, data);
822
823         ret = -EFAULT;
824         if (copy_to_user(useraddr, &stats, sizeof(stats)))
825                 goto out;
826         useraddr += sizeof(stats);
827         if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64)))
828                 goto out;
829         ret = 0;
830
831  out:
832         kfree(data);
833         return ret;
834 }
835
836 static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
837 {
838         struct ethtool_perm_addr epaddr;
839
840         if (copy_from_user(&epaddr, useraddr, sizeof(epaddr)))
841                 return -EFAULT;
842
843         if (epaddr.size < dev->addr_len)
844                 return -ETOOSMALL;
845         epaddr.size = dev->addr_len;
846
847         if (copy_to_user(useraddr, &epaddr, sizeof(epaddr)))
848                 return -EFAULT;
849         useraddr += sizeof(epaddr);
850         if (copy_to_user(useraddr, dev->perm_addr, epaddr.size))
851                 return -EFAULT;
852         return 0;
853 }
854
855 static int ethtool_get_value(struct net_device *dev, char __user *useraddr,
856                              u32 cmd, u32 (*actor)(struct net_device *))
857 {
858         struct ethtool_value edata = { cmd };
859
860         if (!actor)
861                 return -EOPNOTSUPP;
862
863         edata.data = actor(dev);
864
865         if (copy_to_user(useraddr, &edata, sizeof(edata)))
866                 return -EFAULT;
867         return 0;
868 }
869
870 static int ethtool_set_value_void(struct net_device *dev, char __user *useraddr,
871                              void (*actor)(struct net_device *, u32))
872 {
873         struct ethtool_value edata;
874
875         if (!actor)
876                 return -EOPNOTSUPP;
877
878         if (copy_from_user(&edata, useraddr, sizeof(edata)))
879                 return -EFAULT;
880
881         actor(dev, edata.data);
882         return 0;
883 }
884
885 static int ethtool_set_value(struct net_device *dev, char __user *useraddr,
886                              int (*actor)(struct net_device *, u32))
887 {
888         struct ethtool_value edata;
889
890         if (!actor)
891                 return -EOPNOTSUPP;
892
893         if (copy_from_user(&edata, useraddr, sizeof(edata)))
894                 return -EFAULT;
895
896         return actor(dev, edata.data);
897 }
898
899 /* The main entry point in this file.  Called from net/core/dev.c */
900
901 int dev_ethtool(struct net *net, struct ifreq *ifr)
902 {
903         struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
904         void __user *useraddr = ifr->ifr_data;
905         u32 ethcmd;
906         int rc;
907         unsigned long old_features;
908
909         if (!dev || !netif_device_present(dev))
910                 return -ENODEV;
911
912         if (!dev->ethtool_ops)
913                 return -EOPNOTSUPP;
914
915         if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
916                 return -EFAULT;
917
918         /* Allow some commands to be done by anyone */
919         switch(ethcmd) {
920         case ETHTOOL_GDRVINFO:
921         case ETHTOOL_GMSGLVL:
922         case ETHTOOL_GCOALESCE:
923         case ETHTOOL_GRINGPARAM:
924         case ETHTOOL_GPAUSEPARAM:
925         case ETHTOOL_GRXCSUM:
926         case ETHTOOL_GTXCSUM:
927         case ETHTOOL_GSG:
928         case ETHTOOL_GSTRINGS:
929         case ETHTOOL_GTSO:
930         case ETHTOOL_GPERMADDR:
931         case ETHTOOL_GUFO:
932         case ETHTOOL_GGSO:
933         case ETHTOOL_GFLAGS:
934         case ETHTOOL_GPFLAGS:
935         case ETHTOOL_GRXFH:
936         case ETHTOOL_GRXRINGS:
937         case ETHTOOL_GRXCLSRLCNT:
938         case ETHTOOL_GRXCLSRULE:
939         case ETHTOOL_GRXCLSRLALL:
940                 break;
941         default:
942                 if (!capable(CAP_NET_ADMIN))
943                         return -EPERM;
944         }
945
946         if (dev->ethtool_ops->begin)
947                 if ((rc = dev->ethtool_ops->begin(dev)) < 0)
948                         return rc;
949
950         old_features = dev->features;
951
952         switch (ethcmd) {
953         case ETHTOOL_GSET:
954                 rc = ethtool_get_settings(dev, useraddr);
955                 break;
956         case ETHTOOL_SSET:
957                 rc = ethtool_set_settings(dev, useraddr);
958                 break;
959         case ETHTOOL_GDRVINFO:
960                 rc = ethtool_get_drvinfo(dev, useraddr);
961                 break;
962         case ETHTOOL_GREGS:
963                 rc = ethtool_get_regs(dev, useraddr);
964                 break;
965         case ETHTOOL_GWOL:
966                 rc = ethtool_get_wol(dev, useraddr);
967                 break;
968         case ETHTOOL_SWOL:
969                 rc = ethtool_set_wol(dev, useraddr);
970                 break;
971         case ETHTOOL_GMSGLVL:
972                 rc = ethtool_get_value(dev, useraddr, ethcmd,
973                                        dev->ethtool_ops->get_msglevel);
974                 break;
975         case ETHTOOL_SMSGLVL:
976                 rc = ethtool_set_value_void(dev, useraddr,
977                                        dev->ethtool_ops->set_msglevel);
978                 break;
979         case ETHTOOL_NWAY_RST:
980                 rc = ethtool_nway_reset(dev);
981                 break;
982         case ETHTOOL_GLINK:
983                 rc = ethtool_get_value(dev, useraddr, ethcmd,
984                                        dev->ethtool_ops->get_link);
985                 break;
986         case ETHTOOL_GEEPROM:
987                 rc = ethtool_get_eeprom(dev, useraddr);
988                 break;
989         case ETHTOOL_SEEPROM:
990                 rc = ethtool_set_eeprom(dev, useraddr);
991                 break;
992         case ETHTOOL_GCOALESCE:
993                 rc = ethtool_get_coalesce(dev, useraddr);
994                 break;
995         case ETHTOOL_SCOALESCE:
996                 rc = ethtool_set_coalesce(dev, useraddr);
997                 break;
998         case ETHTOOL_GRINGPARAM:
999                 rc = ethtool_get_ringparam(dev, useraddr);
1000                 break;
1001         case ETHTOOL_SRINGPARAM:
1002                 rc = ethtool_set_ringparam(dev, useraddr);
1003                 break;
1004         case ETHTOOL_GPAUSEPARAM:
1005                 rc = ethtool_get_pauseparam(dev, useraddr);
1006                 break;
1007         case ETHTOOL_SPAUSEPARAM:
1008                 rc = ethtool_set_pauseparam(dev, useraddr);
1009                 break;
1010         case ETHTOOL_GRXCSUM:
1011                 rc = ethtool_get_value(dev, useraddr, ethcmd,
1012                                        (dev->ethtool_ops->get_rx_csum ?
1013                                         dev->ethtool_ops->get_rx_csum :
1014                                         ethtool_op_get_rx_csum));
1015                 break;
1016         case ETHTOOL_SRXCSUM:
1017                 rc = ethtool_set_rx_csum(dev, useraddr);
1018                 break;
1019         case ETHTOOL_GTXCSUM:
1020                 rc = ethtool_get_value(dev, useraddr, ethcmd,
1021                                        (dev->ethtool_ops->get_tx_csum ?
1022                                         dev->ethtool_ops->get_tx_csum :
1023                                         ethtool_op_get_tx_csum));
1024                 break;
1025         case ETHTOOL_STXCSUM:
1026                 rc = ethtool_set_tx_csum(dev, useraddr);
1027                 break;
1028         case ETHTOOL_GSG:
1029                 rc = ethtool_get_value(dev, useraddr, ethcmd,
1030                                        (dev->ethtool_ops->get_sg ?
1031                                         dev->ethtool_ops->get_sg :
1032                                         ethtool_op_get_sg));
1033                 break;
1034         case ETHTOOL_SSG:
1035                 rc = ethtool_set_sg(dev, useraddr);
1036                 break;
1037         case ETHTOOL_GTSO:
1038                 rc = ethtool_get_value(dev, useraddr, ethcmd,
1039                                        (dev->ethtool_ops->get_tso ?
1040                                         dev->ethtool_ops->get_tso :
1041                                         ethtool_op_get_tso));
1042                 break;
1043         case ETHTOOL_STSO:
1044                 rc = ethtool_set_tso(dev, useraddr);
1045                 break;
1046         case ETHTOOL_TEST:
1047                 rc = ethtool_self_test(dev, useraddr);
1048                 break;
1049         case ETHTOOL_GSTRINGS:
1050                 rc = ethtool_get_strings(dev, useraddr);
1051                 break;
1052         case ETHTOOL_PHYS_ID:
1053                 rc = ethtool_phys_id(dev, useraddr);
1054                 break;
1055         case ETHTOOL_GSTATS:
1056                 rc = ethtool_get_stats(dev, useraddr);
1057                 break;
1058         case ETHTOOL_GPERMADDR:
1059                 rc = ethtool_get_perm_addr(dev, useraddr);
1060                 break;
1061         case ETHTOOL_GUFO:
1062                 rc = ethtool_get_value(dev, useraddr, ethcmd,
1063                                        (dev->ethtool_ops->get_ufo ?
1064                                         dev->ethtool_ops->get_ufo :
1065                                         ethtool_op_get_ufo));
1066                 break;
1067         case ETHTOOL_SUFO:
1068                 rc = ethtool_set_ufo(dev, useraddr);
1069                 break;
1070         case ETHTOOL_GGSO:
1071                 rc = ethtool_get_gso(dev, useraddr);
1072                 break;
1073         case ETHTOOL_SGSO:
1074                 rc = ethtool_set_gso(dev, useraddr);
1075                 break;
1076         case ETHTOOL_GFLAGS:
1077                 rc = ethtool_get_value(dev, useraddr, ethcmd,
1078                                        (dev->ethtool_ops->get_flags ?
1079                                         dev->ethtool_ops->get_flags :
1080                                         ethtool_op_get_flags));
1081                 break;
1082         case ETHTOOL_SFLAGS:
1083                 rc = ethtool_set_value(dev, useraddr,
1084                                        dev->ethtool_ops->set_flags);
1085                 break;
1086         case ETHTOOL_GPFLAGS:
1087                 rc = ethtool_get_value(dev, useraddr, ethcmd,
1088                                        dev->ethtool_ops->get_priv_flags);
1089                 break;
1090         case ETHTOOL_SPFLAGS:
1091                 rc = ethtool_set_value(dev, useraddr,
1092                                        dev->ethtool_ops->set_priv_flags);
1093                 break;
1094         case ETHTOOL_GRXFH:
1095         case ETHTOOL_GRXRINGS:
1096         case ETHTOOL_GRXCLSRLCNT:
1097         case ETHTOOL_GRXCLSRULE:
1098         case ETHTOOL_GRXCLSRLALL:
1099                 rc = ethtool_get_rxnfc(dev, useraddr);
1100                 break;
1101         case ETHTOOL_SRXFH:
1102         case ETHTOOL_SRXCLSRLDEL:
1103         case ETHTOOL_SRXCLSRLINS:
1104                 rc = ethtool_set_rxnfc(dev, useraddr);
1105                 break;
1106         case ETHTOOL_GGRO:
1107                 rc = ethtool_get_gro(dev, useraddr);
1108                 break;
1109         case ETHTOOL_SGRO:
1110                 rc = ethtool_set_gro(dev, useraddr);
1111                 break;
1112         default:
1113                 rc = -EOPNOTSUPP;
1114         }
1115
1116         if (dev->ethtool_ops->complete)
1117                 dev->ethtool_ops->complete(dev);
1118
1119         if (old_features != dev->features)
1120                 netdev_features_change(dev);
1121
1122         return rc;
1123 }
1124
1125 EXPORT_SYMBOL(ethtool_op_get_link);
1126 EXPORT_SYMBOL(ethtool_op_get_sg);
1127 EXPORT_SYMBOL(ethtool_op_get_tso);
1128 EXPORT_SYMBOL(ethtool_op_get_tx_csum);
1129 EXPORT_SYMBOL(ethtool_op_set_sg);
1130 EXPORT_SYMBOL(ethtool_op_set_tso);
1131 EXPORT_SYMBOL(ethtool_op_set_tx_csum);
1132 EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
1133 EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum);
1134 EXPORT_SYMBOL(ethtool_op_set_ufo);
1135 EXPORT_SYMBOL(ethtool_op_get_ufo);
1136 EXPORT_SYMBOL(ethtool_op_set_flags);
1137 EXPORT_SYMBOL(ethtool_op_get_flags);