187
184
/* Handlers for each ethtool command */
186
#define ETHTOOL_DEV_FEATURE_WORDS 1
188
static void ethtool_get_features_compat(struct net_device *dev,
189
struct ethtool_get_features_block *features)
191
if (!dev->ethtool_ops)
194
/* getting RX checksum */
195
if (dev->ethtool_ops->get_rx_csum)
196
if (dev->ethtool_ops->get_rx_csum(dev))
197
features[0].active |= NETIF_F_RXCSUM;
199
/* mark legacy-changeable features */
200
if (dev->ethtool_ops->set_sg)
201
features[0].available |= NETIF_F_SG;
202
if (dev->ethtool_ops->set_tx_csum)
203
features[0].available |= NETIF_F_ALL_CSUM;
204
if (dev->ethtool_ops->set_tso)
205
features[0].available |= NETIF_F_ALL_TSO;
206
if (dev->ethtool_ops->set_rx_csum)
207
features[0].available |= NETIF_F_RXCSUM;
208
if (dev->ethtool_ops->set_flags)
209
features[0].available |= flags_dup_features;
212
static int ethtool_set_feature_compat(struct net_device *dev,
213
int (*legacy_set)(struct net_device *, u32),
214
struct ethtool_set_features_block *features, u32 mask)
221
if (!(features[0].valid & mask))
224
features[0].valid &= ~mask;
226
do_set = !!(features[0].requested & mask);
228
if (legacy_set(dev, do_set) < 0)
230
"Legacy feature change (%s) failed for 0x%08x\n",
231
do_set ? "set" : "clear", mask);
236
static int ethtool_set_flags_compat(struct net_device *dev,
237
int (*legacy_set)(struct net_device *, u32),
238
struct ethtool_set_features_block *features, u32 mask)
245
if (!(features[0].valid & mask))
248
value = dev->features & ~features[0].valid;
249
value |= features[0].requested;
251
features[0].valid &= ~mask;
253
if (legacy_set(dev, value & mask) < 0)
254
netdev_info(dev, "Legacy flags change failed\n");
259
static int ethtool_set_features_compat(struct net_device *dev,
260
struct ethtool_set_features_block *features)
264
if (!dev->ethtool_ops)
267
compat = ethtool_set_feature_compat(dev, dev->ethtool_ops->set_sg,
268
features, NETIF_F_SG);
269
compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tx_csum,
270
features, NETIF_F_ALL_CSUM);
271
compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tso,
272
features, NETIF_F_ALL_TSO);
273
compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_rx_csum,
274
features, NETIF_F_RXCSUM);
275
compat |= ethtool_set_flags_compat(dev, dev->ethtool_ops->set_flags,
276
features, flags_dup_features);
281
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
283
struct ethtool_gfeatures cmd = {
284
.cmd = ETHTOOL_GFEATURES,
285
.size = ETHTOOL_DEV_FEATURE_WORDS,
287
struct ethtool_get_features_block features[ETHTOOL_DEV_FEATURE_WORDS] = {
289
.available = dev->hw_features,
290
.requested = dev->wanted_features,
291
.active = dev->features,
292
.never_changed = NETIF_F_NEVER_CHANGE,
295
u32 __user *sizeaddr;
298
ethtool_get_features_compat(dev, features);
300
sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size);
301
if (get_user(copy_size, sizeaddr))
304
if (copy_size > ETHTOOL_DEV_FEATURE_WORDS)
305
copy_size = ETHTOOL_DEV_FEATURE_WORDS;
307
if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
309
useraddr += sizeof(cmd);
310
if (copy_to_user(useraddr, features, copy_size * sizeof(*features)))
316
static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
318
struct ethtool_sfeatures cmd;
319
struct ethtool_set_features_block features[ETHTOOL_DEV_FEATURE_WORDS];
322
if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
324
useraddr += sizeof(cmd);
326
if (cmd.size != ETHTOOL_DEV_FEATURE_WORDS)
329
if (copy_from_user(features, useraddr, sizeof(features)))
332
if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
335
if (ethtool_set_features_compat(dev, features))
336
ret |= ETHTOOL_F_COMPAT;
338
if (features[0].valid & ~dev->hw_features) {
339
features[0].valid &= dev->hw_features;
340
ret |= ETHTOOL_F_UNSUPPORTED;
343
dev->wanted_features &= ~features[0].valid;
344
dev->wanted_features |= features[0].valid & features[0].requested;
345
__netdev_update_features(dev);
347
if ((dev->wanted_features ^ dev->features) & features[0].valid)
348
ret |= ETHTOOL_F_WISH;
353
static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GSTRING_LEN] = {
354
/* NETIF_F_SG */ "tx-scatter-gather",
355
/* NETIF_F_IP_CSUM */ "tx-checksum-ipv4",
356
/* NETIF_F_NO_CSUM */ "tx-checksum-unneeded",
357
/* NETIF_F_HW_CSUM */ "tx-checksum-ip-generic",
358
/* NETIF_F_IPV6_CSUM */ "tx-checksum-ipv6",
359
/* NETIF_F_HIGHDMA */ "highdma",
360
/* NETIF_F_FRAGLIST */ "tx-scatter-gather-fraglist",
361
/* NETIF_F_HW_VLAN_TX */ "tx-vlan-hw-insert",
363
/* NETIF_F_HW_VLAN_RX */ "rx-vlan-hw-parse",
364
/* NETIF_F_HW_VLAN_FILTER */ "rx-vlan-filter",
365
/* NETIF_F_VLAN_CHALLENGED */ "vlan-challenged",
366
/* NETIF_F_GSO */ "tx-generic-segmentation",
367
/* NETIF_F_LLTX */ "tx-lockless",
368
/* NETIF_F_NETNS_LOCAL */ "netns-local",
369
/* NETIF_F_GRO */ "rx-gro",
370
/* NETIF_F_LRO */ "rx-lro",
372
/* NETIF_F_TSO */ "tx-tcp-segmentation",
373
/* NETIF_F_UFO */ "tx-udp-fragmentation",
374
/* NETIF_F_GSO_ROBUST */ "tx-gso-robust",
375
/* NETIF_F_TSO_ECN */ "tx-tcp-ecn-segmentation",
376
/* NETIF_F_TSO6 */ "tx-tcp6-segmentation",
377
/* NETIF_F_FSO */ "tx-fcoe-segmentation",
381
/* NETIF_F_FCOE_CRC */ "tx-checksum-fcoe-crc",
382
/* NETIF_F_SCTP_CSUM */ "tx-checksum-sctp",
383
/* NETIF_F_FCOE_MTU */ "fcoe-mtu",
384
/* NETIF_F_NTUPLE */ "rx-ntuple-filter",
385
/* NETIF_F_RXHASH */ "rx-hashing",
386
/* NETIF_F_RXCSUM */ "rx-checksum",
387
/* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy",
388
/* NETIF_F_LOOPBACK */ "loopback",
391
static int __ethtool_get_sset_count(struct net_device *dev, int sset)
393
const struct ethtool_ops *ops = dev->ethtool_ops;
395
if (sset == ETH_SS_FEATURES)
396
return ARRAY_SIZE(netdev_features_strings);
398
if (ops && ops->get_sset_count && ops->get_strings)
399
return ops->get_sset_count(dev, sset);
404
static void __ethtool_get_strings(struct net_device *dev,
405
u32 stringset, u8 *data)
407
const struct ethtool_ops *ops = dev->ethtool_ops;
409
if (stringset == ETH_SS_FEATURES)
410
memcpy(data, netdev_features_strings,
411
sizeof(netdev_features_strings));
413
/* ops->get_strings is valid because checked earlier */
414
ops->get_strings(dev, stringset, data);
417
static u32 ethtool_get_feature_mask(u32 eth_cmd)
419
/* feature masks of legacy discrete ethtool ops */
422
case ETHTOOL_GTXCSUM:
423
case ETHTOOL_STXCSUM:
424
return NETIF_F_ALL_CSUM | NETIF_F_SCTP_CSUM;
425
case ETHTOOL_GRXCSUM:
426
case ETHTOOL_SRXCSUM:
427
return NETIF_F_RXCSUM;
433
return NETIF_F_ALL_TSO;
448
static void *__ethtool_get_one_feature_actor(struct net_device *dev, u32 ethcmd)
450
const struct ethtool_ops *ops = dev->ethtool_ops;
456
case ETHTOOL_GTXCSUM:
457
return ops->get_tx_csum;
458
case ETHTOOL_GRXCSUM:
459
return ops->get_rx_csum;
471
static u32 __ethtool_get_rx_csum_oldbug(struct net_device *dev)
473
return !!(dev->features & NETIF_F_ALL_CSUM);
476
static int ethtool_get_one_feature(struct net_device *dev,
477
char __user *useraddr, u32 ethcmd)
479
u32 mask = ethtool_get_feature_mask(ethcmd);
480
struct ethtool_value edata = {
482
.data = !!(dev->features & mask),
485
/* compatibility with discrete get_ ops */
486
if (!(dev->hw_features & mask)) {
487
u32 (*actor)(struct net_device *);
489
actor = __ethtool_get_one_feature_actor(dev, ethcmd);
491
/* bug compatibility with old get_rx_csum */
492
if (ethcmd == ETHTOOL_GRXCSUM && !actor)
493
actor = __ethtool_get_rx_csum_oldbug;
496
edata.data = actor(dev);
499
if (copy_to_user(useraddr, &edata, sizeof(edata)))
504
static int __ethtool_set_tx_csum(struct net_device *dev, u32 data);
505
static int __ethtool_set_rx_csum(struct net_device *dev, u32 data);
506
static int __ethtool_set_sg(struct net_device *dev, u32 data);
507
static int __ethtool_set_tso(struct net_device *dev, u32 data);
508
static int __ethtool_set_ufo(struct net_device *dev, u32 data);
510
static int ethtool_set_one_feature(struct net_device *dev,
511
void __user *useraddr, u32 ethcmd)
513
struct ethtool_value edata;
516
if (copy_from_user(&edata, useraddr, sizeof(edata)))
519
mask = ethtool_get_feature_mask(ethcmd);
520
mask &= dev->hw_features;
523
dev->wanted_features |= mask;
525
dev->wanted_features &= ~mask;
527
__netdev_update_features(dev);
531
/* Driver is not converted to ndo_fix_features or does not
532
* support changing this offload. In the latter case it won't
533
* have corresponding ethtool_ops field set.
535
* Following part is to be removed after all drivers advertise
536
* their changeable features in netdev->hw_features and stop
537
* using discrete offload setting ops.
541
case ETHTOOL_STXCSUM:
542
return __ethtool_set_tx_csum(dev, edata.data);
543
case ETHTOOL_SRXCSUM:
544
return __ethtool_set_rx_csum(dev, edata.data);
546
return __ethtool_set_sg(dev, edata.data);
548
return __ethtool_set_tso(dev, edata.data);
550
return __ethtool_set_ufo(dev, edata.data);
556
int __ethtool_set_flags(struct net_device *dev, u32 data)
560
if (data & ~flags_dup_features)
563
/* legacy set_flags() op */
564
if (dev->ethtool_ops->set_flags) {
565
if (unlikely(dev->hw_features & flags_dup_features))
567
"driver BUG: mixed hw_features and set_flags()\n");
568
return dev->ethtool_ops->set_flags(dev, data);
571
/* allow changing only bits set in hw_features */
572
changed = (data ^ dev->features) & flags_dup_features;
573
if (changed & ~dev->hw_features)
574
return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
576
dev->wanted_features =
577
(dev->wanted_features & ~changed) | (data & dev->hw_features);
579
__netdev_update_features(dev);
189
584
static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
191
586
struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
1120
1549
return dev->ethtool_ops->set_sg(dev, data);
1123
static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr)
1552
static int __ethtool_set_tx_csum(struct net_device *dev, u32 data)
1125
struct ethtool_value edata;
1128
1556
if (!dev->ethtool_ops->set_tx_csum)
1129
1557
return -EOPNOTSUPP;
1131
if (copy_from_user(&edata, useraddr, sizeof(edata)))
1134
if (!edata.data && dev->ethtool_ops->set_sg) {
1559
if (!data && dev->ethtool_ops->set_sg) {
1135
1560
err = __ethtool_set_sg(dev, 0);
1140
return dev->ethtool_ops->set_tx_csum(dev, edata.data);
1565
return dev->ethtool_ops->set_tx_csum(dev, data);
1142
EXPORT_SYMBOL(ethtool_op_set_tx_csum);
1144
static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr)
1568
static int __ethtool_set_rx_csum(struct net_device *dev, u32 data)
1146
struct ethtool_value edata;
1148
1570
if (!dev->ethtool_ops->set_rx_csum)
1149
1571
return -EOPNOTSUPP;
1151
if (copy_from_user(&edata, useraddr, sizeof(edata)))
1154
if (!edata.data && dev->ethtool_ops->set_sg)
1155
1574
dev->features &= ~NETIF_F_GRO;
1157
return dev->ethtool_ops->set_rx_csum(dev, edata.data);
1160
static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
1162
struct ethtool_value edata;
1164
if (!dev->ethtool_ops->set_sg)
1167
if (copy_from_user(&edata, useraddr, sizeof(edata)))
1171
!(dev->features & NETIF_F_ALL_CSUM))
1174
return __ethtool_set_sg(dev, edata.data);
1177
static int ethtool_set_tso(struct net_device *dev, char __user *useraddr)
1179
struct ethtool_value edata;
1576
return dev->ethtool_ops->set_rx_csum(dev, data);
1579
static int __ethtool_set_tso(struct net_device *dev, u32 data)
1181
1581
if (!dev->ethtool_ops->set_tso)
1182
1582
return -EOPNOTSUPP;
1184
if (copy_from_user(&edata, useraddr, sizeof(edata)))
1187
if (edata.data && !(dev->features & NETIF_F_SG))
1584
if (data && !(dev->features & NETIF_F_SG))
1188
1585
return -EINVAL;
1190
return dev->ethtool_ops->set_tso(dev, edata.data);
1587
return dev->ethtool_ops->set_tso(dev, data);
1193
static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
1590
static int __ethtool_set_ufo(struct net_device *dev, u32 data)
1195
struct ethtool_value edata;
1197
1592
if (!dev->ethtool_ops->set_ufo)
1198
1593
return -EOPNOTSUPP;
1199
if (copy_from_user(&edata, useraddr, sizeof(edata)))
1201
if (edata.data && !(dev->features & NETIF_F_SG))
1594
if (data && !(dev->features & NETIF_F_SG))
1202
1595
return -EINVAL;
1203
if (edata.data && !((dev->features & NETIF_F_GEN_CSUM) ||
1596
if (data && !((dev->features & NETIF_F_GEN_CSUM) ||
1204
1597
(dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
1205
1598
== (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)))
1206
1599
return -EINVAL;
1207
return dev->ethtool_ops->set_ufo(dev, edata.data);
1210
static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
1212
struct ethtool_value edata = { ETHTOOL_GGSO };
1214
edata.data = dev->features & NETIF_F_GSO;
1215
if (copy_to_user(useraddr, &edata, sizeof(edata)))
1220
static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
1222
struct ethtool_value edata;
1224
if (copy_from_user(&edata, useraddr, sizeof(edata)))
1227
dev->features |= NETIF_F_GSO;
1229
dev->features &= ~NETIF_F_GSO;
1233
static int ethtool_get_gro(struct net_device *dev, char __user *useraddr)
1235
struct ethtool_value edata = { ETHTOOL_GGRO };
1237
edata.data = dev->features & NETIF_F_GRO;
1238
if (copy_to_user(useraddr, &edata, sizeof(edata)))
1243
static int ethtool_set_gro(struct net_device *dev, char __user *useraddr)
1245
struct ethtool_value edata;
1247
if (copy_from_user(&edata, useraddr, sizeof(edata)))
1251
u32 rxcsum = dev->ethtool_ops->get_rx_csum ?
1252
dev->ethtool_ops->get_rx_csum(dev) :
1253
ethtool_op_get_rx_csum(dev);
1257
dev->features |= NETIF_F_GRO;
1259
dev->features &= ~NETIF_F_GRO;
1600
return dev->ethtool_ops->set_ufo(dev, data);
1264
1603
static int ethtool_self_test(struct net_device *dev, char __user *useraddr)