return 0;
}
-#define BOND_INTERSECT_FEATURES \
- (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO)
+#define BOND_VLAN_FEATURES \
+ (NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX | \
+ NETIF_F_HW_VLAN_FILTER)
/*
* Compute the common dev->feature set available to all slaves. Some
- * feature bits are managed elsewhere, so preserve feature bits set on
- * master device that are not part of the examined set.
+ * feature bits are managed elsewhere, so preserve those feature bits
+ * on the master device.
*/
static int bond_compute_features(struct bonding *bond)
{
- unsigned long features = BOND_INTERSECT_FEATURES;
struct slave *slave;
struct net_device *bond_dev = bond->dev;
+ unsigned long features = bond_dev->features & ~BOND_VLAN_FEATURES;
unsigned short max_hard_header_len = ETH_HLEN;
int i;
bond_for_each_slave(bond, slave, i) {
- features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
+ features = netdev_compute_features(features,
+ slave->dev->features);
if (slave->dev->hard_header_len > max_hard_header_len)
max_hard_header_len = slave->dev->hard_header_len;
}
- if ((features & NETIF_F_SG) &&
- !(features & NETIF_F_ALL_CSUM))
- features &= ~NETIF_F_SG;
-
- /*
- * features will include NETIF_F_TSO (NETIF_F_UFO) iff all
- * slave devices support NETIF_F_TSO (NETIF_F_UFO), which
- * implies that all slaves also support scatter-gather
- * (NETIF_F_SG), which implies that features also includes
- * NETIF_F_SG. So no need to check whether we have an
- * illegal combination of NETIF_F_{TSO,UFO} and
- * !NETIF_F_SG
- */
-
- features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
+ features |= (bond_dev->features & BOND_VLAN_FEATURES);
bond_dev->features = features;
bond_dev->hard_header_len = max_hard_header_len;
extern void linkwatch_run_queue(void);
+extern int netdev_compute_features(unsigned long all, unsigned long one);
+
static inline int net_gso_ok(int features, int gso_type)
{
int feature = gso_type << NETIF_F_GSO_SHIFT;
dev->priv_flags = IFF_EBRIDGE;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
- NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
+ NETIF_F_GSO_SOFTWARE | NETIF_F_NO_CSUM |
+ NETIF_F_GSO_ROBUST | NETIF_F_LLTX;
}
void br_features_recompute(struct net_bridge *br)
{
struct net_bridge_port *p;
- unsigned long features, checksum;
+ unsigned long features;
- checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0;
- features = br->feature_mask & ~NETIF_F_ALL_CSUM;
+ features = br->feature_mask;
list_for_each_entry(p, &br->port_list, list) {
- unsigned long feature = p->dev->features;
-
- if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
- checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
- if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
- checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
- if (!(feature & NETIF_F_IP_CSUM))
- checksum = 0;
-
- if (feature & NETIF_F_GSO)
- feature |= NETIF_F_GSO_SOFTWARE;
- feature |= NETIF_F_GSO;
-
- features &= feature;
+ features = netdev_compute_features(features, p->dev->features);
}
- if (!(checksum & NETIF_F_ALL_CSUM))
- features &= ~NETIF_F_SG;
- if (!(features & NETIF_F_SG))
- features &= ~NETIF_F_GSO_MASK;
-
- br->dev->features = features | checksum | NETIF_F_LLTX |
- NETIF_F_GSO_ROBUST;
+ br->dev->features = features;
}
/* called with RTNL */
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
+ *
+ * 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.
+ */
+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 */
+ if (all & NETIF_F_HW_CSUM && !(one & NETIF_F_HW_CSUM))
+ all ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
+
+ if (one & NETIF_F_GSO)
+ one |= NETIF_F_GSO_SOFTWARE;
+ one |= NETIF_F_GSO;
+
+ /* If even one device supports robust GSO, enable it for all. */
+ if (one & NETIF_F_GSO_ROBUST)
+ all |= NETIF_F_GSO_ROBUST;
+
+ all &= one | NETIF_F_LLTX;
+
+ if (!(all & NETIF_F_ALL_CSUM))
+ all &= ~NETIF_F_SG;
+ if (!(all & NETIF_F_SG))
+ all &= ~NETIF_F_GSO_MASK;
+
+ return all;
+}
+EXPORT_SYMBOL(netdev_compute_features);
+
/*
* Initialize the DEV module. At boot time this walks the device list and
* unhooks any devices that fail to initialise (normally hardware not