aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ibm/ibmvnic.c
diff options
context:
space:
mode:
authorThomas Falcon <tlfalcon@linux.vnet.ibm.com>2017-10-17 13:36:55 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-19 08:20:32 -0400
commitfdb061056f57e849a05cac072a4998c7f33d797e (patch)
treecaaab1f2413f48ef728f4221f741de9ac6b1eb94 /drivers/net/ethernet/ibm/ibmvnic.c
parent154820563dd4621c78e03e98e70216e832422f8e (diff)
ibmvnic: Enable TSO support
This patch enables TSO support. It includes additional buffers reserved exclusively for large packets. Throughput is greatly increased with TSO enabled, from about 1 Gb/s to 9 Gb/s on our test systems. 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/ibmvnic.c')
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index b508877397e1..aedb81c230a6 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,10 +1217,21 @@ 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 data_dma_addr = tx_pool->long_term_buff.addr + offset; 1223 dst = tx_pool->tso_ltb.buff + 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 }
1208 1235
1209 if (skb_shinfo(skb)->nr_frags) { 1236 if (skb_shinfo(skb)->nr_frags) {
1210 int cur, i; 1237 int cur, i;
@@ -1245,7 +1272,10 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
1245 tx_crq.v1.n_sge = 1; 1272 tx_crq.v1.n_sge = 1;
1246 tx_crq.v1.flags1 = IBMVNIC_TX_COMP_NEEDED; 1273 tx_crq.v1.flags1 = IBMVNIC_TX_COMP_NEEDED;
1247 tx_crq.v1.correlator = cpu_to_be32(index); 1274 tx_crq.v1.correlator = cpu_to_be32(index);
1248 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);
1249 tx_crq.v1.sge_len = cpu_to_be32(skb->len); 1279 tx_crq.v1.sge_len = cpu_to_be32(skb->len);
1250 tx_crq.v1.ioba = cpu_to_be64(data_dma_addr); 1280 tx_crq.v1.ioba = cpu_to_be64(data_dma_addr);
1251 1281
@@ -1270,6 +1300,11 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
1270 tx_crq.v1.flags1 |= IBMVNIC_TX_CHKSUM_OFFLOAD; 1300 tx_crq.v1.flags1 |= IBMVNIC_TX_CHKSUM_OFFLOAD;
1271 hdrs += 2; 1301 hdrs += 2;
1272 } 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 }
1273 /* determine if l2/3/4 headers are sent to firmware */ 1308 /* determine if l2/3/4 headers are sent to firmware */
1274 if ((*hdrs >> 7) & 1 && 1309 if ((*hdrs >> 7) & 1 &&
1275 (skb->protocol == htons(ETH_P_IP) || 1310 (skb->protocol == htons(ETH_P_IP) ||
@@ -2960,10 +2995,10 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
2960 adapter->ip_offload_ctrl.udp_ipv4_chksum = buf->udp_ipv4_chksum; 2995 adapter->ip_offload_ctrl.udp_ipv4_chksum = buf->udp_ipv4_chksum;
2961 adapter->ip_offload_ctrl.tcp_ipv6_chksum = buf->tcp_ipv6_chksum; 2996 adapter->ip_offload_ctrl.tcp_ipv6_chksum = buf->tcp_ipv6_chksum;
2962 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;
2963 3000
2964 /* large_tx/rx disabled for now, additional features needed */ 3001 /* large_rx disabled for now, additional features needed */
2965 adapter->ip_offload_ctrl.large_tx_ipv4 = 0;
2966 adapter->ip_offload_ctrl.large_tx_ipv6 = 0;
2967 adapter->ip_offload_ctrl.large_rx_ipv4 = 0; 3002 adapter->ip_offload_ctrl.large_rx_ipv4 = 0;
2968 adapter->ip_offload_ctrl.large_rx_ipv6 = 0; 3003 adapter->ip_offload_ctrl.large_rx_ipv6 = 0;
2969 3004
@@ -2979,6 +3014,11 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
2979 (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))) 3014 (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
2980 adapter->netdev->features |= NETIF_F_RXCSUM; 3015 adapter->netdev->features |= NETIF_F_RXCSUM;
2981 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
2982 memset(&crq, 0, sizeof(crq)); 3022 memset(&crq, 0, sizeof(crq));
2983 crq.control_ip_offload.first = IBMVNIC_CRQ_CMD; 3023 crq.control_ip_offload.first = IBMVNIC_CRQ_CMD;
2984 crq.control_ip_offload.cmd = CONTROL_IP_OFFLOAD; 3024 crq.control_ip_offload.cmd = CONTROL_IP_OFFLOAD;