]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/hyperv/rndis_filter.c
Merge branch 'qed_hw_gro'
[mirror_ubuntu-artful-kernel.git] / drivers / net / hyperv / rndis_filter.c
CommitLineData
fceaf24a 1/*
fceaf24a
HJ
2 * Copyright (c) 2009, Microsoft Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
adf8d3ff 14 * this program; if not, see <http://www.gnu.org/licenses/>.
fceaf24a
HJ
15 *
16 * Authors:
17 * Haiyang Zhang <haiyangz@microsoft.com>
18 * Hank Janssen <hjanssen@microsoft.com>
fceaf24a 19 */
5654e932 20#include <linux/kernel.h>
0c3b7b2f
S
21#include <linux/sched.h>
22#include <linux/wait.h>
45da89e5 23#include <linux/highmem.h>
5a0e3ad6 24#include <linux/slab.h>
0120ee0d 25#include <linux/io.h>
9f8bd8ba 26#include <linux/if_ether.h>
eb335bc4 27#include <linux/netdevice.h>
1f5f3a75 28#include <linux/if_vlan.h>
1ce09e89 29#include <linux/nls.h>
d6472302 30#include <linux/vmalloc.h>
3f335ea2 31
5ca7252a 32#include "hyperv_net.h"
fceaf24a 33
fceaf24a 34
5b54dac8 35#define RNDIS_EXT_LEN PAGE_SIZE
e681b954 36struct rndis_request {
c2a4efdd 37 struct list_head list_ent;
98d79690 38 struct completion wait_event;
fceaf24a 39
a3a6cab5 40 struct rndis_message response_msg;
0120ee0d 41 /*
a3a6cab5
HZ
42 * The buffer for extended info after the RNDIS response message. It's
43 * referenced based on the data offset in the RNDIS message. Its size
44 * is enough for current needs, and should be sufficient for the near
45 * future.
0120ee0d 46 */
a3a6cab5 47 u8 response_ext[RNDIS_EXT_LEN];
fceaf24a 48
454f18a9 49 /* Simplify allocation by having a netvsc packet inline */
c2a4efdd 50 struct hv_netvsc_packet pkt;
0f48917b 51
c2a4efdd 52 struct rndis_message request_msg;
0f48917b 53 /*
a3a6cab5
HZ
54 * The buffer for the extended info after the RNDIS request message.
55 * It is referenced and sized in a similar way as response_ext.
0f48917b 56 */
a3a6cab5 57 u8 request_ext[RNDIS_EXT_LEN];
e681b954 58};
fceaf24a 59
9c26aa0d 60static struct rndis_device *get_rndis_device(void)
fceaf24a 61{
e681b954 62 struct rndis_device *device;
fceaf24a 63
e681b954 64 device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
fceaf24a 65 if (!device)
fceaf24a 66 return NULL;
fceaf24a 67
880fb89c 68 spin_lock_init(&device->request_lock);
fceaf24a 69
c2a4efdd 70 INIT_LIST_HEAD(&device->req_list);
fceaf24a 71
c2a4efdd 72 device->state = RNDIS_DEV_UNINITIALIZED;
fceaf24a
HJ
73
74 return device;
75}
76
9c26aa0d 77static struct rndis_request *get_rndis_request(struct rndis_device *dev,
c2a4efdd
HZ
78 u32 msg_type,
79 u32 msg_len)
fceaf24a 80{
e681b954 81 struct rndis_request *request;
c2a4efdd 82 struct rndis_message *rndis_msg;
9f33d054 83 struct rndis_set_request *set;
880fb89c 84 unsigned long flags;
fceaf24a 85
e681b954 86 request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
fceaf24a 87 if (!request)
fceaf24a 88 return NULL;
fceaf24a 89
98d79690 90 init_completion(&request->wait_event);
fceaf24a 91
c2a4efdd 92 rndis_msg = &request->request_msg;
a388eb17
HZ
93 rndis_msg->ndis_msg_type = msg_type;
94 rndis_msg->msg_len = msg_len;
fceaf24a 95
5b54dac8
HZ
96 request->pkt.q_idx = 0;
97
0120ee0d
GKH
98 /*
99 * Set the request id. This field is always after the rndis header for
100 * request/response packet types so we just used the SetRequest as a
101 * template
102 */
a388eb17
HZ
103 set = &rndis_msg->msg.set_req;
104 set->req_id = atomic_inc_return(&dev->new_req_id);
fceaf24a 105
454f18a9 106 /* Add to the request list */
c2a4efdd
HZ
107 spin_lock_irqsave(&dev->request_lock, flags);
108 list_add_tail(&request->list_ent, &dev->req_list);
109 spin_unlock_irqrestore(&dev->request_lock, flags);
fceaf24a
HJ
110
111 return request;
112}
113
9c26aa0d 114static void put_rndis_request(struct rndis_device *dev,
c2a4efdd 115 struct rndis_request *req)
fceaf24a 116{
880fb89c
GKH
117 unsigned long flags;
118
c2a4efdd
HZ
119 spin_lock_irqsave(&dev->request_lock, flags);
120 list_del(&req->list_ent);
121 spin_unlock_irqrestore(&dev->request_lock, flags);
fceaf24a 122
c2a4efdd 123 kfree(req);
fceaf24a
HJ
124}
125
729a2849
HZ
126static void dump_rndis_message(struct hv_device *hv_dev,
127 struct rndis_message *rndis_msg)
fceaf24a 128{
2ddd5e5f
S
129 struct net_device *netdev;
130 struct netvsc_device *net_device;
131
132 net_device = hv_get_drvdata(hv_dev);
133 netdev = net_device->ndev;
729a2849 134
a388eb17 135 switch (rndis_msg->ndis_msg_type) {
51491167
LW
136 case RNDIS_MSG_PACKET:
137 netdev_dbg(netdev, "RNDIS_MSG_PACKET (len %u, "
0120ee0d
GKH
138 "data offset %u data len %u, # oob %u, "
139 "oob offset %u, oob len %u, pkt offset %u, "
729a2849 140 "pkt len %u\n",
a388eb17
HZ
141 rndis_msg->msg_len,
142 rndis_msg->msg.pkt.data_offset,
143 rndis_msg->msg.pkt.data_len,
144 rndis_msg->msg.pkt.num_oob_data_elements,
145 rndis_msg->msg.pkt.oob_data_offset,
146 rndis_msg->msg.pkt.oob_data_len,
147 rndis_msg->msg.pkt.per_pkt_info_offset,
148 rndis_msg->msg.pkt.per_pkt_info_len);
fceaf24a
HJ
149 break;
150
51491167
LW
151 case RNDIS_MSG_INIT_C:
152 netdev_dbg(netdev, "RNDIS_MSG_INIT_C "
0120ee0d
GKH
153 "(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
154 "device flags %d, max xfer size 0x%x, max pkts %u, "
729a2849 155 "pkt aligned %u)\n",
a388eb17
HZ
156 rndis_msg->msg_len,
157 rndis_msg->msg.init_complete.req_id,
158 rndis_msg->msg.init_complete.status,
159 rndis_msg->msg.init_complete.major_ver,
160 rndis_msg->msg.init_complete.minor_ver,
161 rndis_msg->msg.init_complete.dev_flags,
162 rndis_msg->msg.init_complete.max_xfer_size,
163 rndis_msg->msg.init_complete.
164 max_pkt_per_msg,
165 rndis_msg->msg.init_complete.
166 pkt_alignment_factor);
fceaf24a
HJ
167 break;
168
51491167
LW
169 case RNDIS_MSG_QUERY_C:
170 netdev_dbg(netdev, "RNDIS_MSG_QUERY_C "
0120ee0d 171 "(len %u, id 0x%x, status 0x%x, buf len %u, "
729a2849 172 "buf offset %u)\n",
a388eb17
HZ
173 rndis_msg->msg_len,
174 rndis_msg->msg.query_complete.req_id,
175 rndis_msg->msg.query_complete.status,
176 rndis_msg->msg.query_complete.
177 info_buflen,
178 rndis_msg->msg.query_complete.
179 info_buf_offset);
fceaf24a
HJ
180 break;
181
51491167 182 case RNDIS_MSG_SET_C:
729a2849 183 netdev_dbg(netdev,
51491167 184 "RNDIS_MSG_SET_C (len %u, id 0x%x, status 0x%x)\n",
a388eb17
HZ
185 rndis_msg->msg_len,
186 rndis_msg->msg.set_complete.req_id,
187 rndis_msg->msg.set_complete.status);
fceaf24a
HJ
188 break;
189
51491167
LW
190 case RNDIS_MSG_INDICATE:
191 netdev_dbg(netdev, "RNDIS_MSG_INDICATE "
729a2849 192 "(len %u, status 0x%x, buf len %u, buf offset %u)\n",
a388eb17
HZ
193 rndis_msg->msg_len,
194 rndis_msg->msg.indicate_status.status,
195 rndis_msg->msg.indicate_status.status_buflen,
196 rndis_msg->msg.indicate_status.status_buf_offset);
fceaf24a
HJ
197 break;
198
199 default:
729a2849 200 netdev_dbg(netdev, "0x%x (len %u)\n",
a388eb17
HZ
201 rndis_msg->ndis_msg_type,
202 rndis_msg->msg_len);
fceaf24a
HJ
203 break;
204 }
205}
206
9c26aa0d 207static int rndis_filter_send_request(struct rndis_device *dev,
c2a4efdd 208 struct rndis_request *req)
fceaf24a 209{
0120ee0d 210 int ret;
4193d4f4 211 struct hv_netvsc_packet *packet;
b08cc791 212 struct hv_page_buffer page_buf[2];
a9f2e2d6 213 struct hv_page_buffer *pb = page_buf;
fceaf24a 214
454f18a9 215 /* Setup the packet to send it */
c2a4efdd 216 packet = &req->pkt;
fceaf24a 217
a388eb17 218 packet->total_data_buflen = req->request_msg.msg_len;
72a2f5bd 219 packet->page_buf_cnt = 1;
fceaf24a 220
a9f2e2d6 221 pb[0].pfn = virt_to_phys(&req->request_msg) >>
0120ee0d 222 PAGE_SHIFT;
a9f2e2d6
KS
223 pb[0].len = req->request_msg.msg_len;
224 pb[0].offset =
c2a4efdd 225 (unsigned long)&req->request_msg & (PAGE_SIZE - 1);
fceaf24a 226
99e3fcfa 227 /* Add one page_buf when request_msg crossing page boundary */
a9f2e2d6 228 if (pb[0].offset + pb[0].len > PAGE_SIZE) {
99e3fcfa 229 packet->page_buf_cnt++;
a9f2e2d6
KS
230 pb[0].len = PAGE_SIZE -
231 pb[0].offset;
232 pb[1].pfn = virt_to_phys((void *)&req->request_msg
233 + pb[0].len) >> PAGE_SHIFT;
234 pb[1].offset = 0;
235 pb[1].len = req->request_msg.msg_len -
236 pb[0].len;
99e3fcfa
HZ
237 }
238
3a3d9a0a 239 ret = netvsc_send(dev->net_dev->dev, packet, NULL, &pb, NULL);
fceaf24a
HJ
240 return ret;
241}
242
1b07da51
HZ
243static void rndis_set_link_state(struct rndis_device *rdev,
244 struct rndis_request *request)
245{
246 u32 link_status;
247 struct rndis_query_complete *query_complete;
248
249 query_complete = &request->response_msg.msg.query_complete;
250
251 if (query_complete->status == RNDIS_STATUS_SUCCESS &&
252 query_complete->info_buflen == sizeof(u32)) {
253 memcpy(&link_status, (void *)((unsigned long)query_complete +
254 query_complete->info_buf_offset), sizeof(u32));
255 rdev->link_state = link_status != 0;
256 }
257}
258
9c26aa0d 259static void rndis_filter_receive_response(struct rndis_device *dev,
c2a4efdd 260 struct rndis_message *resp)
fceaf24a 261{
e681b954 262 struct rndis_request *request = NULL;
0e727613 263 bool found = false;
880fb89c 264 unsigned long flags;
2ddd5e5f
S
265 struct net_device *ndev;
266
267 ndev = dev->net_dev->ndev;
fceaf24a 268
c2a4efdd
HZ
269 spin_lock_irqsave(&dev->request_lock, flags);
270 list_for_each_entry(request, &dev->req_list, list_ent) {
0120ee0d
GKH
271 /*
272 * All request/response message contains RequestId as the 1st
273 * field
274 */
a388eb17
HZ
275 if (request->request_msg.msg.init_req.req_id
276 == resp->msg.init_complete.req_id) {
0e727613 277 found = true;
fceaf24a
HJ
278 break;
279 }
280 }
c2a4efdd 281 spin_unlock_irqrestore(&dev->request_lock, flags);
fceaf24a 282
0120ee0d 283 if (found) {
a3a6cab5
HZ
284 if (resp->msg_len <=
285 sizeof(struct rndis_message) + RNDIS_EXT_LEN) {
c2a4efdd 286 memcpy(&request->response_msg, resp,
a388eb17 287 resp->msg_len);
1b07da51
HZ
288 if (request->request_msg.ndis_msg_type ==
289 RNDIS_MSG_QUERY && request->request_msg.msg.
290 query_req.oid == RNDIS_OID_GEN_MEDIA_CONNECT_STATUS)
291 rndis_set_link_state(dev, request);
0120ee0d 292 } else {
d9871158 293 netdev_err(ndev,
eb335bc4
HJ
294 "rndis response buffer overflow "
295 "detected (size %u max %zu)\n",
296 resp->msg_len,
86eedacc 297 sizeof(struct rndis_message));
0120ee0d 298
a388eb17 299 if (resp->ndis_msg_type ==
51491167 300 RNDIS_MSG_RESET_C) {
0120ee0d 301 /* does not have a request id field */
a388eb17 302 request->response_msg.msg.reset_complete.
007e5c8e 303 status = RNDIS_STATUS_BUFFER_OVERFLOW;
0120ee0d 304 } else {
a388eb17
HZ
305 request->response_msg.msg.
306 init_complete.status =
007e5c8e 307 RNDIS_STATUS_BUFFER_OVERFLOW;
fceaf24a
HJ
308 }
309 }
310
98d79690 311 complete(&request->wait_event);
0120ee0d 312 } else {
d9871158 313 netdev_err(ndev,
eb335bc4
HJ
314 "no rndis request found for this response "
315 "(id 0x%x res type 0x%x)\n",
316 resp->msg.init_complete.req_id,
317 resp->ndis_msg_type);
fceaf24a 318 }
fceaf24a
HJ
319}
320
1f5f3a75
HZ
321/*
322 * Get the Per-Packet-Info with the specified type
323 * return NULL if not found.
324 */
325static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type)
326{
327 struct rndis_per_packet_info *ppi;
328 int len;
329
330 if (rpkt->per_pkt_info_offset == 0)
331 return NULL;
332
333 ppi = (struct rndis_per_packet_info *)((ulong)rpkt +
334 rpkt->per_pkt_info_offset);
335 len = rpkt->per_pkt_info_len;
336
337 while (len > 0) {
338 if (ppi->type == type)
339 return (void *)((ulong)ppi + ppi->ppi_offset);
340 len -= ppi->size;
341 ppi = (struct rndis_per_packet_info *)((ulong)ppi + ppi->size);
342 }
343
344 return NULL;
345}
346
10082f98 347static int rndis_filter_receive_data(struct rndis_device *dev,
c2a4efdd 348 struct rndis_message *msg,
25b85ee8 349 struct hv_netvsc_packet *pkt,
c4b20c63 350 void **data,
25b85ee8 351 struct vmbus_channel *channel)
fceaf24a 352{
c2a4efdd
HZ
353 struct rndis_packet *rndis_pkt;
354 u32 data_offset;
1f5f3a75 355 struct ndis_pkt_8021q_info *vlan;
e3d605ed 356 struct ndis_tcp_ip_checksum_info *csum_info;
760d1e36 357 u16 vlan_tci = 0;
fceaf24a 358
a388eb17 359 rndis_pkt = &msg->msg.pkt;
fceaf24a 360
454f18a9 361 /* Remove the rndis header and pass it back up the stack */
a388eb17 362 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
fceaf24a 363
72a2f5bd 364 pkt->total_data_buflen -= data_offset;
4b8a8bc9
WY
365
366 /*
367 * Make sure we got a valid RNDIS message, now total_data_buflen
368 * should be the data packet size plus the trailer padding size
369 */
370 if (pkt->total_data_buflen < rndis_pkt->data_len) {
371 netdev_err(dev->net_dev->ndev, "rndis message buffer "
372 "overflow detected (got %u, min %u)"
373 "...dropping this message!\n",
374 pkt->total_data_buflen, rndis_pkt->data_len);
10082f98 375 return NVSP_STAT_FAIL;
4b8a8bc9
WY
376 }
377
378 /*
379 * Remove the rndis trailer padding from rndis packet message
380 * rndis_pkt->data_len tell us the real data length, we only copy
381 * the data packet to the stack, without the rndis trailer padding
382 */
383 pkt->total_data_buflen = rndis_pkt->data_len;
c4b20c63 384 *data = (void *)((unsigned long)(*data) + data_offset);
669c1fc6 385
1f5f3a75
HZ
386 vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO);
387 if (vlan) {
760d1e36 388 vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid |
1f5f3a75 389 (vlan->pri << VLAN_PRIO_SHIFT);
1f5f3a75
HZ
390 }
391
e3d605ed 392 csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO);
10082f98 393 return netvsc_recv_callback(dev->net_dev->dev, pkt, data,
760d1e36 394 csum_info, channel, vlan_tci);
fceaf24a
HJ
395}
396
5fcc4115 397int rndis_filter_receive(struct hv_device *dev,
25b85ee8 398 struct hv_netvsc_packet *pkt,
c4b20c63 399 void **data,
25b85ee8 400 struct vmbus_channel *channel)
fceaf24a 401{
2ddd5e5f 402 struct netvsc_device *net_dev = hv_get_drvdata(dev);
c2a4efdd 403 struct rndis_device *rndis_dev;
ef31bef6 404 struct rndis_message *rndis_msg;
2ddd5e5f 405 struct net_device *ndev;
63f6921d 406 int ret = 0;
2ddd5e5f 407
63f6921d 408 if (!net_dev) {
10082f98 409 ret = NVSP_STAT_FAIL;
63f6921d
HZ
410 goto exit;
411 }
8a62d716 412
715a4801
S
413 ndev = net_dev->ndev;
414
454f18a9 415 /* Make sure the rndis device state is initialized */
53d21fdb 416 if (!net_dev->extension) {
d9871158 417 netdev_err(ndev, "got rndis message but no rndis device - "
eb335bc4 418 "dropping this message!\n");
10082f98 419 ret = NVSP_STAT_FAIL;
63f6921d 420 goto exit;
fceaf24a
HJ
421 }
422
53d21fdb 423 rndis_dev = (struct rndis_device *)net_dev->extension;
c2a4efdd 424 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
d9871158 425 netdev_err(ndev, "got rndis message but rndis device "
eb335bc4 426 "uninitialized...dropping this message!\n");
10082f98 427 ret = NVSP_STAT_FAIL;
63f6921d 428 goto exit;
fceaf24a
HJ
429 }
430
c4b20c63 431 rndis_msg = *data;
fceaf24a 432
3f300ff4
SX
433 if (netif_msg_rx_err(net_dev->nd_ctx))
434 dump_rndis_message(dev, rndis_msg);
fceaf24a 435
ef31bef6 436 switch (rndis_msg->ndis_msg_type) {
51491167 437 case RNDIS_MSG_PACKET:
0120ee0d 438 /* data msg */
10082f98
KS
439 ret = rndis_filter_receive_data(rndis_dev, rndis_msg, pkt,
440 data, channel);
fceaf24a
HJ
441 break;
442
51491167
LW
443 case RNDIS_MSG_INIT_C:
444 case RNDIS_MSG_QUERY_C:
445 case RNDIS_MSG_SET_C:
0120ee0d 446 /* completion msgs */
ef31bef6 447 rndis_filter_receive_response(rndis_dev, rndis_msg);
fceaf24a
HJ
448 break;
449
51491167 450 case RNDIS_MSG_INDICATE:
0120ee0d 451 /* notification msgs */
3a494e71 452 netvsc_linkstatus_callback(dev, rndis_msg);
fceaf24a
HJ
453 break;
454 default:
d9871158 455 netdev_err(ndev,
eb335bc4 456 "unhandled rndis message (type %u len %u)\n",
ef31bef6
HZ
457 rndis_msg->ndis_msg_type,
458 rndis_msg->msg_len);
fceaf24a
HJ
459 break;
460 }
461
63f6921d 462exit:
63f6921d 463 return ret;
fceaf24a
HJ
464}
465
9c26aa0d 466static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
c2a4efdd 467 void *result, u32 *result_size)
fceaf24a 468{
e681b954 469 struct rndis_request *request;
c2a4efdd 470 u32 inresult_size = *result_size;
9f33d054 471 struct rndis_query_request *query;
c2a4efdd 472 struct rndis_query_complete *query_complete;
0120ee0d 473 int ret = 0;
999028cc 474 unsigned long t;
fceaf24a 475
c2a4efdd 476 if (!result)
8a62d716 477 return -EINVAL;
fceaf24a 478
c2a4efdd 479 *result_size = 0;
51491167 480 request = get_rndis_request(dev, RNDIS_MSG_QUERY,
0120ee0d
GKH
481 RNDIS_MESSAGE_SIZE(struct rndis_query_request));
482 if (!request) {
de6e0580 483 ret = -ENOMEM;
1c627870 484 goto cleanup;
fceaf24a
HJ
485 }
486
454f18a9 487 /* Setup the rndis query */
a388eb17
HZ
488 query = &request->request_msg.msg.query_req;
489 query->oid = oid;
490 query->info_buf_offset = sizeof(struct rndis_query_request);
491 query->info_buflen = 0;
492 query->dev_vc_handle = 0;
fceaf24a 493
5b54dac8
HZ
494 if (oid == OID_GEN_RECEIVE_SCALE_CAPABILITIES) {
495 struct ndis_recv_scale_cap *cap;
496
497 request->request_msg.msg_len +=
498 sizeof(struct ndis_recv_scale_cap);
499 query->info_buflen = sizeof(struct ndis_recv_scale_cap);
500 cap = (struct ndis_recv_scale_cap *)((unsigned long)query +
501 query->info_buf_offset);
502 cap->hdr.type = NDIS_OBJECT_TYPE_RSS_CAPABILITIES;
503 cap->hdr.rev = NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
504 cap->hdr.size = sizeof(struct ndis_recv_scale_cap);
505 }
506
9c26aa0d 507 ret = rndis_filter_send_request(dev, request);
fceaf24a 508 if (ret != 0)
1c627870 509 goto cleanup;
fceaf24a 510
5c5781b3 511 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
98d79690 512 if (t == 0) {
0c3b7b2f 513 ret = -ETIMEDOUT;
1c627870 514 goto cleanup;
0c3b7b2f 515 }
fceaf24a 516
454f18a9 517 /* Copy the response back */
a388eb17 518 query_complete = &request->response_msg.msg.query_complete;
fceaf24a 519
a388eb17 520 if (query_complete->info_buflen > inresult_size) {
fceaf24a 521 ret = -1;
1c627870 522 goto cleanup;
fceaf24a
HJ
523 }
524
c2a4efdd
HZ
525 memcpy(result,
526 (void *)((unsigned long)query_complete +
a388eb17
HZ
527 query_complete->info_buf_offset),
528 query_complete->info_buflen);
fceaf24a 529
a388eb17 530 *result_size = query_complete->info_buflen;
fceaf24a 531
1c627870 532cleanup:
fceaf24a 533 if (request)
9c26aa0d 534 put_rndis_request(dev, request);
fceaf24a
HJ
535
536 return ret;
537}
538
9c26aa0d 539static int rndis_filter_query_device_mac(struct rndis_device *dev)
fceaf24a 540{
9f8bd8ba 541 u32 size = ETH_ALEN;
fceaf24a 542
9c26aa0d 543 return rndis_filter_query_device(dev,
0120ee0d 544 RNDIS_OID_802_3_PERMANENT_ADDRESS,
c2a4efdd 545 dev->hw_mac_adr, &size);
fceaf24a
HJ
546}
547
1ce09e89
HZ
548#define NWADR_STR "NetworkAddress"
549#define NWADR_STRLEN 14
550
551int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac)
552{
553 struct netvsc_device *nvdev = hv_get_drvdata(hdev);
554 struct rndis_device *rdev = nvdev->extension;
555 struct net_device *ndev = nvdev->ndev;
556 struct rndis_request *request;
557 struct rndis_set_request *set;
558 struct rndis_config_parameter_info *cpi;
559 wchar_t *cfg_nwadr, *cfg_mac;
560 struct rndis_set_complete *set_complete;
561 char macstr[2*ETH_ALEN+1];
562 u32 extlen = sizeof(struct rndis_config_parameter_info) +
563 2*NWADR_STRLEN + 4*ETH_ALEN;
999028cc
NMG
564 int ret;
565 unsigned long t;
1ce09e89
HZ
566
567 request = get_rndis_request(rdev, RNDIS_MSG_SET,
568 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
569 if (!request)
570 return -ENOMEM;
571
572 set = &request->request_msg.msg.set_req;
573 set->oid = RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER;
574 set->info_buflen = extlen;
575 set->info_buf_offset = sizeof(struct rndis_set_request);
576 set->dev_vc_handle = 0;
577
578 cpi = (struct rndis_config_parameter_info *)((ulong)set +
579 set->info_buf_offset);
580 cpi->parameter_name_offset =
581 sizeof(struct rndis_config_parameter_info);
582 /* Multiply by 2 because host needs 2 bytes (utf16) for each char */
583 cpi->parameter_name_length = 2*NWADR_STRLEN;
584 cpi->parameter_type = RNDIS_CONFIG_PARAM_TYPE_STRING;
585 cpi->parameter_value_offset =
586 cpi->parameter_name_offset + cpi->parameter_name_length;
587 /* Multiply by 4 because each MAC byte displayed as 2 utf16 chars */
588 cpi->parameter_value_length = 4*ETH_ALEN;
589
590 cfg_nwadr = (wchar_t *)((ulong)cpi + cpi->parameter_name_offset);
591 cfg_mac = (wchar_t *)((ulong)cpi + cpi->parameter_value_offset);
592 ret = utf8s_to_utf16s(NWADR_STR, NWADR_STRLEN, UTF16_HOST_ENDIAN,
593 cfg_nwadr, NWADR_STRLEN);
594 if (ret < 0)
595 goto cleanup;
596 snprintf(macstr, 2*ETH_ALEN+1, "%pm", mac);
597 ret = utf8s_to_utf16s(macstr, 2*ETH_ALEN, UTF16_HOST_ENDIAN,
598 cfg_mac, 2*ETH_ALEN);
599 if (ret < 0)
600 goto cleanup;
601
602 ret = rndis_filter_send_request(rdev, request);
603 if (ret != 0)
604 goto cleanup;
605
606 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
607 if (t == 0) {
608 netdev_err(ndev, "timeout before we got a set response...\n");
609 /*
610 * can't put_rndis_request, since we may still receive a
611 * send-completion.
612 */
613 return -EBUSY;
614 } else {
615 set_complete = &request->response_msg.msg.set_complete;
b02a8067
HZ
616 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
617 netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
618 set_complete->status);
1ce09e89 619 ret = -EINVAL;
b02a8067 620 }
1ce09e89
HZ
621 }
622
623cleanup:
624 put_rndis_request(rdev, request);
625 return ret;
626}
627
da19fcd0
LP
628static int
629rndis_filter_set_offload_params(struct hv_device *hdev,
4a0e70ae
KS
630 struct ndis_offload_params *req_offloads)
631{
632 struct netvsc_device *nvdev = hv_get_drvdata(hdev);
633 struct rndis_device *rdev = nvdev->extension;
634 struct net_device *ndev = nvdev->ndev;
635 struct rndis_request *request;
636 struct rndis_set_request *set;
637 struct ndis_offload_params *offload_params;
638 struct rndis_set_complete *set_complete;
639 u32 extlen = sizeof(struct ndis_offload_params);
999028cc
NMG
640 int ret;
641 unsigned long t;
af9893a3
KS
642 u32 vsp_version = nvdev->nvsp_version;
643
644 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
645 extlen = VERSION_4_OFFLOAD_SIZE;
646 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
647 * UDP checksum offload.
648 */
649 req_offloads->udp_ip_v4_csum = 0;
650 req_offloads->udp_ip_v6_csum = 0;
651 }
4a0e70ae
KS
652
653 request = get_rndis_request(rdev, RNDIS_MSG_SET,
654 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
655 if (!request)
656 return -ENOMEM;
657
658 set = &request->request_msg.msg.set_req;
659 set->oid = OID_TCP_OFFLOAD_PARAMETERS;
660 set->info_buflen = extlen;
661 set->info_buf_offset = sizeof(struct rndis_set_request);
662 set->dev_vc_handle = 0;
663
664 offload_params = (struct ndis_offload_params *)((ulong)set +
665 set->info_buf_offset);
666 *offload_params = *req_offloads;
667 offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
668 offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
669 offload_params->header.size = extlen;
670
671 ret = rndis_filter_send_request(rdev, request);
672 if (ret != 0)
673 goto cleanup;
674
675 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
676 if (t == 0) {
677 netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n");
678 /* can't put_rndis_request, since we may still receive a
679 * send-completion.
680 */
681 return -EBUSY;
682 } else {
683 set_complete = &request->response_msg.msg.set_complete;
684 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
af9893a3 685 netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
4a0e70ae
KS
686 set_complete->status);
687 ret = -EINVAL;
688 }
689 }
690
691cleanup:
692 put_rndis_request(rdev, request);
693 return ret;
694}
1ce09e89 695
5b54dac8
HZ
696u8 netvsc_hash_key[HASH_KEYLEN] = {
697 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
698 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
699 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
700 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
701 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
702};
703
da19fcd0 704static int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
5b54dac8
HZ
705{
706 struct net_device *ndev = rdev->net_dev->ndev;
707 struct rndis_request *request;
708 struct rndis_set_request *set;
709 struct rndis_set_complete *set_complete;
710 u32 extlen = sizeof(struct ndis_recv_scale_param) +
711 4*ITAB_NUM + HASH_KEYLEN;
712 struct ndis_recv_scale_param *rssp;
713 u32 *itab;
714 u8 *keyp;
999028cc
NMG
715 int i, ret;
716 unsigned long t;
5b54dac8
HZ
717
718 request = get_rndis_request(
719 rdev, RNDIS_MSG_SET,
720 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
721 if (!request)
722 return -ENOMEM;
723
724 set = &request->request_msg.msg.set_req;
725 set->oid = OID_GEN_RECEIVE_SCALE_PARAMETERS;
726 set->info_buflen = extlen;
727 set->info_buf_offset = sizeof(struct rndis_set_request);
728 set->dev_vc_handle = 0;
729
730 rssp = (struct ndis_recv_scale_param *)(set + 1);
731 rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
732 rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
733 rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
734 rssp->flag = 0;
735 rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
4c87454a
HZ
736 NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
737 NDIS_HASH_TCP_IPV6;
5b54dac8
HZ
738 rssp->indirect_tabsize = 4*ITAB_NUM;
739 rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
740 rssp->hashkey_size = HASH_KEYLEN;
741 rssp->kashkey_offset = rssp->indirect_taboffset +
742 rssp->indirect_tabsize;
743
744 /* Set indirection table entries */
745 itab = (u32 *)(rssp + 1);
746 for (i = 0; i < ITAB_NUM; i++)
747 itab[i] = i % num_queue;
748
749 /* Set hask key values */
750 keyp = (u8 *)((unsigned long)rssp + rssp->kashkey_offset);
751 for (i = 0; i < HASH_KEYLEN; i++)
752 keyp[i] = netvsc_hash_key[i];
753
754
755 ret = rndis_filter_send_request(rdev, request);
756 if (ret != 0)
757 goto cleanup;
758
759 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
760 if (t == 0) {
761 netdev_err(ndev, "timeout before we got a set response...\n");
762 /* can't put_rndis_request, since we may still receive a
763 * send-completion.
764 */
765 return -ETIMEDOUT;
766 } else {
767 set_complete = &request->response_msg.msg.set_complete;
768 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
769 netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
770 set_complete->status);
771 ret = -EINVAL;
772 }
773 }
774
775cleanup:
776 put_rndis_request(rdev, request);
777 return ret;
778}
779
780
9c26aa0d 781static int rndis_filter_query_device_link_status(struct rndis_device *dev)
fceaf24a 782{
0120ee0d 783 u32 size = sizeof(u32);
6f27457b
S
784 u32 link_status;
785 int ret;
fceaf24a 786
6f27457b 787 ret = rndis_filter_query_device(dev,
0120ee0d 788 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
6f27457b 789 &link_status, &size);
6f27457b
S
790
791 return ret;
fceaf24a
HJ
792}
793
d426b2e3 794int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
fceaf24a 795{
e681b954 796 struct rndis_request *request;
9f33d054 797 struct rndis_set_request *set;
c2a4efdd 798 struct rndis_set_complete *set_complete;
4d643114 799 u32 status;
999028cc
NMG
800 int ret;
801 unsigned long t;
2ddd5e5f
S
802 struct net_device *ndev;
803
804 ndev = dev->net_dev->ndev;
fceaf24a 805
51491167 806 request = get_rndis_request(dev, RNDIS_MSG_SET,
0120ee0d
GKH
807 RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
808 sizeof(u32));
809 if (!request) {
58ef3977 810 ret = -ENOMEM;
1c627870 811 goto cleanup;
fceaf24a
HJ
812 }
813
454f18a9 814 /* Setup the rndis set */
a388eb17
HZ
815 set = &request->request_msg.msg.set_req;
816 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
817 set->info_buflen = sizeof(u32);
818 set->info_buf_offset = sizeof(struct rndis_set_request);
fceaf24a 819
0120ee0d 820 memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
c2a4efdd 821 &new_filter, sizeof(u32));
fceaf24a 822
9c26aa0d 823 ret = rndis_filter_send_request(dev, request);
fceaf24a 824 if (ret != 0)
1c627870 825 goto cleanup;
fceaf24a 826
5c5781b3 827 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
98d79690
S
828
829 if (t == 0) {
d9871158 830 netdev_err(ndev,
eb335bc4 831 "timeout before we got a set response...\n");
ea496374 832 ret = -ETIMEDOUT;
0120ee0d 833 /*
25985edc 834 * We can't deallocate the request since we may still receive a
0120ee0d
GKH
835 * send completion for it.
836 */
5585d81e 837 goto exit;
0120ee0d 838 } else {
a388eb17
HZ
839 set_complete = &request->response_msg.msg.set_complete;
840 status = set_complete->status;
fceaf24a
HJ
841 }
842
1c627870 843cleanup:
fceaf24a 844 if (request)
9c26aa0d 845 put_rndis_request(dev, request);
5585d81e 846exit:
fceaf24a
HJ
847 return ret;
848}
849
fceaf24a 850
9c26aa0d 851static int rndis_filter_init_device(struct rndis_device *dev)
fceaf24a 852{
e681b954 853 struct rndis_request *request;
9f33d054 854 struct rndis_initialize_request *init;
c2a4efdd 855 struct rndis_initialize_complete *init_complete;
4d643114 856 u32 status;
999028cc
NMG
857 int ret;
858 unsigned long t;
7c3877f2 859 struct netvsc_device *nvdev = dev->net_dev;
fceaf24a 860
51491167 861 request = get_rndis_request(dev, RNDIS_MSG_INIT,
0120ee0d
GKH
862 RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
863 if (!request) {
bc49b926 864 ret = -ENOMEM;
1c627870 865 goto cleanup;
fceaf24a
HJ
866 }
867
454f18a9 868 /* Setup the rndis set */
a388eb17
HZ
869 init = &request->request_msg.msg.init_req;
870 init->major_ver = RNDIS_MAJOR_VERSION;
871 init->minor_ver = RNDIS_MINOR_VERSION;
fb1d074e 872 init->max_xfer_size = 0x4000;
fceaf24a 873
c2a4efdd 874 dev->state = RNDIS_DEV_INITIALIZING;
fceaf24a 875
9c26aa0d 876 ret = rndis_filter_send_request(dev, request);
0120ee0d 877 if (ret != 0) {
c2a4efdd 878 dev->state = RNDIS_DEV_UNINITIALIZED;
1c627870 879 goto cleanup;
fceaf24a
HJ
880 }
881
0c3b7b2f 882
5c5781b3 883 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
98d79690
S
884
885 if (t == 0) {
0c3b7b2f 886 ret = -ETIMEDOUT;
1c627870 887 goto cleanup;
0c3b7b2f 888 }
fceaf24a 889
a388eb17
HZ
890 init_complete = &request->response_msg.msg.init_complete;
891 status = init_complete->status;
0120ee0d 892 if (status == RNDIS_STATUS_SUCCESS) {
c2a4efdd 893 dev->state = RNDIS_DEV_INITIALIZED;
7c3877f2
HZ
894 nvdev->max_pkt = init_complete->max_pkt_per_msg;
895 nvdev->pkt_align = 1 << init_complete->pkt_alignment_factor;
fceaf24a 896 ret = 0;
0120ee0d 897 } else {
c2a4efdd 898 dev->state = RNDIS_DEV_UNINITIALIZED;
bc49b926 899 ret = -EINVAL;
fceaf24a
HJ
900 }
901
1c627870 902cleanup:
fceaf24a 903 if (request)
9c26aa0d 904 put_rndis_request(dev, request);
fceaf24a
HJ
905
906 return ret;
907}
908
9c26aa0d 909static void rndis_filter_halt_device(struct rndis_device *dev)
fceaf24a 910{
e681b954 911 struct rndis_request *request;
9f33d054 912 struct rndis_halt_request *halt;
ae9e63bb
HZ
913 struct netvsc_device *nvdev = dev->net_dev;
914 struct hv_device *hdev = nvdev->dev;
915 ulong flags;
fceaf24a 916
454f18a9 917 /* Attempt to do a rndis device halt */
51491167 918 request = get_rndis_request(dev, RNDIS_MSG_HALT,
0120ee0d 919 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
fceaf24a 920 if (!request)
1c627870 921 goto cleanup;
fceaf24a 922
454f18a9 923 /* Setup the rndis set */
a388eb17
HZ
924 halt = &request->request_msg.msg.halt_req;
925 halt->req_id = atomic_inc_return(&dev->new_req_id);
fceaf24a 926
454f18a9 927 /* Ignore return since this msg is optional. */
9c26aa0d 928 rndis_filter_send_request(dev, request);
fceaf24a 929
c2a4efdd 930 dev->state = RNDIS_DEV_UNINITIALIZED;
fceaf24a 931
1c627870 932cleanup:
ae9e63bb
HZ
933 spin_lock_irqsave(&hdev->channel->inbound_lock, flags);
934 nvdev->destroy = true;
935 spin_unlock_irqrestore(&hdev->channel->inbound_lock, flags);
936
937 /* Wait for all send completions */
938 wait_event(nvdev->wait_drain,
939 atomic_read(&nvdev->num_outstanding_sends) == 0);
940
fceaf24a 941 if (request)
9c26aa0d 942 put_rndis_request(dev, request);
fceaf24a
HJ
943 return;
944}
945
9c26aa0d 946static int rndis_filter_open_device(struct rndis_device *dev)
fceaf24a 947{
0120ee0d 948 int ret;
fceaf24a 949
c2a4efdd 950 if (dev->state != RNDIS_DEV_INITIALIZED)
fceaf24a
HJ
951 return 0;
952
9c26aa0d 953 ret = rndis_filter_set_packet_filter(dev,
0120ee0d 954 NDIS_PACKET_TYPE_BROADCAST |
95beae90 955 NDIS_PACKET_TYPE_ALL_MULTICAST |
0120ee0d 956 NDIS_PACKET_TYPE_DIRECTED);
fceaf24a 957 if (ret == 0)
c2a4efdd 958 dev->state = RNDIS_DEV_DATAINITIALIZED;
fceaf24a 959
fceaf24a
HJ
960 return ret;
961}
962
9c26aa0d 963static int rndis_filter_close_device(struct rndis_device *dev)
fceaf24a
HJ
964{
965 int ret;
966
c2a4efdd 967 if (dev->state != RNDIS_DEV_DATAINITIALIZED)
fceaf24a
HJ
968 return 0;
969
9c26aa0d 970 ret = rndis_filter_set_packet_filter(dev, 0);
c3582a2c
HZ
971 if (ret == -ENODEV)
972 ret = 0;
973
fceaf24a 974 if (ret == 0)
c2a4efdd 975 dev->state = RNDIS_DEV_INITIALIZED;
fceaf24a 976
fceaf24a
HJ
977 return ret;
978}
979
5b54dac8
HZ
980static void netvsc_sc_open(struct vmbus_channel *new_sc)
981{
982 struct netvsc_device *nvscdev;
983 u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
984 int ret;
b3e6b82a 985 unsigned long flags;
5b54dac8
HZ
986
987 nvscdev = hv_get_drvdata(new_sc->primary_channel->device_obj);
988
b3e6b82a
KS
989 spin_lock_irqsave(&nvscdev->sc_lock, flags);
990 nvscdev->num_sc_offered--;
991 spin_unlock_irqrestore(&nvscdev->sc_lock, flags);
992 if (nvscdev->num_sc_offered == 0)
993 complete(&nvscdev->channel_init_wait);
994
5b54dac8
HZ
995 if (chn_index >= nvscdev->num_chn)
996 return;
997
998 set_per_channel_state(new_sc, nvscdev->sub_cb_buf + (chn_index - 1) *
999 NETVSC_PACKET_SIZE);
1000
1001 ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
1002 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
1003 netvsc_channel_cb, new_sc);
1004
1005 if (ret == 0)
1006 nvscdev->chn_table[chn_index] = new_sc;
1007}
1008
bdbad576 1009int rndis_filter_device_add(struct hv_device *dev,
c2a4efdd 1010 void *additional_info)
fceaf24a
HJ
1011{
1012 int ret;
86c921af 1013 struct netvsc_device *net_device;
b13cc345 1014 struct rndis_device *rndis_device;
3c4debad 1015 struct netvsc_device_info *device_info = additional_info;
4a0e70ae 1016 struct ndis_offload_params offloads;
5b54dac8 1017 struct nvsp_message *init_packet;
999028cc 1018 unsigned long t;
5b54dac8
HZ
1019 struct ndis_recv_scale_cap rsscap;
1020 u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
4d3c9d37 1021 u32 mtu, size;
e01ec219 1022 u32 num_rss_qs;
b3e6b82a 1023 u32 sc_delta;
e01ec219
KS
1024 const struct cpumask *node_cpu_mask;
1025 u32 num_possible_rss_qs;
b3e6b82a 1026 unsigned long flags;
fceaf24a 1027
b13cc345
S
1028 rndis_device = get_rndis_device();
1029 if (!rndis_device)
327efbae 1030 return -ENODEV;
fceaf24a 1031
0120ee0d
GKH
1032 /*
1033 * Let the inner driver handle this first to create the netvsc channel
1034 * NOTE! Once the channel is created, we may get a receive callback
1035 * (RndisFilterOnReceive()) before this call is completed
1036 */
ce5bf661 1037 ret = netvsc_device_add(dev, additional_info);
0120ee0d 1038 if (ret != 0) {
b13cc345 1039 kfree(rndis_device);
fceaf24a
HJ
1040 return ret;
1041 }
1042
454f18a9
BP
1043
1044 /* Initialize the rndis device */
86c921af 1045 net_device = hv_get_drvdata(dev);
59995370 1046 net_device->max_chn = 1;
5b54dac8 1047 net_device->num_chn = 1;
fceaf24a 1048
b3e6b82a
KS
1049 spin_lock_init(&net_device->sc_lock);
1050
b13cc345
S
1051 net_device->extension = rndis_device;
1052 rndis_device->net_dev = net_device;
fceaf24a 1053
454f18a9 1054 /* Send the rndis initialization message */
b13cc345 1055 ret = rndis_filter_init_device(rndis_device);
0120ee0d 1056 if (ret != 0) {
5243e7bd
HZ
1057 rndis_filter_device_remove(dev);
1058 return ret;
fceaf24a
HJ
1059 }
1060
4d3c9d37
HZ
1061 /* Get the MTU from the host */
1062 size = sizeof(u32);
1063 ret = rndis_filter_query_device(rndis_device,
1064 RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
1065 &mtu, &size);
f9cbce34 1066 if (ret == 0 && size == sizeof(u32) && mtu < net_device->ndev->mtu)
4d3c9d37
HZ
1067 net_device->ndev->mtu = mtu;
1068
454f18a9 1069 /* Get the mac address */
b13cc345 1070 ret = rndis_filter_query_device_mac(rndis_device);
0120ee0d 1071 if (ret != 0) {
5243e7bd
HZ
1072 rndis_filter_device_remove(dev);
1073 return ret;
fceaf24a
HJ
1074 }
1075
3c4debad 1076 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
fceaf24a 1077
4a0e70ae
KS
1078 /* Turn on the offloads; the host supports all of the relevant
1079 * offloads.
1080 */
1081 memset(&offloads, 0, sizeof(struct ndis_offload_params));
1082 /* A value of zero means "no change"; now turn on what we
1083 * want.
1084 */
1085 offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1086 offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1087 offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1088 offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1089 offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1090 offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1091
1092
1093 ret = rndis_filter_set_offload_params(dev, &offloads);
1094 if (ret)
1095 goto err_dev_remv;
1096
b13cc345 1097 rndis_filter_query_device_link_status(rndis_device);
fceaf24a 1098
6f27457b 1099 device_info->link_state = rndis_device->link_state;
eb335bc4 1100
6f27457b 1101 dev_info(&dev->device, "Device MAC %pM link state %s\n",
b13cc345 1102 rndis_device->hw_mac_adr,
6f27457b 1103 device_info->link_state ? "down" : "up");
fceaf24a 1104
5b54dac8
HZ
1105 if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
1106 return 0;
1107
1108 /* vRSS setup */
1109 memset(&rsscap, 0, rsscap_size);
1110 ret = rndis_filter_query_device(rndis_device,
1111 OID_GEN_RECEIVE_SCALE_CAPABILITIES,
1112 &rsscap, &rsscap_size);
1113 if (ret || rsscap.num_recv_que < 2)
1114 goto out;
1115
e01ec219
KS
1116 num_rss_qs = min(device_info->max_num_vrss_chns, rsscap.num_recv_que);
1117
59995370 1118 net_device->max_chn = rsscap.num_recv_que;
e01ec219
KS
1119
1120 /*
1121 * We will limit the VRSS channels to the number CPUs in the NUMA node
1122 * the primary channel is currently bound to.
1123 */
1124 node_cpu_mask = cpumask_of_node(cpu_to_node(dev->channel->target_cpu));
1125 num_possible_rss_qs = cpumask_weight(node_cpu_mask);
8ebdcc52
AS
1126
1127 /* We will use the given number of channels if available. */
1128 if (device_info->num_chn && device_info->num_chn < net_device->max_chn)
1129 net_device->num_chn = device_info->num_chn;
1130 else
1131 net_device->num_chn = min(num_possible_rss_qs, num_rss_qs);
e01ec219 1132
b3e6b82a
KS
1133 num_rss_qs = net_device->num_chn - 1;
1134 net_device->num_sc_offered = num_rss_qs;
1135
5b54dac8
HZ
1136 if (net_device->num_chn == 1)
1137 goto out;
1138
1139 net_device->sub_cb_buf = vzalloc((net_device->num_chn - 1) *
1140 NETVSC_PACKET_SIZE);
1141 if (!net_device->sub_cb_buf) {
1142 net_device->num_chn = 1;
1143 dev_info(&dev->device, "No memory for subchannels.\n");
1144 goto out;
1145 }
1146
1147 vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
1148
1149 init_packet = &net_device->channel_init_pkt;
1150 memset(init_packet, 0, sizeof(struct nvsp_message));
1151 init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL;
1152 init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE;
1153 init_packet->msg.v5_msg.subchn_req.num_subchannels =
1154 net_device->num_chn - 1;
1155 ret = vmbus_sendpacket(dev->channel, init_packet,
1156 sizeof(struct nvsp_message),
1157 (unsigned long)init_packet,
1158 VM_PKT_DATA_INBAND,
1159 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1160 if (ret)
1161 goto out;
1162 t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
1163 if (t == 0) {
1164 ret = -ETIMEDOUT;
1165 goto out;
1166 }
1167 if (init_packet->msg.v5_msg.subchn_comp.status !=
1168 NVSP_STAT_SUCCESS) {
1169 ret = -ENODEV;
1170 goto out;
1171 }
1172 net_device->num_chn = 1 +
1173 init_packet->msg.v5_msg.subchn_comp.num_subchannels;
1174
5b54dac8
HZ
1175 ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn);
1176
b3e6b82a
KS
1177 /*
1178 * Wait for the host to send us the sub-channel offers.
1179 */
1180 spin_lock_irqsave(&net_device->sc_lock, flags);
1181 sc_delta = num_rss_qs - (net_device->num_chn - 1);
1182 net_device->num_sc_offered -= sc_delta;
1183 spin_unlock_irqrestore(&net_device->sc_lock, flags);
1184
1185 while (net_device->num_sc_offered != 0) {
1186 t = wait_for_completion_timeout(&net_device->channel_init_wait, 10*HZ);
1187 if (t == 0)
1188 WARN(1, "Netvsc: Waiting for sub-channel processing");
1189 }
5b54dac8 1190out:
59995370
AS
1191 if (ret) {
1192 net_device->max_chn = 1;
5b54dac8 1193 net_device->num_chn = 1;
59995370 1194 }
b3e6b82a 1195
5b54dac8 1196 return 0; /* return 0 because primary channel can be used alone */
4a0e70ae
KS
1197
1198err_dev_remv:
1199 rndis_filter_device_remove(dev);
1200 return ret;
fceaf24a
HJ
1201}
1202
df06bcff 1203void rndis_filter_device_remove(struct hv_device *dev)
fceaf24a 1204{
2ddd5e5f 1205 struct netvsc_device *net_dev = hv_get_drvdata(dev);
53d21fdb 1206 struct rndis_device *rndis_dev = net_dev->extension;
fceaf24a 1207
454f18a9 1208 /* Halt and release the rndis device */
9c26aa0d 1209 rndis_filter_halt_device(rndis_dev);
fceaf24a 1210
c2a4efdd 1211 kfree(rndis_dev);
53d21fdb 1212 net_dev->extension = NULL;
fceaf24a 1213
3fae5c8f 1214 netvsc_device_remove(dev);
fceaf24a
HJ
1215}
1216
fceaf24a 1217
9c26aa0d 1218int rndis_filter_open(struct hv_device *dev)
fceaf24a 1219{
86c921af 1220 struct netvsc_device *net_device = hv_get_drvdata(dev);
fceaf24a 1221
86c921af 1222 if (!net_device)
8a62d716
BP
1223 return -EINVAL;
1224
86c921af 1225 return rndis_filter_open_device(net_device->extension);
fceaf24a
HJ
1226}
1227
9c26aa0d 1228int rndis_filter_close(struct hv_device *dev)
fceaf24a 1229{
5fccab3b 1230 struct netvsc_device *nvdev = hv_get_drvdata(dev);
fceaf24a 1231
5fccab3b 1232 if (!nvdev)
8a62d716
BP
1233 return -EINVAL;
1234
5fccab3b 1235 return rndis_filter_close_device(nvdev->extension);
fceaf24a 1236}