aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_main.c34
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--net/bridge/br_device.c2
-rw-r--r--net/bridge/br_if.c36
-rw-r--r--net/core/dev.c39
5 files changed, 59 insertions, 54 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 070b78d959cc..1afda3230def 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1202,43 +1202,35 @@ static int bond_sethwaddr(struct net_device *bond_dev,
1202 return 0; 1202 return 0;
1203} 1203}
1204 1204
1205#define BOND_INTERSECT_FEATURES \ 1205#define BOND_VLAN_FEATURES \
1206 (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO) 1206 (NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | \
1207 NETIF_F_HW_VLAN_FILTER)
1207 1208
1208/* 1209/*
1209 * Compute the common dev->feature set available to all slaves. Some 1210 * Compute the common dev->feature set available to all slaves. Some
1210 * feature bits are managed elsewhere, so preserve feature bits set on 1211 * feature bits are managed elsewhere, so preserve those feature bits
1211 * master device that are not part of the examined set. 1212 * on the master device.
1212 */ 1213 */
1213static int bond_compute_features(struct bonding *bond) 1214static int bond_compute_features(struct bonding *bond)
1214{ 1215{
1215 unsigned long features = BOND_INTERSECT_FEATURES;
1216 struct slave *slave; 1216 struct slave *slave;
1217 struct net_device *bond_dev = bond->dev; 1217 struct net_device *bond_dev = bond->dev;
1218 unsigned long features = bond_dev->features;
1218 unsigned short max_hard_header_len = ETH_HLEN; 1219 unsigned short max_hard_header_len = ETH_HLEN;
1219 int i; 1220 int i;
1220 1221
1222 features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES);
1223 features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
1224 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM;
1225
1221 bond_for_each_slave(bond, slave, i) { 1226 bond_for_each_slave(bond, slave, i) {
1222 features &= (slave->dev->features & BOND_INTERSECT_FEATURES); 1227 features = netdev_compute_features(features,
1228 slave->dev->features);
1223 if (slave->dev->hard_header_len > max_hard_header_len) 1229 if (slave->dev->hard_header_len > max_hard_header_len)
1224 max_hard_header_len = slave->dev->hard_header_len; 1230 max_hard_header_len = slave->dev->hard_header_len;
1225 } 1231 }
1226 1232
1227 if ((features & NETIF_F_SG) && 1233 features |= (bond_dev->features & BOND_VLAN_FEATURES);
1228 !(features & NETIF_F_ALL_CSUM))
1229 features &= ~NETIF_F_SG;
1230
1231 /*
1232 * features will include NETIF_F_TSO (NETIF_F_UFO) iff all
1233 * slave devices support NETIF_F_TSO (NETIF_F_UFO), which
1234 * implies that all slaves also support scatter-gather
1235 * (NETIF_F_SG), which implies that features also includes
1236 * NETIF_F_SG. So no need to check whether we have an
1237 * illegal combination of NETIF_F_{TSO,UFO} and
1238 * !NETIF_F_SG
1239 */
1240
1241 features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
1242 bond_dev->features = features; 1234 bond_dev->features = features;
1243 bond_dev->hard_header_len = max_hard_header_len; 1235 bond_dev->hard_header_len = max_hard_header_len;
1244 1236
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4a616d73cc25..e679b2751665 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1131,6 +1131,8 @@ extern void dev_seq_stop(struct seq_file *seq, void *v);
1131 1131
1132extern void linkwatch_run_queue(void); 1132extern void linkwatch_run_queue(void);
1133 1133
1134extern int netdev_compute_features(unsigned long all, unsigned long one);
1135
1134static inline int net_gso_ok(int features, int gso_type) 1136static inline int net_gso_ok(int features, int gso_type)
1135{ 1137{
1136 int feature = gso_type << NETIF_F_GSO_SHIFT; 1138 int feature = gso_type << NETIF_F_GSO_SHIFT;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 5e1892d8d874..0eded176ce99 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -179,5 +179,5 @@ void br_dev_setup(struct net_device *dev)
179 dev->priv_flags = IFF_EBRIDGE; 179 dev->priv_flags = IFF_EBRIDGE;
180 180
181 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | 181 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
182 NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST; 182 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX;
183} 183}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index b40dada002bf..749f0e8f541d 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -349,43 +349,15 @@ int br_min_mtu(const struct net_bridge *br)
349void br_features_recompute(struct net_bridge *br) 349void br_features_recompute(struct net_bridge *br)
350{ 350{
351 struct net_bridge_port *p; 351 struct net_bridge_port *p;
352 unsigned long features, checksum; 352 unsigned long features;
353 353
354 checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0; 354 features = br->feature_mask;
355 features = br->feature_mask & ~NETIF_F_ALL_CSUM;
356 355
357 list_for_each_entry(p, &br->port_list, list) { 356 list_for_each_entry(p, &br->port_list, list) {
358 unsigned long feature = p->dev->features; 357 features = netdev_compute_features(features, p->dev->features);
359
360 /* if device needs checksumming, downgrade to hw checksumming */
361 if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
362 checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
363
364 /* if device can't do all checksum, downgrade to ipv4/ipv6 */
365 if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
366 checksum ^= NETIF_F_HW_CSUM
367 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
368
369 if (checksum & NETIF_F_IPV6_CSUM && !(feature & NETIF_F_IPV6_CSUM))
370 checksum &= ~NETIF_F_IPV6_CSUM;
371
372 if (!(feature & NETIF_F_IP_CSUM))
373 checksum = 0;
374
375 if (feature & NETIF_F_GSO)
376 feature |= NETIF_F_GSO_SOFTWARE;
377 feature |= NETIF_F_GSO;
378
379 features &= feature;
380 } 358 }
381 359
382 if (!(checksum & NETIF_F_ALL_CSUM)) 360 br->dev->features = features;
383 features &= ~NETIF_F_SG;
384 if (!(features & NETIF_F_SG))
385 features &= ~NETIF_F_GSO_MASK;
386
387 br->dev->features = features | checksum | NETIF_F_LLTX |
388 NETIF_F_GSO_ROBUST;
389} 361}
390 362
391/* called with RTNL */ 363/* called with RTNL */
diff --git a/net/core/dev.c b/net/core/dev.c
index 6cc8a70350ac..a76021c71207 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3993,6 +3993,45 @@ static int __init netdev_dma_register(void)
3993static int __init netdev_dma_register(void) { return -ENODEV; } 3993static int __init netdev_dma_register(void) { return -ENODEV; }
3994#endif /* CONFIG_NET_DMA */ 3994#endif /* CONFIG_NET_DMA */
3995 3995
3996/**
3997 * netdev_compute_feature - compute conjunction of two feature sets
3998 * @all: first feature set
3999 * @one: second feature set
4000 *
4001 * Computes a new feature set after adding a device with feature set
4002 * @one to the master device with current feature set @all. Returns
4003 * the new feature set.
4004 */
4005int netdev_compute_features(unsigned long all, unsigned long one)
4006{
4007 /* if device needs checksumming, downgrade to hw checksumming */
4008 if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM))
4009 all ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
4010
4011 /* if device can't do all checksum, downgrade to ipv4/ipv6 */
4012 if (all & NETIF_F_HW_CSUM && !(one & NETIF_F_HW_CSUM))
4013 all ^= NETIF_F_HW_CSUM
4014 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
4015
4016 if (one & NETIF_F_GSO)
4017 one |= NETIF_F_GSO_SOFTWARE;
4018 one |= NETIF_F_GSO;
4019
4020 /* If even one device supports robust GSO, enable it for all. */
4021 if (one & NETIF_F_GSO_ROBUST)
4022 all |= NETIF_F_GSO_ROBUST;
4023
4024 all &= one | NETIF_F_LLTX;
4025
4026 if (!(all & NETIF_F_ALL_CSUM))
4027 all &= ~NETIF_F_SG;
4028 if (!(all & NETIF_F_SG))
4029 all &= ~NETIF_F_GSO_MASK;
4030
4031 return all;
4032}
4033EXPORT_SYMBOL(netdev_compute_features);
4034
3996/* 4035/*
3997 * Initialize the DEV module. At boot time this walks the device list and 4036 * Initialize the DEV module. At boot time this walks the device list and
3998 * unhooks any devices that fail to initialise (normally hardware not 4037 * unhooks any devices that fail to initialise (normally hardware not