Imported Upstream version 16.07.2
[deb_dpdk.git] / lib / librte_eal / linuxapp / kni / ethtool / igb / kcompat_ethtool.c
1 /*******************************************************************************
2
3   Intel(R) Gigabit Ethernet Linux driver
4   Copyright(c) 2007-2013 Intel Corporation.
5
6   This program is free software; you can redistribute it and/or modify it
7   under the terms and conditions of the GNU General Public License,
8   version 2, as published by the Free Software Foundation.
9
10   This program is distributed in the hope it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13   more details.
14
15   You should have received a copy of the GNU General Public License along with
16   this program; if not, write to the Free Software Foundation, Inc.,
17   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19   The full GNU General Public License is included in this distribution in
20   the file called "COPYING".
21
22   Contact Information:
23   e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
24   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
25
26 *******************************************************************************/
27
28 /*
29  * net/core/ethtool.c - Ethtool ioctl handler
30  * Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx>
31  *
32  * This file is where we call all the ethtool_ops commands to get
33  * the information ethtool needs.  We fall back to calling do_ioctl()
34  * for drivers which haven't been converted to ethtool_ops yet.
35  *
36  * It's GPL, stupid.
37  *
38  * Modification by sfeldma@pobox.com to work as backward compat
39  * solution for pre-ethtool_ops kernels.
40  *      - copied struct ethtool_ops from ethtool.h
41  *      - defined SET_ETHTOOL_OPS
42  *      - put in some #ifndef NETIF_F_xxx wrappers
43  *      - changes refs to dev->ethtool_ops to ethtool_ops
44  *      - changed dev_ethtool to ethtool_ioctl
45  *      - remove EXPORT_SYMBOL()s
46  *      - added _kc_ prefix in built-in ethtool_op_xxx ops.
47  */
48
49 #include <linux/module.h>
50 #include <linux/types.h>
51 #include <linux/errno.h>
52 #include <linux/mii.h>
53 #include <linux/ethtool.h>
54 #include <linux/netdevice.h>
55 #include <asm/uaccess.h>
56
57 #include "kcompat.h"
58
59 #undef SUPPORTED_10000baseT_Full
60 #define SUPPORTED_10000baseT_Full       (1 << 12)
61 #undef ADVERTISED_10000baseT_Full
62 #define ADVERTISED_10000baseT_Full      (1 << 12)
63 #undef SPEED_10000
64 #define SPEED_10000             10000
65
66 #undef ethtool_ops
67 #define ethtool_ops _kc_ethtool_ops
68
69 struct _kc_ethtool_ops {
70         int  (*get_settings)(struct net_device *, struct ethtool_cmd *);
71         int  (*set_settings)(struct net_device *, struct ethtool_cmd *);
72         void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
73         int  (*get_regs_len)(struct net_device *);
74         void (*get_regs)(struct net_device *, struct ethtool_regs *, void *);
75         void (*get_wol)(struct net_device *, struct ethtool_wolinfo *);
76         int  (*set_wol)(struct net_device *, struct ethtool_wolinfo *);
77         u32  (*get_msglevel)(struct net_device *);
78         void (*set_msglevel)(struct net_device *, u32);
79         int  (*nway_reset)(struct net_device *);
80         u32  (*get_link)(struct net_device *);
81         int  (*get_eeprom_len)(struct net_device *);
82         int  (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
83         int  (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
84         int  (*get_coalesce)(struct net_device *, struct ethtool_coalesce *);
85         int  (*set_coalesce)(struct net_device *, struct ethtool_coalesce *);
86         void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *);
87         int  (*set_ringparam)(struct net_device *, struct ethtool_ringparam *);
88         void (*get_pauseparam)(struct net_device *,
89                                struct ethtool_pauseparam*);
90         int  (*set_pauseparam)(struct net_device *,
91                                struct ethtool_pauseparam*);
92         u32  (*get_rx_csum)(struct net_device *);
93         int  (*set_rx_csum)(struct net_device *, u32);
94         u32  (*get_tx_csum)(struct net_device *);
95         int  (*set_tx_csum)(struct net_device *, u32);
96         u32  (*get_sg)(struct net_device *);
97         int  (*set_sg)(struct net_device *, u32);
98         u32  (*get_tso)(struct net_device *);
99         int  (*set_tso)(struct net_device *, u32);
100         int  (*self_test_count)(struct net_device *);
101         void (*self_test)(struct net_device *, struct ethtool_test *, u64 *);
102         void (*get_strings)(struct net_device *, u32 stringset, u8 *);
103         int  (*phys_id)(struct net_device *, u32);
104         int  (*get_stats_count)(struct net_device *);
105         void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *,
106                                   u64 *);
107 } *ethtool_ops = NULL;
108
109 #undef SET_ETHTOOL_OPS
110 #define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops))
111
112 /*
113  * Some useful ethtool_ops methods that are device independent. If we find that
114  * all drivers want to do the same thing here, we can turn these into dev_()
115  * function calls.
116  */
117
118 #undef ethtool_op_get_link
119 #define ethtool_op_get_link _kc_ethtool_op_get_link
120 u32 _kc_ethtool_op_get_link(struct net_device *dev)
121 {
122         return netif_carrier_ok(dev) ? 1 : 0;
123 }
124
125 #undef ethtool_op_get_tx_csum
126 #define ethtool_op_get_tx_csum _kc_ethtool_op_get_tx_csum
127 u32 _kc_ethtool_op_get_tx_csum(struct net_device *dev)
128 {
129 #ifdef NETIF_F_IP_CSUM
130         return (dev->features & NETIF_F_IP_CSUM) != 0;
131 #else
132         return 0;
133 #endif
134 }
135
136 #undef ethtool_op_set_tx_csum
137 #define ethtool_op_set_tx_csum _kc_ethtool_op_set_tx_csum
138 int _kc_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
139 {
140 #ifdef NETIF_F_IP_CSUM
141         if (data)
142 #ifdef NETIF_F_IPV6_CSUM
143                 dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
144         else
145                 dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
146 #else
147                 dev->features |= NETIF_F_IP_CSUM;
148         else
149                 dev->features &= ~NETIF_F_IP_CSUM;
150 #endif
151 #endif
152
153         return 0;
154 }
155
156 #undef ethtool_op_get_sg
157 #define ethtool_op_get_sg _kc_ethtool_op_get_sg
158 u32 _kc_ethtool_op_get_sg(struct net_device *dev)
159 {
160 #ifdef NETIF_F_SG
161         return (dev->features & NETIF_F_SG) != 0;
162 #else
163         return 0;
164 #endif
165 }
166
167 #undef ethtool_op_set_sg
168 #define ethtool_op_set_sg _kc_ethtool_op_set_sg
169 int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data)
170 {
171 #ifdef NETIF_F_SG
172         if (data)
173                 dev->features |= NETIF_F_SG;
174         else
175                 dev->features &= ~NETIF_F_SG;
176 #endif
177
178         return 0;
179 }
180
181 #undef ethtool_op_get_tso
182 #define ethtool_op_get_tso _kc_ethtool_op_get_tso
183 u32 _kc_ethtool_op_get_tso(struct net_device *dev)
184 {
185 #ifdef NETIF_F_TSO
186         return (dev->features & NETIF_F_TSO) != 0;
187 #else
188         return 0;
189 #endif
190 }
191
192 #undef ethtool_op_set_tso
193 #define ethtool_op_set_tso _kc_ethtool_op_set_tso
194 int _kc_ethtool_op_set_tso(struct net_device *dev, u32 data)
195 {
196 #ifdef NETIF_F_TSO
197         if (data)
198                 dev->features |= NETIF_F_TSO;
199         else
200                 dev->features &= ~NETIF_F_TSO;
201 #endif
202
203         return 0;
204 }
205
206 /* Handlers for each ethtool command */
207
208 static int ethtool_get_settings(struct net_device *dev, void *useraddr)
209 {
210         struct ethtool_cmd cmd = { ETHTOOL_GSET };
211         int err;
212
213         if (!ethtool_ops->get_settings)
214                 return -EOPNOTSUPP;
215
216         err = ethtool_ops->get_settings(dev, &cmd);
217         if (err < 0)
218                 return err;
219
220         if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
221                 return -EFAULT;
222         return 0;
223 }
224
225 static int ethtool_set_settings(struct net_device *dev, void *useraddr)
226 {
227         struct ethtool_cmd cmd;
228
229         if (!ethtool_ops->set_settings)
230                 return -EOPNOTSUPP;
231
232         if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
233                 return -EFAULT;
234
235         return ethtool_ops->set_settings(dev, &cmd);
236 }
237
238 static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr)
239 {
240         struct ethtool_drvinfo info;
241         struct ethtool_ops *ops = ethtool_ops;
242
243         if (!ops->get_drvinfo)
244                 return -EOPNOTSUPP;
245
246         memset(&info, 0, sizeof(info));
247         info.cmd = ETHTOOL_GDRVINFO;
248         ops->get_drvinfo(dev, &info);
249
250         if (ops->self_test_count)
251                 info.testinfo_len = ops->self_test_count(dev);
252         if (ops->get_stats_count)
253                 info.n_stats = ops->get_stats_count(dev);
254         if (ops->get_regs_len)
255                 info.regdump_len = ops->get_regs_len(dev);
256         if (ops->get_eeprom_len)
257                 info.eedump_len = ops->get_eeprom_len(dev);
258
259         if (copy_to_user(useraddr, &info, sizeof(info)))
260                 return -EFAULT;
261         return 0;
262 }
263
264 static int ethtool_get_regs(struct net_device *dev, char *useraddr)
265 {
266         struct ethtool_regs regs;
267         struct ethtool_ops *ops = ethtool_ops;
268         void *regbuf;
269         int reglen, ret;
270
271         if (!ops->get_regs || !ops->get_regs_len)
272                 return -EOPNOTSUPP;
273
274         if (copy_from_user(&regs, useraddr, sizeof(regs)))
275                 return -EFAULT;
276
277         reglen = ops->get_regs_len(dev);
278         if (regs.len > reglen)
279                 regs.len = reglen;
280
281         regbuf = kmalloc(reglen, GFP_USER);
282         if (!regbuf)
283                 return -ENOMEM;
284
285         ops->get_regs(dev, &regs, regbuf);
286
287         ret = -EFAULT;
288         if (copy_to_user(useraddr, &regs, sizeof(regs)))
289                 goto out;
290         useraddr += offsetof(struct ethtool_regs, data);
291         if (copy_to_user(useraddr, regbuf, reglen))
292                 goto out;
293         ret = 0;
294
295 out:
296         kfree(regbuf);
297         return ret;
298 }
299
300 static int ethtool_get_wol(struct net_device *dev, char *useraddr)
301 {
302         struct ethtool_wolinfo wol = { ETHTOOL_GWOL };
303
304         if (!ethtool_ops->get_wol)
305                 return -EOPNOTSUPP;
306
307         ethtool_ops->get_wol(dev, &wol);
308
309         if (copy_to_user(useraddr, &wol, sizeof(wol)))
310                 return -EFAULT;
311         return 0;
312 }
313
314 static int ethtool_set_wol(struct net_device *dev, char *useraddr)
315 {
316         struct ethtool_wolinfo wol;
317
318         if (!ethtool_ops->set_wol)
319                 return -EOPNOTSUPP;
320
321         if (copy_from_user(&wol, useraddr, sizeof(wol)))
322                 return -EFAULT;
323
324         return ethtool_ops->set_wol(dev, &wol);
325 }
326
327 static int ethtool_get_msglevel(struct net_device *dev, char *useraddr)
328 {
329         struct ethtool_value edata = { ETHTOOL_GMSGLVL };
330
331         if (!ethtool_ops->get_msglevel)
332                 return -EOPNOTSUPP;
333
334         edata.data = ethtool_ops->get_msglevel(dev);
335
336         if (copy_to_user(useraddr, &edata, sizeof(edata)))
337                 return -EFAULT;
338         return 0;
339 }
340
341 static int ethtool_set_msglevel(struct net_device *dev, char *useraddr)
342 {
343         struct ethtool_value edata;
344
345         if (!ethtool_ops->set_msglevel)
346                 return -EOPNOTSUPP;
347
348         if (copy_from_user(&edata, useraddr, sizeof(edata)))
349                 return -EFAULT;
350
351         ethtool_ops->set_msglevel(dev, edata.data);
352         return 0;
353 }
354
355 static int ethtool_nway_reset(struct net_device *dev)
356 {
357         if (!ethtool_ops->nway_reset)
358                 return -EOPNOTSUPP;
359
360         return ethtool_ops->nway_reset(dev);
361 }
362
363 static int ethtool_get_link(struct net_device *dev, void *useraddr)
364 {
365         struct ethtool_value edata = { ETHTOOL_GLINK };
366
367         if (!ethtool_ops->get_link)
368                 return -EOPNOTSUPP;
369
370         edata.data = ethtool_ops->get_link(dev);
371
372         if (copy_to_user(useraddr, &edata, sizeof(edata)))
373                 return -EFAULT;
374         return 0;
375 }
376
377 static int ethtool_get_eeprom(struct net_device *dev, void *useraddr)
378 {
379         struct ethtool_eeprom eeprom;
380         struct ethtool_ops *ops = ethtool_ops;
381         u8 *data;
382         int ret;
383
384         if (!ops->get_eeprom || !ops->get_eeprom_len)
385                 return -EOPNOTSUPP;
386
387         if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
388                 return -EFAULT;
389
390         /* Check for wrap and zero */
391         if (eeprom.offset + eeprom.len <= eeprom.offset)
392                 return -EINVAL;
393
394         /* Check for exceeding total eeprom len */
395         if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
396                 return -EINVAL;
397
398         data = kmalloc(eeprom.len, GFP_USER);
399         if (!data)
400                 return -ENOMEM;
401
402         ret = -EFAULT;
403         if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
404                 goto out;
405
406         ret = ops->get_eeprom(dev, &eeprom, data);
407         if (ret)
408                 goto out;
409
410         ret = -EFAULT;
411         if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
412                 goto out;
413         if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
414                 goto out;
415         ret = 0;
416
417 out:
418         kfree(data);
419         return ret;
420 }
421
422 static int ethtool_set_eeprom(struct net_device *dev, void *useraddr)
423 {
424         struct ethtool_eeprom eeprom;
425         struct ethtool_ops *ops = ethtool_ops;
426         u8 *data;
427         int ret;
428
429         if (!ops->set_eeprom || !ops->get_eeprom_len)
430                 return -EOPNOTSUPP;
431
432         if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
433                 return -EFAULT;
434
435         /* Check for wrap and zero */
436         if (eeprom.offset + eeprom.len <= eeprom.offset)
437                 return -EINVAL;
438
439         /* Check for exceeding total eeprom len */
440         if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
441                 return -EINVAL;
442
443         data = kmalloc(eeprom.len, GFP_USER);
444         if (!data)
445                 return -ENOMEM;
446
447         ret = -EFAULT;
448         if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
449                 goto out;
450
451         ret = ops->set_eeprom(dev, &eeprom, data);
452         if (ret)
453                 goto out;
454
455         if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
456                 ret = -EFAULT;
457
458 out:
459         kfree(data);
460         return ret;
461 }
462
463 static int ethtool_get_coalesce(struct net_device *dev, void *useraddr)
464 {
465         struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE };
466
467         if (!ethtool_ops->get_coalesce)
468                 return -EOPNOTSUPP;
469
470         ethtool_ops->get_coalesce(dev, &coalesce);
471
472         if (copy_to_user(useraddr, &coalesce, sizeof(coalesce)))
473                 return -EFAULT;
474         return 0;
475 }
476
477 static int ethtool_set_coalesce(struct net_device *dev, void *useraddr)
478 {
479         struct ethtool_coalesce coalesce;
480
481         if (!ethtool_ops->get_coalesce)
482                 return -EOPNOTSUPP;
483
484         if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
485                 return -EFAULT;
486
487         return ethtool_ops->set_coalesce(dev, &coalesce);
488 }
489
490 static int ethtool_get_ringparam(struct net_device *dev, void *useraddr)
491 {
492         struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM };
493
494         if (!ethtool_ops->get_ringparam)
495                 return -EOPNOTSUPP;
496
497         ethtool_ops->get_ringparam(dev, &ringparam);
498
499         if (copy_to_user(useraddr, &ringparam, sizeof(ringparam)))
500                 return -EFAULT;
501         return 0;
502 }
503
504 static int ethtool_set_ringparam(struct net_device *dev, void *useraddr)
505 {
506         struct ethtool_ringparam ringparam;
507
508         if (!ethtool_ops->get_ringparam)
509                 return -EOPNOTSUPP;
510
511         if (copy_from_user(&ringparam, useraddr, sizeof(ringparam)))
512                 return -EFAULT;
513
514         return ethtool_ops->set_ringparam(dev, &ringparam);
515 }
516
517 static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr)
518 {
519         struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM };
520
521         if (!ethtool_ops->get_pauseparam)
522                 return -EOPNOTSUPP;
523
524         ethtool_ops->get_pauseparam(dev, &pauseparam);
525
526         if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam)))
527                 return -EFAULT;
528         return 0;
529 }
530
531 static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr)
532 {
533         struct ethtool_pauseparam pauseparam;
534
535         if (!ethtool_ops->get_pauseparam)
536                 return -EOPNOTSUPP;
537
538         if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam)))
539                 return -EFAULT;
540
541         return ethtool_ops->set_pauseparam(dev, &pauseparam);
542 }
543
544 static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr)
545 {
546         struct ethtool_value edata = { ETHTOOL_GRXCSUM };
547
548         if (!ethtool_ops->get_rx_csum)
549                 return -EOPNOTSUPP;
550
551         edata.data = ethtool_ops->get_rx_csum(dev);
552
553         if (copy_to_user(useraddr, &edata, sizeof(edata)))
554                 return -EFAULT;
555         return 0;
556 }
557
558 static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr)
559 {
560         struct ethtool_value edata;
561
562         if (!ethtool_ops->set_rx_csum)
563                 return -EOPNOTSUPP;
564
565         if (copy_from_user(&edata, useraddr, sizeof(edata)))
566                 return -EFAULT;
567
568         ethtool_ops->set_rx_csum(dev, edata.data);
569         return 0;
570 }
571
572 static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr)
573 {
574         struct ethtool_value edata = { ETHTOOL_GTXCSUM };
575
576         if (!ethtool_ops->get_tx_csum)
577                 return -EOPNOTSUPP;
578
579         edata.data = ethtool_ops->get_tx_csum(dev);
580
581         if (copy_to_user(useraddr, &edata, sizeof(edata)))
582                 return -EFAULT;
583         return 0;
584 }
585
586 static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr)
587 {
588         struct ethtool_value edata;
589
590         if (!ethtool_ops->set_tx_csum)
591                 return -EOPNOTSUPP;
592
593         if (copy_from_user(&edata, useraddr, sizeof(edata)))
594                 return -EFAULT;
595
596         return ethtool_ops->set_tx_csum(dev, edata.data);
597 }
598
599 static int ethtool_get_sg(struct net_device *dev, char *useraddr)
600 {
601         struct ethtool_value edata = { ETHTOOL_GSG };
602
603         if (!ethtool_ops->get_sg)
604                 return -EOPNOTSUPP;
605
606         edata.data = ethtool_ops->get_sg(dev);
607
608         if (copy_to_user(useraddr, &edata, sizeof(edata)))
609                 return -EFAULT;
610         return 0;
611 }
612
613 static int ethtool_set_sg(struct net_device *dev, char *useraddr)
614 {
615         struct ethtool_value edata;
616
617         if (!ethtool_ops->set_sg)
618                 return -EOPNOTSUPP;
619
620         if (copy_from_user(&edata, useraddr, sizeof(edata)))
621                 return -EFAULT;
622
623         return ethtool_ops->set_sg(dev, edata.data);
624 }
625
626 static int ethtool_get_tso(struct net_device *dev, char *useraddr)
627 {
628         struct ethtool_value edata = { ETHTOOL_GTSO };
629
630         if (!ethtool_ops->get_tso)
631                 return -EOPNOTSUPP;
632
633         edata.data = ethtool_ops->get_tso(dev);
634
635         if (copy_to_user(useraddr, &edata, sizeof(edata)))
636                 return -EFAULT;
637         return 0;
638 }
639
640 static int ethtool_set_tso(struct net_device *dev, char *useraddr)
641 {
642         struct ethtool_value edata;
643
644         if (!ethtool_ops->set_tso)
645                 return -EOPNOTSUPP;
646
647         if (copy_from_user(&edata, useraddr, sizeof(edata)))
648                 return -EFAULT;
649
650         return ethtool_ops->set_tso(dev, edata.data);
651 }
652
653 static int ethtool_self_test(struct net_device *dev, char *useraddr)
654 {
655         struct ethtool_test test;
656         struct ethtool_ops *ops = 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 *useraddr)
687 {
688         struct ethtool_gstrings gstrings;
689         struct ethtool_ops *ops = 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 *useraddr)
734 {
735         struct ethtool_value id;
736
737         if (!ethtool_ops->phys_id)
738                 return -EOPNOTSUPP;
739
740         if (copy_from_user(&id, useraddr, sizeof(id)))
741                 return -EFAULT;
742
743         return ethtool_ops->phys_id(dev, id.data);
744 }
745
746 static int ethtool_get_stats(struct net_device *dev, void *useraddr)
747 {
748         struct ethtool_stats stats;
749         struct ethtool_ops *ops = 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 /* The main entry point in this file.  Called from net/core/dev.c */
780
781 #define ETHTOOL_OPS_COMPAT
782 int ethtool_ioctl(struct ifreq *ifr)
783 {
784         struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
785         void *useraddr = (void *) ifr->ifr_data;
786         u32 ethcmd;
787
788         /*
789          * XXX: This can be pushed down into the ethtool_* handlers that
790          * need it.  Keep existing behavior for the moment.
791          */
792         if (!capable(CAP_NET_ADMIN))
793                 return -EPERM;
794
795         if (!dev || !netif_device_present(dev))
796                 return -ENODEV;
797
798         if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
799                 return -EFAULT;
800
801         switch (ethcmd) {
802         case ETHTOOL_GSET:
803                 return ethtool_get_settings(dev, useraddr);
804         case ETHTOOL_SSET:
805                 return ethtool_set_settings(dev, useraddr);
806         case ETHTOOL_GDRVINFO:
807                 return ethtool_get_drvinfo(dev, useraddr);
808         case ETHTOOL_GREGS:
809                 return ethtool_get_regs(dev, useraddr);
810         case ETHTOOL_GWOL:
811                 return ethtool_get_wol(dev, useraddr);
812         case ETHTOOL_SWOL:
813                 return ethtool_set_wol(dev, useraddr);
814         case ETHTOOL_GMSGLVL:
815                 return ethtool_get_msglevel(dev, useraddr);
816         case ETHTOOL_SMSGLVL:
817                 return ethtool_set_msglevel(dev, useraddr);
818         case ETHTOOL_NWAY_RST:
819                 return ethtool_nway_reset(dev);
820         case ETHTOOL_GLINK:
821                 return ethtool_get_link(dev, useraddr);
822         case ETHTOOL_GEEPROM:
823                 return ethtool_get_eeprom(dev, useraddr);
824         case ETHTOOL_SEEPROM:
825                 return ethtool_set_eeprom(dev, useraddr);
826         case ETHTOOL_GCOALESCE:
827                 return ethtool_get_coalesce(dev, useraddr);
828         case ETHTOOL_SCOALESCE:
829                 return ethtool_set_coalesce(dev, useraddr);
830         case ETHTOOL_GRINGPARAM:
831                 return ethtool_get_ringparam(dev, useraddr);
832         case ETHTOOL_SRINGPARAM:
833                 return ethtool_set_ringparam(dev, useraddr);
834         case ETHTOOL_GPAUSEPARAM:
835                 return ethtool_get_pauseparam(dev, useraddr);
836         case ETHTOOL_SPAUSEPARAM:
837                 return ethtool_set_pauseparam(dev, useraddr);
838         case ETHTOOL_GRXCSUM:
839                 return ethtool_get_rx_csum(dev, useraddr);
840         case ETHTOOL_SRXCSUM:
841                 return ethtool_set_rx_csum(dev, useraddr);
842         case ETHTOOL_GTXCSUM:
843                 return ethtool_get_tx_csum(dev, useraddr);
844         case ETHTOOL_STXCSUM:
845                 return ethtool_set_tx_csum(dev, useraddr);
846         case ETHTOOL_GSG:
847                 return ethtool_get_sg(dev, useraddr);
848         case ETHTOOL_SSG:
849                 return ethtool_set_sg(dev, useraddr);
850         case ETHTOOL_GTSO:
851                 return ethtool_get_tso(dev, useraddr);
852         case ETHTOOL_STSO:
853                 return ethtool_set_tso(dev, useraddr);
854         case ETHTOOL_TEST:
855                 return ethtool_self_test(dev, useraddr);
856         case ETHTOOL_GSTRINGS:
857                 return ethtool_get_strings(dev, useraddr);
858         case ETHTOOL_PHYS_ID:
859                 return ethtool_phys_id(dev, useraddr);
860         case ETHTOOL_GSTATS:
861                 return ethtool_get_stats(dev, useraddr);
862         default:
863                 return -EOPNOTSUPP;
864         }
865
866         return -EOPNOTSUPP;
867 }
868
869 #define mii_if_info _kc_mii_if_info
870 struct _kc_mii_if_info {
871         int phy_id;
872         int advertising;
873         int phy_id_mask;
874         int reg_num_mask;
875
876         unsigned int full_duplex : 1;   /* is full duplex? */
877         unsigned int force_media : 1;   /* is autoneg. disabled? */
878
879         struct net_device *dev;
880         int (*mdio_read) (struct net_device *dev, int phy_id, int location);
881         void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
882 };
883
884 struct ethtool_cmd;
885 struct mii_ioctl_data;
886
887 #undef mii_link_ok
888 #define mii_link_ok _kc_mii_link_ok
889 #undef mii_nway_restart
890 #define mii_nway_restart _kc_mii_nway_restart
891 #undef mii_ethtool_gset
892 #define mii_ethtool_gset _kc_mii_ethtool_gset
893 #undef mii_ethtool_sset
894 #define mii_ethtool_sset _kc_mii_ethtool_sset
895 #undef mii_check_link
896 #define mii_check_link _kc_mii_check_link
897 extern int _kc_mii_link_ok (struct mii_if_info *mii);
898 extern int _kc_mii_nway_restart (struct mii_if_info *mii);
899 extern int _kc_mii_ethtool_gset(struct mii_if_info *mii,
900                                 struct ethtool_cmd *ecmd);
901 extern int _kc_mii_ethtool_sset(struct mii_if_info *mii,
902                                 struct ethtool_cmd *ecmd);
903 extern void _kc_mii_check_link (struct mii_if_info *mii);
904 #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6) )
905 #undef generic_mii_ioctl
906 #define generic_mii_ioctl _kc_generic_mii_ioctl
907 extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,
908                                  struct mii_ioctl_data *mii_data, int cmd,
909                                  unsigned int *duplex_changed);
910 #endif /* > 2.4.6 */
911
912
913 struct _kc_pci_dev_ext {
914         struct pci_dev *dev;
915         void *pci_drvdata;
916         struct pci_driver *driver;
917 };
918
919 struct _kc_net_dev_ext {
920         struct net_device *dev;
921         unsigned int carrier;
922 };
923
924
925 /**************************************/
926 /* mii support */
927
928 int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
929 {
930         struct net_device *dev = mii->dev;
931         u32 advert, bmcr, lpa, nego;
932
933         ecmd->supported =
934             (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
935              SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
936              SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
937
938         /* only supports twisted-pair */
939         ecmd->port = PORT_MII;
940
941         /* only supports internal transceiver */
942         ecmd->transceiver = XCVR_INTERNAL;
943
944         /* this isn't fully supported at higher layers */
945         ecmd->phy_address = mii->phy_id;
946
947         ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
948         advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
949         if (advert & ADVERTISE_10HALF)
950                 ecmd->advertising |= ADVERTISED_10baseT_Half;
951         if (advert & ADVERTISE_10FULL)
952                 ecmd->advertising |= ADVERTISED_10baseT_Full;
953         if (advert & ADVERTISE_100HALF)
954                 ecmd->advertising |= ADVERTISED_100baseT_Half;
955         if (advert & ADVERTISE_100FULL)
956                 ecmd->advertising |= ADVERTISED_100baseT_Full;
957
958         bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
959         lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
960         if (bmcr & BMCR_ANENABLE) {
961                 ecmd->advertising |= ADVERTISED_Autoneg;
962                 ecmd->autoneg = AUTONEG_ENABLE;
963
964                 nego = mii_nway_result(advert & lpa);
965                 if (nego == LPA_100FULL || nego == LPA_100HALF)
966                         ecmd->speed = SPEED_100;
967                 else
968                         ecmd->speed = SPEED_10;
969                 if (nego == LPA_100FULL || nego == LPA_10FULL) {
970                         ecmd->duplex = DUPLEX_FULL;
971                         mii->full_duplex = 1;
972                 } else {
973                         ecmd->duplex = DUPLEX_HALF;
974                         mii->full_duplex = 0;
975                 }
976         } else {
977                 ecmd->autoneg = AUTONEG_DISABLE;
978
979                 ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
980                 ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
981         }
982
983         /* ignore maxtxpkt, maxrxpkt for now */
984
985         return 0;
986 }
987
988 int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
989 {
990         struct net_device *dev = mii->dev;
991
992         if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
993                 return -EINVAL;
994         if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
995                 return -EINVAL;
996         if (ecmd->port != PORT_MII)
997                 return -EINVAL;
998         if (ecmd->transceiver != XCVR_INTERNAL)
999                 return -EINVAL;
1000         if (ecmd->phy_address != mii->phy_id)
1001                 return -EINVAL;
1002         if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
1003                 return -EINVAL;
1004
1005         /* ignore supported, maxtxpkt, maxrxpkt */
1006
1007         if (ecmd->autoneg == AUTONEG_ENABLE) {
1008                 u32 bmcr, advert, tmp;
1009
1010                 if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
1011                                           ADVERTISED_10baseT_Full |
1012                                           ADVERTISED_100baseT_Half |
1013                                           ADVERTISED_100baseT_Full)) == 0)
1014                         return -EINVAL;
1015
1016                 /* advertise only what has been requested */
1017                 advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
1018                 tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
1019                 if (ADVERTISED_10baseT_Half)
1020                         tmp |= ADVERTISE_10HALF;
1021                 if (ADVERTISED_10baseT_Full)
1022                         tmp |= ADVERTISE_10FULL;
1023                 if (ADVERTISED_100baseT_Half)
1024                         tmp |= ADVERTISE_100HALF;
1025                 if (ADVERTISED_100baseT_Full)
1026                         tmp |= ADVERTISE_100FULL;
1027                 if (advert != tmp) {
1028                         mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
1029                         mii->advertising = tmp;
1030                 }
1031
1032                 /* turn on autonegotiation, and force a renegotiate */
1033                 bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
1034                 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
1035                 mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
1036
1037                 mii->force_media = 0;
1038         } else {
1039                 u32 bmcr, tmp;
1040
1041                 /* turn off auto negotiation, set speed and duplexity */
1042                 bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
1043                 tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
1044                 if (ecmd->speed == SPEED_100)
1045                         tmp |= BMCR_SPEED100;
1046                 if (ecmd->duplex == DUPLEX_FULL) {
1047                         tmp |= BMCR_FULLDPLX;
1048                         mii->full_duplex = 1;
1049                 } else
1050                         mii->full_duplex = 0;
1051                 if (bmcr != tmp)
1052                         mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);
1053
1054                 mii->force_media = 1;
1055         }
1056         return 0;
1057 }
1058
1059 int _kc_mii_link_ok (struct mii_if_info *mii)
1060 {
1061         /* first, a dummy read, needed to latch some MII phys */
1062         mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
1063         if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
1064                 return 1;
1065         return 0;
1066 }
1067
1068 int _kc_mii_nway_restart (struct mii_if_info *mii)
1069 {
1070         int bmcr;
1071         int r = -EINVAL;
1072
1073         /* if autoneg is off, it's an error */
1074         bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
1075
1076         if (bmcr & BMCR_ANENABLE) {
1077                 bmcr |= BMCR_ANRESTART;
1078                 mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
1079                 r = 0;
1080         }
1081
1082         return r;
1083 }
1084
1085 void _kc_mii_check_link (struct mii_if_info *mii)
1086 {
1087         int cur_link = mii_link_ok(mii);
1088         int prev_link = netif_carrier_ok(mii->dev);
1089
1090         if (cur_link && !prev_link)
1091                 netif_carrier_on(mii->dev);
1092         else if (prev_link && !cur_link)
1093                 netif_carrier_off(mii->dev);
1094 }
1095
1096 #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6) )
1097 int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,
1098                           struct mii_ioctl_data *mii_data, int cmd,
1099                           unsigned int *duplex_chg_out)
1100 {
1101         int rc = 0;
1102         unsigned int duplex_changed = 0;
1103
1104         if (duplex_chg_out)
1105                 *duplex_chg_out = 0;
1106
1107         mii_data->phy_id &= mii_if->phy_id_mask;
1108         mii_data->reg_num &= mii_if->reg_num_mask;
1109
1110         switch(cmd) {
1111         case SIOCDEVPRIVATE:    /* binary compat, remove in 2.5 */
1112         case SIOCGMIIPHY:
1113                 mii_data->phy_id = mii_if->phy_id;
1114                 /* fall through */
1115
1116         case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */
1117         case SIOCGMIIREG:
1118                 mii_data->val_out =
1119                         mii_if->mdio_read(mii_if->dev, mii_data->phy_id,
1120                                           mii_data->reg_num);
1121                 break;
1122
1123         case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */
1124         case SIOCSMIIREG: {
1125                 u16 val = mii_data->val_in;
1126
1127                 if (!capable(CAP_NET_ADMIN))
1128                         return -EPERM;
1129
1130                 if (mii_data->phy_id == mii_if->phy_id) {
1131                         switch(mii_data->reg_num) {
1132                         case MII_BMCR: {
1133                                 unsigned int new_duplex = 0;
1134                                 if (val & (BMCR_RESET|BMCR_ANENABLE))
1135                                         mii_if->force_media = 0;
1136                                 else
1137                                         mii_if->force_media = 1;
1138                                 if (mii_if->force_media &&
1139                                     (val & BMCR_FULLDPLX))
1140                                         new_duplex = 1;
1141                                 if (mii_if->full_duplex != new_duplex) {
1142                                         duplex_changed = 1;
1143                                         mii_if->full_duplex = new_duplex;
1144                                 }
1145                                 break;
1146                         }
1147                         case MII_ADVERTISE:
1148                                 mii_if->advertising = val;
1149                                 break;
1150                         default:
1151                                 /* do nothing */
1152                                 break;
1153                         }
1154                 }
1155
1156                 mii_if->mdio_write(mii_if->dev, mii_data->phy_id,
1157                                    mii_data->reg_num, val);
1158                 break;
1159         }
1160
1161         default:
1162                 rc = -EOPNOTSUPP;
1163                 break;
1164         }
1165
1166         if ((rc == 0) && (duplex_chg_out) && (duplex_changed))
1167                 *duplex_chg_out = 1;
1168
1169         return rc;
1170 }
1171 #endif /* > 2.4.6 */