aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ibmveth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ibmveth.c')
-rw-r--r--drivers/net/ibmveth.c59
1 files changed, 48 insertions, 11 deletions
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index ab80d8fcccbf..25cf7e0476d0 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -50,6 +50,7 @@
50#include <linux/proc_fs.h> 50#include <linux/proc_fs.h>
51#include <linux/in.h> 51#include <linux/in.h>
52#include <linux/ip.h> 52#include <linux/ip.h>
53#include <linux/ipv6.h>
53#include <linux/slab.h> 54#include <linux/slab.h>
54#include <net/net_namespace.h> 55#include <net/net_namespace.h>
55#include <asm/hvcall.h> 56#include <asm/hvcall.h>
@@ -148,6 +149,8 @@ struct ibmveth_stat ibmveth_stats[] = {
148 { "rx_no_buffer", IBMVETH_STAT_OFF(rx_no_buffer) }, 149 { "rx_no_buffer", IBMVETH_STAT_OFF(rx_no_buffer) },
149 { "tx_map_failed", IBMVETH_STAT_OFF(tx_map_failed) }, 150 { "tx_map_failed", IBMVETH_STAT_OFF(tx_map_failed) },
150 { "tx_send_failed", IBMVETH_STAT_OFF(tx_send_failed) }, 151 { "tx_send_failed", IBMVETH_STAT_OFF(tx_send_failed) },
152 { "fw_enabled_ipv4_csum", IBMVETH_STAT_OFF(fw_ipv4_csum_support) },
153 { "fw_enabled_ipv6_csum", IBMVETH_STAT_OFF(fw_ipv6_csum_support) },
151}; 154};
152 155
153/* simple methods of getting data from the current rxq entry */ 156/* simple methods of getting data from the current rxq entry */
@@ -773,6 +776,7 @@ static void ibmveth_set_rx_csum_flags(struct net_device *dev, u32 data)
773 */ 776 */
774 adapter->rx_csum = 0; 777 adapter->rx_csum = 0;
775 dev->features &= ~NETIF_F_IP_CSUM; 778 dev->features &= ~NETIF_F_IP_CSUM;
779 dev->features &= ~NETIF_F_IPV6_CSUM;
776 } 780 }
777} 781}
778 782
@@ -781,10 +785,15 @@ static void ibmveth_set_tx_csum_flags(struct net_device *dev, u32 data)
781 struct ibmveth_adapter *adapter = netdev_priv(dev); 785 struct ibmveth_adapter *adapter = netdev_priv(dev);
782 786
783 if (data) { 787 if (data) {
784 dev->features |= NETIF_F_IP_CSUM; 788 if (adapter->fw_ipv4_csum_support)
789 dev->features |= NETIF_F_IP_CSUM;
790 if (adapter->fw_ipv6_csum_support)
791 dev->features |= NETIF_F_IPV6_CSUM;
785 adapter->rx_csum = 1; 792 adapter->rx_csum = 1;
786 } else 793 } else {
787 dev->features &= ~NETIF_F_IP_CSUM; 794 dev->features &= ~NETIF_F_IP_CSUM;
795 dev->features &= ~NETIF_F_IPV6_CSUM;
796 }
788} 797}
789 798
790static int ibmveth_set_csum_offload(struct net_device *dev, u32 data, 799static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
@@ -792,7 +801,8 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
792{ 801{
793 struct ibmveth_adapter *adapter = netdev_priv(dev); 802 struct ibmveth_adapter *adapter = netdev_priv(dev);
794 unsigned long set_attr, clr_attr, ret_attr; 803 unsigned long set_attr, clr_attr, ret_attr;
795 long ret; 804 unsigned long set_attr6, clr_attr6;
805 long ret, ret6;
796 int rc1 = 0, rc2 = 0; 806 int rc1 = 0, rc2 = 0;
797 int restart = 0; 807 int restart = 0;
798 808
@@ -806,10 +816,13 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
806 set_attr = 0; 816 set_attr = 0;
807 clr_attr = 0; 817 clr_attr = 0;
808 818
809 if (data) 819 if (data) {
810 set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM; 820 set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
811 else 821 set_attr6 = IBMVETH_ILLAN_IPV6_TCP_CSUM;
822 } else {
812 clr_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM; 823 clr_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
824 clr_attr6 = IBMVETH_ILLAN_IPV6_TCP_CSUM;
825 }
813 826
814 ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr); 827 ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr);
815 828
@@ -820,14 +833,33 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
820 set_attr, &ret_attr); 833 set_attr, &ret_attr);
821 834
822 if (ret != H_SUCCESS) { 835 if (ret != H_SUCCESS) {
823 rc1 = -EIO; 836 ibmveth_error_printk("unable to change IPv4 checksum "
824 ibmveth_error_printk("unable to change checksum offload settings." 837 "offload settings. %d rc=%ld\n",
825 " %d rc=%ld\n", data, ret); 838 data, ret);
826 839
827 ret = h_illan_attributes(adapter->vdev->unit_address, 840 ret = h_illan_attributes(adapter->vdev->unit_address,
828 set_attr, clr_attr, &ret_attr); 841 set_attr, clr_attr, &ret_attr);
829 } else 842 } else
843 adapter->fw_ipv4_csum_support = data;
844
845 ret6 = h_illan_attributes(adapter->vdev->unit_address,
846 clr_attr6, set_attr6, &ret_attr);
847
848 if (ret6 != H_SUCCESS) {
849 ibmveth_error_printk("unable to change IPv6 checksum "
850 "offload settings. %d rc=%ld\n",
851 data, ret);
852
853 ret = h_illan_attributes(adapter->vdev->unit_address,
854 set_attr6, clr_attr6,
855 &ret_attr);
856 } else
857 adapter->fw_ipv6_csum_support = data;
858
859 if (ret == H_SUCCESS || ret6 == H_SUCCESS)
830 done(dev, data); 860 done(dev, data);
861 else
862 rc1 = -EIO;
831 } else { 863 } else {
832 rc1 = -EIO; 864 rc1 = -EIO;
833 ibmveth_error_printk("unable to change checksum offload settings." 865 ibmveth_error_printk("unable to change checksum offload settings."
@@ -855,9 +887,9 @@ static int ibmveth_set_tx_csum(struct net_device *dev, u32 data)
855 struct ibmveth_adapter *adapter = netdev_priv(dev); 887 struct ibmveth_adapter *adapter = netdev_priv(dev);
856 int rc = 0; 888 int rc = 0;
857 889
858 if (data && (dev->features & NETIF_F_IP_CSUM)) 890 if (data && (dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
859 return 0; 891 return 0;
860 if (!data && !(dev->features & NETIF_F_IP_CSUM)) 892 if (!data && !(dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
861 return 0; 893 return 0;
862 894
863 if (data && !adapter->rx_csum) 895 if (data && !adapter->rx_csum)
@@ -975,7 +1007,12 @@ static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
975 1007
976 /* veth can't checksum offload UDP */ 1008 /* veth can't checksum offload UDP */
977 if (skb->ip_summed == CHECKSUM_PARTIAL && 1009 if (skb->ip_summed == CHECKSUM_PARTIAL &&
978 ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) { 1010 ((skb->protocol == htons(ETH_P_IP) &&
1011 ip_hdr(skb)->protocol != IPPROTO_TCP) ||
1012 (skb->protocol == htons(ETH_P_IPV6) &&
1013 ipv6_hdr(skb)->nexthdr != IPPROTO_TCP)) &&
1014 skb_checksum_help(skb)) {
1015
979 ibmveth_error_printk("tx: failed to checksum packet\n"); 1016 ibmveth_error_printk("tx: failed to checksum packet\n");
980 netdev->stats.tx_dropped++; 1017 netdev->stats.tx_dropped++;
981 goto out; 1018 goto out;