]> bbs.cooldavid.org Git - net-next-2.6.git/blame - net/core/ethtool.c
ethtool: Add support for control of RX flow hash indirection
[net-next-2.6.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>
5a0e3ad6 22#include <linux/slab.h>
1da177e4 23
4ec93edb 24/*
1da177e4
LT
25 * Some useful ethtool_ops methods that're device independent.
26 * If we find that all drivers want to do the same thing here,
27 * we can turn these into dev_() function calls.
28 */
29
30u32 ethtool_op_get_link(struct net_device *dev)
31{
32 return netif_carrier_ok(dev) ? 1 : 0;
33}
97f8aefb 34EXPORT_SYMBOL(ethtool_op_get_link);
1da177e4 35
1896e61f
SS
36u32 ethtool_op_get_rx_csum(struct net_device *dev)
37{
38 return (dev->features & NETIF_F_ALL_CSUM) != 0;
39}
8a729fce 40EXPORT_SYMBOL(ethtool_op_get_rx_csum);
1896e61f 41
1da177e4
LT
42u32 ethtool_op_get_tx_csum(struct net_device *dev)
43{
8648b305 44 return (dev->features & NETIF_F_ALL_CSUM) != 0;
1da177e4 45}
8a729fce 46EXPORT_SYMBOL(ethtool_op_get_tx_csum);
1da177e4
LT
47
48int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
49{
50 if (data)
51 dev->features |= NETIF_F_IP_CSUM;
52 else
53 dev->features &= ~NETIF_F_IP_CSUM;
54
55 return 0;
56}
57
69f6a0fa
JM
58int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data)
59{
60 if (data)
61 dev->features |= NETIF_F_HW_CSUM;
62 else
63 dev->features &= ~NETIF_F_HW_CSUM;
64
65 return 0;
66}
97f8aefb 67EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
6460d948
MC
68
69int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data)
70{
71 if (data)
72 dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
73 else
74 dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
75
76 return 0;
77}
97f8aefb 78EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum);
6460d948 79
1da177e4
LT
80u32 ethtool_op_get_sg(struct net_device *dev)
81{
82 return (dev->features & NETIF_F_SG) != 0;
83}
97f8aefb 84EXPORT_SYMBOL(ethtool_op_get_sg);
1da177e4
LT
85
86int ethtool_op_set_sg(struct net_device *dev, u32 data)
87{
88 if (data)
89 dev->features |= NETIF_F_SG;
90 else
91 dev->features &= ~NETIF_F_SG;
92
93 return 0;
94}
97f8aefb 95EXPORT_SYMBOL(ethtool_op_set_sg);
1da177e4
LT
96
97u32 ethtool_op_get_tso(struct net_device *dev)
98{
99 return (dev->features & NETIF_F_TSO) != 0;
100}
97f8aefb 101EXPORT_SYMBOL(ethtool_op_get_tso);
1da177e4
LT
102
103int ethtool_op_set_tso(struct net_device *dev, u32 data)
104{
105 if (data)
106 dev->features |= NETIF_F_TSO;
107 else
108 dev->features &= ~NETIF_F_TSO;
109
110 return 0;
111}
97f8aefb 112EXPORT_SYMBOL(ethtool_op_set_tso);
1da177e4 113
e89e9cf5
AR
114u32 ethtool_op_get_ufo(struct net_device *dev)
115{
116 return (dev->features & NETIF_F_UFO) != 0;
117}
97f8aefb 118EXPORT_SYMBOL(ethtool_op_get_ufo);
e89e9cf5
AR
119
120int ethtool_op_set_ufo(struct net_device *dev, u32 data)
121{
122 if (data)
123 dev->features |= NETIF_F_UFO;
124 else
125 dev->features &= ~NETIF_F_UFO;
126 return 0;
127}
97f8aefb 128EXPORT_SYMBOL(ethtool_op_set_ufo);
e89e9cf5 129
3ae7c0b2
JG
130/* the following list of flags are the same as their associated
131 * NETIF_F_xxx values in include/linux/netdevice.h
132 */
133static const u32 flags_dup_features =
b00fabb4 134 (ETH_FLAG_LRO | ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH);
3ae7c0b2
JG
135
136u32 ethtool_op_get_flags(struct net_device *dev)
137{
138 /* in the future, this function will probably contain additional
139 * handling for flags which are not so easily handled
140 * by a simple masking operation
141 */
142
143 return dev->features & flags_dup_features;
144}
97f8aefb 145EXPORT_SYMBOL(ethtool_op_get_flags);
3ae7c0b2 146
1437ce39 147int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
3ae7c0b2 148{
1437ce39
BH
149 if (data & ~supported)
150 return -EINVAL;
0d643e1f 151
1437ce39
BH
152 dev->features = ((dev->features & ~flags_dup_features) |
153 (data & flags_dup_features));
3ae7c0b2
JG
154 return 0;
155}
97f8aefb 156EXPORT_SYMBOL(ethtool_op_set_flags);
3ae7c0b2 157
15682bc4
PWJ
158void ethtool_ntuple_flush(struct net_device *dev)
159{
160 struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
161
162 list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
163 list_del(&fsc->list);
164 kfree(fsc);
165 }
166 dev->ethtool_ntuple_list.count = 0;
167}
168EXPORT_SYMBOL(ethtool_ntuple_flush);
169
1da177e4
LT
170/* Handlers for each ethtool command */
171
172static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
173{
8e557421 174 struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
1da177e4
LT
175 int err;
176
177 if (!dev->ethtool_ops->get_settings)
178 return -EOPNOTSUPP;
179
180 err = dev->ethtool_ops->get_settings(dev, &cmd);
181 if (err < 0)
182 return err;
183
184 if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
185 return -EFAULT;
186 return 0;
187}
188
189static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
190{
191 struct ethtool_cmd cmd;
192
193 if (!dev->ethtool_ops->set_settings)
194 return -EOPNOTSUPP;
195
196 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
197 return -EFAULT;
198
199 return dev->ethtool_ops->set_settings(dev, &cmd);
200}
201
97f8aefb 202static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev,
203 void __user *useraddr)
1da177e4
LT
204{
205 struct ethtool_drvinfo info;
76fd8593 206 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4
LT
207
208 if (!ops->get_drvinfo)
209 return -EOPNOTSUPP;
210
211 memset(&info, 0, sizeof(info));
212 info.cmd = ETHTOOL_GDRVINFO;
213 ops->get_drvinfo(dev, &info);
214
723b2f57
JG
215 /*
216 * this method of obtaining string set info is deprecated;
d17792eb 217 * Use ETHTOOL_GSSET_INFO instead.
723b2f57 218 */
ff03d49f
JG
219 if (ops->get_sset_count) {
220 int rc;
221
222 rc = ops->get_sset_count(dev, ETH_SS_TEST);
223 if (rc >= 0)
224 info.testinfo_len = rc;
225 rc = ops->get_sset_count(dev, ETH_SS_STATS);
226 if (rc >= 0)
227 info.n_stats = rc;
339bf024
JG
228 rc = ops->get_sset_count(dev, ETH_SS_PRIV_FLAGS);
229 if (rc >= 0)
230 info.n_priv_flags = rc;
ff03d49f 231 }
1da177e4
LT
232 if (ops->get_regs_len)
233 info.regdump_len = ops->get_regs_len(dev);
234 if (ops->get_eeprom_len)
235 info.eedump_len = ops->get_eeprom_len(dev);
236
237 if (copy_to_user(useraddr, &info, sizeof(info)))
238 return -EFAULT;
239 return 0;
240}
241
f5c445ed 242static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev,
97f8aefb 243 void __user *useraddr)
723b2f57
JG
244{
245 struct ethtool_sset_info info;
246 const struct ethtool_ops *ops = dev->ethtool_ops;
247 u64 sset_mask;
248 int i, idx = 0, n_bits = 0, ret, rc;
249 u32 *info_buf = NULL;
250
251 if (!ops->get_sset_count)
252 return -EOPNOTSUPP;
253
254 if (copy_from_user(&info, useraddr, sizeof(info)))
255 return -EFAULT;
256
257 /* store copy of mask, because we zero struct later on */
258 sset_mask = info.sset_mask;
259 if (!sset_mask)
260 return 0;
261
262 /* calculate size of return buffer */
d17792eb 263 n_bits = hweight64(sset_mask);
723b2f57
JG
264
265 memset(&info, 0, sizeof(info));
266 info.cmd = ETHTOOL_GSSET_INFO;
267
268 info_buf = kzalloc(n_bits * sizeof(u32), GFP_USER);
269 if (!info_buf)
270 return -ENOMEM;
271
272 /*
273 * fill return buffer based on input bitmask and successful
274 * get_sset_count return
275 */
276 for (i = 0; i < 64; i++) {
277 if (!(sset_mask & (1ULL << i)))
278 continue;
279
280 rc = ops->get_sset_count(dev, i);
281 if (rc >= 0) {
282 info.sset_mask |= (1ULL << i);
283 info_buf[idx++] = rc;
284 }
285 }
286
287 ret = -EFAULT;
288 if (copy_to_user(useraddr, &info, sizeof(info)))
289 goto out;
290
291 useraddr += offsetof(struct ethtool_sset_info, data);
292 if (copy_to_user(useraddr, info_buf, idx * sizeof(u32)))
293 goto out;
294
295 ret = 0;
296
297out:
298 kfree(info_buf);
299 return ret;
300}
301
97f8aefb 302static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
303 void __user *useraddr)
0853ad66
SB
304{
305 struct ethtool_rxnfc cmd;
306
59089d8d 307 if (!dev->ethtool_ops->set_rxnfc)
0853ad66
SB
308 return -EOPNOTSUPP;
309
310 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
311 return -EFAULT;
312
59089d8d 313 return dev->ethtool_ops->set_rxnfc(dev, &cmd);
0853ad66
SB
314}
315
97f8aefb 316static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
317 void __user *useraddr)
0853ad66
SB
318{
319 struct ethtool_rxnfc info;
59089d8d
SB
320 const struct ethtool_ops *ops = dev->ethtool_ops;
321 int ret;
322 void *rule_buf = NULL;
0853ad66 323
59089d8d 324 if (!ops->get_rxnfc)
0853ad66
SB
325 return -EOPNOTSUPP;
326
327 if (copy_from_user(&info, useraddr, sizeof(info)))
328 return -EFAULT;
329
59089d8d
SB
330 if (info.cmd == ETHTOOL_GRXCLSRLALL) {
331 if (info.rule_cnt > 0) {
332 rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
333 GFP_USER);
334 if (!rule_buf)
335 return -ENOMEM;
336 }
337 }
0853ad66 338
59089d8d
SB
339 ret = ops->get_rxnfc(dev, &info, rule_buf);
340 if (ret < 0)
341 goto err_out;
342
343 ret = -EFAULT;
0853ad66 344 if (copy_to_user(useraddr, &info, sizeof(info)))
59089d8d
SB
345 goto err_out;
346
347 if (rule_buf) {
348 useraddr += offsetof(struct ethtool_rxnfc, rule_locs);
349 if (copy_to_user(useraddr, rule_buf,
350 info.rule_cnt * sizeof(u32)))
351 goto err_out;
352 }
353 ret = 0;
354
355err_out:
c9caceca 356 kfree(rule_buf);
59089d8d
SB
357
358 return ret;
0853ad66
SB
359}
360
a5b6ee29
BH
361static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
362 void __user *useraddr)
363{
364 struct ethtool_rxfh_indir *indir;
365 u32 table_size;
366 size_t full_size;
367 int ret;
368
369 if (!dev->ethtool_ops->get_rxfh_indir)
370 return -EOPNOTSUPP;
371
372 if (copy_from_user(&table_size,
373 useraddr + offsetof(struct ethtool_rxfh_indir, size),
374 sizeof(table_size)))
375 return -EFAULT;
376
377 if (table_size >
378 (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
379 return -ENOMEM;
380 full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
381 indir = kmalloc(full_size, GFP_USER);
382 if (!indir)
383 return -ENOMEM;
384
385 indir->cmd = ETHTOOL_GRXFHINDIR;
386 indir->size = table_size;
387 ret = dev->ethtool_ops->get_rxfh_indir(dev, indir);
388 if (ret)
389 goto out;
390
391 if (copy_to_user(useraddr, indir, full_size))
392 ret = -EFAULT;
393
394out:
395 kfree(indir);
396 return ret;
397}
398
399static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
400 void __user *useraddr)
401{
402 struct ethtool_rxfh_indir *indir;
403 u32 table_size;
404 size_t full_size;
405 int ret;
406
407 if (!dev->ethtool_ops->set_rxfh_indir)
408 return -EOPNOTSUPP;
409
410 if (copy_from_user(&table_size,
411 useraddr + offsetof(struct ethtool_rxfh_indir, size),
412 sizeof(table_size)))
413 return -EFAULT;
414
415 if (table_size >
416 (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index))
417 return -ENOMEM;
418 full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size;
419 indir = kmalloc(full_size, GFP_USER);
420 if (!indir)
421 return -ENOMEM;
422
423 if (copy_from_user(indir, useraddr, full_size)) {
424 ret = -EFAULT;
425 goto out;
426 }
427
428 ret = dev->ethtool_ops->set_rxfh_indir(dev, indir);
429
430out:
431 kfree(indir);
432 return ret;
433}
434
e8589118 435static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
97f8aefb 436 struct ethtool_rx_ntuple_flow_spec *spec,
437 struct ethtool_rx_ntuple_flow_spec_container *fsc)
15682bc4 438{
15682bc4
PWJ
439
440 /* don't add filters forever */
e8589118
PW
441 if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) {
442 /* free the container */
443 kfree(fsc);
444 return;
445 }
15682bc4
PWJ
446
447 /* Copy the whole filter over */
448 fsc->fs.flow_type = spec->flow_type;
449 memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u));
450 memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u));
451
452 fsc->fs.vlan_tag = spec->vlan_tag;
453 fsc->fs.vlan_tag_mask = spec->vlan_tag_mask;
454 fsc->fs.data = spec->data;
455 fsc->fs.data_mask = spec->data_mask;
456 fsc->fs.action = spec->action;
457
458 /* add to the list */
459 list_add_tail_rcu(&fsc->list, &list->list);
460 list->count++;
15682bc4
PWJ
461}
462
97f8aefb 463static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev,
464 void __user *useraddr)
15682bc4
PWJ
465{
466 struct ethtool_rx_ntuple cmd;
467 const struct ethtool_ops *ops = dev->ethtool_ops;
e8589118 468 struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL;
15682bc4
PWJ
469 int ret;
470
15682bc4
PWJ
471 if (!(dev->features & NETIF_F_NTUPLE))
472 return -EINVAL;
473
474 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
475 return -EFAULT;
476
15682bc4
PWJ
477 /*
478 * Cache filter in dev struct for GET operation only if
479 * the underlying driver doesn't have its own GET operation, and
e8589118
PW
480 * only if the filter was added successfully. First make sure we
481 * can allocate the filter, then continue if successful.
15682bc4 482 */
e8589118
PW
483 if (!ops->get_rx_ntuple) {
484 fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC);
485 if (!fsc)
15682bc4 486 return -ENOMEM;
e8589118
PW
487 }
488
489 ret = ops->set_rx_ntuple(dev, &cmd);
490 if (ret) {
491 kfree(fsc);
492 return ret;
493 }
494
495 if (!ops->get_rx_ntuple)
496 __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc);
15682bc4
PWJ
497
498 return ret;
499}
500
501static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
502{
503 struct ethtool_gstrings gstrings;
504 const struct ethtool_ops *ops = dev->ethtool_ops;
505 struct ethtool_rx_ntuple_flow_spec_container *fsc;
506 u8 *data;
507 char *p;
508 int ret, i, num_strings = 0;
509
510 if (!ops->get_sset_count)
511 return -EOPNOTSUPP;
512
513 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
514 return -EFAULT;
515
516 ret = ops->get_sset_count(dev, gstrings.string_set);
517 if (ret < 0)
518 return ret;
519
520 gstrings.len = ret;
521
522 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
523 if (!data)
524 return -ENOMEM;
525
526 if (ops->get_rx_ntuple) {
527 /* driver-specific filter grab */
528 ret = ops->get_rx_ntuple(dev, gstrings.string_set, data);
529 goto copy;
530 }
531
532 /* default ethtool filter grab */
533 i = 0;
534 p = (char *)data;
535 list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) {
536 sprintf(p, "Filter %d:\n", i);
537 p += ETH_GSTRING_LEN;
538 num_strings++;
539
540 switch (fsc->fs.flow_type) {
541 case TCP_V4_FLOW:
542 sprintf(p, "\tFlow Type: TCP\n");
543 p += ETH_GSTRING_LEN;
544 num_strings++;
545 break;
546 case UDP_V4_FLOW:
547 sprintf(p, "\tFlow Type: UDP\n");
548 p += ETH_GSTRING_LEN;
549 num_strings++;
550 break;
551 case SCTP_V4_FLOW:
552 sprintf(p, "\tFlow Type: SCTP\n");
553 p += ETH_GSTRING_LEN;
554 num_strings++;
555 break;
556 case AH_ESP_V4_FLOW:
557 sprintf(p, "\tFlow Type: AH ESP\n");
558 p += ETH_GSTRING_LEN;
559 num_strings++;
560 break;
561 case ESP_V4_FLOW:
562 sprintf(p, "\tFlow Type: ESP\n");
563 p += ETH_GSTRING_LEN;
564 num_strings++;
565 break;
566 case IP_USER_FLOW:
567 sprintf(p, "\tFlow Type: Raw IP\n");
568 p += ETH_GSTRING_LEN;
569 num_strings++;
570 break;
571 case IPV4_FLOW:
572 sprintf(p, "\tFlow Type: IPv4\n");
573 p += ETH_GSTRING_LEN;
574 num_strings++;
575 break;
576 default:
577 sprintf(p, "\tFlow Type: Unknown\n");
578 p += ETH_GSTRING_LEN;
579 num_strings++;
580 goto unknown_filter;
ccbd6a5a 581 }
15682bc4
PWJ
582
583 /* now the rest of the filters */
584 switch (fsc->fs.flow_type) {
585 case TCP_V4_FLOW:
586 case UDP_V4_FLOW:
587 case SCTP_V4_FLOW:
588 sprintf(p, "\tSrc IP addr: 0x%x\n",
97f8aefb 589 fsc->fs.h_u.tcp_ip4_spec.ip4src);
15682bc4
PWJ
590 p += ETH_GSTRING_LEN;
591 num_strings++;
592 sprintf(p, "\tSrc IP mask: 0x%x\n",
97f8aefb 593 fsc->fs.m_u.tcp_ip4_spec.ip4src);
15682bc4
PWJ
594 p += ETH_GSTRING_LEN;
595 num_strings++;
596 sprintf(p, "\tDest IP addr: 0x%x\n",
97f8aefb 597 fsc->fs.h_u.tcp_ip4_spec.ip4dst);
15682bc4
PWJ
598 p += ETH_GSTRING_LEN;
599 num_strings++;
600 sprintf(p, "\tDest IP mask: 0x%x\n",
97f8aefb 601 fsc->fs.m_u.tcp_ip4_spec.ip4dst);
15682bc4
PWJ
602 p += ETH_GSTRING_LEN;
603 num_strings++;
604 sprintf(p, "\tSrc Port: %d, mask: 0x%x\n",
97f8aefb 605 fsc->fs.h_u.tcp_ip4_spec.psrc,
606 fsc->fs.m_u.tcp_ip4_spec.psrc);
15682bc4
PWJ
607 p += ETH_GSTRING_LEN;
608 num_strings++;
609 sprintf(p, "\tDest Port: %d, mask: 0x%x\n",
97f8aefb 610 fsc->fs.h_u.tcp_ip4_spec.pdst,
611 fsc->fs.m_u.tcp_ip4_spec.pdst);
15682bc4
PWJ
612 p += ETH_GSTRING_LEN;
613 num_strings++;
614 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
97f8aefb 615 fsc->fs.h_u.tcp_ip4_spec.tos,
616 fsc->fs.m_u.tcp_ip4_spec.tos);
15682bc4
PWJ
617 p += ETH_GSTRING_LEN;
618 num_strings++;
619 break;
620 case AH_ESP_V4_FLOW:
621 case ESP_V4_FLOW:
622 sprintf(p, "\tSrc IP addr: 0x%x\n",
97f8aefb 623 fsc->fs.h_u.ah_ip4_spec.ip4src);
15682bc4
PWJ
624 p += ETH_GSTRING_LEN;
625 num_strings++;
626 sprintf(p, "\tSrc IP mask: 0x%x\n",
97f8aefb 627 fsc->fs.m_u.ah_ip4_spec.ip4src);
15682bc4
PWJ
628 p += ETH_GSTRING_LEN;
629 num_strings++;
630 sprintf(p, "\tDest IP addr: 0x%x\n",
97f8aefb 631 fsc->fs.h_u.ah_ip4_spec.ip4dst);
15682bc4
PWJ
632 p += ETH_GSTRING_LEN;
633 num_strings++;
634 sprintf(p, "\tDest IP mask: 0x%x\n",
97f8aefb 635 fsc->fs.m_u.ah_ip4_spec.ip4dst);
15682bc4
PWJ
636 p += ETH_GSTRING_LEN;
637 num_strings++;
638 sprintf(p, "\tSPI: %d, mask: 0x%x\n",
97f8aefb 639 fsc->fs.h_u.ah_ip4_spec.spi,
640 fsc->fs.m_u.ah_ip4_spec.spi);
15682bc4
PWJ
641 p += ETH_GSTRING_LEN;
642 num_strings++;
643 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
97f8aefb 644 fsc->fs.h_u.ah_ip4_spec.tos,
645 fsc->fs.m_u.ah_ip4_spec.tos);
15682bc4
PWJ
646 p += ETH_GSTRING_LEN;
647 num_strings++;
648 break;
649 case IP_USER_FLOW:
650 sprintf(p, "\tSrc IP addr: 0x%x\n",
97f8aefb 651 fsc->fs.h_u.raw_ip4_spec.ip4src);
15682bc4
PWJ
652 p += ETH_GSTRING_LEN;
653 num_strings++;
654 sprintf(p, "\tSrc IP mask: 0x%x\n",
97f8aefb 655 fsc->fs.m_u.raw_ip4_spec.ip4src);
15682bc4
PWJ
656 p += ETH_GSTRING_LEN;
657 num_strings++;
658 sprintf(p, "\tDest IP addr: 0x%x\n",
97f8aefb 659 fsc->fs.h_u.raw_ip4_spec.ip4dst);
15682bc4
PWJ
660 p += ETH_GSTRING_LEN;
661 num_strings++;
662 sprintf(p, "\tDest IP mask: 0x%x\n",
97f8aefb 663 fsc->fs.m_u.raw_ip4_spec.ip4dst);
15682bc4
PWJ
664 p += ETH_GSTRING_LEN;
665 num_strings++;
666 break;
667 case IPV4_FLOW:
668 sprintf(p, "\tSrc IP addr: 0x%x\n",
97f8aefb 669 fsc->fs.h_u.usr_ip4_spec.ip4src);
15682bc4
PWJ
670 p += ETH_GSTRING_LEN;
671 num_strings++;
672 sprintf(p, "\tSrc IP mask: 0x%x\n",
97f8aefb 673 fsc->fs.m_u.usr_ip4_spec.ip4src);
15682bc4
PWJ
674 p += ETH_GSTRING_LEN;
675 num_strings++;
676 sprintf(p, "\tDest IP addr: 0x%x\n",
97f8aefb 677 fsc->fs.h_u.usr_ip4_spec.ip4dst);
15682bc4
PWJ
678 p += ETH_GSTRING_LEN;
679 num_strings++;
680 sprintf(p, "\tDest IP mask: 0x%x\n",
97f8aefb 681 fsc->fs.m_u.usr_ip4_spec.ip4dst);
15682bc4
PWJ
682 p += ETH_GSTRING_LEN;
683 num_strings++;
684 sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n",
97f8aefb 685 fsc->fs.h_u.usr_ip4_spec.l4_4_bytes,
686 fsc->fs.m_u.usr_ip4_spec.l4_4_bytes);
15682bc4
PWJ
687 p += ETH_GSTRING_LEN;
688 num_strings++;
689 sprintf(p, "\tTOS: %d, mask: 0x%x\n",
97f8aefb 690 fsc->fs.h_u.usr_ip4_spec.tos,
691 fsc->fs.m_u.usr_ip4_spec.tos);
15682bc4
PWJ
692 p += ETH_GSTRING_LEN;
693 num_strings++;
694 sprintf(p, "\tIP Version: %d, mask: 0x%x\n",
97f8aefb 695 fsc->fs.h_u.usr_ip4_spec.ip_ver,
696 fsc->fs.m_u.usr_ip4_spec.ip_ver);
15682bc4
PWJ
697 p += ETH_GSTRING_LEN;
698 num_strings++;
699 sprintf(p, "\tProtocol: %d, mask: 0x%x\n",
97f8aefb 700 fsc->fs.h_u.usr_ip4_spec.proto,
701 fsc->fs.m_u.usr_ip4_spec.proto);
15682bc4
PWJ
702 p += ETH_GSTRING_LEN;
703 num_strings++;
704 break;
ccbd6a5a 705 }
15682bc4 706 sprintf(p, "\tVLAN: %d, mask: 0x%x\n",
97f8aefb 707 fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask);
15682bc4
PWJ
708 p += ETH_GSTRING_LEN;
709 num_strings++;
710 sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data);
711 p += ETH_GSTRING_LEN;
712 num_strings++;
713 sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask);
714 p += ETH_GSTRING_LEN;
715 num_strings++;
716 if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
717 sprintf(p, "\tAction: Drop\n");
718 else
719 sprintf(p, "\tAction: Direct to queue %d\n",
97f8aefb 720 fsc->fs.action);
15682bc4
PWJ
721 p += ETH_GSTRING_LEN;
722 num_strings++;
723unknown_filter:
724 i++;
725 }
726copy:
727 /* indicate to userspace how many strings we actually have */
728 gstrings.len = num_strings;
729 ret = -EFAULT;
730 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
731 goto out;
732 useraddr += sizeof(gstrings);
733 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
734 goto out;
735 ret = 0;
736
737out:
738 kfree(data);
739 return ret;
740}
741
1da177e4
LT
742static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
743{
744 struct ethtool_regs regs;
76fd8593 745 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4
LT
746 void *regbuf;
747 int reglen, ret;
748
749 if (!ops->get_regs || !ops->get_regs_len)
750 return -EOPNOTSUPP;
751
752 if (copy_from_user(&regs, useraddr, sizeof(regs)))
753 return -EFAULT;
754
755 reglen = ops->get_regs_len(dev);
756 if (regs.len > reglen)
757 regs.len = reglen;
758
759 regbuf = kmalloc(reglen, GFP_USER);
760 if (!regbuf)
761 return -ENOMEM;
762
763 ops->get_regs(dev, &regs, regbuf);
764
765 ret = -EFAULT;
766 if (copy_to_user(useraddr, &regs, sizeof(regs)))
767 goto out;
768 useraddr += offsetof(struct ethtool_regs, data);
769 if (copy_to_user(useraddr, regbuf, regs.len))
770 goto out;
771 ret = 0;
772
773 out:
774 kfree(regbuf);
775 return ret;
776}
777
d73d3a8c
BH
778static int ethtool_reset(struct net_device *dev, char __user *useraddr)
779{
780 struct ethtool_value reset;
781 int ret;
782
783 if (!dev->ethtool_ops->reset)
784 return -EOPNOTSUPP;
785
786 if (copy_from_user(&reset, useraddr, sizeof(reset)))
787 return -EFAULT;
788
789 ret = dev->ethtool_ops->reset(dev, &reset.data);
790 if (ret)
791 return ret;
792
793 if (copy_to_user(useraddr, &reset, sizeof(reset)))
794 return -EFAULT;
795 return 0;
796}
797
1da177e4
LT
798static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
799{
8e557421 800 struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
1da177e4
LT
801
802 if (!dev->ethtool_ops->get_wol)
803 return -EOPNOTSUPP;
804
805 dev->ethtool_ops->get_wol(dev, &wol);
806
807 if (copy_to_user(useraddr, &wol, sizeof(wol)))
808 return -EFAULT;
809 return 0;
810}
811
812static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
813{
814 struct ethtool_wolinfo wol;
815
816 if (!dev->ethtool_ops->set_wol)
817 return -EOPNOTSUPP;
818
819 if (copy_from_user(&wol, useraddr, sizeof(wol)))
820 return -EFAULT;
821
822 return dev->ethtool_ops->set_wol(dev, &wol);
823}
824
1da177e4
LT
825static int ethtool_nway_reset(struct net_device *dev)
826{
827 if (!dev->ethtool_ops->nway_reset)
828 return -EOPNOTSUPP;
829
830 return dev->ethtool_ops->nway_reset(dev);
831}
832
1da177e4
LT
833static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
834{
835 struct ethtool_eeprom eeprom;
76fd8593 836 const struct ethtool_ops *ops = dev->ethtool_ops;
b131dd5d
MSB
837 void __user *userbuf = useraddr + sizeof(eeprom);
838 u32 bytes_remaining;
1da177e4 839 u8 *data;
b131dd5d 840 int ret = 0;
1da177e4
LT
841
842 if (!ops->get_eeprom || !ops->get_eeprom_len)
843 return -EOPNOTSUPP;
844
845 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
846 return -EFAULT;
847
848 /* Check for wrap and zero */
849 if (eeprom.offset + eeprom.len <= eeprom.offset)
850 return -EINVAL;
851
852 /* Check for exceeding total eeprom len */
853 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
854 return -EINVAL;
855
b131dd5d 856 data = kmalloc(PAGE_SIZE, GFP_USER);
1da177e4
LT
857 if (!data)
858 return -ENOMEM;
859
b131dd5d
MSB
860 bytes_remaining = eeprom.len;
861 while (bytes_remaining > 0) {
862 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
863
864 ret = ops->get_eeprom(dev, &eeprom, data);
865 if (ret)
866 break;
867 if (copy_to_user(userbuf, data, eeprom.len)) {
868 ret = -EFAULT;
869 break;
870 }
871 userbuf += eeprom.len;
872 eeprom.offset += eeprom.len;
873 bytes_remaining -= eeprom.len;
874 }
1da177e4 875
c5835df9
MSB
876 eeprom.len = userbuf - (useraddr + sizeof(eeprom));
877 eeprom.offset -= eeprom.len;
878 if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
879 ret = -EFAULT;
880
1da177e4
LT
881 kfree(data);
882 return ret;
883}
884
885static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
886{
887 struct ethtool_eeprom eeprom;
76fd8593 888 const struct ethtool_ops *ops = dev->ethtool_ops;
b131dd5d
MSB
889 void __user *userbuf = useraddr + sizeof(eeprom);
890 u32 bytes_remaining;
1da177e4 891 u8 *data;
b131dd5d 892 int ret = 0;
1da177e4
LT
893
894 if (!ops->set_eeprom || !ops->get_eeprom_len)
895 return -EOPNOTSUPP;
896
897 if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
898 return -EFAULT;
899
900 /* Check for wrap and zero */
901 if (eeprom.offset + eeprom.len <= eeprom.offset)
902 return -EINVAL;
903
904 /* Check for exceeding total eeprom len */
905 if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
906 return -EINVAL;
907
b131dd5d 908 data = kmalloc(PAGE_SIZE, GFP_USER);
1da177e4
LT
909 if (!data)
910 return -ENOMEM;
911
b131dd5d
MSB
912 bytes_remaining = eeprom.len;
913 while (bytes_remaining > 0) {
914 eeprom.len = min(bytes_remaining, (u32)PAGE_SIZE);
915
916 if (copy_from_user(data, userbuf, eeprom.len)) {
917 ret = -EFAULT;
918 break;
919 }
920 ret = ops->set_eeprom(dev, &eeprom, data);
921 if (ret)
922 break;
923 userbuf += eeprom.len;
924 eeprom.offset += eeprom.len;
925 bytes_remaining -= eeprom.len;
926 }
1da177e4 927
1da177e4
LT
928 kfree(data);
929 return ret;
930}
931
97f8aefb 932static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev,
933 void __user *useraddr)
1da177e4 934{
8e557421 935 struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE };
1da177e4
LT
936
937 if (!dev->ethtool_ops->get_coalesce)
938 return -EOPNOTSUPP;
939
940 dev->ethtool_ops->get_coalesce(dev, &coalesce);
941
942 if (copy_to_user(useraddr, &coalesce, sizeof(coalesce)))
943 return -EFAULT;
944 return 0;
945}
946
97f8aefb 947static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev,
948 void __user *useraddr)
1da177e4
LT
949{
950 struct ethtool_coalesce coalesce;
951
fa04ae5c 952 if (!dev->ethtool_ops->set_coalesce)
1da177e4
LT
953 return -EOPNOTSUPP;
954
955 if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
956 return -EFAULT;
957
958 return dev->ethtool_ops->set_coalesce(dev, &coalesce);
959}
960
961static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr)
962{
8e557421 963 struct ethtool_ringparam ringparam = { .cmd = ETHTOOL_GRINGPARAM };
1da177e4
LT
964
965 if (!dev->ethtool_ops->get_ringparam)
966 return -EOPNOTSUPP;
967
968 dev->ethtool_ops->get_ringparam(dev, &ringparam);
969
970 if (copy_to_user(useraddr, &ringparam, sizeof(ringparam)))
971 return -EFAULT;
972 return 0;
973}
974
975static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr)
976{
977 struct ethtool_ringparam ringparam;
978
979 if (!dev->ethtool_ops->set_ringparam)
980 return -EOPNOTSUPP;
981
982 if (copy_from_user(&ringparam, useraddr, sizeof(ringparam)))
983 return -EFAULT;
984
985 return dev->ethtool_ops->set_ringparam(dev, &ringparam);
986}
987
988static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr)
989{
990 struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM };
991
992 if (!dev->ethtool_ops->get_pauseparam)
993 return -EOPNOTSUPP;
994
995 dev->ethtool_ops->get_pauseparam(dev, &pauseparam);
996
997 if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam)))
998 return -EFAULT;
999 return 0;
1000}
1001
1002static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr)
1003{
1004 struct ethtool_pauseparam pauseparam;
1005
e1b90c41 1006 if (!dev->ethtool_ops->set_pauseparam)
1da177e4
LT
1007 return -EOPNOTSUPP;
1008
1009 if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam)))
1010 return -EFAULT;
1011
1012 return dev->ethtool_ops->set_pauseparam(dev, &pauseparam);
1013}
1014
1da177e4
LT
1015static int __ethtool_set_sg(struct net_device *dev, u32 data)
1016{
1017 int err;
1018
1019 if (!data && dev->ethtool_ops->set_tso) {
1020 err = dev->ethtool_ops->set_tso(dev, 0);
1021 if (err)
1022 return err;
1023 }
1024
e89e9cf5
AR
1025 if (!data && dev->ethtool_ops->set_ufo) {
1026 err = dev->ethtool_ops->set_ufo(dev, 0);
1027 if (err)
1028 return err;
1029 }
1da177e4
LT
1030 return dev->ethtool_ops->set_sg(dev, data);
1031}
1032
1033static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr)
1034{
1035 struct ethtool_value edata;
1036 int err;
1037
1038 if (!dev->ethtool_ops->set_tx_csum)
1039 return -EOPNOTSUPP;
1040
1041 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1042 return -EFAULT;
1043
1044 if (!edata.data && dev->ethtool_ops->set_sg) {
1045 err = __ethtool_set_sg(dev, 0);
1046 if (err)
1047 return err;
1048 }
1049
1050 return dev->ethtool_ops->set_tx_csum(dev, edata.data);
1051}
97f8aefb 1052EXPORT_SYMBOL(ethtool_op_set_tx_csum);
1da177e4 1053
b240a0e5
HX
1054static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr)
1055{
1056 struct ethtool_value edata;
1057
1058 if (!dev->ethtool_ops->set_rx_csum)
1059 return -EOPNOTSUPP;
1060
1061 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1062 return -EFAULT;
1063
1064 if (!edata.data && dev->ethtool_ops->set_sg)
1065 dev->features &= ~NETIF_F_GRO;
1066
1067 return dev->ethtool_ops->set_rx_csum(dev, edata.data);
1068}
1069
1da177e4
LT
1070static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
1071{
1072 struct ethtool_value edata;
1073
1074 if (!dev->ethtool_ops->set_sg)
1075 return -EOPNOTSUPP;
1076
1077 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1078 return -EFAULT;
1079
4ec93edb 1080 if (edata.data &&
8648b305 1081 !(dev->features & NETIF_F_ALL_CSUM))
1da177e4
LT
1082 return -EINVAL;
1083
1084 return __ethtool_set_sg(dev, edata.data);
1085}
1086
1da177e4
LT
1087static int ethtool_set_tso(struct net_device *dev, char __user *useraddr)
1088{
1089 struct ethtool_value edata;
1090
1091 if (!dev->ethtool_ops->set_tso)
1092 return -EOPNOTSUPP;
1093
1094 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1095 return -EFAULT;
1096
1097 if (edata.data && !(dev->features & NETIF_F_SG))
1098 return -EINVAL;
1099
1100 return dev->ethtool_ops->set_tso(dev, edata.data);
1101}
1102
e89e9cf5
AR
1103static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
1104{
1105 struct ethtool_value edata;
1106
1107 if (!dev->ethtool_ops->set_ufo)
1108 return -EOPNOTSUPP;
1109 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1110 return -EFAULT;
1111 if (edata.data && !(dev->features & NETIF_F_SG))
1112 return -EINVAL;
1113 if (edata.data && !(dev->features & NETIF_F_HW_CSUM))
1114 return -EINVAL;
1115 return dev->ethtool_ops->set_ufo(dev, edata.data);
1116}
1117
37c3185a
HX
1118static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
1119{
1120 struct ethtool_value edata = { ETHTOOL_GGSO };
1121
1122 edata.data = dev->features & NETIF_F_GSO;
1123 if (copy_to_user(useraddr, &edata, sizeof(edata)))
97f8aefb 1124 return -EFAULT;
37c3185a
HX
1125 return 0;
1126}
1127
1128static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
1129{
1130 struct ethtool_value edata;
1131
1132 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1133 return -EFAULT;
1134 if (edata.data)
1135 dev->features |= NETIF_F_GSO;
1136 else
1137 dev->features &= ~NETIF_F_GSO;
1138 return 0;
1139}
1140
b240a0e5
HX
1141static int ethtool_get_gro(struct net_device *dev, char __user *useraddr)
1142{
1143 struct ethtool_value edata = { ETHTOOL_GGRO };
1144
1145 edata.data = dev->features & NETIF_F_GRO;
1146 if (copy_to_user(useraddr, &edata, sizeof(edata)))
97f8aefb 1147 return -EFAULT;
b240a0e5
HX
1148 return 0;
1149}
1150
1151static int ethtool_set_gro(struct net_device *dev, char __user *useraddr)
1152{
1153 struct ethtool_value edata;
1154
1155 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1156 return -EFAULT;
1157
1158 if (edata.data) {
1159 if (!dev->ethtool_ops->get_rx_csum ||
1160 !dev->ethtool_ops->get_rx_csum(dev))
1161 return -EINVAL;
1162 dev->features |= NETIF_F_GRO;
1163 } else
1164 dev->features &= ~NETIF_F_GRO;
1165
1166 return 0;
1167}
1168
1da177e4
LT
1169static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
1170{
1171 struct ethtool_test test;
76fd8593 1172 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4 1173 u64 *data;
ff03d49f 1174 int ret, test_len;
1da177e4 1175
a9828ec6 1176 if (!ops->self_test || !ops->get_sset_count)
1da177e4
LT
1177 return -EOPNOTSUPP;
1178
a9828ec6 1179 test_len = ops->get_sset_count(dev, ETH_SS_TEST);
ff03d49f
JG
1180 if (test_len < 0)
1181 return test_len;
1182 WARN_ON(test_len == 0);
1183
1da177e4
LT
1184 if (copy_from_user(&test, useraddr, sizeof(test)))
1185 return -EFAULT;
1186
ff03d49f
JG
1187 test.len = test_len;
1188 data = kmalloc(test_len * sizeof(u64), GFP_USER);
1da177e4
LT
1189 if (!data)
1190 return -ENOMEM;
1191
1192 ops->self_test(dev, &test, data);
1193
1194 ret = -EFAULT;
1195 if (copy_to_user(useraddr, &test, sizeof(test)))
1196 goto out;
1197 useraddr += sizeof(test);
1198 if (copy_to_user(useraddr, data, test.len * sizeof(u64)))
1199 goto out;
1200 ret = 0;
1201
1202 out:
1203 kfree(data);
1204 return ret;
1205}
1206
1207static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
1208{
1209 struct ethtool_gstrings gstrings;
76fd8593 1210 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4
LT
1211 u8 *data;
1212 int ret;
1213
a9828ec6 1214 if (!ops->get_strings || !ops->get_sset_count)
1da177e4
LT
1215 return -EOPNOTSUPP;
1216
1217 if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
1218 return -EFAULT;
1219
a9828ec6
BH
1220 ret = ops->get_sset_count(dev, gstrings.string_set);
1221 if (ret < 0)
1222 return ret;
1223
1224 gstrings.len = ret;
1da177e4
LT
1225
1226 data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
1227 if (!data)
1228 return -ENOMEM;
1229
1230 ops->get_strings(dev, gstrings.string_set, data);
1231
1232 ret = -EFAULT;
1233 if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
1234 goto out;
1235 useraddr += sizeof(gstrings);
1236 if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
1237 goto out;
1238 ret = 0;
1239
1240 out:
1241 kfree(data);
1242 return ret;
1243}
1244
1245static int ethtool_phys_id(struct net_device *dev, void __user *useraddr)
1246{
1247 struct ethtool_value id;
1248
1249 if (!dev->ethtool_ops->phys_id)
1250 return -EOPNOTSUPP;
1251
1252 if (copy_from_user(&id, useraddr, sizeof(id)))
1253 return -EFAULT;
1254
1255 return dev->ethtool_ops->phys_id(dev, id.data);
1256}
1257
1258static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
1259{
1260 struct ethtool_stats stats;
76fd8593 1261 const struct ethtool_ops *ops = dev->ethtool_ops;
1da177e4 1262 u64 *data;
ff03d49f 1263 int ret, n_stats;
1da177e4 1264
a9828ec6 1265 if (!ops->get_ethtool_stats || !ops->get_sset_count)
1da177e4
LT
1266 return -EOPNOTSUPP;
1267
a9828ec6 1268 n_stats = ops->get_sset_count(dev, ETH_SS_STATS);
ff03d49f
JG
1269 if (n_stats < 0)
1270 return n_stats;
1271 WARN_ON(n_stats == 0);
1272
1da177e4
LT
1273 if (copy_from_user(&stats, useraddr, sizeof(stats)))
1274 return -EFAULT;
1275
ff03d49f
JG
1276 stats.n_stats = n_stats;
1277 data = kmalloc(n_stats * sizeof(u64), GFP_USER);
1da177e4
LT
1278 if (!data)
1279 return -ENOMEM;
1280
1281 ops->get_ethtool_stats(dev, &stats, data);
1282
1283 ret = -EFAULT;
1284 if (copy_to_user(useraddr, &stats, sizeof(stats)))
1285 goto out;
1286 useraddr += sizeof(stats);
1287 if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64)))
1288 goto out;
1289 ret = 0;
1290
1291 out:
1292 kfree(data);
1293 return ret;
1294}
1295
0bf0519d 1296static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
a6f9a705
JW
1297{
1298 struct ethtool_perm_addr epaddr;
a6f9a705 1299
313674af 1300 if (copy_from_user(&epaddr, useraddr, sizeof(epaddr)))
a6f9a705
JW
1301 return -EFAULT;
1302
313674af
MW
1303 if (epaddr.size < dev->addr_len)
1304 return -ETOOSMALL;
1305 epaddr.size = dev->addr_len;
a6f9a705 1306
a6f9a705 1307 if (copy_to_user(useraddr, &epaddr, sizeof(epaddr)))
313674af 1308 return -EFAULT;
a6f9a705 1309 useraddr += sizeof(epaddr);
313674af
MW
1310 if (copy_to_user(useraddr, dev->perm_addr, epaddr.size))
1311 return -EFAULT;
1312 return 0;
a6f9a705
JW
1313}
1314
13c99b24
JG
1315static int ethtool_get_value(struct net_device *dev, char __user *useraddr,
1316 u32 cmd, u32 (*actor)(struct net_device *))
3ae7c0b2 1317{
8e557421 1318 struct ethtool_value edata = { .cmd = cmd };
3ae7c0b2 1319
13c99b24 1320 if (!actor)
3ae7c0b2
JG
1321 return -EOPNOTSUPP;
1322
13c99b24 1323 edata.data = actor(dev);
3ae7c0b2
JG
1324
1325 if (copy_to_user(useraddr, &edata, sizeof(edata)))
1326 return -EFAULT;
1327 return 0;
1328}
1329
13c99b24
JG
1330static int ethtool_set_value_void(struct net_device *dev, char __user *useraddr,
1331 void (*actor)(struct net_device *, u32))
3ae7c0b2
JG
1332{
1333 struct ethtool_value edata;
1334
13c99b24 1335 if (!actor)
3ae7c0b2
JG
1336 return -EOPNOTSUPP;
1337
1338 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1339 return -EFAULT;
1340
13c99b24 1341 actor(dev, edata.data);
339bf024
JG
1342 return 0;
1343}
1344
13c99b24
JG
1345static int ethtool_set_value(struct net_device *dev, char __user *useraddr,
1346 int (*actor)(struct net_device *, u32))
339bf024
JG
1347{
1348 struct ethtool_value edata;
1349
13c99b24 1350 if (!actor)
339bf024
JG
1351 return -EOPNOTSUPP;
1352
1353 if (copy_from_user(&edata, useraddr, sizeof(edata)))
1354 return -EFAULT;
1355
13c99b24 1356 return actor(dev, edata.data);
339bf024
JG
1357}
1358
97f8aefb 1359static noinline_for_stack int ethtool_flash_device(struct net_device *dev,
1360 char __user *useraddr)
05c6a8d7
AK
1361{
1362 struct ethtool_flash efl;
1363
1364 if (copy_from_user(&efl, useraddr, sizeof(efl)))
1365 return -EFAULT;
1366
1367 if (!dev->ethtool_ops->flash_device)
1368 return -EOPNOTSUPP;
1369
1370 return dev->ethtool_ops->flash_device(dev, &efl);
1371}
1372
1da177e4
LT
1373/* The main entry point in this file. Called from net/core/dev.c */
1374
881d966b 1375int dev_ethtool(struct net *net, struct ifreq *ifr)
1da177e4 1376{
881d966b 1377 struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
1da177e4
LT
1378 void __user *useraddr = ifr->ifr_data;
1379 u32 ethcmd;
1380 int rc;
81e81575 1381 unsigned long old_features;
1da177e4 1382
1da177e4
LT
1383 if (!dev || !netif_device_present(dev))
1384 return -ENODEV;
1385
1386 if (!dev->ethtool_ops)
61a44b9c 1387 return -EOPNOTSUPP;
1da177e4 1388
97f8aefb 1389 if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
1da177e4
LT
1390 return -EFAULT;
1391
75f3123c 1392 /* Allow some commands to be done by anyone */
97f8aefb 1393 switch (ethcmd) {
75f3123c 1394 case ETHTOOL_GDRVINFO:
75f3123c 1395 case ETHTOOL_GMSGLVL:
75f3123c
SH
1396 case ETHTOOL_GCOALESCE:
1397 case ETHTOOL_GRINGPARAM:
1398 case ETHTOOL_GPAUSEPARAM:
1399 case ETHTOOL_GRXCSUM:
1400 case ETHTOOL_GTXCSUM:
1401 case ETHTOOL_GSG:
1402 case ETHTOOL_GSTRINGS:
75f3123c
SH
1403 case ETHTOOL_GTSO:
1404 case ETHTOOL_GPERMADDR:
1405 case ETHTOOL_GUFO:
1406 case ETHTOOL_GGSO:
1cab819b 1407 case ETHTOOL_GGRO:
339bf024
JG
1408 case ETHTOOL_GFLAGS:
1409 case ETHTOOL_GPFLAGS:
0853ad66 1410 case ETHTOOL_GRXFH:
59089d8d
SB
1411 case ETHTOOL_GRXRINGS:
1412 case ETHTOOL_GRXCLSRLCNT:
1413 case ETHTOOL_GRXCLSRULE:
1414 case ETHTOOL_GRXCLSRLALL:
75f3123c
SH
1415 break;
1416 default:
1417 if (!capable(CAP_NET_ADMIN))
1418 return -EPERM;
1419 }
1420
97f8aefb 1421 if (dev->ethtool_ops->begin) {
1422 rc = dev->ethtool_ops->begin(dev);
1423 if (rc < 0)
1da177e4 1424 return rc;
97f8aefb 1425 }
d8a33ac4
SH
1426 old_features = dev->features;
1427
1da177e4
LT
1428 switch (ethcmd) {
1429 case ETHTOOL_GSET:
1430 rc = ethtool_get_settings(dev, useraddr);
1431 break;
1432 case ETHTOOL_SSET:
1433 rc = ethtool_set_settings(dev, useraddr);
1434 break;
1435 case ETHTOOL_GDRVINFO:
1436 rc = ethtool_get_drvinfo(dev, useraddr);
1da177e4
LT
1437 break;
1438 case ETHTOOL_GREGS:
1439 rc = ethtool_get_regs(dev, useraddr);
1440 break;
1441 case ETHTOOL_GWOL:
1442 rc = ethtool_get_wol(dev, useraddr);
1443 break;
1444 case ETHTOOL_SWOL:
1445 rc = ethtool_set_wol(dev, useraddr);
1446 break;
1447 case ETHTOOL_GMSGLVL:
13c99b24
JG
1448 rc = ethtool_get_value(dev, useraddr, ethcmd,
1449 dev->ethtool_ops->get_msglevel);
1da177e4
LT
1450 break;
1451 case ETHTOOL_SMSGLVL:
13c99b24
JG
1452 rc = ethtool_set_value_void(dev, useraddr,
1453 dev->ethtool_ops->set_msglevel);
1da177e4
LT
1454 break;
1455 case ETHTOOL_NWAY_RST:
1456 rc = ethtool_nway_reset(dev);
1457 break;
1458 case ETHTOOL_GLINK:
13c99b24
JG
1459 rc = ethtool_get_value(dev, useraddr, ethcmd,
1460 dev->ethtool_ops->get_link);
1da177e4
LT
1461 break;
1462 case ETHTOOL_GEEPROM:
1463 rc = ethtool_get_eeprom(dev, useraddr);
1464 break;
1465 case ETHTOOL_SEEPROM:
1466 rc = ethtool_set_eeprom(dev, useraddr);
1467 break;
1468 case ETHTOOL_GCOALESCE:
1469 rc = ethtool_get_coalesce(dev, useraddr);
1470 break;
1471 case ETHTOOL_SCOALESCE:
1472 rc = ethtool_set_coalesce(dev, useraddr);
1473 break;
1474 case ETHTOOL_GRINGPARAM:
1475 rc = ethtool_get_ringparam(dev, useraddr);
1476 break;
1477 case ETHTOOL_SRINGPARAM:
1478 rc = ethtool_set_ringparam(dev, useraddr);
1479 break;
1480 case ETHTOOL_GPAUSEPARAM:
1481 rc = ethtool_get_pauseparam(dev, useraddr);
1482 break;
1483 case ETHTOOL_SPAUSEPARAM:
1484 rc = ethtool_set_pauseparam(dev, useraddr);
1485 break;
1486 case ETHTOOL_GRXCSUM:
13c99b24 1487 rc = ethtool_get_value(dev, useraddr, ethcmd,
1896e61f
SS
1488 (dev->ethtool_ops->get_rx_csum ?
1489 dev->ethtool_ops->get_rx_csum :
1490 ethtool_op_get_rx_csum));
1da177e4
LT
1491 break;
1492 case ETHTOOL_SRXCSUM:
b240a0e5 1493 rc = ethtool_set_rx_csum(dev, useraddr);
1da177e4
LT
1494 break;
1495 case ETHTOOL_GTXCSUM:
13c99b24 1496 rc = ethtool_get_value(dev, useraddr, ethcmd,
88d3aafd
JG
1497 (dev->ethtool_ops->get_tx_csum ?
1498 dev->ethtool_ops->get_tx_csum :
1499 ethtool_op_get_tx_csum));
1da177e4
LT
1500 break;
1501 case ETHTOOL_STXCSUM:
1502 rc = ethtool_set_tx_csum(dev, useraddr);
1503 break;
1504 case ETHTOOL_GSG:
13c99b24 1505 rc = ethtool_get_value(dev, useraddr, ethcmd,
88d3aafd
JG
1506 (dev->ethtool_ops->get_sg ?
1507 dev->ethtool_ops->get_sg :
1508 ethtool_op_get_sg));
1da177e4
LT
1509 break;
1510 case ETHTOOL_SSG:
1511 rc = ethtool_set_sg(dev, useraddr);
1512 break;
1513 case ETHTOOL_GTSO:
13c99b24 1514 rc = ethtool_get_value(dev, useraddr, ethcmd,
88d3aafd
JG
1515 (dev->ethtool_ops->get_tso ?
1516 dev->ethtool_ops->get_tso :
1517 ethtool_op_get_tso));
1da177e4
LT
1518 break;
1519 case ETHTOOL_STSO:
1520 rc = ethtool_set_tso(dev, useraddr);
1521 break;
1522 case ETHTOOL_TEST:
1523 rc = ethtool_self_test(dev, useraddr);
1524 break;
1525 case ETHTOOL_GSTRINGS:
1526 rc = ethtool_get_strings(dev, useraddr);
1527 break;
1528 case ETHTOOL_PHYS_ID:
1529 rc = ethtool_phys_id(dev, useraddr);
1530 break;
1531 case ETHTOOL_GSTATS:
1532 rc = ethtool_get_stats(dev, useraddr);
1533 break;
a6f9a705
JW
1534 case ETHTOOL_GPERMADDR:
1535 rc = ethtool_get_perm_addr(dev, useraddr);
1536 break;
e89e9cf5 1537 case ETHTOOL_GUFO:
13c99b24 1538 rc = ethtool_get_value(dev, useraddr, ethcmd,
88d3aafd
JG
1539 (dev->ethtool_ops->get_ufo ?
1540 dev->ethtool_ops->get_ufo :
1541 ethtool_op_get_ufo));
e89e9cf5
AR
1542 break;
1543 case ETHTOOL_SUFO:
1544 rc = ethtool_set_ufo(dev, useraddr);
1545 break;
37c3185a
HX
1546 case ETHTOOL_GGSO:
1547 rc = ethtool_get_gso(dev, useraddr);
1548 break;
1549 case ETHTOOL_SGSO:
1550 rc = ethtool_set_gso(dev, useraddr);
1551 break;
3ae7c0b2 1552 case ETHTOOL_GFLAGS:
13c99b24 1553 rc = ethtool_get_value(dev, useraddr, ethcmd,
1896e61f
SS
1554 (dev->ethtool_ops->get_flags ?
1555 dev->ethtool_ops->get_flags :
1556 ethtool_op_get_flags));
3ae7c0b2
JG
1557 break;
1558 case ETHTOOL_SFLAGS:
13c99b24
JG
1559 rc = ethtool_set_value(dev, useraddr,
1560 dev->ethtool_ops->set_flags);
3ae7c0b2 1561 break;
339bf024 1562 case ETHTOOL_GPFLAGS:
13c99b24
JG
1563 rc = ethtool_get_value(dev, useraddr, ethcmd,
1564 dev->ethtool_ops->get_priv_flags);
339bf024
JG
1565 break;
1566 case ETHTOOL_SPFLAGS:
13c99b24
JG
1567 rc = ethtool_set_value(dev, useraddr,
1568 dev->ethtool_ops->set_priv_flags);
339bf024 1569 break;
0853ad66 1570 case ETHTOOL_GRXFH:
59089d8d
SB
1571 case ETHTOOL_GRXRINGS:
1572 case ETHTOOL_GRXCLSRLCNT:
1573 case ETHTOOL_GRXCLSRULE:
1574 case ETHTOOL_GRXCLSRLALL:
1575 rc = ethtool_get_rxnfc(dev, useraddr);
0853ad66
SB
1576 break;
1577 case ETHTOOL_SRXFH:
59089d8d
SB
1578 case ETHTOOL_SRXCLSRLDEL:
1579 case ETHTOOL_SRXCLSRLINS:
1580 rc = ethtool_set_rxnfc(dev, useraddr);
0853ad66 1581 break;
b240a0e5
HX
1582 case ETHTOOL_GGRO:
1583 rc = ethtool_get_gro(dev, useraddr);
1584 break;
1585 case ETHTOOL_SGRO:
1586 rc = ethtool_set_gro(dev, useraddr);
1587 break;
05c6a8d7
AK
1588 case ETHTOOL_FLASHDEV:
1589 rc = ethtool_flash_device(dev, useraddr);
1590 break;
d73d3a8c
BH
1591 case ETHTOOL_RESET:
1592 rc = ethtool_reset(dev, useraddr);
1593 break;
15682bc4
PWJ
1594 case ETHTOOL_SRXNTUPLE:
1595 rc = ethtool_set_rx_ntuple(dev, useraddr);
1596 break;
1597 case ETHTOOL_GRXNTUPLE:
1598 rc = ethtool_get_rx_ntuple(dev, useraddr);
1599 break;
723b2f57
JG
1600 case ETHTOOL_GSSET_INFO:
1601 rc = ethtool_get_sset_info(dev, useraddr);
1602 break;
a5b6ee29
BH
1603 case ETHTOOL_GRXFHINDIR:
1604 rc = ethtool_get_rxfh_indir(dev, useraddr);
1605 break;
1606 case ETHTOOL_SRXFHINDIR:
1607 rc = ethtool_set_rxfh_indir(dev, useraddr);
1608 break;
1da177e4 1609 default:
61a44b9c 1610 rc = -EOPNOTSUPP;
1da177e4 1611 }
4ec93edb 1612
e71a4783 1613 if (dev->ethtool_ops->complete)
1da177e4 1614 dev->ethtool_ops->complete(dev);
d8a33ac4
SH
1615
1616 if (old_features != dev->features)
1617 netdev_features_change(dev);
1618
1da177e4 1619 return rc;
1da177e4 1620}