Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 117799
b: refs/heads/master
c: b63365a
h: refs/heads/master
i:
  117797: 5af1a45
  117795: 598ab92
  117791: 1b5bf9f
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Oct 23, 2008
1 parent 821eb70 commit 0938333
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 76 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2e3f92dad6bdbee796274bae5c1c50a6ddd31cbb
refs/heads/master: b63365a2d60268a3988285d6c3c6003d7066f93a
16 changes: 11 additions & 5 deletions trunk/drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1341,18 +1341,24 @@ static int bond_compute_features(struct bonding *bond)
int i;

features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES);
features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
NETIF_F_GSO_MASK | NETIF_F_NO_CSUM;
features |= NETIF_F_GSO_MASK | NETIF_F_NO_CSUM;

if (!bond->first_slave)
goto done;

features &= ~NETIF_F_ONE_FOR_ALL;

bond_for_each_slave(bond, slave, i) {
features = netdev_compute_features(features,
slave->dev->features);
features = netdev_increment_features(features,
slave->dev->features,
NETIF_F_ONE_FOR_ALL);
if (slave->dev->hard_header_len > max_hard_header_len)
max_hard_header_len = slave->dev->hard_header_len;
}

done:
features |= (bond_dev->features & BOND_VLAN_FEATURES);
bond_dev->features = features;
bond_dev->features = netdev_fix_features(features, NULL);
bond_dev->hard_header_len = max_hard_header_len;

return 0;
Expand Down
12 changes: 11 additions & 1 deletion trunk/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,14 @@ struct net_device
#define NETIF_F_V6_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
#define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)

/*
* If one device supports one of these features, then enable them
* for all in netdev_increment_features.
*/
#define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
NETIF_F_SG | NETIF_F_HIGHDMA | \
NETIF_F_FRAGLIST)

/* Interface index. Unique device identifier */
int ifindex;
int iflink;
Expand Down Expand Up @@ -1698,7 +1706,9 @@ extern char *netdev_drivername(const struct net_device *dev, char *buffer, int l

extern void linkwatch_run_queue(void);

extern int netdev_compute_features(unsigned long all, unsigned long one);
unsigned long netdev_increment_features(unsigned long all, unsigned long one,
unsigned long mask);
unsigned long netdev_fix_features(unsigned long features, const char *name);

static inline int net_gso_ok(int features, int gso_type)
{
Expand Down
2 changes: 1 addition & 1 deletion trunk/net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,5 @@ void br_dev_setup(struct net_device *dev)

dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX |
NETIF_F_NETNS_LOCAL;
NETIF_F_NETNS_LOCAL | NETIF_F_GSO;
}
14 changes: 10 additions & 4 deletions trunk/net/bridge/br_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,15 +347,21 @@ int br_min_mtu(const struct net_bridge *br)
void br_features_recompute(struct net_bridge *br)
{
struct net_bridge_port *p;
unsigned long features;
unsigned long features, mask;

features = br->feature_mask;
features = mask = br->feature_mask;
if (list_empty(&br->port_list))
goto done;

features &= ~NETIF_F_ONE_FOR_ALL;

list_for_each_entry(p, &br->port_list, list) {
features = netdev_compute_features(features, p->dev->features);
features = netdev_increment_features(features,
p->dev->features, mask);
}

br->dev->features = features;
done:
br->dev->features = netdev_fix_features(features, NULL);
}

/* called with RTNL */
Expand Down
135 changes: 71 additions & 64 deletions trunk/net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3947,6 +3947,46 @@ static void netdev_init_queue_locks(struct net_device *dev)
__netdev_init_queue_locks_one(dev, &dev->rx_queue, NULL);
}

unsigned long netdev_fix_features(unsigned long features, const char *name)
{
/* Fix illegal SG+CSUM combinations. */
if ((features & NETIF_F_SG) &&
!(features & NETIF_F_ALL_CSUM)) {
if (name)
printk(KERN_NOTICE "%s: Dropping NETIF_F_SG since no "
"checksum feature.\n", name);
features &= ~NETIF_F_SG;
}

/* TSO requires that SG is present as well. */
if ((features & NETIF_F_TSO) && !(features & NETIF_F_SG)) {
if (name)
printk(KERN_NOTICE "%s: Dropping NETIF_F_TSO since no "
"SG feature.\n", name);
features &= ~NETIF_F_TSO;
}

if (features & NETIF_F_UFO) {
if (!(features & NETIF_F_GEN_CSUM)) {
if (name)
printk(KERN_ERR "%s: Dropping NETIF_F_UFO "
"since no NETIF_F_HW_CSUM feature.\n",
name);
features &= ~NETIF_F_UFO;
}

if (!(features & NETIF_F_SG)) {
if (name)
printk(KERN_ERR "%s: Dropping NETIF_F_UFO "
"since no NETIF_F_SG feature.\n", name);
features &= ~NETIF_F_UFO;
}
}

return features;
}
EXPORT_SYMBOL(netdev_fix_features);

