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