]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/linux/0007-Drivers-net-hyperv-Enable-offloads-on-the-host.patch
make.sh limit build to 23 parallel threads.
[ipfire-2.x.git] / src / patches / linux / 0007-Drivers-net-hyperv-Enable-offloads-on-the-host.patch
1 From 6b15b5f37e976a5f3840c7ea59560e10c6251250 Mon Sep 17 00:00:00 2001
2 From: KY Srinivasan <kys@microsoft.com>
3 Date: Sat, 8 Mar 2014 19:23:15 -0800
4 Subject: [PATCH 07/25] Drivers: net: hyperv: Enable offloads on the host
5
6 Prior to enabling guest side offloads, enable the offloads on the host.
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 | 55 +++++++++++++++++++++++++++
13 drivers/net/hyperv/rndis_filter.c | 80 +++++++++++++++++++++++++++++++++++++++
14 2 files changed, 135 insertions(+)
15
16 diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
17 index 694bf7cada90..8bc4e766589b 100644
18 --- a/drivers/net/hyperv/hyperv_net.h
19 +++ b/drivers/net/hyperv/hyperv_net.h
20 @@ -721,6 +721,61 @@ struct ndis_pkt_8021q_info {
21 };
22 };
23
24 +struct ndis_oject_header {
25 + u8 type;
26 + u8 revision;
27 + u16 size;
28 +};
29 +
30 +#define NDIS_OBJECT_TYPE_DEFAULT 0x80
31 +#define NDIS_OFFLOAD_PARAMETERS_REVISION_3 3
32 +#define NDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0
33 +#define NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1
34 +#define NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED 2
35 +#define NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED 2
36 +#define NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1
37 +#define NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2
38 +#define NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1
39 +#define NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2
40 +#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
41 +#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
42 +
43 +/*
44 + * New offload OIDs for NDIS 6
45 + */
46 +#define OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */
47 +#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C /* set only */
48 +#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */
49 +#define OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */
50 +#define OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */
51 +#define OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */
52 +
53 +struct ndis_offload_params {
54 + struct ndis_oject_header header;
55 + u8 ip_v4_csum;
56 + u8 tcp_ip_v4_csum;
57 + u8 udp_ip_v4_csum;
58 + u8 tcp_ip_v6_csum;
59 + u8 udp_ip_v6_csum;
60 + u8 lso_v1;
61 + u8 ip_sec_v1;
62 + u8 lso_v2_ipv4;
63 + u8 lso_v2_ipv6;
64 + u8 tcp_connection_ip_v4;
65 + u8 tcp_connection_ip_v6;
66 + u32 flags;
67 + u8 ip_sec_v2;
68 + u8 ip_sec_v2_ip_v4;
69 + struct {
70 + u8 rsc_ip_v4;
71 + u8 rsc_ip_v6;
72 + };
73 + struct {
74 + u8 encapsulated_packet_task_offload;
75 + u8 encapsulation_types;
76 + };
77 +};
78 +
79 #define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
80 sizeof(struct ndis_pkt_8021q_info))
81
82 diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
83 index dcbf144ea7da..9b02f21097a7 100644
84 --- a/drivers/net/hyperv/rndis_filter.c
85 +++ b/drivers/net/hyperv/rndis_filter.c
86 @@ -627,6 +627,61 @@ cleanup:
87 return ret;
88 }
89
90 +int rndis_filter_set_offload_params(struct hv_device *hdev,
91 + struct ndis_offload_params *req_offloads)
92 +{
93 + struct netvsc_device *nvdev = hv_get_drvdata(hdev);
94 + struct rndis_device *rdev = nvdev->extension;
95 + struct net_device *ndev = nvdev->ndev;
96 + struct rndis_request *request;
97 + struct rndis_set_request *set;
98 + struct ndis_offload_params *offload_params;
99 + struct rndis_set_complete *set_complete;
100 + u32 extlen = sizeof(struct ndis_offload_params);
101 + int ret, t;
102 +
103 + request = get_rndis_request(rdev, RNDIS_MSG_SET,
104 + RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
105 + if (!request)
106 + return -ENOMEM;
107 +
108 + set = &request->request_msg.msg.set_req;
109 + set->oid = OID_TCP_OFFLOAD_PARAMETERS;
110 + set->info_buflen = extlen;
111 + set->info_buf_offset = sizeof(struct rndis_set_request);
112 + set->dev_vc_handle = 0;
113 +
114 + offload_params = (struct ndis_offload_params *)((ulong)set +
115 + set->info_buf_offset);
116 + *offload_params = *req_offloads;
117 + offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
118 + offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
119 + offload_params->header.size = extlen;
120 +
121 + ret = rndis_filter_send_request(rdev, request);
122 + if (ret != 0)
123 + goto cleanup;
124 +
125 + t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
126 + if (t == 0) {
127 + netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n");
128 + /* can't put_rndis_request, since we may still receive a
129 + * send-completion.
130 + */
131 + return -EBUSY;
132 + } else {
133 + set_complete = &request->response_msg.msg.set_complete;
134 + if (set_complete->status != RNDIS_STATUS_SUCCESS) {
135 + netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
136 + set_complete->status);
137 + ret = -EINVAL;
138 + }
139 + }
140 +
141 +cleanup:
142 + put_rndis_request(rdev, request);
143 + return ret;
144 +}
145
146 static int rndis_filter_query_device_link_status(struct rndis_device *dev)
147 {
148 @@ -826,6 +881,7 @@ int rndis_filter_device_add(struct hv_device *dev,
149 struct netvsc_device *net_device;
150 struct rndis_device *rndis_device;
151 struct netvsc_device_info *device_info = additional_info;
152 + struct ndis_offload_params offloads;
153
154 rndis_device = get_rndis_device();
155 if (!rndis_device)
156 @@ -865,6 +921,26 @@ int rndis_filter_device_add(struct hv_device *dev,
157
158 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
159
160 + /* Turn on the offloads; the host supports all of the relevant
161 + * offloads.
162 + */
163 + memset(&offloads, 0, sizeof(struct ndis_offload_params));
164 + /* A value of zero means "no change"; now turn on what we
165 + * want.
166 + */
167 + offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
168 + offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
169 + offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
170 + offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
171 + offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
172 + offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
173 +
174 +
175 + ret = rndis_filter_set_offload_params(dev, &offloads);
176 + if (ret)
177 + goto err_dev_remv;
178 +
179 +
180 rndis_filter_query_device_link_status(rndis_device);
181
182 device_info->link_state = rndis_device->link_state;
183 @@ -874,6 +950,10 @@ int rndis_filter_device_add(struct hv_device *dev,
184 device_info->link_state ? "down" : "up");
185
186 return ret;
187 +
188 +err_dev_remv:
189 + rndis_filter_device_remove(dev);
190 + return ret;
191 }
192
193 void rndis_filter_device_remove(struct hv_device *dev)
194 --
195 2.4.3
196