diff options
| -rw-r--r-- | drivers/net/bonding/bond_main.c | 34 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 2 | ||||
| -rw-r--r-- | net/bridge/br_device.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 36 | ||||
| -rw-r--r-- | net/core/dev.c | 39 |
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 | */ |
| 1213 | static int bond_compute_features(struct bonding *bond) | 1214 | static 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 | ||
| 1132 | extern void linkwatch_run_queue(void); | 1132 | extern void linkwatch_run_queue(void); |
| 1133 | 1133 | ||
| 1134 | extern int netdev_compute_features(unsigned long all, unsigned long one); | ||
| 1135 | |||
| 1134 | static inline int net_gso_ok(int features, int gso_type) | 1136 | static 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) | |||
| 349 | void br_features_recompute(struct net_bridge *br) | 349 | void 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) | |||
| 3993 | static int __init netdev_dma_register(void) { return -ENODEV; } | 3993 | static 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 | */ | ||
| 4005 | int 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 | } | ||
| 4033 | EXPORT_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 |
