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