/**
* register_netdevice - register a network device
* @dev: device to register
Expand Down Expand Up @@ -4032,36 +4072,7 @@ int register_netdevice(struct net_device *dev)
dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
}


/* Fix illegal SG+CSUM combinations. */
if ((dev->features & NETIF_F_SG) &&
!(dev->features & NETIF_F_ALL_CSUM)) {
printk(KERN_NOTICE "%s: Dropping NETIF_F_SG since no checksum feature.\n",
dev->name);
dev->features &= ~NETIF_F_SG;
}

/* TSO requires that SG is present as well. */
if ((dev->features & NETIF_F_TSO) &&
!(dev->features & NETIF_F_SG)) {
printk(KERN_NOTICE "%s: Dropping NETIF_F_TSO since no SG feature.\n",
dev->name);
dev->features &= ~NETIF_F_TSO;
}
if (dev->features & NETIF_F_UFO) {
if (!(dev->features & NETIF_F_HW_CSUM)) {
printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
"NETIF_F_HW_CSUM feature.\n",
dev->name);
dev->features &= ~NETIF_F_UFO;
}
if (!(dev->features & NETIF_F_SG)) {
printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
"NETIF_F_SG feature.\n",
dev->name);
dev->features &= ~NETIF_F_UFO;
}
}
dev->features = netdev_fix_features(dev->features, dev->name);

/* Enable software GSO if SG is supported. */
if (dev->features & NETIF_F_SG)
Expand Down Expand Up @@ -4700,49 +4711,45 @@ static int __init netdev_dma_register(void) { return -ENODEV; }
#endif /* CONFIG_NET_DMA */

/**
* netdev_compute_feature - compute conjunction of two feature sets
* @all: first feature set
* @one: second feature set
* netdev_increment_features - increment feature set by one
* @all: current feature set
* @one: new feature set
* @mask: mask feature set
*
* Computes a new feature set after adding a device with feature set
* @one to the master device with current feature set @all. Returns
* the new feature set.
* @one to the master device with current feature set @all. Will not
* enable anything that is off in @mask. Returns the new feature set.
*/
int netdev_compute_features(unsigned long all, unsigned long one)
{
/* if device needs checksumming, downgrade to hw checksumming */
if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM))
all ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;

/* if device can't do all checksum, downgrade to ipv4/ipv6 */
if (all & NETIF_F_HW_CSUM && !(one & NETIF_F_HW_CSUM))
all ^= NETIF_F_HW_CSUM
| NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;

if (one & NETIF_F_GSO)
one |= NETIF_F_GSO_SOFTWARE;
one |= NETIF_F_GSO;

/*
* If even one device supports a GSO protocol with software fallback,
* enable it for all.
*/
all |= one & NETIF_F_GSO_SOFTWARE;
unsigned long netdev_increment_features(unsigned long all, unsigned long one,
unsigned long mask)
{
/* If device needs checksumming, downgrade to it. */
if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM))
all ^= NETIF_F_NO_CSUM | (one & NETIF_F_ALL_CSUM);
else if (mask & NETIF_F_ALL_CSUM) {
/* If one device supports v4/v6 checksumming, set for all. */
if (one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) &&
!(all & NETIF_F_GEN_CSUM)) {
all &= ~NETIF_F_ALL_CSUM;
all |= one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
}

/* If even one device supports robust GSO, enable it for all. */
if (one & NETIF_F_GSO_ROBUST)
all |= NETIF_F_GSO_ROBUST;
/* If one device supports hw checksumming, set for all. */
if (one & NETIF_F_GEN_CSUM && !(all & NETIF_F_GEN_CSUM)) {
all &= ~NETIF_F_ALL_CSUM;
all |= NETIF_F_HW_CSUM;
}
}

all &= one | NETIF_F_LLTX;
one |= NETIF_F_ALL_CSUM;

if (!(all & NETIF_F_ALL_CSUM))
all &= ~NETIF_F_SG;
if (!(all & NETIF_F_SG))
all &= ~NETIF_F_GSO_MASK;
one |= all & NETIF_F_ONE_FOR_ALL;
all &= one | NETIF_F_LLTX | NETIF_F_GSO;
all |= one & mask & NETIF_F_ONE_FOR_ALL;

return all;
}
EXPORT_SYMBOL(netdev_compute_features);
EXPORT_SYMBOL(netdev_increment_features);

static struct hlist_head *netdev_create_hash(void)
{
Expand Down

0 comments on commit 0938333

Please sign in to comment.