net: introduce and use netdev_features_t for device features sets
[deliverable/linux.git] / net / core / ethtool.c
CommitLineData
1da177e4
LT
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
61a44b9c 6 * the information ethtool needs.
1da177e4 7 *
61a44b9c
MW
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.
1da177e4
LT
12 */
13
14#include <linux/module.h>
15#include <linux/types.h>
4fc268d2 16#include <linux/capability.h>
1da177e4
LT
17#include <linux/errno.h>
18#include <linux/ethtool.h>
19#include <linux/netdevice.h>
d17792eb 20#include <linux/bitops.h>
97f8aefb 21#include <linux/uaccess.h>
73da16c2 22#include <linux/vmalloc.h>
5a0e3ad6 23#include <linux/slab.h>
68f512f2
BH
24#include <linux/rtnetlink.h>
25#include <linux/sched.h>
1da177e4 26
4ec93edb 27/*
1da177e4
LT
28 * Some useful ethtool_ops methods that're device independent.
29 * If we find that all drivers want to do the same thing here,
30 * we can turn these into dev_() function calls.
31 */
32
33u32 ethtool_op_get_link(struct net_device *dev)
34{
35 return netif_carrier_ok(dev) ? 1 : 0;
36}
97f8aefb 37EXPORT_SYMBOL(ethtool_op_get_link);
1da177e4 38
1da177e4
LT
39/* Handlers for each ethtool command */
40
5455c699
MM
41#define ETHTOOL_DEV_FEATURE_WORDS 1
42
43static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
44{
45 struct ethtool_gfeatures cmd = {
46 .cmd = ETHTOOL_GFEATURES,
47 .size = ETHTOOL_DEV_FEATURE_WORDS,
48 };
49 struct ethtool_get_features_block features[ETHTOOL_DEV_FEATURE_WORDS] = {
50 {
51 .available = dev->hw_features,
52 .requested = dev->wanted_features,
53 .active = dev->features,
54 .never_changed = NETIF_F_NEVER_CHANGE,
55 },
56 };
57 u32 __user *sizeaddr;
58 u32 copy_size;
59
60 sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size);
61 if (get_user(copy_size, sizeaddr))
62 return -EFAULT;
63
64 if (copy_size > ETHTOOL_DEV_FEATURE_WORDS)
65 copy_size = ETHTOOL_DEV_FEATURE_WORDS;
66
67 if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
68 return -EFAULT;
69 useraddr += sizeof(cmd);
70 if (copy_to_user(useraddr, features, copy_size * sizeof(*features)))
71 return -EFAULT;
72
73 return 0;
74}
75
76static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
77{
78 struct ethtool_sfeatures cmd;
79 struct ethtool_set_features_block features[ETHTOOL_DEV_FEATURE_WORDS];
80 int ret = 0;
81
82 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
83 return -EFAULT;
84 useraddr += sizeof(cmd);
85
86 if (cmd.size != ETHTOOL_DEV_FEATURE_WORDS)
87 return -EINVAL;
88
89 if (copy_from_user(features, useraddr, sizeof(features)))
90 return -EFAULT;
91
92 if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
93 return -EINVAL;
94
95 if (features[0].valid & ~dev->hw_features) {
96 features[0].valid &= dev->hw_features;
97 ret |= ETHTOOL_F_UNSUPPORTED;
98 }
99
100 dev->wanted_features &= ~features[0].valid;
101 dev->wanted_features |= features[0].valid & features[0].requested;
6cb6a27c 102 __netdev_update_features(dev);
5455c699
MM
103
104 if ((dev->wanted_features ^ dev->features) & features[0].valid)
105 ret |= ETHTOOL_F_WISH;
106
107 return ret;
108}
109
110static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GSTRING_LEN] = {
111 /* NETIF_F_SG */ "tx-scatter-gather",
112 /* NETIF_F_IP_CSUM */ "tx-checksum-ipv4",
113 /* NETIF_F_NO_CSUM */ "tx-checksum-unneeded",
114 /* NETIF_F_HW_CSUM */ "tx-checksum-ip-generic",
7cc31a9a 115 /* NETIF_F_IPV6_CSUM */ "tx-checksum-ipv6",
5455c699
MM
116 /* NETIF_F_HIGHDMA */ "highdma",
117 /* NETIF_F_FRAGLIST */ "tx-scatter-gather-fraglist",
118 /* NETIF_F_HW_VLAN_TX */ "tx-vlan-hw-insert",
119
120 /* NETIF_F_HW_VLAN_RX */ "rx-vlan-hw-parse",
121 /* NETIF_F_HW_VLAN_FILTER */ "rx-vlan-filter",
122 /* NETIF_F_VLAN_CHALLENGED */ "vlan-challenged",
123 /* NETIF_F_GSO */ "tx-generic-segmentation",
124 /* NETIF_F_LLTX */ "tx-lockless",
125 /* NETIF_F_NETNS_LOCAL */ "netns-local",
126 /* NETIF_F_GRO */ "rx-gro",
127 /* NETIF_F_LRO */ "rx-lro",
128
129 /* NETIF_F_TSO */ "tx-tcp-segmentation",
130 /* NETIF_F_UFO */ "tx-udp-fragmentation",
131 /* NETIF_F_GSO_ROBUST */ "tx-gso-robust",
132 /* NETIF_F_TSO_ECN */ "tx-tcp-ecn-segmentation",
133 /* NETIF_F_TSO6 */ "tx-tcp6-segmentation",
134 /* NETIF_F_FSO */ "tx-fcoe-segmentation",
135 "",
136 "",
137
138 /* NETIF_F_FCOE_CRC */ "tx-checksum-fcoe-crc",
139 /* NETIF_F_SCTP_CSUM */ "tx-checksum-sctp",
140 /* NETIF_F_FCOE_MTU */ "fcoe-mtu",
141 /* NETIF_F_NTUPLE */ "rx-ntuple-filter",
142 /* NETIF_F_RXHASH */ "rx-hashing",
e83d360d 143 /* NETIF_F_RXCSUM */ "rx-checksum",
864b5418 144 /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy",
eed2a12f 145 /* NETIF_F_LOOPBACK */ "loopback",
5455c699
MM
146};
147
340ae165
MM
148static int __ethtool_get_sset_count(struct net_device *dev, int sset)
149{
150 const struct ethtool_ops *ops = dev->ethtool_ops;
151
5455c699
MM
152 if (sset == ETH_SS_FEATURES)
153 return ARRAY_SIZE(netdev_features_strings);
154
340ae165
MM
155 if (ops && ops->get_sset_count && ops->get_strings)
156 return ops->get_sset_count(dev, sset);
157 else
158 return -EOPNOTSUPP;
159}
160
161static void __ethtool_get_strings(struct net_device *dev,
162 u32 stringset, u8 *data)
163{
164 const struct ethtool_ops *ops = dev->ethtool_ops;
165
5455c699
MM
166 if (stringset == ETH_SS_FEATURES)
167 memcpy(data, netdev_features_strings,
168 sizeof(netdev_features_strings));
169 else
170 /* ops->get_strings is valid because checked earlier */
171 ops->get_strings(dev, stringset, data);
340ae165
MM
172}
173
c8f44aff 174static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd)
0a417704
MM
175{
176 /* feature masks of legacy discrete ethtool ops */
177
178 switch (eth_cmd) {
179 case ETHTOOL_GTXCSUM:
180 case ETHTOOL_STXCSUM:
181 return NETIF_F_ALL_CSUM | NETIF_F_SCTP_CSUM;
e83d360d
MM
182 case ETHTOOL_GRXCSUM:
183 case ETHTOOL_SRXCSUM:
184 return NETIF_F_RXCSUM;
0a417704
MM
185 case ETHTOOL_GSG:
186 case ETHTOOL_SSG:
187 return NETIF_F_SG;
188 case ETHTOOL_GTSO:
189 case ETHTOOL_STSO:
190 return NETIF_F_ALL_TSO;
191 case ETHTOOL_GUFO:
192 case ETHTOOL_SUFO:
193 return NETIF_F_UFO;
194 case ETHTOOL_GGSO:
195 case ETHTOOL_SGSO:
196 return NETIF_F_GSO;
197 case ETHTOOL_GGRO:
198 case ETHTOOL_SGRO:
199 return NETIF_F_GRO;
200 default:
201 BUG();
202 }
203}
204
0a417704
MM
205static int ethtool_get_one_feature(struct net_device *dev,
206 char __user *useraddr, u32 ethcmd)
207{
c8f44aff 208 netdev_features_t mask = ethtool_get_feature_mask(ethcmd);
0a417704
MM
209 struct ethtool_value edata = {
210 .cmd = ethcmd,
86794881 211 .data = !!(dev->features & mask),
0a417704 212 };
0a417704 213
0a417704
MM
214 if (copy_to_user(useraddr, &edata, sizeof(edata)))
215 return -EFAULT;
216 return 0;
217}
218
0a417704
MM
219static int ethtool_set_one_feature(struct net_device *dev,
220 void __user *useraddr, u32 ethcmd)
221{
222 struct ethtool_value edata;
c8f44aff 223 netdev_features_t mask;
0a417704
MM
224
225 if (copy_from_user(&edata, useraddr, sizeof(edata)))
226 return -EFAULT;
227
86794881
MM
228 mask = ethtool_get_feature_mask(ethcmd);
229 mask &= dev->hw_features;
bc5787c6
MM
230 if (!mask)
231 return -EOPNOTSUPP;
86794881 232
bc5787c6
MM
233 if (edata.data)
234 dev->wanted_features |= mask;
235 else
236 dev->wanted_features &= ~mask;
86794881 237
bc5787c6 238 __netdev_update_features(dev);
86794881 239
bc5787c6
MM
240 return 0;
241}
242
02b3a552
MM
243#define ETH_ALL_FLAGS (ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | \
244 ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH)
245#define ETH_ALL_FEATURES (NETIF_F_LRO | NETIF_F_HW_VLAN_RX | \
246 NETIF_F_HW_VLAN_TX | NETIF_F_NTUPLE | NETIF_F_RXHASH)
bc5787c6
MM
247
248static u32 __ethtool_get_flags(struct net_device *dev)
249{
02b3a552
MM
250 u32 flags = 0;
251
252 if (dev->features & NETIF_F_LRO) flags |= ETH_FLAG_LRO;
253 if (dev->features & NETIF_F_HW_VLAN_RX) flags |= ETH_FLAG_RXVLAN;
254 if (dev->features & NETIF_F_HW_VLAN_TX) flags |= ETH_FLAG_TXVLAN;
255 if (dev->features & NETIF_F_NTUPLE) flags |= ETH_FLAG_NTUPLE;
256 if (dev->features & NETIF_F_RXHASH) flags |= ETH_FLAG_RXHASH;
257
258 return flags;
0a417704
MM
259}
260
bc5787c6 261static int __ethtool_set_flags(struct net_device *dev, u32 data)
da8ac86c 262{
c8f44aff 263 netdev_features_t features = 0, changed;
da8ac86c 264
02b3a552 265 if (data & ~ETH_ALL_FLAGS)
da8ac86c
MM
266 return -EINVAL;
267
02b3a552
MM
268 if (data & ETH_FLAG_LRO) features |= NETIF_F_LRO;
269 if (data & ETH_FLAG_RXVLAN) features |= NETIF_F_HW_VLAN_RX;
270 if (data & ETH_FLAG_TXVLAN) features |= NETIF_F_HW_VLAN_TX;
271 if (data & ETH_FLAG_NTUPLE) features |= NETIF_F_NTUPLE;
272 if (data & ETH_FLAG_RXHASH) features |= NETIF_F_RXHASH;
273
da8ac86c 274 /* allow changing only bits set in hw_features */
02b3a552 275 changed = (features ^ dev->features) & ETH_ALL_FEATURES;
da8ac86c
MM
276 if (changed & ~dev->hw_features)
277 return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
278
279 dev->wanted_features =
02b3a552 280 (dev->wanted_features & ~changed) | (features & changed);
da8ac86c 281
6cb6a27c 282 __netdev_update_features(dev);
da8ac86c
MM
283
284 return 0;
285}
286
4bc71cb9 287int __ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1da177e4 288{
4bc71cb9 289 ASSERT_RTNL();
1da177e4 290
4bc71cb9 291 if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings)
1da177e4
LT
292 return -EOPNOTSUPP;
293
4bc71cb9
JP
294 memset(cmd, 0, sizeof(struct ethtool_cmd));
295 cmd->cmd = ETHTOOL_GSET;
296 return dev->ethtool_ops->get_settings(dev, cmd);
297}
298EXPORT_SYMBOL(__ethtool_get_settings);
299
300static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
301{
302 int err;
303 struct ethtool_cmd cmd;
304
305 err = __ethtool_get_settings(dev, &cmd);
1da177e4
LT
306 if (err < 0)
307 return err;
308
309 if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
310 return -EFAULT;
311 return 0;
312}
313
314static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
315{
316 struct ethtool_cmd cmd;
317
318 if (!dev->ethtool_ops->set_settings)
319 return -EOPNOTSUPP;
320
321 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
322 return -EFAULT;
323
324 return dev->ethtool_ops->set_settings(dev, &cmd);
325}
326
97f8aefb 327static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev,
328 void __user *useraddr)
1da177e4
LT
329{
330 struct ethtool_drvinfo info;
76fd8593 331 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4 332
1da177e4
LT
333 memset(&info, 0, sizeof(info));
334 info.cmd = ETHTOOL_GDRVINFO;
01414802
BH
335 if (ops && ops->get_drvinfo) {
336 ops->get_drvinfo(dev, &info);
337 } else if (dev->dev.parent && dev->dev.parent->driver) {
338 strlcpy(info.bus_info, dev_name(dev->dev.parent),
339 sizeof(info.bus_info));
340 strlcpy(info.driver, dev->dev.parent->driver->name,
341 sizeof(info.driver));
342 } else {
343 return -EOPNOTSUPP;
344 }
1da177e4 345
723b2f57
JG
346 /*
347 * this method of obtaining string set info is deprecated;
d17792eb 348 * Use ETHTOOL_GSSET_INFO instead.
723b2f57 349 */
01414802 350 if (ops && ops->get_sset_count) {
ff03d49f
JG
351 int rc;
352
353 rc = ops->get_sset_count(dev, ETH_SS_TEST);
354 if (rc >= 0)
355 info.testinfo_len = rc;
356 rc = ops->get_sset_count(dev, ETH_SS_STATS);
357 if (rc >= 0)
358 info.n_stats = rc;
339bf024
JG
359 rc = ops->get_sset_count(dev, ETH_SS_PRIV_FLAGS);
360 if (rc >= 0)
361 info.n_priv_flags = rc;
ff03d49f 362 }
01414802 363 if (ops && ops->get_regs_len)
1da177e4 364 info.regdump_len = ops->get_regs_len(dev);
01414802 365 if (ops && ops->get_eeprom_len)
1da177e4
LT
366 info.eedump_len = ops->get_eeprom_len(dev);
367
368 if (copy_to_user(useraddr, &info, sizeof(info)))
369 return -EFAULT;
370 return 0;
371}
372
f5c445ed 373static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev,
97f8aefb 374 void __user *useraddr)
723b2f57
JG
375{
376 struct ethtool_sset_info info;
723b2f57
JG
377 u64 sset_mask;
378 int i, idx = 0, n_bits = 0, ret, rc;
379 u32 *info_buf = NULL;
380
723b2f57
JG
381 if (copy_from_user(&info, useraddr, sizeof(info)))
382 return -EFAULT;
383
384 /* store copy of mask, because we zero struct later on */
385 sset_mask = info.sset_mask;
386 if (!sset_mask)
387 return 0;
388
389 /* calculate size of return buffer */
d17792eb 390 n_bits = hweight64(sset_mask);
723b2f57
JG
391
392 memset(&info, 0, sizeof(info));
393 info.cmd = ETHTOOL_GSSET_INFO;
394
395 info_buf = kzalloc(n_bits * sizeof(u32), GFP_USER);
396 if (!info_buf)
397 return -ENOMEM;
398
399 /*
400 * fill return buffer based on input bitmask and successful
401 * get_sset_count return
402 */
403 for (i = 0; i < 64; i++) {
404 if (!(sset_mask & (1ULL << i)))
405 continue;
406
340ae165 407 rc = __ethtool_get_sset_count(dev, i);
723b2f57
JG
408 if (rc >= 0) {
409 info.sset_mask |= (1ULL << i);
410 info_buf[idx++] = rc;
411 }
412 }
413
414 ret = -EFAULT;
415 if (copy_to_user(useraddr, &info, sizeof(info)))
416 goto out;
417
418 useraddr += offsetof(struct ethtool_sset_info, data);
419 if (copy_to_user(useraddr, info_buf, idx * sizeof(u32)))
420 goto out;
421
422 ret = 0;
423
424out:
425 kfree(info_buf);
426 return ret;
427}
428
97f8aefb 429static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
bf988435 430 u32 cmd, void __user *useraddr)
0853ad66 431{
bf988435
BH
432 struct ethtool_rxnfc info;
433 size_t info_size = sizeof(info);
0853ad66 434
59089d8d 435 if (!dev->ethtool_ops->set_rxnfc)
0853ad66
SB
436 return -EOPNOTSUPP;
437
bf988435
BH
438 /* struct ethtool_rxnfc was originally defined for
439 * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
440 * members. User-space might still be using that
441 * definition. */
442 if (cmd == ETHTOOL_SRXFH)
443 info_size = (offsetof(struct ethtool_rxnfc, data) +
444 sizeof(info.data));
445
446 if (copy_from_user(&info, useraddr, info_size))
0853ad66
SB
447 return -EFAULT;
448
bf988435 449 return dev->ethtool_ops->set_rxnfc(dev, &info);
0853ad66
SB
450}
451
97f8aefb 452static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
bf988435 453 u32 cmd, void __user *useraddr)
0853ad66
SB
454{
455 struct ethtool_rxnfc info;
bf988435 456 size_t info_size = sizeof(info);
59089d8d
SB
457 const struct ethtool_ops *ops = dev->ethtool_ops;
458 int ret;
459 void *rule_buf = NULL;
0853ad66 460
59089d8d 461 if (!ops->get_rxnfc)
0853ad66
SB
462 return -EOPNOTSUPP;
463
bf988435
BH
464 /* struct ethtool_rxnfc was originally defined for
465 * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
466 * members. User-space might still be using that
467 * definition. */
468 if (cmd == ETHTOOL_GRXFH)
469 info_size = (offsetof(struct ethtool_rxnfc, data) +
470 sizeof(info.data));
471
472 if (copy_from_user(&info, useraddr, info_size))
0853ad66
SB
473 return -EFAULT;
474
59089d8d
SB
475 if (info.cmd == ETHTOOL_GRXCLSRLALL) {
476 if (info.rule_cnt > 0) {
db048b69 477 if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
ae6df5f9 478 rule_buf = kzalloc(info.rule_cnt * sizeof(u32),
db048b69 479 GFP_USER);
59089d8d
SB
480 if (!rule_buf)
481 return -ENOMEM;
482 }
483 }
0853ad66 484
59089d8d
SB
485 ret = ops->get_rxnfc(dev, &info, rule_buf);
486 if (ret < 0)
487 goto err_out;
488
489 ret = -EFAULT;
bf988435 490 if (copy_to_user(useraddr, &info, info_size))
59089d8d
SB
491 goto err_out;
492
493 if (rule_buf) {
494 useraddr += offsetof(struct ethtool_rxnfc, rule_locs);
495 if (copy_to_user(useraddr, rule_buf,
496 info.rule_cnt * sizeof(u32)))
497 goto err_out;
498 }
499 ret = 0;
500
501err_out:
c9caceca 502 kfree(rule_buf);
59089d8d
SB
503
504 return ret;
0853ad66
SB
505}
506
a5b6ee29
BH
507static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
508 void __user *useraddr)
509{
510 struct ethtool_rxfh_indir *indir;
511 u32 table_size;
512 size_t full_size;
513 int ret;
514
515 if (!dev->ethtool_ops->get_rxfh_indir)
516 return -EOPNOTSUPP;
517
518 if (copy_from_user(&table_size,
519 useraddr + offsetof(struct ethtool_rxfh_indir, size),
520 sizeof(table_size)))
521 return -EFAULT;
522
523 if (table_size >
524 (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
525 return -ENOMEM;
526 full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
b00916b1 527 indir = kzalloc(full_size, GFP_USER);
a5b6ee29
BH
528 if (!indir)
529 return -ENOMEM;
530
531 indir->cmd = ETHTOOL_GRXFHINDIR;
532 indir->size = table_size;
533 ret = dev->ethtool_ops->get_rxfh_indir(dev, indir);
534 if (ret)
535 goto out;
536
537 if (copy_to_user(useraddr, indir, full_size))
538 ret = -EFAULT;
539
540out:
541 kfree(indir);
542 return ret;
543}
544
545static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
546 void __user *useraddr)
547{
548 struct ethtool_rxfh_indir *indir;
549 u32 table_size;
550 size_t full_size;
551 int ret;
552
553 if (!dev->ethtool_ops->set_rxfh_indir)
554 return -EOPNOTSUPP;
555
556 if (copy_from_user(&table_size,
557 useraddr + offsetof(struct ethtool_rxfh_indir, size),
558 sizeof(table_size)))
559 return -EFAULT;
560
561 if (table_size >
562 (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
563 return -ENOMEM;
564 full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
565 indir = kmalloc(full_size, GFP_USER);
566 if (!indir)
567 return -ENOMEM;
568
569 if (copy_from_user(indir, useraddr, full_size)) {
570 ret = -EFAULT;
571 goto out;
572 }
573
574 ret = dev->ethtool_ops->set_rxfh_indir(dev, indir);
575
576out:
577 kfree(indir);
578 return ret;
579}
580
be2902da
BH
581/*
582 * ethtool does not (or did not) set masks for flow parameters that are
583 * not specified, so if both value and mask are 0 then this must be
584 * treated as equivalent to a mask with all bits set. Implement that
585 * here rather than in drivers.
586 */
587static void rx_ntuple_fix_masks(struct ethtool_rx_ntuple_flow_spec *fs)
588{
589 struct ethtool_tcpip4_spec *entry = &fs->h_u.tcp_ip4_spec;
590 struct ethtool_tcpip4_spec *mask = &fs->m_u.tcp_ip4_spec;
591
592 if (fs->flow_type != TCP_V4_FLOW &&
593 fs->flow_type != UDP_V4_FLOW &&
594 fs->flow_type != SCTP_V4_FLOW)
595 return;
596
597 if (!(entry->ip4src | mask->ip4src))
598 mask->ip4src = htonl(0xffffffff);
599 if (!(entry->ip4dst | mask->ip4dst))
600 mask->ip4dst = htonl(0xffffffff);
601 if (!(entry->psrc | mask->psrc))
602 mask->psrc = htons(0xffff);
603 if (!(entry->pdst | mask->pdst))
604 mask->pdst = htons(0xffff);
605 if (!(entry->tos | mask->tos))
606 mask->tos = 0xff;
607 if (!(fs->vlan_tag | fs->vlan_tag_mask))
608 fs->vlan_tag_mask = 0xffff;
609 if (!(fs->data | fs->data_mask))
610 fs->data_mask = 0xffffffffffffffffULL;
611}
612
97f8aefb 613static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
614 void __user *useraddr)
15682bc4
PWJ
615{
616 struct ethtool_rx_ntuple cmd;
617 const struct ethtool_ops *ops = dev->ethtool_ops;
15682bc4 618
5d9f11cf
AD
619 if (!ops->set_rx_ntuple)
620 return -EOPNOTSUPP;
621
15682bc4
PWJ
622 if (!(dev->features & NETIF_F_NTUPLE))
623 return -EINVAL;
624
625 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
626 return -EFAULT;
627
be2902da
BH
628 rx_ntuple_fix_masks(&cmd.fs);
629
bff55273 630 return ops->set_rx_ntuple(dev, &cmd);
15682bc4
PWJ
631}
632
1da177e4
LT
633static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
634{
635 struct ethtool_regs regs;
76fd8593 636 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4
LT
637 void *regbuf;
638 int reglen, ret;
639
640 if (!ops->get_regs || !ops->get_regs_len)
641 return -EOPNOTSUPP;
642
643 if (copy_from_user(&regs, useraddr, sizeof(regs)))
644 return -EFAULT;
645
646 reglen = ops->get_regs_len(dev);
647 if (regs.len > reglen)
648 regs.len = reglen;
649
b7c7d01a 650 regbuf = vzalloc(reglen);
67ae7cf1 651 if (reglen && !regbuf)
1da177e4
LT
652 return -ENOMEM;
653
654 ops->get_regs(dev, &regs, regbuf);
655
656 ret = -EFAULT;
657 if (copy_to_user(useraddr, &regs, sizeof(regs)))
658 goto out;
659 useraddr += offsetof(struct ethtool_regs, data);
67ae7cf1 660 if (regbuf && copy_to_user(useraddr, regbuf, regs.len))
1da177e4
LT
661 goto out;
662 ret = 0;
663
664 out:
a77f5db3 665 vfree(regbuf);
1da177e4
LT
666 return ret;
667}
668
d73d3a8c
BH
669static int ethtool_reset(struct net_device *dev, char __user *useraddr)
670{
671 struct ethtool_value reset;
672 int ret;
673
674 if (!dev->ethtool_ops->reset)
675 return -EOPNOTSUPP;
676
677 if (copy_from_user(&reset, useraddr, sizeof(reset)))
678 return -EFAULT;
679
680 ret = dev->ethtool_ops->reset(dev, &reset.data);
681 if (ret)
682 return ret;
683
684 if (copy_to_user(useraddr, &reset, sizeof(reset)))
685 return -EFAULT;
686 return 0;
687}
688
1da177e4
LT
689static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
690{
8e557421 691 struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
1da177e4
LT
692
693 if (!dev->ethtool_ops->get_wol)
694 return -EOPNOTSUPP;
695
696 dev->ethtool_ops->get_wol(dev, &wol);
697
698 if (copy_to_user(useraddr, &wol, sizeof(wol)))
699 return -EFAULT;
700 return 0;
701}
702
703static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
704{
705 struct ethtool_wolinfo wol;
706
707 if (!dev->ethtool_ops->set_wol)
708 return -EOPNOTSUPP;
709
710 if (copy_from_user(&wol, useraddr, sizeof(wol)))
711 return -EFAULT;
712
713 return dev->ethtool_ops->set_wol(dev, &wol);
714}
715
1da177e4
LT
716static int ethtool_nway_reset(struct net_device *dev)
717{
718 if (!dev->ethtool_ops->nway_reset)
719 return -EOPNOTSUPP;
720
721 return dev->ethtool_ops->nway_reset(dev);
722}
723
e596e6e4
BH
724static int ethtool_get_link(struct net_device *dev, char __user *useraddr)
725{
726 struct ethtool_value edata = { .cmd = ETHTOOL_GLINK };
727
728 if (!dev->ethtool_ops->get_link)
729 return -EOPNOTSUPP;
730
731 edata.data = netif_running(dev) && dev->ethtool_ops->get_link(dev);
732
733 if (copy_to_user(useraddr, &edata, sizeof(edata)))
734 return -EFAULT;
735 return 0;
736}
737
1da177e4
LT
738static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
739{
740 struct ethtool_eeprom eeprom;
76fd8593 741 const struct ethtool_ops *ops = dev->ethtool_ops;
b131dd5d
MSB
742 void __user *userbuf = useraddr + sizeof(eeprom);
743 u32 bytes_remaining;
1da177e4 744 u8 *data;
b131dd5d 745 int ret = 0;
1da177e4
LT
746
747 if (!ops->get_eeprom || !ops->get_eeprom_len)
748 return -EOPNOTSUPP;
749
750 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
751 return -EFAULT;
752
753 /* Check for wrap and zero */
754 if (eeprom.offset + eeprom.len <= eeprom.offset)
755 return -EINVAL;
756
757 /* Check for exceeding total eeprom len */
758 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
759 return -EINVAL;
760
b131dd5d 761 data = kmalloc(PAGE_SIZE, GFP_USER);
1da177e4
LT
762 if (!data)
763 return -ENOMEM;
764
b131dd5d
MSB
765 bytes_remaining = eeprom.len;
766 while (bytes_remaining > 0) {
767 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
768
769 ret = ops->get_eeprom(dev, &eeprom, data);
770 if (ret)
771 break;
772 if (copy_to_user(userbuf, data, eeprom.len)) {
773 ret = -EFAULT;
774 break;
775 }
776 userbuf += eeprom.len;
777 eeprom.offset += eeprom.len;
778 bytes_remaining -= eeprom.len;
779 }
1da177e4 780
c5835df9
MSB
781 eeprom.len = userbuf - (useraddr + sizeof(eeprom));
782 eeprom.offset -= eeprom.len;
783 if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
784 ret = -EFAULT;
785
1da177e4
LT
786 kfree(data);
787 return ret;
788}
789
790static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
791{
792 struct ethtool_eeprom eeprom;
76fd8593 793 const struct ethtool_ops *ops = dev->ethtool_ops;
b131dd5d
MSB
794 void __user *userbuf = useraddr + sizeof(eeprom);
795 u32 bytes_remaining;
1da177e4 796 u8 *data;
b131dd5d 797 int ret = 0;
1da177e4
LT
798
799 if (!ops->set_eeprom || !ops->get_eeprom_len)
800 return -EOPNOTSUPP;
801
802 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
803 return -EFAULT;
804
805 /* Check for wrap and zero */
806 if (eeprom.offset + eeprom.len <= eeprom.offset)
807 return -EINVAL;
808
809 /* Check for exceeding total eeprom len */
810 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
811 return -EINVAL;
812
b131dd5d 813 data = kmalloc(PAGE_SIZE, GFP_USER);
1da177e4
LT
814 if (!data)
815 return -ENOMEM;
816
b131dd5d
MSB
817 bytes_remaining = eeprom.len;
818 while (bytes_remaining > 0) {
819 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
820
821 if (copy_from_user(data, userbuf, eeprom.len)) {
822 ret = -EFAULT;
823 break;
824 }
825 ret = ops->set_eeprom(dev, &eeprom, data);
826 if (ret)
827 break;
828 userbuf += eeprom.len;
829 eeprom.offset += eeprom.len;
830 bytes_remaining -= eeprom.len;
831 }
1da177e4 832
1da177e4
LT
833 kfree(data);
834 return ret;
835}
836
97f8aefb 837static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev,
838 void __user *useraddr)
1da177e4 839{
8e557421 840 struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE };
1da177e4
LT
841
842 if (!dev->ethtool_ops->get_coalesce)
843 return -EOPNOTSUPP;
844
845 dev->ethtool_ops->get_coalesce(dev, &coalesce);
846
847 if (copy_to_user(useraddr, &coalesce, sizeof(coalesce)))
848 return -EFAULT;
849 return 0;
850}
851
97f8aefb 852static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev,
853 void __user *useraddr)
1da177e4
LT
854{
855 struct ethtool_coalesce coalesce;
856
fa04ae5c 857 if (!dev->ethtool_ops->set_coalesce)
1da177e4
LT
858 return -EOPNOTSUPP;
859
860 if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
861 return -EFAULT;
862
863 return dev->ethtool_ops->set_coalesce(dev, &coalesce);
864}
865
866static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr)
867{
8e557421 868 struct ethtool_ringparam ringparam = { .cmd = ETHTOOL_GRINGPARAM };
1da177e4
LT
869
870 if (!dev->ethtool_ops->get_ringparam)
871 return -EOPNOTSUPP;
872
873 dev->ethtool_ops->get_ringparam(dev, &ringparam);
874
875 if (copy_to_user(useraddr, &ringparam, sizeof(ringparam)))
876 return -EFAULT;
877 return 0;
878}
879
880static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr)
881{
882 struct ethtool_ringparam ringparam;
883
884 if (!dev->ethtool_ops->set_ringparam)
885 return -EOPNOTSUPP;
886
887 if (copy_from_user(&ringparam, useraddr, sizeof(ringparam)))
888 return -EFAULT;
889
890 return dev->ethtool_ops->set_ringparam(dev, &ringparam);
891}
892
8b5933c3 893static noinline_for_stack int ethtool_get_channels(struct net_device *dev,
894 void __user *useraddr)
895{
896 struct ethtool_channels channels = { .cmd = ETHTOOL_GCHANNELS };
897
898 if (!dev->ethtool_ops->get_channels)
899 return -EOPNOTSUPP;
900
901 dev->ethtool_ops->get_channels(dev, &channels);
902
903 if (copy_to_user(useraddr, &channels, sizeof(channels)))
904 return -EFAULT;
905 return 0;
906}
907
908static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
909 void __user *useraddr)
910{
911 struct ethtool_channels channels;
912
913 if (!dev->ethtool_ops->set_channels)
914 return -EOPNOTSUPP;
915
916 if (copy_from_user(&channels, useraddr, sizeof(channels)))
917 return -EFAULT;
918
919 return dev->ethtool_ops->set_channels(dev, &channels);
920}
921
1da177e4
LT
922static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr)
923{
924 struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM };
925
926 if (!dev->ethtool_ops->get_pauseparam)
927 return -EOPNOTSUPP;
928
929 dev->ethtool_ops->get_pauseparam(dev, &pauseparam);
930
931 if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam)))
932 return -EFAULT;
933 return 0;
934}
935
936static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr)
937{
938 struct ethtool_pauseparam pauseparam;
939
e1b90c41 940 if (!dev->ethtool_ops->set_pauseparam)
1da177e4
LT
941 return -EOPNOTSUPP;
942
943 if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam)))
944 return -EFAULT;
945
946 return dev->ethtool_ops->set_pauseparam(dev, &pauseparam);
947}
948
1da177e4
LT
949static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
950{
951 struct ethtool_test test;
76fd8593 952 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4 953 u64 *data;
ff03d49f 954 int ret, test_len;
1da177e4 955
a9828ec6 956 if (!ops->self_test || !ops->get_sset_count)
1da177e4
LT
957 return -EOPNOTSUPP;
958
a9828ec6 959 test_len = ops->get_sset_count(dev, ETH_SS_TEST);
ff03d49f
JG
960 if (test_len < 0)
961 return test_len;
962 WARN_ON(test_len == 0);
963
1da177e4
LT
964 if (copy_from_user(&test, useraddr, sizeof(test)))
965 return -EFAULT;
966
ff03d49f
JG
967 test.len = test_len;
968 data = kmalloc(test_len * sizeof(u64), GFP_USER);
1da177e4
LT
969 if (!data)
970 return -ENOMEM;
971
972 ops->self_test(dev, &test, data);
973
974 ret = -EFAULT;
975 if (copy_to_user(useraddr, &test, sizeof(test)))
976 goto out;
977 useraddr += sizeof(test);
978 if (copy_to_user(useraddr, data, test.len * sizeof(u64)))
979 goto out;
980 ret = 0;
981
982 out:
983 kfree(data);
984 return ret;
985}
986
987static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
988{
989 struct ethtool_gstrings gstrings;
1da177e4
LT
990 u8 *data;
991 int ret;
992
1da177e4
LT
993 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
994 return -EFAULT;
995
340ae165 996 ret = __ethtool_get_sset_count(dev, gstrings.string_set);
a9828ec6
BH
997 if (ret < 0)
998 return ret;
999
1000 gstrings.len = ret;
1da177e4
LT
1001
1002 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
1003 if (!data)
1004 return -ENOMEM;
1005
340ae165 1006 __ethtool_get_strings(dev, gstrings.string_set, data);
1da177e4
LT
1007
1008 ret = -EFAULT;
1009 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
1010 goto out;
1011 useraddr += sizeof(gstrings);
1012 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
1013 goto out;
1014 ret = 0;
1015
340ae165 1016out:
1da177e4
LT
1017 kfree(data);
1018 return ret;
1019}
1020
1021static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
1022{
1023 struct ethtool_value id;
68f512f2
BH
1024 static bool busy;
1025 int rc;
1da177e4 1026
1ab7b6ac 1027 if (!dev->ethtool_ops->set_phys_id)
1da177e4
LT
1028 return -EOPNOTSUPP;
1029
68f512f2
BH
1030 if (busy)
1031 return -EBUSY;
1032
1da177e4
LT
1033 if (copy_from_user(&id, useraddr, sizeof(id)))
1034 return -EFAULT;
1035
68f512f2 1036 rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE);
fce55922 1037 if (rc < 0)
68f512f2
BH
1038 return rc;
1039
1040 /* Drop the RTNL lock while waiting, but prevent reentry or
1041 * removal of the device.
1042 */
1043 busy = true;
1044 dev_hold(dev);
1045 rtnl_unlock();
1046
1047 if (rc == 0) {
1048 /* Driver will handle this itself */
1049 schedule_timeout_interruptible(
143780c6 1050 id.data ? (id.data * HZ) : MAX_SCHEDULE_TIMEOUT);
68f512f2 1051 } else {
fce55922
AB
1052 /* Driver expects to be called at twice the frequency in rc */
1053 int n = rc * 2, i, interval = HZ / n;
1054
1055 /* Count down seconds */
68f512f2 1056 do {
fce55922
AB
1057 /* Count down iterations per second */
1058 i = n;
1059 do {
1060 rtnl_lock();
1061 rc = dev->ethtool_ops->set_phys_id(dev,
1062 (i & 1) ? ETHTOOL_ID_OFF : ETHTOOL_ID_ON);
1063 rtnl_unlock();
1064 if (rc)
1065 break;
1066 schedule_timeout_interruptible(interval);
1067 } while (!signal_pending(current) && --i != 0);
68f512f2
BH
1068 } while (!signal_pending(current) &&
1069 (id.data == 0 || --id.data != 0));
1070 }
1071
1072 rtnl_lock();
1073 dev_put(dev);
1074 busy = false;
1075
1076 (void)dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_INACTIVE);
1077 return rc;
1da177e4
LT
1078}
1079
1080static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
1081{
1082 struct ethtool_stats stats;
76fd8593 1083 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4 1084 u64 *data;
ff03d49f 1085 int ret, n_stats;
1da177e4 1086
a9828ec6 1087 if (!ops->get_ethtool_stats || !ops->get_sset_count)
1da177e4
LT
1088 return -EOPNOTSUPP;
1089
a9828ec6 1090 n_stats = ops->get_sset_count(dev, ETH_SS_STATS);
ff03d49f
JG
1091 if (n_stats < 0)
1092 return n_stats;
1093 WARN_ON(n_stats == 0);
1094
1da177e4
LT
1095 if (copy_from_user(&stats, useraddr, sizeof(stats)))
1096 return -EFAULT;
1097
ff03d49f
JG
1098 stats.n_stats = n_stats;
1099 data = kmalloc(n_stats * sizeof(u64), GFP_USER);
1da177e4
LT
1100 if (!data)
1101 return -ENOMEM;
1102
1103 ops->get_ethtool_stats(dev, &stats, data);
1104
1105 ret = -EFAULT;
1106 if (copy_to_user(useraddr, &stats, sizeof(stats)))
1107 goto out;
1108 useraddr += sizeof(stats);
1109 if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64)))
1110 goto out;
1111 ret = 0;
1112
1113 out:
1114 kfree(data);
1115 return ret;
1116}
1117
0bf0519d 1118static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
a6f9a705
JW
1119{
1120 struct ethtool_perm_addr epaddr;
a6f9a705 1121
313674af 1122 if (copy_from_user(&epaddr, useraddr, sizeof(epaddr)))
a6f9a705
JW
1123 return -EFAULT;
1124
313674af
MW
1125 if (epaddr.size < dev->addr_len)
1126 return -ETOOSMALL;
1127 epaddr.size = dev->addr_len;
a6f9a705 1128
a6f9a705 1129 if (copy_to_user(useraddr, &epaddr, sizeof(epaddr)))
313674af 1130 return -EFAULT;
a6f9a705 1131 useraddr += sizeof(epaddr);
313674af
MW
1132 if (copy_to_user(useraddr, dev->perm_addr, epaddr.size))
1133 return -EFAULT;
1134 return 0;
a6f9a705
JW
1135}
1136
13c99b24
JG
1137static int ethtool_get_value(struct net_device *dev, char __user *useraddr,
1138 u32 cmd, u32 (*actor)(struct net_device *))
3ae7c0b2 1139{
8e557421 1140 struct ethtool_value edata = { .cmd = cmd };
3ae7c0b2 1141
13c99b24 1142 if (!actor)
3ae7c0b2
JG
1143 return -EOPNOTSUPP;
1144
13c99b24 1145 edata.data = actor(dev);
3ae7c0b2
JG
1146
1147 if (copy_to_user(useraddr, &edata, sizeof(edata)))
1148 return -EFAULT;
1149 return 0;
1150}
1151
13c99b24
JG
1152static int ethtool_set_value_void(struct net_device *dev, char __user *useraddr,
1153 void (*actor)(struct net_device *, u32))
3ae7c0b2
JG
1154{
1155 struct ethtool_value edata;
1156
13c99b24 1157 if (!actor)
3ae7c0b2
JG
1158 return -EOPNOTSUPP;
1159
1160 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1161 return -EFAULT;
1162
13c99b24 1163 actor(dev, edata.data);
339bf024
JG
1164 return 0;
1165}
1166
13c99b24
JG
1167static int ethtool_set_value(struct net_device *dev, char __user *useraddr,
1168 int (*actor)(struct net_device *, u32))
339bf024
JG
1169{
1170 struct ethtool_value edata;
1171
13c99b24 1172 if (!actor)
339bf024
JG
1173 return -EOPNOTSUPP;
1174
1175 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1176 return -EFAULT;
1177
13c99b24 1178 return actor(dev, edata.data);
339bf024
JG
1179}
1180
97f8aefb 1181static noinline_for_stack int ethtool_flash_device(struct net_device *dev,
1182 char __user *useraddr)
05c6a8d7
AK
1183{
1184 struct ethtool_flash efl;
1185
1186 if (copy_from_user(&efl, useraddr, sizeof(efl)))
1187 return -EFAULT;
1188
1189 if (!dev->ethtool_ops->flash_device)
1190 return -EOPNOTSUPP;
1191
1192 return dev->ethtool_ops->flash_device(dev, &efl);
1193}
1194
29dd54b7
AC
1195static int ethtool_set_dump(struct net_device *dev,
1196 void __user *useraddr)
1197{
1198 struct ethtool_dump dump;
1199
1200 if (!dev->ethtool_ops->set_dump)
1201 return -EOPNOTSUPP;
1202
1203 if (copy_from_user(&dump, useraddr, sizeof(dump)))
1204 return -EFAULT;
1205
1206 return dev->ethtool_ops->set_dump(dev, &dump);
1207}
1208
1209static int ethtool_get_dump_flag(struct net_device *dev,
1210 void __user *useraddr)
1211{
1212 int ret;
1213 struct ethtool_dump dump;
1214 const struct ethtool_ops *ops = dev->ethtool_ops;
1215
1216 if (!dev->ethtool_ops->get_dump_flag)
1217 return -EOPNOTSUPP;
1218
1219 if (copy_from_user(&dump, useraddr, sizeof(dump)))
1220 return -EFAULT;
1221
1222 ret = ops->get_dump_flag(dev, &dump);
1223 if (ret)
1224 return ret;
1225
1226 if (copy_to_user(useraddr, &dump, sizeof(dump)))
1227 return -EFAULT;
1228 return 0;
1229}
1230
1231static int ethtool_get_dump_data(struct net_device *dev,
1232 void __user *useraddr)
1233{
1234 int ret;
1235 __u32 len;
1236 struct ethtool_dump dump, tmp;
1237 const struct ethtool_ops *ops = dev->ethtool_ops;
1238 void *data = NULL;
1239
1240 if (!dev->ethtool_ops->get_dump_data ||
1241 !dev->ethtool_ops->get_dump_flag)
1242 return -EOPNOTSUPP;
1243
1244 if (copy_from_user(&dump, useraddr, sizeof(dump)))
1245 return -EFAULT;
1246
1247 memset(&tmp, 0, sizeof(tmp));
1248 tmp.cmd = ETHTOOL_GET_DUMP_FLAG;
1249 ret = ops->get_dump_flag(dev, &tmp);
1250 if (ret)
1251 return ret;
1252
1253 len = (tmp.len > dump.len) ? dump.len : tmp.len;
1254 if (!len)
1255 return -EFAULT;
1256
1257 data = vzalloc(tmp.len);
1258 if (!data)
1259 return -ENOMEM;
1260 ret = ops->get_dump_data(dev, &dump, data);
1261 if (ret)
1262 goto out;
1263
1264 if (copy_to_user(useraddr, &dump, sizeof(dump))) {
1265 ret = -EFAULT;
1266 goto out;
1267 }
1268 useraddr += offsetof(struct ethtool_dump, data);
1269 if (copy_to_user(useraddr, data, len))
1270 ret = -EFAULT;
1271out:
1272 vfree(data);
1273 return ret;
1274}
1275
1da177e4
LT
1276/* The main entry point in this file. Called from net/core/dev.c */
1277
881d966b 1278int dev_ethtool(struct net *net, struct ifreq *ifr)
1da177e4 1279{
881d966b 1280 struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
1da177e4
LT
1281 void __user *useraddr = ifr->ifr_data;
1282 u32 ethcmd;
1283 int rc;
04ed3e74 1284 u32 old_features;
1da177e4 1285
1da177e4
LT
1286 if (!dev || !netif_device_present(dev))
1287 return -ENODEV;
1288
97f8aefb 1289 if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
1da177e4
LT
1290 return -EFAULT;
1291
01414802
BH
1292 if (!dev->ethtool_ops) {
1293 /* ETHTOOL_GDRVINFO does not require any driver support.
1294 * It is also unprivileged and does not change anything,
1295 * so we can take a shortcut to it. */
1296 if (ethcmd == ETHTOOL_GDRVINFO)
1297 return ethtool_get_drvinfo(dev, useraddr);
1298 else
1299 return -EOPNOTSUPP;
1300 }
1301
75f3123c 1302 /* Allow some commands to be done by anyone */
97f8aefb 1303 switch (ethcmd) {
0fdc100b 1304 case ETHTOOL_GSET:
75f3123c 1305 case ETHTOOL_GDRVINFO:
75f3123c 1306 case ETHTOOL_GMSGLVL:
75f3123c
SH
1307 case ETHTOOL_GCOALESCE:
1308 case ETHTOOL_GRINGPARAM:
1309 case ETHTOOL_GPAUSEPARAM:
1310 case ETHTOOL_GRXCSUM:
1311 case ETHTOOL_GTXCSUM:
1312 case ETHTOOL_GSG:
1313 case ETHTOOL_GSTRINGS:
75f3123c
SH
1314 case ETHTOOL_GTSO:
1315 case ETHTOOL_GPERMADDR:
1316 case ETHTOOL_GUFO:
1317 case ETHTOOL_GGSO:
1cab819b 1318 case ETHTOOL_GGRO:
339bf024
JG
1319 case ETHTOOL_GFLAGS:
1320 case ETHTOOL_GPFLAGS:
0853ad66 1321 case ETHTOOL_GRXFH:
59089d8d
SB
1322 case ETHTOOL_GRXRINGS:
1323 case ETHTOOL_GRXCLSRLCNT:
1324 case ETHTOOL_GRXCLSRULE:
1325 case ETHTOOL_GRXCLSRLALL:
5455c699 1326 case ETHTOOL_GFEATURES:
75f3123c
SH
1327 break;
1328 default:
1329 if (!capable(CAP_NET_ADMIN))
1330 return -EPERM;
1331 }
1332
97f8aefb 1333 if (dev->ethtool_ops->begin) {
1334 rc = dev->ethtool_ops->begin(dev);
1335 if (rc < 0)
1da177e4 1336 return rc;
97f8aefb 1337 }
d8a33ac4
SH
1338 old_features = dev->features;
1339
1da177e4
LT
1340 switch (ethcmd) {
1341 case ETHTOOL_GSET:
1342 rc = ethtool_get_settings(dev, useraddr);
1343 break;
1344 case ETHTOOL_SSET:
1345 rc = ethtool_set_settings(dev, useraddr);
1346 break;
1347 case ETHTOOL_GDRVINFO:
1348 rc = ethtool_get_drvinfo(dev, useraddr);
1da177e4
LT
1349 break;
1350 case ETHTOOL_GREGS:
1351 rc = ethtool_get_regs(dev, useraddr);
1352 break;
1353 case ETHTOOL_GWOL:
1354 rc = ethtool_get_wol(dev, useraddr);
1355 break;
1356 case ETHTOOL_SWOL:
1357 rc = ethtool_set_wol(dev, useraddr);
1358 break;
1359 case ETHTOOL_GMSGLVL:
13c99b24
JG
1360 rc = ethtool_get_value(dev, useraddr, ethcmd,
1361 dev->ethtool_ops->get_msglevel);
1da177e4
LT
1362 break;
1363 case ETHTOOL_SMSGLVL:
13c99b24
JG
1364 rc = ethtool_set_value_void(dev, useraddr,
1365 dev->ethtool_ops->set_msglevel);
1da177e4
LT
1366 break;
1367 case ETHTOOL_NWAY_RST:
1368 rc = ethtool_nway_reset(dev);
1369 break;
1370 case ETHTOOL_GLINK:
e596e6e4 1371 rc = ethtool_get_link(dev, useraddr);
1da177e4
LT
1372 break;
1373 case ETHTOOL_GEEPROM:
1374 rc = ethtool_get_eeprom(dev, useraddr);
1375 break;
1376 case ETHTOOL_SEEPROM:
1377 rc = ethtool_set_eeprom(dev, useraddr);
1378 break;
1379 case ETHTOOL_GCOALESCE:
1380 rc = ethtool_get_coalesce(dev, useraddr);
1381 break;
1382 case ETHTOOL_SCOALESCE:
1383 rc = ethtool_set_coalesce(dev, useraddr);
1384 break;
1385 case ETHTOOL_GRINGPARAM:
1386 rc = ethtool_get_ringparam(dev, useraddr);
1387 break;
1388 case ETHTOOL_SRINGPARAM:
1389 rc = ethtool_set_ringparam(dev, useraddr);
1390 break;
1391 case ETHTOOL_GPAUSEPARAM:
1392 rc = ethtool_get_pauseparam(dev, useraddr);
1393 break;
1394 case ETHTOOL_SPAUSEPARAM:
1395 rc = ethtool_set_pauseparam(dev, useraddr);
1396 break;
1da177e4
LT
1397 case ETHTOOL_TEST:
1398 rc = ethtool_self_test(dev, useraddr);
1399 break;
1400 case ETHTOOL_GSTRINGS:
1401 rc = ethtool_get_strings(dev, useraddr);
1402 break;
1403 case ETHTOOL_PHYS_ID:
1404 rc = ethtool_phys_id(dev, useraddr);
1405 break;
1406 case ETHTOOL_GSTATS:
1407 rc = ethtool_get_stats(dev, useraddr);
1408 break;
a6f9a705
JW
1409 case ETHTOOL_GPERMADDR:
1410 rc = ethtool_get_perm_addr(dev, useraddr);
1411 break;
3ae7c0b2 1412 case ETHTOOL_GFLAGS:
13c99b24 1413 rc = ethtool_get_value(dev, useraddr, ethcmd,
bc5787c6 1414 __ethtool_get_flags);
3ae7c0b2
JG
1415 break;
1416 case ETHTOOL_SFLAGS:
da8ac86c 1417 rc = ethtool_set_value(dev, useraddr, __ethtool_set_flags);
3ae7c0b2 1418 break;
339bf024 1419 case ETHTOOL_GPFLAGS:
13c99b24
JG
1420 rc = ethtool_get_value(dev, useraddr, ethcmd,
1421 dev->ethtool_ops->get_priv_flags);
339bf024
JG
1422 break;
1423 case ETHTOOL_SPFLAGS:
13c99b24
JG
1424 rc = ethtool_set_value(dev, useraddr,
1425 dev->ethtool_ops->set_priv_flags);
339bf024 1426 break;
0853ad66 1427 case ETHTOOL_GRXFH:
59089d8d
SB
1428 case ETHTOOL_GRXRINGS:
1429 case ETHTOOL_GRXCLSRLCNT:
1430 case ETHTOOL_GRXCLSRULE:
1431 case ETHTOOL_GRXCLSRLALL:
bf988435 1432 rc = ethtool_get_rxnfc(dev, ethcmd, useraddr);
0853ad66
SB
1433 break;
1434 case ETHTOOL_SRXFH:
59089d8d
SB
1435 case ETHTOOL_SRXCLSRLDEL:
1436 case ETHTOOL_SRXCLSRLINS:
bf988435 1437 rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);
0853ad66 1438 break;
05c6a8d7
AK
1439 case ETHTOOL_FLASHDEV:
1440 rc = ethtool_flash_device(dev, useraddr);
1441 break;
d73d3a8c
BH
1442 case ETHTOOL_RESET:
1443 rc = ethtool_reset(dev, useraddr);
1444 break;
15682bc4
PWJ
1445 case ETHTOOL_SRXNTUPLE:
1446 rc = ethtool_set_rx_ntuple(dev, useraddr);
1447 break;
723b2f57
JG
1448 case ETHTOOL_GSSET_INFO:
1449 rc = ethtool_get_sset_info(dev, useraddr);
1450 break;
a5b6ee29
BH
1451 case ETHTOOL_GRXFHINDIR:
1452 rc = ethtool_get_rxfh_indir(dev, useraddr);
1453 break;
1454 case ETHTOOL_SRXFHINDIR:
1455 rc = ethtool_set_rxfh_indir(dev, useraddr);
1456 break;
5455c699
MM
1457 case ETHTOOL_GFEATURES:
1458 rc = ethtool_get_features(dev, useraddr);
1459 break;
1460 case ETHTOOL_SFEATURES:
1461 rc = ethtool_set_features(dev, useraddr);
1462 break;
0a417704 1463 case ETHTOOL_GTXCSUM:
e83d360d 1464 case ETHTOOL_GRXCSUM:
0a417704
MM
1465 case ETHTOOL_GSG:
1466 case ETHTOOL_GTSO:
1467 case ETHTOOL_GUFO:
1468 case ETHTOOL_GGSO:
1469 case ETHTOOL_GGRO:
1470 rc = ethtool_get_one_feature(dev, useraddr, ethcmd);
1471 break;
1472 case ETHTOOL_STXCSUM:
e83d360d 1473 case ETHTOOL_SRXCSUM:
0a417704
MM
1474 case ETHTOOL_SSG:
1475 case ETHTOOL_STSO:
1476 case ETHTOOL_SUFO:
1477 case ETHTOOL_SGSO:
1478 case ETHTOOL_SGRO:
1479 rc = ethtool_set_one_feature(dev, useraddr, ethcmd);
1480 break;
8b5933c3 1481 case ETHTOOL_GCHANNELS:
1482 rc = ethtool_get_channels(dev, useraddr);
1483 break;
1484 case ETHTOOL_SCHANNELS:
1485 rc = ethtool_set_channels(dev, useraddr);
1486 break;
29dd54b7
AC
1487 case ETHTOOL_SET_DUMP:
1488 rc = ethtool_set_dump(dev, useraddr);
1489 break;
1490 case ETHTOOL_GET_DUMP_FLAG:
1491 rc = ethtool_get_dump_flag(dev, useraddr);
1492 break;
1493 case ETHTOOL_GET_DUMP_DATA:
1494 rc = ethtool_get_dump_data(dev, useraddr);
1495 break;
1da177e4 1496 default:
61a44b9c 1497 rc = -EOPNOTSUPP;
1da177e4 1498 }
4ec93edb 1499
e71a4783 1500 if (dev->ethtool_ops->complete)
1da177e4 1501 dev->ethtool_ops->complete(dev);
d8a33ac4
SH
1502
1503 if (old_features != dev->features)
1504 netdev_features_change(dev);
1505
1da177e4 1506 return rc;
1da177e4 1507}
This page took 0.692876 seconds and 5 git commands to generate.