]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/linux/0010-Drivers-net-hyperv-Enable-large-send-offload.patch
util-linux: update rootfile (armv5tel)
[ipfire-2.x.git] / src / patches / linux / 0010-Drivers-net-hyperv-Enable-large-send-offload.patch
CommitLineData
a7b0967d
MT
1From a4ec4f58017b456281ee17c35fb82dfe4eab2193 Mon Sep 17 00:00:00 2001
2From: KY Srinivasan <kys@microsoft.com>
3Date: Sat, 8 Mar 2014 19:23:18 -0800
4Subject: [PATCH 10/25] Drivers: net: hyperv: Enable large send offload
5
6Enable segmentation offload.
7
8Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
9Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
10Signed-off-by: David S. Miller <davem@davemloft.net>
11---
12 drivers/net/hyperv/hyperv_net.h | 40 ++++++++++++++++++++++++++++++++++++++++
13 drivers/net/hyperv/netvsc_drv.c | 38 ++++++++++++++++++++++++++++++++++----
14 2 files changed, 74 insertions(+), 4 deletions(-)
15
16diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
17index 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
23
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
27+
28 /*
29 * New offload OIDs for NDIS 6
30 */
31@@ -804,12 +808,48 @@ struct ndis_tcp_ip_checksum_info {
32 };
33 };
34
35+struct ndis_tcp_lso_info {
36+ union {
37+ struct {
38+ u32 unused:30;
39+ u32 type:1;
40+ u32 reserved2:1;
41+ } transmit;
42+ struct {
43+ u32 mss:20;
44+ u32 tcp_header_offset:10;
45+ u32 type:1;
46+ u32 reserved2:1;
47+ } lso_v1_transmit;
48+ struct {
49+ u32 tcp_payload:30;
50+ u32 type:1;
51+ u32 reserved2:1;
52+ } lso_v1_transmit_complete;
53+ struct {
54+ u32 mss:20;
55+ u32 tcp_header_offset:10;
56+ u32 type:1;
57+ u32 ip_version:1;
58+ } lso_v2_transmit;
59+ struct {
60+ u32 reserved:30;
61+ u32 type:1;
62+ u32 reserved2:1;
63+ } lso_v2_transmit_complete;
64+ u32 value;
65+ };
66+};
67+
68 #define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
69 sizeof(struct ndis_pkt_8021q_info))
70
71 #define NDIS_CSUM_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
72 sizeof(struct ndis_tcp_ip_checksum_info))
73
74+#define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
75+ sizeof(struct ndis_tcp_lso_info))
76+
77 /* Format of Information buffer passed in a SetRequest for the OID */
78 /* OID_GEN_RNDIS_CONFIG_PARAMETER. */
79 struct rndis_config_parameter_info {
80diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
81index 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)
85 bool isvlan;
86 struct rndis_per_packet_info *ppi;
87 struct ndis_tcp_ip_checksum_info *csum_info;
88+ struct ndis_tcp_lso_info *lso_info;
89 int hdr_offset;
90 u32 net_trans_info;
91
92@@ -378,7 +379,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
93 * GSO packet.
94 */
95 if (skb_is_gso(skb))
96- goto do_send;
97+ goto do_lso;
98
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;
104 }
105+ goto do_send;
106+
107+do_lso:
108+ rndis_msg_size += NDIS_LSO_PPI_SIZE;
109+ ppi = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE,
110+ TCP_LARGESEND_PKTINFO);
111+
112+ lso_info = (struct ndis_tcp_lso_info *)((void *)ppi +
113+ ppi->ppi_offset);
114+
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);
124+ } else {
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);
131+ }
132+ lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset;
133+ lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size;
134
135 do_send:
136 /* Start filling in the page buffers with the rndis hdr */
137@@ -655,10 +685,10 @@ static int netvsc_probe(struct hv_device *dev,
138
139 net->netdev_ops = &device_ops;
140
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 |
144+ NETIF_F_TSO;
145 net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
146- NETIF_F_IP_CSUM;
147+ NETIF_F_IP_CSUM | NETIF_F_TSO;
148
149 SET_ETHTOOL_OPS(net, &ethtool_ops);
150 SET_NETDEV_DEV(net, &dev->device);
151--
1522.4.3
153