Skip to content

Commit

Permalink
Merge branch 'ibmvnic-next'
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Oct 19, 2017
2 parents 010f245 + aa0bf85 commit ac79a51
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 10 deletions.
81 changes: 71 additions & 10 deletions drivers/net/ethernet/ibm/ibmvnic.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,10 @@ static int reset_tx_pools(struct ibmvnic_adapter *adapter)
if (rc)
return rc;

rc = reset_long_term_buff(adapter, &tx_pool->tso_ltb);
if (rc)
return rc;

memset(tx_pool->tx_buff, 0,
adapter->req_tx_entries_per_subcrq *
sizeof(struct ibmvnic_tx_buff));
Expand All @@ -562,6 +566,7 @@ static int reset_tx_pools(struct ibmvnic_adapter *adapter)

tx_pool->consumer_index = 0;
tx_pool->producer_index = 0;
tx_pool->tso_index = 0;
}

return 0;
Expand All @@ -581,6 +586,7 @@ static void release_tx_pools(struct ibmvnic_adapter *adapter)
tx_pool = &adapter->tx_pool[i];
kfree(tx_pool->tx_buff);
free_long_term_buff(adapter, &tx_pool->long_term_buff);
free_long_term_buff(adapter, &tx_pool->tso_ltb);
kfree(tx_pool->free_map);
}

Expand Down Expand Up @@ -625,6 +631,16 @@ static int init_tx_pools(struct net_device *netdev)
return -1;
}

/* alloc TSO ltb */
if (alloc_long_term_buff(adapter, &tx_pool->tso_ltb,
IBMVNIC_TSO_BUFS *
IBMVNIC_TSO_BUF_SZ)) {
release_tx_pools(adapter);
return -1;
}

tx_pool->tso_index = 0;

tx_pool->free_map = kcalloc(adapter->req_tx_entries_per_subcrq,
sizeof(int), GFP_KERNEL);
if (!tx_pool->free_map) {
Expand Down Expand Up @@ -1201,11 +1217,41 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
be32_to_cpu(adapter->login_rsp_buf->off_txsubm_subcrqs));

index = tx_pool->free_map[tx_pool->consumer_index];
offset = index * adapter->req_mtu;
dst = tx_pool->long_term_buff.buff + offset;
memset(dst, 0, adapter->req_mtu);
skb_copy_from_linear_data(skb, dst, skb->len);
data_dma_addr = tx_pool->long_term_buff.addr + offset;

if (skb_is_gso(skb)) {
offset = tx_pool->tso_index * IBMVNIC_TSO_BUF_SZ;
dst = tx_pool->tso_ltb.buff + offset;
memset(dst, 0, IBMVNIC_TSO_BUF_SZ);
data_dma_addr = tx_pool->tso_ltb.addr + offset;
tx_pool->tso_index++;
if (tx_pool->tso_index == IBMVNIC_TSO_BUFS)
tx_pool->tso_index = 0;
} else {
offset = index * adapter->req_mtu;
dst = tx_pool->long_term_buff.buff + offset;
memset(dst, 0, adapter->req_mtu);
data_dma_addr = tx_pool->long_term_buff.addr + offset;
}

if (skb_shinfo(skb)->nr_frags) {
int cur, i;

/* Copy the head */
skb_copy_from_linear_data(skb, dst, skb_headlen(skb));
cur = skb_headlen(skb);

/* Copy the frags */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];

memcpy(dst + cur,
page_address(skb_frag_page(frag)) +
frag->page_offset, skb_frag_size(frag));
cur += skb_frag_size(frag);
}
} else {
skb_copy_from_linear_data(skb, dst, skb->len);
}

