Commit 79032644 authored by Michał Mirosław's avatar Michał Mirosław Committed by David S. Miller

net: Fix too optimistic NETIF_F_HW_CSUM features

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: default avatarMichał Mirosław <mirq-linux@rere.qmqm.pl>
Acked-by: default avatarJon Mason <jon.mason@exar.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 900d495a
...@@ -2583,10 +2583,12 @@ static void be_netdev_init(struct net_device *netdev) ...@@ -2583,10 +2583,12 @@ static void be_netdev_init(struct net_device *netdev)
int i; int i;
netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | 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; 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)) if (lancer_chip(adapter))
netdev->vlan_features |= NETIF_F_TSO6; netdev->vlan_features |= NETIF_F_TSO6;
......
...@@ -8957,7 +8957,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, ...@@ -8957,7 +8957,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->netdev_ops = &bnx2x_netdev_ops; dev->netdev_ops = &bnx2x_netdev_ops;
bnx2x_set_ethtool_ops(dev); bnx2x_set_ethtool_ops(dev);
dev->features |= NETIF_F_SG; 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) if (bp->flags & USING_DAC_FLAG)
dev->features |= NETIF_F_HIGHDMA; dev->features |= NETIF_F_HIGHDMA;
dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
...@@ -8965,7 +8965,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, ...@@ -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->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
dev->vlan_features |= NETIF_F_SG; 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) if (bp->flags & USING_DAC_FLAG)
dev->vlan_features |= NETIF_F_HIGHDMA; dev->vlan_features |= NETIF_F_HIGHDMA;
dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
......
...@@ -2076,12 +2076,11 @@ jme_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -2076,12 +2076,11 @@ jme_change_mtu(struct net_device *netdev, int new_mtu)
} }
if (new_mtu > 1900) { if (new_mtu > 1900) {
netdev->features &= ~(NETIF_F_HW_CSUM | netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO | NETIF_F_TSO6);
NETIF_F_TSO6);
} else { } else {
if (test_bit(JME_FLAG_TXCSUM, &jme->flags)) 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)) if (test_bit(JME_FLAG_TSO, &jme->flags))
netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; netdev->features |= NETIF_F_TSO | NETIF_F_TSO6;
} }
...@@ -2514,10 +2513,12 @@ jme_set_tx_csum(struct net_device *netdev, u32 on) ...@@ -2514,10 +2513,12 @@ jme_set_tx_csum(struct net_device *netdev, u32 on)
if (on) { if (on) {
set_bit(JME_FLAG_TXCSUM, &jme->flags); set_bit(JME_FLAG_TXCSUM, &jme->flags);
if (netdev->mtu <= 1900) if (netdev->mtu <= 1900)
netdev->features |= NETIF_F_HW_CSUM; netdev->features |=
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
} else { } else {
clear_bit(JME_FLAG_TXCSUM, &jme->flags); 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; return 0;
...@@ -2797,7 +2798,8 @@ jme_init_one(struct pci_dev *pdev, ...@@ -2797,7 +2798,8 @@ jme_init_one(struct pci_dev *pdev,
netdev->netdev_ops = &jme_netdev_ops; netdev->netdev_ops = &jme_netdev_ops;
netdev->ethtool_ops = &jme_ethtool_ops; netdev->ethtool_ops = &jme_ethtool_ops;
netdev->watchdog_timeo = TX_TIMEOUT; 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_SG |
NETIF_F_TSO | NETIF_F_TSO |
NETIF_F_TSO6 | NETIF_F_TSO6 |
......
...@@ -468,18 +468,6 @@ static int pch_gbe_set_rx_csum(struct net_device *netdev, u32 data) ...@@ -468,18 +468,6 @@ static int pch_gbe_set_rx_csum(struct net_device *netdev, u32 data)
return 0; 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 * pch_gbe_set_tx_csum - Turn transmit checksums on or off
* @netdev: Network interface device structure * @netdev: Network interface device structure
...@@ -493,11 +481,7 @@ static int pch_gbe_set_tx_csum(struct net_device *netdev, u32 data) ...@@ -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); struct pch_gbe_adapter *adapter = netdev_priv(netdev);
adapter->tx_csum = data; adapter->tx_csum = data;
if (data) return ethtool_op_set_tx_ipv6_csum(netdev, data);
netdev->features |= NETIF_F_HW_CSUM;
else
netdev->features &= ~NETIF_F_HW_CSUM;
return 0;
} }
/** /**
...@@ -572,7 +556,6 @@ static const struct ethtool_ops pch_gbe_ethtool_ops = { ...@@ -572,7 +556,6 @@ static const struct ethtool_ops pch_gbe_ethtool_ops = {
.set_pauseparam = pch_gbe_set_pauseparam, .set_pauseparam = pch_gbe_set_pauseparam,
.get_rx_csum = pch_gbe_get_rx_csum, .get_rx_csum = pch_gbe_get_rx_csum,
.set_rx_csum = pch_gbe_set_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, .set_tx_csum = pch_gbe_set_tx_csum,
.get_strings = pch_gbe_get_strings, .get_strings = pch_gbe_get_strings,
.get_ethtool_stats = pch_gbe_get_ethtool_stats, .get_ethtool_stats = pch_gbe_get_ethtool_stats,
......
...@@ -2319,7 +2319,7 @@ static int pch_gbe_probe(struct pci_dev *pdev, ...@@ -2319,7 +2319,7 @@ static int pch_gbe_probe(struct pci_dev *pdev,
netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD; netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
netif_napi_add(netdev, &adapter->napi, netif_napi_add(netdev, &adapter->napi,
pch_gbe_napi_poll, PCH_GBE_RX_WEIGHT); 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_set_ethtool_ops(netdev);
pch_gbe_mac_reset_hw(&adapter->hw); pch_gbe_mac_reset_hw(&adapter->hw);
...@@ -2358,9 +2358,9 @@ static int pch_gbe_probe(struct pci_dev *pdev, ...@@ -2358,9 +2358,9 @@ static int pch_gbe_probe(struct pci_dev *pdev,
pch_gbe_check_options(adapter); pch_gbe_check_options(adapter);
if (adapter->tx_csum) if (adapter->tx_csum)
netdev->features |= NETIF_F_HW_CSUM; netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
else 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 */ /* initialize the wol settings based on the eeprom settings */
adapter->wake_up_evt = PCH_GBE_WL_INIT_SETTING; adapter->wake_up_evt = PCH_GBE_WL_INIT_SETTING;
......
...@@ -1449,7 +1449,8 @@ static int __devinit sc92031_probe(struct pci_dev *pdev, ...@@ -1449,7 +1449,8 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
dev->irq = pdev->irq; dev->irq = pdev->irq;
/* faked with skb_copy_and_csum_dev */ /* 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->netdev_ops = &sc92031_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
......
...@@ -197,16 +197,6 @@ static void stmmac_ethtool_gregs(struct net_device *dev, ...@@ -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) static u32 stmmac_ethtool_get_rx_csum(struct net_device *dev)
{ {
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(dev);
...@@ -370,7 +360,7 @@ static struct ethtool_ops stmmac_ethtool_ops = { ...@@ -370,7 +360,7 @@ static struct ethtool_ops stmmac_ethtool_ops = {
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
.get_rx_csum = stmmac_ethtool_get_rx_csum, .get_rx_csum = stmmac_ethtool_get_rx_csum,
.get_tx_csum = ethtool_op_get_tx_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, .get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg, .set_sg = ethtool_op_set_sg,
.get_pauseparam = stmmac_get_pauseparam, .get_pauseparam = stmmac_get_pauseparam,
......
...@@ -1494,7 +1494,8 @@ static int stmmac_probe(struct net_device *dev) ...@@ -1494,7 +1494,8 @@ static int stmmac_probe(struct net_device *dev)
dev->netdev_ops = &stmmac_netdev_ops; dev->netdev_ops = &stmmac_netdev_ops;
stmmac_set_ethtool_ops(dev); 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); dev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED #ifdef STMMAC_VLAN_TAG_USED
/* Both mac100 and gmac support receive VLAN tag detection */ /* Both mac100 and gmac support receive VLAN tag detection */
...@@ -1525,7 +1526,7 @@ static int stmmac_probe(struct net_device *dev) ...@@ -1525,7 +1526,7 @@ static int stmmac_probe(struct net_device *dev)
DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n", DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n",
dev->name, (dev->features & NETIF_F_SG) ? "on" : "off", 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); spin_lock_init(&priv->lock);
......
...@@ -1177,7 +1177,7 @@ static const struct ethtool_ops vxge_ethtool_ops = { ...@@ -1177,7 +1177,7 @@ static const struct ethtool_ops vxge_ethtool_ops = {
.get_rx_csum = vxge_get_rx_csum, .get_rx_csum = vxge_get_rx_csum,
.set_rx_csum = vxge_set_rx_csum, .set_rx_csum = vxge_set_rx_csum,
.get_tx_csum = ethtool_op_get_tx_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, .get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg, .set_sg = ethtool_op_set_sg,
.get_tso = ethtool_op_get_tso, .get_tso = ethtool_op_get_tso,
......
...@@ -3368,7 +3368,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, ...@@ -3368,7 +3368,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
ndev->features |= NETIF_F_SG; 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), vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
"%s : checksuming enabled", __func__); "%s : checksuming enabled", __func__);
......
...@@ -5041,10 +5041,13 @@ unsigned long netdev_fix_features(unsigned long features, const char *name) ...@@ -5041,10 +5041,13 @@ unsigned long netdev_fix_features(unsigned long features, const char *name)
} }
if (features & NETIF_F_UFO) { 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) if (name)
printk(KERN_ERR "%s: Dropping NETIF_F_UFO " printk(KERN_ERR "%s: Dropping NETIF_F_UFO "
"since no NETIF_F_HW_CSUM feature.\n", "since no checksum offload features.\n",
name); name);
features &= ~NETIF_F_UFO; features &= ~NETIF_F_UFO;
} }
......
...@@ -1171,7 +1171,9 @@ static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) ...@@ -1171,7 +1171,9 @@ static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
return -EFAULT; return -EFAULT;
if (edata.data && !(dev->features & NETIF_F_SG)) if (edata.data && !(dev->features & NETIF_F_SG))
return -EINVAL; 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 -EINVAL;
return dev->ethtool_ops->set_ufo(dev, edata.data); return dev->ethtool_ops->set_ufo(dev, edata.data);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment