1 From a4ec4f58017b456281ee17c35fb82dfe4eab2193 Mon Sep 17 00:00:00 2001
2 From: KY Srinivasan <kys@microsoft.com>
3 Date: Sat, 8 Mar 2014 19:23:18 -0800
4 Subject: [PATCH 10/25] Drivers: net: hyperv: Enable large send offload
6 Enable segmentation offload.
8 Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
9 Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
10 Signed-off-by: David S. Miller <davem@davemloft.net>
12 drivers/net/hyperv/hyperv_net.h | 40 ++++++++++++++++++++++++++++++++++++++++
13 drivers/net/hyperv/netvsc_drv.c | 38 ++++++++++++++++++++++++++++++++++----
14 2 files changed, 74 insertions(+), 4 deletions(-)
16 diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
17 index 4cf238234321..7d06b4959383 100644
18 --- a/drivers/net/hyperv/hyperv_net.h
19 +++ b/drivers/net/hyperv/hyperv_net.h
20 @@ -742,6 +742,10 @@ struct ndis_oject_header {
21 #define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
22 #define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
24 +#define NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE 1
25 +#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4 0
26 +#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6 1
29 * New offload OIDs for NDIS 6
31 @@ -804,12 +808,48 @@ struct ndis_tcp_ip_checksum_info {
35 +struct ndis_tcp_lso_info {
44 + u32 tcp_header_offset:10;
52 + } lso_v1_transmit_complete;
55 + u32 tcp_header_offset:10;
63 + } lso_v2_transmit_complete;
68 #define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
69 sizeof(struct ndis_pkt_8021q_info))
71 #define NDIS_CSUM_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
72 sizeof(struct ndis_tcp_ip_checksum_info))
74 +#define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
75 + sizeof(struct ndis_tcp_lso_info))
77 /* Format of Information buffer passed in a SetRequest for the OID */
78 /* OID_GEN_RNDIS_CONFIG_PARAMETER. */
79 struct rndis_config_parameter_info {
80 diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
81 index 2fab69ac61ef..5baa1fa7e692 100644
82 --- a/drivers/net/hyperv/netvsc_drv.c
83 +++ b/drivers/net/hyperv/netvsc_drv.c
84 @@ -299,6 +299,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
86 struct rndis_per_packet_info *ppi;
87 struct ndis_tcp_ip_checksum_info *csum_info;
88 + struct ndis_tcp_lso_info *lso_info;
92 @@ -378,7 +379,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
99 rndis_msg_size += NDIS_CSUM_PPI_SIZE;
100 ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
101 @@ -398,6 +399,35 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
102 } else if (net_trans_info & INFO_UDP) {
103 csum_info->transmit.udp_checksum = 1;
108 + rndis_msg_size += NDIS_LSO_PPI_SIZE;
109 + ppi = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE,
110 + TCP_LARGESEND_PKTINFO);
112 + lso_info = (struct ndis_tcp_lso_info *)((void *)ppi +
115 + lso_info->lso_v2_transmit.type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
116 + if (net_trans_info & (INFO_IPV4 << 16)) {
117 + lso_info->lso_v2_transmit.ip_version =
118 + NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
119 + ip_hdr(skb)->tot_len = 0;
120 + ip_hdr(skb)->check = 0;
121 + tcp_hdr(skb)->check =
122 + ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
123 + ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
125 + lso_info->lso_v2_transmit.ip_version =
126 + NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6;
127 + ipv6_hdr(skb)->payload_len = 0;
128 + tcp_hdr(skb)->check =
129 + ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
130 + &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
132 + lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset;
133 + lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size;
136 /* Start filling in the page buffers with the rndis hdr */
137 @@ -655,10 +685,10 @@ static int netvsc_probe(struct hv_device *dev,
139 net->netdev_ops = &device_ops;
141 - /* TODO: Add GSO and Checksum offload */
142 - net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
143 + net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM |
145 net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
147 + NETIF_F_IP_CSUM | NETIF_F_TSO;
149 SET_ETHTOOL_OPS(net, ðtool_ops);
150 SET_NETDEV_DEV(net, &dev->device);