aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/forcedeth.c85
1 files changed, 77 insertions, 8 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index d9b7345198c..eaf6de9a9df 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -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)