aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-10-19 08:20:32 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-19 08:20:32 -0400
commitac79a512b6fd5831a12859fd1d3c5e38103bcaeb (patch)
tree9f7e2ea3ce19549cf99ddeebc4c0593f434dbd2e
parent010f245b9dd734adda6386c494a4ace953ea8dc4 (diff)
parentaa0bf8510dac901badc6889b208fc0e7d9225924 (diff)
Merge branch 'ibmvnic-next'
Thomas Falcon says: ==================== ibmvnic: Enable SG and TSO feature support This patch set is fairly straightforward. The first patch enables scatter-gather support in the ibmvnic driver. The following patch then enables the TCP Segmentation offload feature. The final patch allows users to enable or disable net device features using ethtool. Enabling SG and TSO grants a large increase in throughput with TX speed increasing from 1Gb/s to 9Gb/s in our initial test runs. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c81
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.h5
2 files changed, 76 insertions, 10 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 4bc14a901571..b991703319f9 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -553,6 +553,10 @@ static int reset_tx_pools(struct ibmvnic_adapter *adapter)
553 if (rc) 553 if (rc)
554 return rc; 554 return rc;
555 555
556 rc = reset_long_term_buff(adapter, &tx_pool->tso_ltb);
557 if (rc)
558 return rc;
559
556 memset(tx_pool->tx_buff, 0, 560 memset(tx_pool->tx_buff, 0,
557 adapter->req_tx_entries_per_subcrq * 561 adapter->req_tx_entries_per_subcrq *
558 sizeof(struct ibmvnic_tx_buff)); 562 sizeof(struct ibmvnic_tx_buff));
@@ -562,6 +566,7 @@ static int reset_tx_pools(struct ibmvnic_adapter *adapter)
562 566
563 tx_pool->consumer_index = 0; 567 tx_pool->consumer_index = 0;
564 tx_pool->producer_index = 0; 568 tx_pool->producer_index = 0;
569 tx_pool->tso_index = 0;
565 } 570 }
566 571
567 return 0; 572 return 0;
@@ -581,6 +586,7 @@ static void release_tx_pools(struct ibmvnic_adapter *adapter)
581 tx_pool = &adapter->tx_pool[i]; 586 tx_pool = &adapter->tx_pool[i];
582 kfree(tx_pool->tx_buff); 587 kfree(tx_pool->tx_buff);
583 free_long_term_buff(adapter, &tx_pool->long_term_buff); 588 free_long_term_buff(adapter, &tx_pool->long_term_buff);
589 free_long_term_buff(adapter, &tx_pool->tso_ltb);
584 kfree(tx_pool->free_map); 590 kfree(tx_pool->free_map);
585 } 591 }
586 592
@@ -625,6 +631,16 @@ static int init_tx_pools(struct net_device *netdev)
625 return -1; 631 return -1;
626 } 632 }
627 633
634 /* alloc TSO ltb */
635 if (alloc_long_term_buff(adapter, &tx_pool->tso_ltb,
636 IBMVNIC_TSO_BUFS *
637 IBMVNIC_TSO_BUF_SZ)) {
638 release_tx_pools(adapter);
639 return -1;
640 }
641
642 tx_pool->tso_index = 0;
643
628 tx_pool->free_map = kcalloc(adapter->req_tx_entries_per_subcrq, 644 tx_pool->free_map = kcalloc(adapter->req_tx_entries_per_subcrq,
629 sizeof(int), GFP_KERNEL); 645 sizeof(int), GFP_KERNEL);
630 if (!tx_pool->free_map) { 646 if (!tx_pool->free_map) {
@@ -1201,11 +1217,41 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
1201 be32_to_cpu(adapter->login_rsp_buf->off_txsubm_subcrqs)); 1217 be32_to_cpu(adapter->login_rsp_buf->off_txsubm_subcrqs));
1202 1218
1203 index = tx_pool->free_map[tx_pool->consumer_index]; 1219 index = tx_pool->free_map[tx_pool->consumer_index];
1204 offset = index * adapter->req_mtu; 1220
1205 dst = tx_pool->long_term_buff.buff + offset; 1221 if (skb_is_gso(skb)) {
1206 memset(dst, 0, adapter->req_mtu); 1222 offset = tx_pool->tso_index * IBMVNIC_TSO_BUF_SZ;
1207 skb_copy_from_linear_data(skb, dst, skb->len); 1223 dst = tx_pool->tso_ltb.buff + offset;
1208 data_dma_addr = tx_pool->long_term_buff.addr + offset; 1224 memset(dst, 0, IBMVNIC_TSO_BUF_SZ);
1225 data_dma_addr = tx_pool->tso_ltb.addr + offset;
1226 tx_pool->tso_index++;
1227 if (tx_pool->tso_index == IBMVNIC_TSO_BUFS)
1228 tx_pool->tso_index = 0;
1229 } else {
1230 offset = index * adapter->req_mtu;
1231 dst = tx_pool->long_term_buff.buff + offset;
1232 memset(dst, 0, adapter->req_mtu);
1233 data_dma_addr = tx_pool->long_term_buff.addr + offset;
1234 }
1235
1236 if (skb_shinfo(skb)->nr_frags) {
1237 int cur, i;
1238
1239 /* Copy the head */
1240 skb_copy_from_linear_data(skb, dst, skb_headlen(skb));
1241 cur = skb_headlen(skb);
1242
1243 /* Copy the frags */
1244 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1245 const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
1246
1247 memcpy(dst + cur,
1248 page_address(skb_frag_page(frag)) +
1249 frag->page_offset, skb_frag_size(frag));
1250 cur += skb_frag_size(frag);
1251 }
1252 } else {
1253 skb_copy_from_linear_data(skb, dst, skb->len);
1254 }
1209 1255
1210 tx_pool->consumer_index = 1256 tx_pool->consumer_index =
1211 (tx_pool->consumer_index + 1) % 1257 (tx_pool->consumer_index + 1) %
@@ -1226,7 +1272,10 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
1226 tx_crq.v1.n_sge = 1; 1272 tx_crq.v1.n_sge = 1;
1227 tx_crq.v1.flags1 = IBMVNIC_TX_COMP_NEEDED; 1273 tx_crq.v1.flags1 = IBMVNIC_TX_COMP_NEEDED;
1228 tx_crq.v1.correlator = cpu_to_be32(index); 1274 tx_crq.v1.correlator = cpu_to_be32(index);
1229 tx_crq.v1.dma_reg = cpu_to_be16(tx_pool->long_term_buff.map_id); 1275 if (skb_is_gso(skb))
1276 tx_crq.v1.dma_reg = cpu_to_be16(tx_pool->tso_ltb.map_id);
1277 else
1278 tx_crq.v1.dma_reg = cpu_to_be16(tx_pool->long_term_buff.map_id);
1230 tx_crq.v1.sge_len = cpu_to_be32(skb->len); 1279 tx_crq.v1.sge_len = cpu_to_be32(skb->len);
1231 tx_crq.v1.ioba = cpu_to_be64(data_dma_addr); 1280 tx_crq.v1.ioba = cpu_to_be64(data_dma_addr);
1232 1281
@@ -1251,6 +1300,11 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
1251 tx_crq.v1.flags1 |= IBMVNIC_TX_CHKSUM_OFFLOAD; 1300 tx_crq.v1.flags1 |= IBMVNIC_TX_CHKSUM_OFFLOAD;
1252 hdrs += 2; 1301 hdrs += 2;
1253 } 1302 }
1303 if (skb_is_gso(skb)) {
1304 tx_crq.v1.flags1 |= IBMVNIC_TX_LSO;
1305 tx_crq.v1.mss = cpu_to_be16(skb_shinfo(skb)->gso_size);
1306 hdrs += 2;
1307 }
1254 /* determine if l2/3/4 headers are sent to firmware */ 1308 /* determine if l2/3/4 headers are sent to firmware */
1255 if ((*hdrs >> 7) & 1 && 1309 if ((*hdrs >> 7) & 1 &&
1256 (skb->protocol == htons(ETH_P_IP) || 1310 (skb->protocol == htons(ETH_P_IP) ||
@@ -2941,14 +2995,14 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
2941 adapter->ip_offload_ctrl.udp_ipv4_chksum = buf->udp_ipv4_chksum; 2995 adapter->ip_offload_ctrl.udp_ipv4_chksum = buf->udp_ipv4_chksum;
2942 adapter->ip_offload_ctrl.tcp_ipv6_chksum = buf->tcp_ipv6_chksum; 2996 adapter->ip_offload_ctrl.tcp_ipv6_chksum = buf->tcp_ipv6_chksum;
2943 adapter->ip_offload_ctrl.udp_ipv6_chksum = buf->udp_ipv6_chksum; 2997 adapter->ip_offload_ctrl.udp_ipv6_chksum = buf->udp_ipv6_chksum;
2998 adapter->ip_offload_ctrl.large_tx_ipv4 = buf->large_tx_ipv4;
2999 adapter->ip_offload_ctrl.large_tx_ipv6 = buf->large_tx_ipv6;
2944 3000
2945 /* large_tx/rx disabled for now, additional features needed */ 3001 /* large_rx disabled for now, additional features needed */
2946 adapter->ip_offload_ctrl.large_tx_ipv4 = 0;
2947 adapter->ip_offload_ctrl.large_tx_ipv6 = 0;
2948 adapter->ip_offload_ctrl.large_rx_ipv4 = 0; 3002 adapter->ip_offload_ctrl.large_rx_ipv4 = 0;
2949 adapter->ip_offload_ctrl.large_rx_ipv6 = 0; 3003 adapter->ip_offload_ctrl.large_rx_ipv6 = 0;
2950 3004
2951 adapter->netdev->features = NETIF_F_GSO; 3005 adapter->netdev->features = NETIF_F_SG | NETIF_F_GSO;
2952 3006
2953 if (buf->tcp_ipv4_chksum || buf->udp_ipv4_chksum) 3007 if (buf->tcp_ipv4_chksum || buf->udp_ipv4_chksum)
2954 adapter->netdev->features |= NETIF_F_IP_CSUM; 3008 adapter->netdev->features |= NETIF_F_IP_CSUM;
@@ -2960,6 +3014,13 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
2960 (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))) 3014 (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
2961 adapter->netdev->features |= NETIF_F_RXCSUM; 3015 adapter->netdev->features |= NETIF_F_RXCSUM;
2962 3016
3017 if (buf->large_tx_ipv4)
3018 adapter->netdev->features |= NETIF_F_TSO;
3019 if (buf->large_tx_ipv6)
3020 adapter->netdev->features |= NETIF_F_TSO6;
3021
3022 adapter->netdev->hw_features |= adapter->netdev->features;
3023
2963 memset(&crq, 0, sizeof(crq)); 3024 memset(&crq, 0, sizeof(crq));
2964 crq.control_ip_offload.first = IBMVNIC_CRQ_CMD; 3025 crq.control_ip_offload.first = IBMVNIC_CRQ_CMD;
2965 crq.control_ip_offload.cmd = CONTROL_IP_OFFLOAD; 3026 crq.control_ip_offload.cmd = CONTROL_IP_OFFLOAD;
diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h
index d02257ccc377..7aa347a21e78 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.h
+++ b/drivers/net/ethernet/ibm/ibmvnic.h
@@ -39,6 +39,9 @@
39#define IBMVNIC_BUFFS_PER_POOL 100 39#define IBMVNIC_BUFFS_PER_POOL 100
40#define IBMVNIC_MAX_TX_QUEUES 5 40#define IBMVNIC_MAX_TX_QUEUES 5
41 41
42#define IBMVNIC_TSO_BUF_SZ 65536
43#define IBMVNIC_TSO_BUFS 64
44
42struct ibmvnic_login_buffer { 45struct ibmvnic_login_buffer {
43 __be32 len; 46 __be32 len;
44 __be32 version; 47 __be32 version;
@@ -896,6 +899,8 @@ struct ibmvnic_tx_pool {
896 wait_queue_head_t ibmvnic_tx_comp_q; 899 wait_queue_head_t ibmvnic_tx_comp_q;
897 struct task_struct *work_thread; 900 struct task_struct *work_thread;
898 struct ibmvnic_long_term_buff long_term_buff; 901 struct ibmvnic_long_term_buff long_term_buff;
902 struct ibmvnic_long_term_buff tso_ltb;
903 int tso_index;
899}; 904};
900 905
901struct ibmvnic_rx_buff { 906struct ibmvnic_rx_buff {