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