]> git.ipfire.org Git - ipfire-2.x.git/blob - 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
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
5
6 Enable segmentation offload.
7
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>
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
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
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 {
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)
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 --
152 2.4.3
153