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