|
@@ -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
|
|
@@ -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)
|
|
@@ -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)
|
|
|
{
|