net: Fix too optimistic NETIF_F_HW_CSUM features
authorMichał Mirosław <mirq-linux@rere.qmqm.pl>
Tue, 30 Nov 2010 06:38:00 +0000 (06:38 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 6 Dec 2010 20:59:04 +0000 (12:59 -0800)
NETIF_F_HW_CSUM is a superset of NETIF_F_IP_CSUM+NETIF_F_IPV6_CSUM, but
some drivers miss the difference. Fix this and also fix UFO dependency
on checksumming offload as it makes the same mistake in assumptions.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Acked-by: Jon Mason <jon.mason@exar.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
12 files changed:
drivers/net/benet/be_main.c
drivers/net/bnx2x/bnx2x_main.c
drivers/net/jme.c
drivers/net/pch_gbe/pch_gbe_ethtool.c
drivers/net/pch_gbe/pch_gbe_main.c
drivers/net/sc92031.c
drivers/net/stmmac/stmmac_ethtool.c
drivers/net/stmmac/stmmac_main.c
drivers/net/vxge/vxge-ethtool.c
drivers/net/vxge/vxge-main.c
net/core/dev.c
net/core/ethtool.c

index 102567ee68c2e22d8efb3cb0c4deff7891056515..275428032ce269dc92f209ed517f5c3c071bc03e 100644 (file)
@@ -2583,10 +2583,12 @@ static void be_netdev_init(struct net_device *netdev)
        int i;
 
        netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
-               NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM |
+               NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
+               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                NETIF_F_GRO | NETIF_F_TSO6;
 
-       netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM;
+       netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO |
+               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 
        if (lancer_chip(adapter))
                netdev->vlan_features |= NETIF_F_TSO6;
index 1552fc3c1351d68741f40263990700b60eea9f06..0068a1dbc064e52537cc894d588b3a161d654e92 100644 (file)
@@ -8957,7 +8957,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
        dev->netdev_ops = &bnx2x_netdev_ops;
        bnx2x_set_ethtool_ops(dev);
        dev->features |= NETIF_F_SG;
-       dev->features |= NETIF_F_HW_CSUM;
+       dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
        if (bp->flags & USING_DAC_FLAG)
                dev->features |= NETIF_F_HIGHDMA;
        dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
@@ -8965,7 +8965,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
        dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
 
        dev->vlan_features |= NETIF_F_SG;
-       dev->vlan_features |= NETIF_F_HW_CSUM;
+       dev->vlan_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
        if (bp->flags & USING_DAC_FLAG)
                dev->vlan_features |= NETIF_F_HIGHDMA;
        dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
index c57d9a43cecacbf8a668a0c4b1cca5e7b93c3521..2411e72ba572d00f6a76646e0f7a34da500f7e53 100644 (file)
@@ -2076,12 +2076,11 @@ jme_change_mtu(struct net_device *netdev, int new_mtu)
        }
 
        if (new_mtu > 1900) {
-               netdev->features &= ~(NETIF_F_HW_CSUM |
-                               NETIF_F_TSO |
-                               NETIF_F_TSO6);
+               netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                               NETIF_F_TSO | NETIF_F_TSO6);
        } else {
                if (test_bit(JME_FLAG_TXCSUM, &jme->flags))
-                       netdev->features |= NETIF_F_HW_CSUM;
+                       netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
                if (test_bit(JME_FLAG_TSO, &jme->flags))
                        netdev->features |= NETIF_F_TSO | NETIF_F_TSO6;
        }
@@ -2514,10 +2513,12 @@ jme_set_tx_csum(struct net_device *netdev, u32 on)
        if (on) {
                set_bit(JME_FLAG_TXCSUM, &jme->flags);
                if (netdev->mtu <= 1900)
-                       netdev->features |= NETIF_F_HW_CSUM;
+                       netdev->features |=
+                               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
        } else {
                clear_bit(JME_FLAG_TXCSUM, &jme->flags);
-               netdev->features &= ~NETIF_F_HW_CSUM;
+               netdev->features &=
+                               ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
        }
 
        return 0;
