[PATCH] forcedeth config: csum
authorAyaz Abdulla <aabdulla@nvidia.com>
Sun, 11 Jun 2006 02:47:59 +0000 (22:47 -0400)
committerJeff Garzik <jeff@garzik.org>
Sun, 11 Jun 2006 13:25:15 +0000 (09:25 -0400)
This patch allows for configurable rx and tx checksum offloads through
ethtool support.

Signed-Off-By: Ayaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/forcedeth.c

index d9b7345..eaf6de9 100644 (file)
@@ -1707,14 +1707,16 @@ static void nv_rx_process(struct net_device *dev)
                                        }
                                }
                        }
-                       Flags &= NV_RX2_CHECKSUMMASK;
-                       if (Flags == NV_RX2_CHECKSUMOK1 ||
-                                       Flags == NV_RX2_CHECKSUMOK2 ||
-                                       Flags == NV_RX2_CHECKSUMOK3) {
-                               dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
-                               np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
-                       } else {
-                               dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name);
+                       if (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) {
+                               Flags &= NV_RX2_CHECKSUMMASK;
+                               if (Flags == NV_RX2_CHECKSUMOK1 ||
+                                   Flags == NV_RX2_CHECKSUMOK2 ||
+                                   Flags == NV_RX2_CHECKSUMOK3) {
+                                       dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
+                                       np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
+                               } else {
+                                       dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name);
+                               }
                        }
                }
                /* got a valid packet - forward it to the network core */
@@ -3021,6 +3023,67 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
        return 0;
 }
 
+static u32 nv_get_rx_csum(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       return (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) != 0;
+}
+
+static int nv_set_rx_csum(struct net_device *dev, u32 data)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       int retcode = 0;
+
+       if (np->driver_data & DEV_HAS_CHECKSUM) {
+
+               if (((np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && data) ||
+                   (!(np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && !data)) {
+                       /* already set or unset */
+                       return 0;
+               }
+
+               if (data) {
+                       np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
+               } else if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE)) {
+                       np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
+               } else {
+                       printk(KERN_INFO "Can not disable rx checksum if vlan is enabled\n");
+                       return -EINVAL;
+               }
+
+               if (netif_running(dev)) {
+                       spin_lock_irq(&np->lock);
+                       writel(np->txrxctl_bits, base + NvRegTxRxControl);
+                       spin_unlock_irq(&np->lock);
+               }
+       } else {
+               return -EINVAL;
+       }
+
+       return retcode;
+}
+
+static int nv_set_tx_csum(struct net_device *dev, u32 data)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       if (np->driver_data & DEV_HAS_CHECKSUM)
+               return ethtool_op_set_tx_hw_csum(dev, data);
+       else
+               return -EOPNOTSUPP;
+}
+
+static int nv_set_sg(struct net_device *dev, u32 data)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       if (np->driver_data & DEV_HAS_CHECKSUM)
+               return ethtool_op_set_sg(dev, data);
+       else
+               return -EOPNOTSUPP;
+}
+
 static struct ethtool_ops ops = {
        .get_drvinfo = nv_get_drvinfo,
        .get_link = ethtool_op_get_link,
@@ -3038,6 +3101,12 @@ static struct ethtool_ops ops = {
        .set_ringparam = nv_set_ringparam,
        .get_pauseparam = nv_get_pauseparam,
        .set_pauseparam = nv_set_pauseparam,
+       .get_rx_csum = nv_get_rx_csum,
+       .set_rx_csum = nv_set_rx_csum,
+       .get_tx_csum = ethtool_op_get_tx_csum,
+       .set_tx_csum = nv_set_tx_csum,
+       .get_sg = ethtool_op_get_sg,
+       .set_sg = nv_set_sg,
 };
 
 static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)