tx_pool->consumer_index =
(tx_pool->consumer_index + 1) %
Expand All @@ -1226,7 +1272,10 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
tx_crq.v1.n_sge = 1;
tx_crq.v1.flags1 = IBMVNIC_TX_COMP_NEEDED;
tx_crq.v1.correlator = cpu_to_be32(index);
tx_crq.v1.dma_reg = cpu_to_be16(tx_pool->long_term_buff.map_id);
if (skb_is_gso(skb))
tx_crq.v1.dma_reg = cpu_to_be16(tx_pool->tso_ltb.map_id);
else
tx_crq.v1.dma_reg = cpu_to_be16(tx_pool->long_term_buff.map_id);
tx_crq.v1.sge_len = cpu_to_be32(skb->len);
tx_crq.v1.ioba = cpu_to_be64(data_dma_addr);

Expand All @@ -1251,6 +1300,11 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
tx_crq.v1.flags1 |= IBMVNIC_TX_CHKSUM_OFFLOAD;
hdrs += 2;
}
if (skb_is_gso(skb)) {
tx_crq.v1.flags1 |= IBMVNIC_TX_LSO;
tx_crq.v1.mss = cpu_to_be16(skb_shinfo(skb)->gso_size);
hdrs += 2;
}
/* determine if l2/3/4 headers are sent to firmware */
if ((*hdrs >> 7) & 1 &&
(skb->protocol == htons(ETH_P_IP) ||
Expand Down Expand Up @@ -2941,14 +2995,14 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
adapter->ip_offload_ctrl.udp_ipv4_chksum = buf->udp_ipv4_chksum;
adapter->ip_offload_ctrl.tcp_ipv6_chksum = buf->tcp_ipv6_chksum;
adapter->ip_offload_ctrl.udp_ipv6_chksum = buf->udp_ipv6_chksum;
adapter->ip_offload_ctrl.large_tx_ipv4 = buf->large_tx_ipv4;
adapter->ip_offload_ctrl.large_tx_ipv6 = buf->large_tx_ipv6;

/* large_tx/rx disabled for now, additional features needed */
adapter->ip_offload_ctrl.large_tx_ipv4 = 0;
adapter->ip_offload_ctrl.large_tx_ipv6 = 0;
/* large_rx disabled for now, additional features needed */
adapter->ip_offload_ctrl.large_rx_ipv4 = 0;
adapter->ip_offload_ctrl.large_rx_ipv6 = 0;

adapter->netdev->features = NETIF_F_GSO;
adapter->netdev->features = NETIF_F_SG | NETIF_F_GSO;

if (buf->tcp_ipv4_chksum || buf->udp_ipv4_chksum)
adapter->netdev->features |= NETIF_F_IP_CSUM;
Expand All @@ -2960,6 +3014,13 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))
adapter->netdev->features |= NETIF_F_RXCSUM;

if (buf->large_tx_ipv4)
adapter->netdev->features |= NETIF_F_TSO;
if (buf->large_tx_ipv6)
adapter->netdev->features |= NETIF_F_TSO6;

adapter->netdev->hw_features |= adapter->netdev->features;

memset(&crq, 0, sizeof(crq));
crq.control_ip_offload.first = IBMVNIC_CRQ_CMD;
crq.control_ip_offload.cmd = CONTROL_IP_OFFLOAD;
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/ibm/ibmvnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
#define IBMVNIC_BUFFS_PER_POOL 100
#define IBMVNIC_MAX_TX_QUEUES 5

#define IBMVNIC_TSO_BUF_SZ 65536
#define IBMVNIC_TSO_BUFS 64

struct ibmvnic_login_buffer {
__be32 len;
__be32 version;
Expand Down Expand Up @@ -896,6 +899,8 @@ struct ibmvnic_tx_pool {
wait_queue_head_t ibmvnic_tx_comp_q;
struct task_struct *work_thread;
struct ibmvnic_long_term_buff long_term_buff;
struct ibmvnic_long_term_buff tso_ltb;
int tso_index;
};

struct ibmvnic_rx_buff {
Expand Down

0 comments on commit ac79a51

Please sign in to comment.