@@ -2797,7 +2798,8 @@ jme_init_one(struct pci_dev *pdev,
        netdev->netdev_ops = &jme_netdev_ops;
        netdev->ethtool_ops             = &jme_ethtool_ops;
        netdev->watchdog_timeo          = TX_TIMEOUT;
-       netdev->features                =       NETIF_F_HW_CSUM |
+       netdev->features                =       NETIF_F_IP_CSUM |
+                                               NETIF_F_IPV6_CSUM |
                                                NETIF_F_SG |
                                                NETIF_F_TSO |
                                                NETIF_F_TSO6 |
index c8cc32c0edc9678d6174693412e977e43a4ebf29..c8c873b31a899a47ae002826efff438893646178 100644 (file)
@@ -468,18 +468,6 @@ static int pch_gbe_set_rx_csum(struct net_device *netdev, u32 data)
        return 0;
 }
 
-/**
- * pch_gbe_get_tx_csum - Report whether transmit checksums are turned on or off
- * @netdev:  Network interface device structure
- * Returns
- *     true(1):  Checksum On
- *     false(0): Checksum Off
- */
-static u32 pch_gbe_get_tx_csum(struct net_device *netdev)
-{
-       return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
 /**
  * pch_gbe_set_tx_csum - Turn transmit checksums on or off
  * @netdev: Network interface device structure
@@ -493,11 +481,7 @@ static int pch_gbe_set_tx_csum(struct net_device *netdev, u32 data)
        struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 
        adapter->tx_csum = data;
-       if (data)
-               netdev->features |= NETIF_F_HW_CSUM;
-       else
-               netdev->features &= ~NETIF_F_HW_CSUM;
-       return 0;
+       return ethtool_op_set_tx_ipv6_csum(netdev, data);
 }
 
 /**
@@ -572,7 +556,6 @@ static const struct ethtool_ops pch_gbe_ethtool_ops = {
        .set_pauseparam = pch_gbe_set_pauseparam,
        .get_rx_csum = pch_gbe_get_rx_csum,
        .set_rx_csum = pch_gbe_set_rx_csum,
-       .get_tx_csum = pch_gbe_get_tx_csum,
        .set_tx_csum = pch_gbe_set_tx_csum,
        .get_strings = pch_gbe_get_strings,
        .get_ethtool_stats = pch_gbe_get_ethtool_stats,
index afb75066b14d1cce3505963d74d4f0b26d83f8fe..58e79033a8ee88e5c7f9adc51193af828ece428f 100644 (file)
@@ -2319,7 +2319,7 @@ static int pch_gbe_probe(struct pci_dev *pdev,
        netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
        netif_napi_add(netdev, &adapter->napi,
                       pch_gbe_napi_poll, PCH_GBE_RX_WEIGHT);
-       netdev->features = NETIF_F_HW_CSUM | NETIF_F_GRO;
+       netdev->features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO;
        pch_gbe_set_ethtool_ops(netdev);
 
        pch_gbe_mac_reset_hw(&adapter->hw);
@@ -2358,9 +2358,9 @@ static int pch_gbe_probe(struct pci_dev *pdev,
        pch_gbe_check_options(adapter);
 
        if (adapter->tx_csum)
-               netdev->features |= NETIF_F_HW_CSUM;
+               netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
        else
-               netdev->features &= ~NETIF_F_HW_CSUM;
+               netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 
        /* initialize the wol settings based on the eeprom settings */
        adapter->wake_up_evt = PCH_GBE_WL_INIT_SETTING;
index 417adf372828bca69bcc3fd8c274e29fdfb6ac8b..76290a8c3c146f8eec24bd8e93cf201469c1082a 100644 (file)
@@ -1449,7 +1449,8 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
        dev->irq = pdev->irq;
 
        /* faked with skb_copy_and_csum_dev */
-       dev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
+       dev->features = NETIF_F_SG | NETIF_F_HIGHDMA |
+               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 
        dev->netdev_ops         = &sc92031_netdev_ops;
        dev->watchdog_timeo     = TX_TIMEOUT;
index f2695fd180ca08531cb857c51e91ff7ca0223237..fd719edc7f7c1842682c14e668d448af3c75361c 100644 (file)
@@ -197,16 +197,6 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
        }
 }
 
-static int stmmac_ethtool_set_tx_csum(struct net_device *netdev, u32 data)
-{
-       if (data)
-               netdev->features |= NETIF_F_HW_CSUM;
-       else
-               netdev->features &= ~NETIF_F_HW_CSUM;
-
-       return 0;
-}
-
 static u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
