aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ibm
diff options
context:
space:
mode:
authorThomas Falcon <tlfalcon@linux.vnet.ibm.com>2015-07-14 11:51:51 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-16 00:34:56 -0400
commit07e6a97da1eba064bb35cfd5c121e90865393a60 (patch)
tree1239911c74e7f15a61a64360e26e4786a72f59c9 /drivers/net/ethernet/ibm
parent2de8530ba0c71a2fba02590681af0f3a2a187a9b (diff)
ibmveth: add support for TSO6
This patch adds support for a new method of signalling the firmware that TSO packets are being sent. The new method removes the need to alter the ip and tcp checksums and allows TSO6 support. Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/ibm')
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c145
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.h18
2 files changed, 135 insertions, 28 deletions
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 29bbb628d712..7af870a3c549 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -79,6 +79,11 @@ static unsigned int rx_flush __read_mostly = 0;
79module_param(rx_flush, uint, 0644); 79module_param(rx_flush, uint, 0644);
80MODULE_PARM_DESC(rx_flush, "Flush receive buffers before use"); 80MODULE_PARM_DESC(rx_flush, "Flush receive buffers before use");
81 81
82static bool old_large_send __read_mostly;
83module_param(old_large_send, bool, S_IRUGO);
84MODULE_PARM_DESC(old_large_send,
85 "Use old large send method on firmware that supports the new method");
86
82struct ibmveth_stat { 87struct ibmveth_stat {
83 char name[ETH_GSTRING_LEN]; 88 char name[ETH_GSTRING_LEN];
84 int offset; 89 int offset;
@@ -101,7 +106,8 @@ struct ibmveth_stat ibmveth_stats[] = {
101 { "fw_enabled_ipv4_csum", IBMVETH_STAT_OFF(fw_ipv4_csum_support) }, 106 { "fw_enabled_ipv4_csum", IBMVETH_STAT_OFF(fw_ipv4_csum_support) },
102 { "fw_enabled_ipv6_csum", IBMVETH_STAT_OFF(fw_ipv6_csum_support) }, 107 { "fw_enabled_ipv6_csum", IBMVETH_STAT_OFF(fw_ipv6_csum_support) },
103 { "tx_large_packets", IBMVETH_STAT_OFF(tx_large_packets) }, 108 { "tx_large_packets", IBMVETH_STAT_OFF(tx_large_packets) },
104 { "rx_large_packets", IBMVETH_STAT_OFF(rx_large_packets) } 109 { "rx_large_packets", IBMVETH_STAT_OFF(rx_large_packets) },
110 { "fw_enabled_large_send", IBMVETH_STAT_OFF(fw_large_send_support) }
105}; 111};
106 112
107/* simple methods of getting data from the current rxq entry */ 113/* simple methods of getting data from the current rxq entry */
@@ -848,25 +854,91 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
848 return rc1 ? rc1 : rc2; 854 return rc1 ? rc1 : rc2;
849} 855}
850 856
857static int ibmveth_set_tso(struct net_device *dev, u32 data)
858{
859 struct ibmveth_adapter *adapter = netdev_priv(dev);
860 unsigned long set_attr, clr_attr, ret_attr;
861 long ret1, ret2;
862 int rc1 = 0, rc2 = 0;
863 int restart = 0;
864
865 if (netif_running(dev)) {
866 restart = 1;
867 adapter->pool_config = 1;
868 ibmveth_close(dev);
869 adapter->pool_config = 0;
870 }
871
872 set_attr = 0;
873 clr_attr = 0;
874
875 if (data)
876 set_attr = IBMVETH_ILLAN_LRG_SR_ENABLED;
877 else
878 clr_attr = IBMVETH_ILLAN_LRG_SR_ENABLED;
879
880 ret1 = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr);
881
882 if (ret1 == H_SUCCESS && (ret_attr & IBMVETH_ILLAN_LRG_SND_SUPPORT) &&
883 !old_large_send) {
884 ret2 = h_illan_attributes(adapter->vdev->unit_address, clr_attr,
885 set_attr, &ret_attr);
886
887 if (ret2 != H_SUCCESS) {
888 netdev_err(dev, "unable to change tso settings. %d rc=%ld\n",
889 data, ret2);
890
891 h_illan_attributes(adapter->vdev->unit_address,
892 set_attr, clr_attr, &ret_attr);
893
894 if (data == 1)
895 dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
896 rc1 = -EIO;
897
898 } else {
899 adapter->fw_large_send_support = data;
900 adapter->large_send = data;
901 }
902 } else {
903 /* Older firmware version of large send offload does not
904 * support tcp6/ipv6
905 */
906 if (data == 1) {
907 dev->features &= ~NETIF_F_TSO6;
908 netdev_info(dev, "TSO feature requires all partitions to have updated driver");
909 }
910 adapter->large_send = data;
911 }
912
913 if (restart)
914 rc2 = ibmveth_open(dev);
915
916 return rc1 ? rc1 : rc2;
917}
918
851static int ibmveth_set_features(struct net_device *dev, 919static int ibmveth_set_features(struct net_device *dev,
852 netdev_features_t features) 920 netdev_features_t features)
853{ 921{
854 struct ibmveth_adapter *adapter = netdev_priv(dev); 922 struct ibmveth_adapter *adapter = netdev_priv(dev);
855 int rx_csum = !!(features & NETIF_F_RXCSUM); 923 int rx_csum = !!(features & NETIF_F_RXCSUM);
856 int rc; 924 int large_send = !!(features & (NETIF_F_TSO | NETIF_F_TSO6));
857 netdev_features_t changed = features ^ dev->features; 925 int rc1 = 0, rc2 = 0;
858
859 if (features & NETIF_F_TSO & changed)
860 netdev_info(dev, "TSO feature requires all partitions to have updated driver");
861 926
862 if (rx_csum == adapter->rx_csum) 927 if (rx_csum != adapter->rx_csum) {
863 return 0; 928 rc1 = ibmveth_set_csum_offload(dev, rx_csum);
929 if (rc1 && !adapter->rx_csum)
930 dev->features =
931 features & ~(NETIF_F_ALL_CSUM | NETIF_F_RXCSUM);
932 }
864 933
865 rc = ibmveth_set_csum_offload(dev, rx_csum); 934 if (large_send != adapter->large_send) {
866 if (rc && !adapter->rx_csum) 935 rc2 = ibmveth_set_tso(dev, large_send);
867 dev->features = features & ~(NETIF_F_ALL_CSUM | NETIF_F_RXCSUM); 936 if (rc2 && !adapter->large_send)
937 dev->features =
938 features & ~(NETIF_F_TSO | NETIF_F_TSO6);
939 }
868 940
869 return rc; 941 return rc1 ? rc1 : rc2;
870} 942}
871 943
872static void ibmveth_get_strings(struct net_device *dev, u32 stringset, u8 *data) 944static void ibmveth_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -917,7 +989,7 @@ static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
917#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1)) 989#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1))
918 990
919static int ibmveth_send(struct ibmveth_adapter *adapter, 991static int ibmveth_send(struct ibmveth_adapter *adapter,
920 union ibmveth_buf_desc *descs) 992 union ibmveth_buf_desc *descs, unsigned long mss)
921{ 993{
922 unsigned long correlator; 994 unsigned long correlator;
923 unsigned int retry_count; 995 unsigned int retry_count;
@@ -934,7 +1006,8 @@ static int ibmveth_send(struct ibmveth_adapter *adapter,
934 descs[0].desc, descs[1].desc, 1006 descs[0].desc, descs[1].desc,
935 descs[2].desc, descs[3].desc, 1007 descs[2].desc, descs[3].desc,
936 descs[4].desc, descs[5].desc, 1008 descs[4].desc, descs[5].desc,
937 correlator, &correlator); 1009 correlator, &correlator, mss,
1010 adapter->fw_large_send_support);
938 } while ((ret == H_BUSY) && (retry_count--)); 1011 } while ((ret == H_BUSY) && (retry_count--));
939 1012
940 if (ret != H_SUCCESS && ret != H_DROPPED) { 1013 if (ret != H_SUCCESS && ret != H_DROPPED) {
@@ -955,6 +1028,7 @@ static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
955 int last, i; 1028 int last, i;
956 int force_bounce = 0; 1029 int force_bounce = 0;
957 dma_addr_t dma_addr; 1030 dma_addr_t dma_addr;
1031 unsigned long mss = 0;
958 1032
959 /* 1033 /*
960 * veth handles a maximum of 6 segments including the header, so 1034 * veth handles a maximum of 6 segments including the header, so
@@ -980,6 +1054,9 @@ static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
980 1054
981 desc_flags = IBMVETH_BUF_VALID; 1055 desc_flags = IBMVETH_BUF_VALID;
982 1056
1057 if (skb_is_gso(skb) && adapter->fw_large_send_support)
1058 desc_flags |= IBMVETH_BUF_LRG_SND;
1059
983 if (skb->ip_summed == CHECKSUM_PARTIAL) { 1060 if (skb->ip_summed == CHECKSUM_PARTIAL) {
984 unsigned char *buf = skb_transport_header(skb) + 1061 unsigned char *buf = skb_transport_header(skb) +
985 skb->csum_offset; 1062 skb->csum_offset;
@@ -1007,7 +1084,7 @@ retry_bounce:
1007 descs[0].fields.flags_len = desc_flags | skb->len; 1084 descs[0].fields.flags_len = desc_flags | skb->len;
1008 descs[0].fields.address = adapter->bounce_buffer_dma; 1085 descs[0].fields.address = adapter->bounce_buffer_dma;
1009 1086
1010 if (ibmveth_send(adapter, descs)) { 1087 if (ibmveth_send(adapter, descs, 0)) {
1011 adapter->tx_send_failed++; 1088 adapter->tx_send_failed++;
1012 netdev->stats.tx_dropped++; 1089 netdev->stats.tx_dropped++;
1013 } else { 1090 } else {
@@ -1041,16 +1118,23 @@ retry_bounce:
1041 descs[i+1].fields.address = dma_addr; 1118 descs[i+1].fields.address = dma_addr;
1042 } 1119 }
1043 1120
1044 if (skb_is_gso(skb) && !skb_is_gso_v6(skb)) { 1121 if (skb_is_gso(skb)) {
1045 /* Put -1 in the IP checksum to tell phyp it 1122 if (adapter->fw_large_send_support) {
1046 * is a largesend packet and put the mss in the TCP checksum. 1123 mss = (unsigned long)skb_shinfo(skb)->gso_size;
1047 */ 1124 adapter->tx_large_packets++;
1048 ip_hdr(skb)->check = 0xffff; 1125 } else if (!skb_is_gso_v6(skb)) {
1049 tcp_hdr(skb)->check = cpu_to_be16(skb_shinfo(skb)->gso_size); 1126 /* Put -1 in the IP checksum to tell phyp it
1050 adapter->tx_large_packets++; 1127 * is a largesend packet. Put the mss in
1128 * the TCP checksum.
1129 */
1130 ip_hdr(skb)->check = 0xffff;
1131 tcp_hdr(skb)->check =
1132 cpu_to_be16(skb_shinfo(skb)->gso_size);
1133 adapter->tx_large_packets++;
1134 }
1051 } 1135 }
1052 1136
1053 if (ibmveth_send(adapter, descs)) { 1137 if (ibmveth_send(adapter, descs, mss)) {
1054 adapter->tx_send_failed++; 1138 adapter->tx_send_failed++;
1055 netdev->stats.tx_dropped++; 1139 netdev->stats.tx_dropped++;
1056 } else { 1140 } else {
@@ -1401,6 +1485,8 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
1401 struct ibmveth_adapter *adapter; 1485 struct ibmveth_adapter *adapter;
1402 unsigned char *mac_addr_p; 1486 unsigned char *mac_addr_p;
1403 unsigned int *mcastFilterSize_p; 1487 unsigned int *mcastFilterSize_p;
1488 long ret;
1489 unsigned long ret_attr;
1404 1490
1405 dev_dbg(&dev->dev, "entering ibmveth_probe for UA 0x%x\n", 1491 dev_dbg(&dev->dev, "entering ibmveth_probe for UA 0x%x\n",
1406 dev->unit_address); 1492 dev->unit_address);
@@ -1449,10 +1535,19 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
1449 SET_NETDEV_DEV(netdev, &dev->dev); 1535 SET_NETDEV_DEV(netdev, &dev->dev);
1450 netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | 1536 netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
1451 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; 1537 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
1538
1452 netdev->features |= netdev->hw_features; 1539 netdev->features |= netdev->hw_features;
1453 1540
1454 /* TSO is disabled by default */ 1541 ret = h_illan_attributes(adapter->vdev->unit_address, 0, 0, &ret_attr);
1455 netdev->hw_features |= NETIF_F_TSO; 1542
1543 /* If running older firmware, TSO should not be enabled by default */
1544 if (ret == H_SUCCESS && (ret_attr & IBMVETH_ILLAN_LRG_SND_SUPPORT) &&
1545 !old_large_send) {
1546 netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
1547 netdev->features |= netdev->hw_features;
1548 } else {
1549 netdev->hw_features |= NETIF_F_TSO;
1550 }
1456 1551
1457 memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN); 1552 memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN);
1458 1553
diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h
index 41dedb1fb2ae..4eade67fe30c 100644
--- a/drivers/net/ethernet/ibm/ibmveth.h
+++ b/drivers/net/ethernet/ibm/ibmveth.h
@@ -40,6 +40,8 @@
40#define IbmVethMcastRemoveFilter 0x2UL 40#define IbmVethMcastRemoveFilter 0x2UL
41#define IbmVethMcastClearFilterTable 0x3UL 41#define IbmVethMcastClearFilterTable 0x3UL
42 42
43#define IBMVETH_ILLAN_LRG_SR_ENABLED 0x0000000000010000UL
44#define IBMVETH_ILLAN_LRG_SND_SUPPORT 0x0000000000008000UL
43#define IBMVETH_ILLAN_PADDED_PKT_CSUM 0x0000000000002000UL 45#define IBMVETH_ILLAN_PADDED_PKT_CSUM 0x0000000000002000UL
44#define IBMVETH_ILLAN_TRUNK_PRI_MASK 0x0000000000000F00UL 46#define IBMVETH_ILLAN_TRUNK_PRI_MASK 0x0000000000000F00UL
45#define IBMVETH_ILLAN_IPV6_TCP_CSUM 0x0000000000000004UL 47#define IBMVETH_ILLAN_IPV6_TCP_CSUM 0x0000000000000004UL
@@ -59,13 +61,20 @@
59static inline long h_send_logical_lan(unsigned long unit_address, 61static inline long h_send_logical_lan(unsigned long unit_address,
60 unsigned long desc1, unsigned long desc2, unsigned long desc3, 62 unsigned long desc1, unsigned long desc2, unsigned long desc3,
61 unsigned long desc4, unsigned long desc5, unsigned long desc6, 63 unsigned long desc4, unsigned long desc5, unsigned long desc6,
62 unsigned long corellator_in, unsigned long *corellator_out) 64 unsigned long corellator_in, unsigned long *corellator_out,
65 unsigned long mss, unsigned long large_send_support)
63{ 66{
64 long rc; 67 long rc;
65 unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; 68 unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
66 69
67 rc = plpar_hcall9(H_SEND_LOGICAL_LAN, retbuf, unit_address, desc1, 70 if (large_send_support)
68 desc2, desc3, desc4, desc5, desc6, corellator_in); 71 rc = plpar_hcall9(H_SEND_LOGICAL_LAN, retbuf, unit_address,
72 desc1, desc2, desc3, desc4, desc5, desc6,
73 corellator_in, mss);
74 else
75 rc = plpar_hcall9(H_SEND_LOGICAL_LAN, retbuf, unit_address,
76 desc1, desc2, desc3, desc4, desc5, desc6,
77 corellator_in);
69 78
70 *corellator_out = retbuf[0]; 79 *corellator_out = retbuf[0];
71 80
@@ -147,11 +156,13 @@ struct ibmveth_adapter {
147 struct ibmveth_rx_q rx_queue; 156 struct ibmveth_rx_q rx_queue;
148 int pool_config; 157 int pool_config;
149 int rx_csum; 158 int rx_csum;
159 int large_send;
150 void *bounce_buffer; 160 void *bounce_buffer;
151 dma_addr_t bounce_buffer_dma; 161 dma_addr_t bounce_buffer_dma;
152 162
153 u64 fw_ipv6_csum_support; 163 u64 fw_ipv6_csum_support;
154 u64 fw_ipv4_csum_support; 164 u64 fw_ipv4_csum_support;
165 u64 fw_large_send_support;
155 /* adapter specific stats */ 166 /* adapter specific stats */
156 u64 replenish_task_cycles; 167 u64 replenish_task_cycles;
157 u64 replenish_no_mem; 168 u64 replenish_no_mem;
@@ -182,6 +193,7 @@ struct ibmveth_buf_desc_fields {
182#endif 193#endif
183#define IBMVETH_BUF_VALID 0x80000000 194#define IBMVETH_BUF_VALID 0x80000000
184#define IBMVETH_BUF_TOGGLE 0x40000000 195#define IBMVETH_BUF_TOGGLE 0x40000000
196#define IBMVETH_BUF_LRG_SND 0x04000000
185#define IBMVETH_BUF_NO_CSUM 0x02000000 197#define IBMVETH_BUF_NO_CSUM 0x02000000
186#define IBMVETH_BUF_CSUM_GOOD 0x01000000 198#define IBMVETH_BUF_CSUM_GOOD 0x01000000
187#define IBMVETH_BUF_LEN_MASK 0x00FFFFFF 199#define IBMVETH_BUF_LEN_MASK 0x00FFFFFF