diff options
| -rw-r--r-- | drivers/net/bonding/bond_main.c | 16 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 12 | ||||
| -rw-r--r-- | net/bridge/br_device.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 14 | ||||
| -rw-r--r-- | net/core/dev.c | 135 |
5 files changed, 104 insertions, 75 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 8e2be24f3fe4..832739f38db4 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -1341,18 +1341,24 @@ static int bond_compute_features(struct bonding *bond) | |||
| 1341 | int i; | 1341 | int i; |
| 1342 | 1342 | ||
| 1343 | features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); | 1343 | features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES); |
| 1344 | features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | | 1344 | features |= NETIF_F_GSO_MASK | NETIF_F_NO_CSUM; |
| 1345 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM; | 1345 | |
| 1346 | if (!bond->first_slave) | ||
| 1347 | goto done; | ||
| 1348 | |||
| 1349 | features &= ~NETIF_F_ONE_FOR_ALL; | ||
| 1346 | 1350 | ||
| 1347 | bond_for_each_slave(bond, slave, i) { | 1351 | bond_for_each_slave(bond, slave, i) { |
| 1348 | features = netdev_compute_features(features, | 1352 | features = netdev_increment_features(features, |
| 1349 | slave->dev->features); | 1353 | slave->dev->features, |
| 1354 | NETIF_F_ONE_FOR_ALL); | ||
| 1350 | if (slave->dev->hard_header_len > max_hard_header_len) | 1355 | if (slave->dev->hard_header_len > max_hard_header_len) |
| 1351 | max_hard_header_len = slave->dev->hard_header_len; | 1356 | max_hard_header_len = slave->dev->hard_header_len; |
| 1352 | } | 1357 | } |
| 1353 | 1358 | ||
| 1359 | done: | ||
| 1354 | features |= (bond_dev->features & BOND_VLAN_FEATURES); | 1360 | features |= (bond_dev->features & BOND_VLAN_FEATURES); |
| 1355 | bond_dev->features = features; | 1361 | bond_dev->features = netdev_fix_features(features, NULL); |
| 1356 | bond_dev->hard_header_len = max_hard_header_len; | 1362 | bond_dev->hard_header_len = max_hard_header_len; |
| 1357 | 1363 | ||
| 1358 | return 0; | 1364 | return 0; |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 64875859d654..c8bcb59adfdf 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -541,6 +541,14 @@ struct net_device | |||
| 541 | #define NETIF_F_V6_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM) | 541 | #define NETIF_F_V6_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM) |
| 542 | #define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM) | 542 | #define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM) |
| 543 | 543 | ||
| 544 | /* | ||
| 545 | * If one device supports one of these features, then enable them | ||
| 546 | * for all in netdev_increment_features. | ||
| 547 | */ | ||
| 548 | #define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \ | ||
| 549 | NETIF_F_SG | NETIF_F_HIGHDMA | \ | ||
| 550 | NETIF_F_FRAGLIST) | ||
| 551 | |||
| 544 | /* Interface index. Unique device identifier */ | 552 | /* Interface index. Unique device identifier */ |
| 545 | int ifindex; | 553 | int ifindex; |
| 546 | int iflink; | 554 | int iflink; |
| @@ -1698,7 +1706,9 @@ extern char *netdev_drivername(const struct net_device *dev, char *buffer, int l | |||
| 1698 | 1706 | ||
| 1699 | extern void linkwatch_run_queue(void); | 1707 | extern void linkwatch_run_queue(void); |
| 1700 | 1708 | ||
| 1701 | extern int netdev_compute_features(unsigned long all, unsigned long one); | 1709 | unsigned long netdev_increment_features(unsigned long all, unsigned long one, |
| 1710 | unsigned long mask); | ||
| 1711 | unsigned long netdev_fix_features(unsigned long features, const char *name); | ||
| 1702 | 1712 | ||
| 1703 | static inline int net_gso_ok(int features, int gso_type) | 1713 | static inline int net_gso_ok(int features, int gso_type) |
| 1704 | { | 1714 | { |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 22ba8632196f..6c023f0f8252 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 | 179 | ||
| 180 | dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | | 180 | dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | |
| 181 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | | 181 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | |
| 182 | NETIF_F_NETNS_LOCAL; | 182 | NETIF_F_NETNS_LOCAL | NETIF_F_GSO; |
| 183 | } | 183 | } |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 573e20f7dba4..0a09ccf68c1c 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -347,15 +347,21 @@ int br_min_mtu(const struct net_bridge *br) | |||
| 347 | void br_features_recompute(struct net_bridge *br) | 347 | void br_features_recompute(struct net_bridge *br) |
| 348 | { | 348 | { |
| 349 | struct net_bridge_port *p; | 349 | struct net_bridge_port *p; |
| 350 | unsigned long features; | 350 | unsigned long features, mask; |
| 351 | 351 | ||
| 352 | features = br->feature_mask; | 352 | features = mask = br->feature_mask; |
| 353 | if (list_empty(&br->port_list)) | ||
| 354 | goto done; | ||
| 355 | |||
| 356 | features &= ~NETIF_F_ONE_FOR_ALL; | ||
| 353 | 357 | ||
| 354 | list_for_each_entry(p, &br->port_list, list) { | 358 | list_for_each_entry(p, &br->port_list, list) { |
| 355 | features = netdev_compute_features(features, p->dev->features); | 359 | features = netdev_increment_features(features, |
| 360 | p->dev->features, mask); | ||
| 356 | } | 361 | } |
| 357 | 362 | ||
| 358 | br->dev->features = features; | 363 | done: |
| 364 | br->dev->features = netdev_fix_features(features, NULL); | ||
| 359 | } | 365 | } |
| 360 | 366 | ||
| 361 | /* called with RTNL */ | 367 | /* called with RTNL */ |
diff --git a/net/core/dev.c b/net/core/dev.c index b8a4fd0806af..d9038e328cc1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -3947,6 +3947,46 @@ static void netdev_init_queue_locks(struct net_device *dev) | |||
| 3947 | __netdev_init_queue_locks_one(dev, &dev->rx_queue, NULL); | 3947 | __netdev_init_queue_locks_one(dev, &dev->rx_queue, NULL); |
| 3948 | } | 3948 | } |
| 3949 | 3949 | ||
| 3950 | unsigned long netdev_fix_features(unsigned long features, const char *name) | ||
| 3951 | { | ||
| 3952 | /* Fix illegal SG+CSUM combinations. */ | ||
| 3953 | if ((features & NETIF_F_SG) && | ||
| 3954 | !(features & NETIF_F_ALL_CSUM)) { | ||
| 3955 | if (name) | ||
| 3956 | printk(KERN_NOTICE "%s: Dropping NETIF_F_SG since no " | ||
| 3957 | "checksum feature.\n", name); | ||
| 3958 | features &= ~NETIF_F_SG; | ||
| 3959 | } | ||
| 3960 | |||
| 3961 | /* TSO requires that SG is present as well. */ | ||
| 3962 | if ((features & NETIF_F_TSO) && !(features & NETIF_F_SG)) { | ||
| 3963 | if (name) | ||
| 3964 | printk(KERN_NOTICE "%s: Dropping NETIF_F_TSO since no " | ||
| 3965 | "SG feature.\n", name); | ||
| 3966 | features &= ~NETIF_F_TSO; | ||
| 3967 | } | ||
| 3968 | |||
| 3969 | if (features & NETIF_F_UFO) { | ||
| 3970 | if (!(features & NETIF_F_GEN_CSUM)) { | ||
| 3971 | if (name) | ||
| 3972 | printk(KERN_ERR "%s: Dropping NETIF_F_UFO " | ||
| 3973 | "since no NETIF_F_HW_CSUM feature.\n", | ||
| 3974 | name); | ||
| 3975 | features &= ~NETIF_F_UFO; | ||
| 3976 | } | ||
| 3977 | |||
| 3978 | if (!(features & NETIF_F_SG)) { | ||
| 3979 | if (name) | ||
| 3980 | printk(KERN_ERR "%s: Dropping NETIF_F_UFO " | ||
| 3981 | "since no NETIF_F_SG feature.\n", name); | ||
| 3982 | features &= ~NETIF_F_UFO; | ||
| 3983 | } | ||
| 3984 | } | ||
| 3985 | |||
| 3986 | return features; | ||
| 3987 | } | ||
| 3988 | EXPORT_SYMBOL(netdev_fix_features); | ||
| 3989 | |||
| 3950 | /** | 3990 | /** |
| 3951 | * register_netdevice - register a network device | 3991 | * register_netdevice - register a network device |
| 3952 | * @dev: device to register | 3992 | * @dev: device to register |
| @@ -4032,36 +4072,7 @@ int register_netdevice(struct net_device *dev) | |||
| 4032 | dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); | 4072 | dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); |
| 4033 | } | 4073 | } |
| 4034 | 4074 | ||
| 4035 | 4075 | dev->features = netdev_fix_features(dev->features, dev->name); | |
| 4036 | /* Fix illegal SG+CSUM combinations. */ | ||
| 4037 | if ((dev->features & NETIF_F_SG) && | ||
| 4038 | !(dev->features & NETIF_F_ALL_CSUM)) { | ||
| 4039 | printk(KERN_NOTICE "%s: Dropping NETIF_F_SG since no checksum feature.\n", | ||
| 4040 | dev->name); | ||
| 4041 | dev->features &= ~NETIF_F_SG; | ||
| 4042 | } | ||
| 4043 | |||
| 4044 | /* TSO requires that SG is present as well. */ | ||
| 4045 | if ((dev->features & NETIF_F_TSO) && | ||
| 4046 | !(dev->features & NETIF_F_SG)) { | ||
| 4047 | printk(KERN_NOTICE "%s: Dropping NETIF_F_TSO since no SG feature.\n", | ||
| 4048 | dev->name); | ||
| 4049 | dev->features &= ~NETIF_F_TSO; | ||
| 4050 | } | ||
| 4051 | if (dev->features & NETIF_F_UFO) { | ||
| 4052 | if (!(dev->features & NETIF_F_HW_CSUM)) { | ||
| 4053 | printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no " | ||
| 4054 | "NETIF_F_HW_CSUM feature.\n", | ||
| 4055 | dev->name); | ||
| 4056 | dev->features &= ~NETIF_F_UFO; | ||
| 4057 | } | ||
| 4058 | if (!(dev->features & NETIF_F_SG)) { | ||
| 4059 | printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no " | ||
| 4060 | |||
