From 7903264402546f45f9bac8ad2bfdb00d00eb124a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Tue, 30 Nov 2010 06:38:00 +0000 Subject: [PATCH] net: Fix too optimistic NETIF_F_HW_CSUM features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Jon Mason Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 6 ++++-- drivers/net/bnx2x/bnx2x_main.c | 4 ++-- drivers/net/jme.c | 16 +++++++++------- drivers/net/pch_gbe/pch_gbe_ethtool.c | 19 +------------------ drivers/net/pch_gbe/pch_gbe_main.c | 6 +++--- drivers/net/sc92031.c | 3 ++- drivers/net/stmmac/stmmac_ethtool.c | 12 +----------- drivers/net/stmmac/stmmac_main.c | 5 +++-- drivers/net/vxge/vxge-ethtool.c | 2 +- drivers/net/vxge/vxge-main.c | 2 +- net/core/dev.c | 7 +++++-- net/core/ethtool.c | 4 +++- 12 files changed, 35 insertions(+), 51 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 102567ee68c2..275428032ce2 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -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; diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 1552fc3c1351..0068a1dbc064 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -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); diff --git a/drivers/net/jme.c b/drivers/net/jme.c index c57d9a43ceca..2411e72ba572 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -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 | diff --git a/drivers/net/pch_gbe/pch_gbe_ethtool.c b/drivers/net/pch_gbe/pch_gbe_ethtool.c index c8cc32c0edc9..c8c873b31a89 100644 --- a/drivers/net/pch_gbe/pch_gbe_ethtool.c +++ b/drivers/net/pch_gbe/pch_gbe_ethtool.c @@ -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, diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index afb75066b14d..58e79033a8ee 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -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; diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 417adf372828..76290a8c3c14 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -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; diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index f2695fd180ca..fd719edc7f7c 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -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, diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 730a6fd79ee0..bfc2d1251502 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -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); diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index bc9bd1035706..1dd3a21b3a43 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c @@ -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, diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index 8a84152e320a..4877b3b8a29e 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -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__); diff --git a/net/core/dev.c b/net/core/dev.c index cd2437495428..55ff66fabce4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -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; } diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 956a9f4971cb..d5bc28818883 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -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); }