@@ -370,7 +360,7 @@ static struct ethtool_ops stmmac_ethtool_ops = {
        .get_link = ethtool_op_get_link,
        .get_rx_csum = stmmac_ethtool_get_rx_csum,
        .get_tx_csum = ethtool_op_get_tx_csum,
-       .set_tx_csum = stmmac_ethtool_set_tx_csum,
+       .set_tx_csum = ethtool_op_set_tx_ipv6_csum,
        .get_sg = ethtool_op_get_sg,
        .set_sg = ethtool_op_set_sg,
        .get_pauseparam = stmmac_get_pauseparam,
index 730a6fd79ee005a0f7c452653af678ff23930ac0..bfc2d1251502e273cc79a3c568b8eb1f55c5fd31 100644 (file)
@@ -1494,7 +1494,8 @@ static int stmmac_probe(struct net_device *dev)
        dev->netdev_ops = &stmmac_netdev_ops;
        stmmac_set_ethtool_ops(dev);
 
-       dev->features |= (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA);
+       dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA |
+               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
        dev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
        /* Both mac100 and gmac support receive VLAN tag detection */
@@ -1525,7 +1526,7 @@ static int stmmac_probe(struct net_device *dev)
 
        DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n",
            dev->name, (dev->features & NETIF_F_SG) ? "on" : "off",
-           (dev->features & NETIF_F_HW_CSUM) ? "on" : "off");
+           (dev->features & NETIF_F_IP_CSUM) ? "on" : "off");
 
        spin_lock_init(&priv->lock);
 
index bc9bd10357060e429146f613554923e7e3bda01c..1dd3a21b3a4365110690f2ae3953185d361baba6 100644 (file)
@@ -1177,7 +1177,7 @@ static const struct ethtool_ops vxge_ethtool_ops = {
        .get_rx_csum            = vxge_get_rx_csum,
        .set_rx_csum            = vxge_set_rx_csum,
        .get_tx_csum            = ethtool_op_get_tx_csum,
-       .set_tx_csum            = ethtool_op_set_tx_hw_csum,
+       .set_tx_csum            = ethtool_op_set_tx_ipv6_csum,
        .get_sg                 = ethtool_op_get_sg,
        .set_sg                 = ethtool_op_set_sg,
        .get_tso                = ethtool_op_get_tso,
index 8a84152e320a19f8635a99767b2f95c8ddffbe02..4877b3b8a29e9f8ba92a374266bd9d8519449c0c 100644 (file)
@@ -3368,7 +3368,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 
        ndev->features |= NETIF_F_SG;
 
-       ndev->features |= NETIF_F_HW_CSUM;
+       ndev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
        vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
                "%s : checksuming enabled", __func__);
 
index cd2437495428dd2316af7e55e4e41cfdf12b6132..55ff66fabce46270a23dcfd56cc97403c650e831 100644 (file)
@@ -5041,10 +5041,13 @@ unsigned long netdev_fix_features(unsigned long features, const char *name)
        }
 
        if (features & NETIF_F_UFO) {
-               if (!(features & NETIF_F_GEN_CSUM)) {
+               /* maybe split UFO into V4 and V6? */
+               if (!((features & NETIF_F_GEN_CSUM) ||
+                   (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
+                           == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
                        if (name)
                                printk(KERN_ERR "%s: Dropping NETIF_F_UFO "
-                                      "since no NETIF_F_HW_CSUM feature.\n",
+                                      "since no checksum offload features.\n",
                                       name);
                        features &= ~NETIF_F_UFO;
                }
index 956a9f4971cbc2e7f81c4ab5d8c8a8b909d00bf1..d5bc288188830970a4e0439f7e26b4b131082f00 100644 (file)
@@ -1171,7 +1171,9 @@ static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
                return -EFAULT;
        if (edata.data && !(dev->features & NETIF_F_SG))
                return -EINVAL;
-       if (edata.data && !(dev->features & NETIF_F_HW_CSUM))
+       if (edata.data && !((dev->features & NETIF_F_GEN_CSUM) ||
+               (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
+                       == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)))
                return -EINVAL;
        return dev->ethtool_ops->set_ufo(dev, edata.data);
 }