aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ibmveth.c
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2007-08-17 10:16:31 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:50:43 -0400
commit5fc7e01cb77132f96e171a37f9f792270b1603f6 (patch)
tree44c4e1926a803ef1e53f5a1985f976ba6dd35171 /drivers/net/ibmveth.c
parentf4ff28720f45354573dcf4e0eb5a2dc5452cb3e1 (diff)
ibmveth: Implement ethtool hooks to enable/disable checksum offload
This patch adds the appropriate ethtool hooks to allow for enabling/disabling of hypervisor assisted checksum offload for TCP. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/ibmveth.c')
-rw-r--r--drivers/net/ibmveth.c125
1 files changed, 123 insertions, 2 deletions
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 9353890dcda0..9c16928e20ed 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -652,12 +652,132 @@ static u32 netdev_get_link(struct net_device *dev) {
652 return 1; 652 return 1;
653} 653}
654 654
655static void ibmveth_set_rx_csum_flags(struct net_device *dev, u32 data)
656{
657 struct ibmveth_adapter *adapter = dev->priv;
658
659 if (data)
660 adapter->rx_csum = 1;
661 else {
662 /*
663 * Since the ibmveth firmware interface does not have the concept of
664 * separate tx/rx checksum offload enable, if rx checksum is disabled
665 * we also have to disable tx checksum offload. Once we disable rx
666 * checksum offload, we are no longer allowed to send tx buffers that
667 * are not properly checksummed.
668 */
669 adapter->rx_csum = 0;
670 dev->features &= ~NETIF_F_IP_CSUM;
671 }
672}
673
674static void ibmveth_set_tx_csum_flags(struct net_device *dev, u32 data)
675{
676 struct ibmveth_adapter *adapter = dev->priv;
677
678 if (data) {
679 dev->features |= NETIF_F_IP_CSUM;
680 adapter->rx_csum = 1;
681 } else
682 dev->features &= ~NETIF_F_IP_CSUM;
683}
684
685static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
686 void (*done) (struct net_device *, u32))
687{
688 struct ibmveth_adapter *adapter = dev->priv;
689 union ibmveth_illan_attributes set_attr, clr_attr, ret_attr;
690 long ret;
691 int rc1 = 0, rc2 = 0;
692 int restart = 0;
693
694 if (netif_running(dev)) {
695 restart = 1;
696 adapter->pool_config = 1;
697 ibmveth_close(dev);
698 adapter->pool_config = 0;
699 }
700
701 set_attr.desc = 0;
702 clr_attr.desc = 0;
703
704 if (data)
705 set_attr.fields.tcp_csum_offload_ipv4 = 1;
706 else
707 clr_attr.fields.tcp_csum_offload_ipv4 = 1;
708
709 ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr.desc);
710
711 if (ret == H_SUCCESS && !ret_attr.fields.active_trunk &&
712 !ret_attr.fields.trunk_priority &&
713 ret_attr.fields.csum_offload_padded_pkt_support) {
714 ret = h_illan_attributes(adapter->vdev->unit_address, clr_attr.desc,
715 set_attr.desc, &ret_attr.desc);
716
717 if (ret != H_SUCCESS) {
718 rc1 = -EIO;
719 ibmveth_error_printk("unable to change checksum offload settings."
720 " %d rc=%ld\n", data, ret);
721
722 ret = h_illan_attributes(adapter->vdev->unit_address,
723 set_attr.desc, clr_attr.desc, &ret_attr.desc);
724 } else
725 done(dev, data);
726 } else {
727 rc1 = -EIO;
728 ibmveth_error_printk("unable to change checksum offload settings."
729 " %d rc=%ld ret_attr=%lx\n", data, ret, ret_attr.desc);
730 }
731
732 if (restart)
733 rc2 = ibmveth_open(dev);
734
735 return rc1 ? rc1 : rc2;
736}
737
738static int ibmveth_set_rx_csum(struct net_device *dev, u32 data)
739{
740 struct ibmveth_adapter *adapter = dev->priv;
741
742 if ((data && adapter->rx_csum) || (!data && !adapter->rx_csum))
743 return 0;
744
745 return ibmveth_set_csum_offload(dev, data, ibmveth_set_rx_csum_flags);
746}
747
748static int ibmveth_set_tx_csum(struct net_device *dev, u32 data)
749{
750 struct ibmveth_adapter *adapter = dev->priv;
751 int rc = 0;
752
753 if (data && (dev->features & NETIF_F_IP_CSUM))
754 return 0;
755 if (!data && !(dev->features & NETIF_F_IP_CSUM))
756 return 0;
757
758 if (data && !adapter->rx_csum)
759 rc = ibmveth_set_csum_offload(dev, data, ibmveth_set_tx_csum_flags);
760 else
761 ibmveth_set_tx_csum_flags(dev, data);
762
763 return rc;
764}
765
766static u32 ibmveth_get_rx_csum(struct net_device *dev)
767{
768 struct ibmveth_adapter *adapter = dev->priv;
769 return adapter->rx_csum;
770}
771
655static const struct ethtool_ops netdev_ethtool_ops = { 772static const struct ethtool_ops netdev_ethtool_ops = {
656 .get_drvinfo = netdev_get_drvinfo, 773 .get_drvinfo = netdev_get_drvinfo,
657 .get_settings = netdev_get_settings, 774 .get_settings = netdev_get_settings,
658 .get_link = netdev_get_link, 775 .get_link = netdev_get_link,
659 .get_sg = ethtool_op_get_sg, 776 .get_sg = ethtool_op_get_sg,
660 .get_tx_csum = ethtool_op_get_tx_csum, 777 .get_tx_csum = ethtool_op_get_tx_csum,
778 .set_tx_csum = ibmveth_set_tx_csum,
779 .get_rx_csum = ibmveth_get_rx_csum,
780 .set_rx_csum = ibmveth_set_rx_csum,
661}; 781};
662 782
663static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 783static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1103,9 +1223,10 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
1103 ret = h_illan_attributes(dev->unit_address, 0, set_attr.desc, 1223 ret = h_illan_attributes(dev->unit_address, 0, set_attr.desc,
1104 &ret_attr.desc); 1224 &ret_attr.desc);
1105 1225
1106 if (ret == H_SUCCESS) 1226 if (ret == H_SUCCESS) {
1227 adapter->rx_csum = 1;
1107 netdev->features |= NETIF_F_IP_CSUM; 1228 netdev->features |= NETIF_F_IP_CSUM;
1108 else 1229 } else
1109 ret = h_illan_attributes(dev->unit_address, set_attr.desc, 1230 ret = h_illan_attributes(dev->unit_address, set_attr.desc,
1110 0, &ret_attr.desc); 1231 0, &ret_attr.desc);
1111 } 1232 }