]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/hyperv/rndis_filter.c
hv_netvsc: pass struct net_device to rndis_filter_set_device_mac()
[mirror_ubuntu-artful-kernel.git] / drivers / net / hyperv / rndis_filter.c
CommitLineData
fceaf24a 1/*
fceaf24a
HJ
2 * Copyright (c) 2009, Microsoft Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
adf8d3ff 14 * this program; if not, see <http://www.gnu.org/licenses/>.
fceaf24a
HJ
15 *
16 * Authors:
17 * Haiyang Zhang <haiyangz@microsoft.com>
18 * Hank Janssen <hjanssen@microsoft.com>
fceaf24a 19 */
5654e932 20#include <linux/kernel.h>
0c3b7b2f
S
21#include <linux/sched.h>
22#include <linux/wait.h>
45da89e5 23#include <linux/highmem.h>
5a0e3ad6 24#include <linux/slab.h>
0120ee0d 25#include <linux/io.h>
9f8bd8ba 26#include <linux/if_ether.h>
eb335bc4 27#include <linux/netdevice.h>
1f5f3a75 28#include <linux/if_vlan.h>
1ce09e89 29#include <linux/nls.h>
d6472302 30#include <linux/vmalloc.h>
3f335ea2 31
5ca7252a 32#include "hyperv_net.h"
fceaf24a 33
fceaf24a 34
5b54dac8 35#define RNDIS_EXT_LEN PAGE_SIZE
e681b954 36struct rndis_request {
c2a4efdd 37 struct list_head list_ent;
98d79690 38 struct completion wait_event;
fceaf24a 39
a3a6cab5 40 struct rndis_message response_msg;
0120ee0d 41 /*
a3a6cab5
HZ
42 * The buffer for extended info after the RNDIS response message. It's
43 * referenced based on the data offset in the RNDIS message. Its size
44 * is enough for current needs, and should be sufficient for the near
45 * future.
0120ee0d 46 */
a3a6cab5 47 u8 response_ext[RNDIS_EXT_LEN];
fceaf24a 48
454f18a9 49 /* Simplify allocation by having a netvsc packet inline */
c2a4efdd 50 struct hv_netvsc_packet pkt;
0f48917b 51
c2a4efdd 52 struct rndis_message request_msg;
0f48917b 53 /*
a3a6cab5
HZ
54 * The buffer for the extended info after the RNDIS request message.
55 * It is referenced and sized in a similar way as response_ext.
0f48917b 56 */
a3a6cab5 57 u8 request_ext[RNDIS_EXT_LEN];
e681b954 58};
fceaf24a 59
9c26aa0d 60static struct rndis_device *get_rndis_device(void)
fceaf24a 61{
e681b954 62 struct rndis_device *device;
fceaf24a 63
e681b954 64 device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
fceaf24a 65 if (!device)
fceaf24a 66 return NULL;
fceaf24a 67
880fb89c 68 spin_lock_init(&device->request_lock);
fceaf24a 69
c2a4efdd 70 INIT_LIST_HEAD(&device->req_list);
fceaf24a 71
c2a4efdd 72 device->state = RNDIS_DEV_UNINITIALIZED;
fceaf24a
HJ
73
74 return device;
75}
76
9c26aa0d 77static struct rndis_request *get_rndis_request(struct rndis_device *dev,
c2a4efdd
HZ
78 u32 msg_type,
79 u32 msg_len)
fceaf24a 80{
e681b954 81 struct rndis_request *request;
c2a4efdd 82 struct rndis_message *rndis_msg;
9f33d054 83 struct rndis_set_request *set;
880fb89c 84 unsigned long flags;
fceaf24a 85
e681b954 86 request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
fceaf24a 87 if (!request)
fceaf24a 88 return NULL;
fceaf24a 89
98d79690 90 init_completion(&request->wait_event);
fceaf24a 91
c2a4efdd 92 rndis_msg = &request->request_msg;
a388eb17
HZ
93 rndis_msg->ndis_msg_type = msg_type;
94 rndis_msg->msg_len = msg_len;
fceaf24a 95
5b54dac8
HZ
96 request->pkt.q_idx = 0;
97
0120ee0d
GKH
98 /*
99 * Set the request id. This field is always after the rndis header for
100 * request/response packet types so we just used the SetRequest as a
101 * template
102 */
a388eb17
HZ
103 set = &rndis_msg->msg.set_req;
104 set->req_id = atomic_inc_return(&dev->new_req_id);
fceaf24a 105
454f18a9 106 /* Add to the request list */
c2a4efdd
HZ
107 spin_lock_irqsave(&dev->request_lock, flags);
108 list_add_tail(&request->list_ent, &dev->req_list);
109 spin_unlock_irqrestore(&dev->request_lock, flags);
fceaf24a
HJ
110
111 return request;
112}
113
9c26aa0d 114static void put_rndis_request(struct rndis_device *dev,
c2a4efdd 115 struct rndis_request *req)
fceaf24a 116{
880fb89c
GKH
117 unsigned long flags;
118
c2a4efdd
HZ
119 spin_lock_irqsave(&dev->request_lock, flags);
120 list_del(&req->list_ent);
121 spin_unlock_irqrestore(&dev->request_lock, flags);
fceaf24a 122
c2a4efdd 123 kfree(req);
fceaf24a
HJ
124}
125
729a2849
HZ
126static void dump_rndis_message(struct hv_device *hv_dev,
127 struct rndis_message *rndis_msg)
fceaf24a 128{
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
e834da9a 546int rndis_filter_set_device_mac(struct net_device *ndev, char *mac)
1ce09e89 547{
2625466d 548 struct netvsc_device *nvdev = net_device_to_netvsc_device(ndev);
1ce09e89 549 struct rndis_device *rdev = nvdev->extension;
1ce09e89
HZ
550 struct rndis_request *request;
551 struct rndis_set_request *set;
552 struct rndis_config_parameter_info *cpi;
553 wchar_t *cfg_nwadr, *cfg_mac;
554 struct rndis_set_complete *set_complete;
555 char macstr[2*ETH_ALEN+1];
556 u32 extlen = sizeof(struct rndis_config_parameter_info) +
557 2*NWADR_STRLEN + 4*ETH_ALEN;
999028cc
NMG
558 int ret;
559 unsigned long t;
1ce09e89
HZ
560
561 request = get_rndis_request(rdev, RNDIS_MSG_SET,
562 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
563 if (!request)
564 return -ENOMEM;
565
566 set = &request->request_msg.msg.set_req;
567 set->oid = RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER;
568 set->info_buflen = extlen;
569 set->info_buf_offset = sizeof(struct rndis_set_request);
570 set->dev_vc_handle = 0;
571
572 cpi = (struct rndis_config_parameter_info *)((ulong)set +
573 set->info_buf_offset);
574 cpi->parameter_name_offset =
575 sizeof(struct rndis_config_parameter_info);
576 /* Multiply by 2 because host needs 2 bytes (utf16) for each char */
577 cpi->parameter_name_length = 2*NWADR_STRLEN;
578 cpi->parameter_type = RNDIS_CONFIG_PARAM_TYPE_STRING;
579 cpi->parameter_value_offset =
580 cpi->parameter_name_offset + cpi->parameter_name_length;
581 /* Multiply by 4 because each MAC byte displayed as 2 utf16 chars */
582 cpi->parameter_value_length = 4*ETH_ALEN;
583
584 cfg_nwadr = (wchar_t *)((ulong)cpi + cpi->parameter_name_offset);
585 cfg_mac = (wchar_t *)((ulong)cpi + cpi->parameter_value_offset);
586 ret = utf8s_to_utf16s(NWADR_STR, NWADR_STRLEN, UTF16_HOST_ENDIAN,
587 cfg_nwadr, NWADR_STRLEN);
588 if (ret < 0)
589 goto cleanup;
590 snprintf(macstr, 2*ETH_ALEN+1, "%pm", mac);
591 ret = utf8s_to_utf16s(macstr, 2*ETH_ALEN, UTF16_HOST_ENDIAN,
592 cfg_mac, 2*ETH_ALEN);
593 if (ret < 0)
594 goto cleanup;
595
596 ret = rndis_filter_send_request(rdev, request);
597 if (ret != 0)
598 goto cleanup;
599
600 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
601 if (t == 0) {
602 netdev_err(ndev, "timeout before we got a set response...\n");
603 /*
604 * can't put_rndis_request, since we may still receive a
605 * send-completion.
606 */
607 return -EBUSY;
608 } else {
609 set_complete = &request->response_msg.msg.set_complete;
b02a8067
HZ
610 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
611 netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
612 set_complete->status);
1ce09e89 613 ret = -EINVAL;
b02a8067 614 }
1ce09e89
HZ
615 }
616
617cleanup:
618 put_rndis_request(rdev, request);
619 return ret;
620}
621
da19fcd0
LP
622static int
623rndis_filter_set_offload_params(struct hv_device *hdev,
4a0e70ae
KS
624 struct ndis_offload_params *req_offloads)
625{
3d541ac5 626 struct net_device *ndev = hv_get_drvdata(hdev);
2625466d 627 struct netvsc_device *nvdev = net_device_to_netvsc_device(ndev);
4a0e70ae 628 struct rndis_device *rdev = nvdev->extension;
4a0e70ae
KS
629 struct rndis_request *request;
630 struct rndis_set_request *set;
631 struct ndis_offload_params *offload_params;
632 struct rndis_set_complete *set_complete;
633 u32 extlen = sizeof(struct ndis_offload_params);
999028cc
NMG
634 int ret;
635 unsigned long t;
af9893a3
KS
636 u32 vsp_version = nvdev->nvsp_version;
637
638 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
639 extlen = VERSION_4_OFFLOAD_SIZE;
640 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
641 * UDP checksum offload.
642 */
643 req_offloads->udp_ip_v4_csum = 0;
644 req_offloads->udp_ip_v6_csum = 0;
645 }
4a0e70ae
KS
646
647 request = get_rndis_request(rdev, RNDIS_MSG_SET,
648 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
649 if (!request)
650 return -ENOMEM;
651
652 set = &request->request_msg.msg.set_req;
653 set->oid = OID_TCP_OFFLOAD_PARAMETERS;
654 set->info_buflen = extlen;
655 set->info_buf_offset = sizeof(struct rndis_set_request);
656 set->dev_vc_handle = 0;
657
658 offload_params = (struct ndis_offload_params *)((ulong)set +
659 set->info_buf_offset);
660 *offload_params = *req_offloads;
661 offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
662 offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
663 offload_params->header.size = extlen;
664
665 ret = rndis_filter_send_request(rdev, request);
666 if (ret != 0)
667 goto cleanup;
668
669 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
670 if (t == 0) {
671 netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n");
672 /* can't put_rndis_request, since we may still receive a
673 * send-completion.
674 */
675 return -EBUSY;
676 } else {
677 set_complete = &request->response_msg.msg.set_complete;
678 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
af9893a3 679 netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
4a0e70ae
KS
680 set_complete->status);
681 ret = -EINVAL;
682 }
683 }
684
685cleanup:
686 put_rndis_request(rdev, request);
687 return ret;
688}
1ce09e89 689
5b54dac8
HZ
690u8 netvsc_hash_key[HASH_KEYLEN] = {
691 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
692 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
693 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
694 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
695 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
696};
697
da19fcd0 698static int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
5b54dac8 699{
3d541ac5 700 struct net_device *ndev = rdev->ndev;
5b54dac8
HZ
701 struct rndis_request *request;
702 struct rndis_set_request *set;
703 struct rndis_set_complete *set_complete;
704 u32 extlen = sizeof(struct ndis_recv_scale_param) +
705 4*ITAB_NUM + HASH_KEYLEN;
706 struct ndis_recv_scale_param *rssp;
707 u32 *itab;
708 u8 *keyp;
999028cc
NMG
709 int i, ret;
710 unsigned long t;
5b54dac8
HZ
711
712 request = get_rndis_request(
713 rdev, RNDIS_MSG_SET,
714 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
715 if (!request)
716 return -ENOMEM;
717
718 set = &request->request_msg.msg.set_req;
719 set->oid = OID_GEN_RECEIVE_SCALE_PARAMETERS;
720 set->info_buflen = extlen;
721 set->info_buf_offset = sizeof(struct rndis_set_request);
722 set->dev_vc_handle = 0;
723
724 rssp = (struct ndis_recv_scale_param *)(set + 1);
725 rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
726 rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
727 rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
728 rssp->flag = 0;
729 rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
4c87454a
HZ
730 NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
731 NDIS_HASH_TCP_IPV6;
5b54dac8
HZ
732 rssp->indirect_tabsize = 4*ITAB_NUM;
733 rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
734 rssp->hashkey_size = HASH_KEYLEN;
735 rssp->kashkey_offset = rssp->indirect_taboffset +
736 rssp->indirect_tabsize;
737
738 /* Set indirection table entries */
739 itab = (u32 *)(rssp + 1);
740 for (i = 0; i < ITAB_NUM; i++)
741 itab[i] = i % num_queue;
742
743 /* Set hask key values */
744 keyp = (u8 *)((unsigned long)rssp + rssp->kashkey_offset);
745 for (i = 0; i < HASH_KEYLEN; i++)
746 keyp[i] = netvsc_hash_key[i];
747
748
749 ret = rndis_filter_send_request(rdev, request);
750 if (ret != 0)
751 goto cleanup;
752
753 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
754 if (t == 0) {
755 netdev_err(ndev, "timeout before we got a set response...\n");
756 /* can't put_rndis_request, since we may still receive a
757 * send-completion.
758 */
759 return -ETIMEDOUT;
760 } else {
761 set_complete = &request->response_msg.msg.set_complete;
762 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
763 netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
764 set_complete->status);
765 ret = -EINVAL;
766 }
767 }
768
769cleanup:
770 put_rndis_request(rdev, request);
771 return ret;
772}
773
774
9c26aa0d 775static int rndis_filter_query_device_link_status(struct rndis_device *dev)
fceaf24a 776{
0120ee0d 777 u32 size = sizeof(u32);
6f27457b
S
778 u32 link_status;
779 int ret;
fceaf24a 780
6f27457b 781 ret = rndis_filter_query_device(dev,
0120ee0d 782 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
6f27457b 783 &link_status, &size);
6f27457b
S
784
785 return ret;
fceaf24a
HJ
786}
787
d426b2e3 788int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
fceaf24a 789{
e681b954 790 struct rndis_request *request;
9f33d054 791 struct rndis_set_request *set;
c2a4efdd 792 struct rndis_set_complete *set_complete;
4d643114 793 u32 status;
999028cc
NMG
794 int ret;
795 unsigned long t;
3d541ac5 796 struct net_device *ndev = dev->ndev;
fceaf24a 797
51491167 798 request = get_rndis_request(dev, RNDIS_MSG_SET,
0120ee0d
GKH
799 RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
800 sizeof(u32));
801 if (!request) {
58ef3977 802 ret = -ENOMEM;
1c627870 803 goto cleanup;
fceaf24a
HJ
804 }
805
454f18a9 806 /* Setup the rndis set */
a388eb17
HZ
807 set = &request->request_msg.msg.set_req;
808 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
809 set->info_buflen = sizeof(u32);
810 set->info_buf_offset = sizeof(struct rndis_set_request);
fceaf24a 811
0120ee0d 812 memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
c2a4efdd 813 &new_filter, sizeof(u32));
fceaf24a 814
9c26aa0d 815 ret = rndis_filter_send_request(dev, request);
fceaf24a 816 if (ret != 0)
1c627870 817 goto cleanup;
fceaf24a 818
5c5781b3 819 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
98d79690
S
820
821 if (t == 0) {
d9871158 822 netdev_err(ndev,
eb335bc4 823 "timeout before we got a set response...\n");
ea496374 824 ret = -ETIMEDOUT;
0120ee0d 825 /*
25985edc 826 * We can't deallocate the request since we may still receive a
0120ee0d
GKH
827 * send completion for it.
828 */
5585d81e 829 goto exit;
0120ee0d 830 } else {
a388eb17
HZ
831 set_complete = &request->response_msg.msg.set_complete;
832 status = set_complete->status;
fceaf24a
HJ
833 }
834
1c627870 835cleanup:
fceaf24a 836 if (request)
9c26aa0d 837 put_rndis_request(dev, request);
5585d81e 838exit:
fceaf24a
HJ
839 return ret;
840}
841
fceaf24a 842
9c26aa0d 843static int rndis_filter_init_device(struct rndis_device *dev)
fceaf24a 844{
e681b954 845 struct rndis_request *request;
9f33d054 846 struct rndis_initialize_request *init;
c2a4efdd 847 struct rndis_initialize_complete *init_complete;
4d643114 848 u32 status;
999028cc
NMG
849 int ret;
850 unsigned long t;
2625466d 851 struct netvsc_device *nvdev = net_device_to_netvsc_device(dev->ndev);
fceaf24a 852
51491167 853 request = get_rndis_request(dev, RNDIS_MSG_INIT,
0120ee0d
GKH
854 RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
855 if (!request) {
bc49b926 856 ret = -ENOMEM;
1c627870 857 goto cleanup;
fceaf24a
HJ
858 }
859
454f18a9 860 /* Setup the rndis set */
a388eb17
HZ
861 init = &request->request_msg.msg.init_req;
862 init->major_ver = RNDIS_MAJOR_VERSION;
863 init->minor_ver = RNDIS_MINOR_VERSION;
fb1d074e 864 init->max_xfer_size = 0x4000;
fceaf24a 865
c2a4efdd 866 dev->state = RNDIS_DEV_INITIALIZING;
fceaf24a 867
9c26aa0d 868 ret = rndis_filter_send_request(dev, request);
0120ee0d 869 if (ret != 0) {
c2a4efdd 870 dev->state = RNDIS_DEV_UNINITIALIZED;
1c627870 871 goto cleanup;
fceaf24a
HJ
872 }
873
5c5781b3 874 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
98d79690
S
875
876 if (t == 0) {
0c3b7b2f 877 ret = -ETIMEDOUT;
1c627870 878 goto cleanup;
0c3b7b2f 879 }
fceaf24a 880
a388eb17
HZ
881 init_complete = &request->response_msg.msg.init_complete;
882 status = init_complete->status;
0120ee0d 883 if (status == RNDIS_STATUS_SUCCESS) {
c2a4efdd 884 dev->state = RNDIS_DEV_INITIALIZED;
7c3877f2
HZ
885 nvdev->max_pkt = init_complete->max_pkt_per_msg;
886 nvdev->pkt_align = 1 << init_complete->pkt_alignment_factor;
fceaf24a 887 ret = 0;
0120ee0d 888 } else {
c2a4efdd 889 dev->state = RNDIS_DEV_UNINITIALIZED;
bc49b926 890 ret = -EINVAL;
fceaf24a
HJ
891 }
892
1c627870 893cleanup:
fceaf24a 894 if (request)
9c26aa0d 895 put_rndis_request(dev, request);
fceaf24a
HJ
896
897 return ret;
898}
899
9c26aa0d 900static void rndis_filter_halt_device(struct rndis_device *dev)
fceaf24a 901{
e681b954 902 struct rndis_request *request;
9f33d054 903 struct rndis_halt_request *halt;
3d541ac5
VK
904 struct net_device_context *net_device_ctx = netdev_priv(dev->ndev);
905 struct netvsc_device *nvdev = net_device_ctx->nvdev;
906 struct hv_device *hdev = net_device_ctx->device_ctx;
ae9e63bb 907 ulong flags;
fceaf24a 908
454f18a9 909 /* Attempt to do a rndis device halt */
51491167 910 request = get_rndis_request(dev, RNDIS_MSG_HALT,
0120ee0d 911 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
fceaf24a 912 if (!request)
1c627870 913 goto cleanup;
fceaf24a 914
454f18a9 915 /* Setup the rndis set */
a388eb17
HZ
916 halt = &request->request_msg.msg.halt_req;
917 halt->req_id = atomic_inc_return(&dev->new_req_id);
fceaf24a 918
454f18a9 919 /* Ignore return since this msg is optional. */
9c26aa0d 920 rndis_filter_send_request(dev, request);
fceaf24a 921
c2a4efdd 922 dev->state = RNDIS_DEV_UNINITIALIZED;
fceaf24a 923
1c627870 924cleanup:
ae9e63bb
HZ
925 spin_lock_irqsave(&hdev->channel->inbound_lock, flags);
926 nvdev->destroy = true;
927 spin_unlock_irqrestore(&hdev->channel->inbound_lock, flags);
928
929 /* Wait for all send completions */
930 wait_event(nvdev->wait_drain,
931 atomic_read(&nvdev->num_outstanding_sends) == 0);
932
fceaf24a 933 if (request)
9c26aa0d 934 put_rndis_request(dev, request);
fceaf24a
HJ
935 return;
936}
937
9c26aa0d 938static int rndis_filter_open_device(struct rndis_device *dev)
fceaf24a 939{
0120ee0d 940 int ret;
fceaf24a 941
c2a4efdd 942 if (dev->state != RNDIS_DEV_INITIALIZED)
fceaf24a
HJ
943 return 0;
944
9c26aa0d 945 ret = rndis_filter_set_packet_filter(dev,
0120ee0d 946 NDIS_PACKET_TYPE_BROADCAST |
95beae90 947 NDIS_PACKET_TYPE_ALL_MULTICAST |
0120ee0d 948 NDIS_PACKET_TYPE_DIRECTED);
fceaf24a 949 if (ret == 0)
c2a4efdd 950 dev->state = RNDIS_DEV_DATAINITIALIZED;
fceaf24a 951
fceaf24a
HJ
952 return ret;
953}
954
9c26aa0d 955static int rndis_filter_close_device(struct rndis_device *dev)
fceaf24a
HJ
956{
957 int ret;
958
c2a4efdd 959 if (dev->state != RNDIS_DEV_DATAINITIALIZED)
fceaf24a
HJ
960 return 0;
961
9c26aa0d 962 ret = rndis_filter_set_packet_filter(dev, 0);
c3582a2c
HZ
963 if (ret == -ENODEV)
964 ret = 0;
965
fceaf24a 966 if (ret == 0)
c2a4efdd 967 dev->state = RNDIS_DEV_INITIALIZED;
fceaf24a 968
fceaf24a
HJ
969 return ret;
970}
971
5b54dac8
HZ
972static void netvsc_sc_open(struct vmbus_channel *new_sc)
973{
3d541ac5
VK
974 struct net_device *ndev =
975 hv_get_drvdata(new_sc->primary_channel->device_obj);
2625466d 976 struct netvsc_device *nvscdev = net_device_to_netvsc_device(ndev);
5b54dac8
HZ
977 u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
978 int ret;
b3e6b82a 979 unsigned long flags;
5b54dac8 980
5b54dac8
HZ
981 if (chn_index >= nvscdev->num_chn)
982 return;
983
984 set_per_channel_state(new_sc, nvscdev->sub_cb_buf + (chn_index - 1) *
985 NETVSC_PACKET_SIZE);
986
987 ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
988 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
989 netvsc_channel_cb, new_sc);
990
991 if (ret == 0)
992 nvscdev->chn_table[chn_index] = new_sc;
3f735131
HZ
993
994 spin_lock_irqsave(&nvscdev->sc_lock, flags);
995 nvscdev->num_sc_offered--;
996 spin_unlock_irqrestore(&nvscdev->sc_lock, flags);
997 if (nvscdev->num_sc_offered == 0)
998 complete(&nvscdev->channel_init_wait);
5b54dac8
HZ
999}
1000
bdbad576 1001int rndis_filter_device_add(struct hv_device *dev,
c2a4efdd 1002 void *additional_info)
fceaf24a
HJ
1003{
1004 int ret;
3d541ac5
VK
1005 struct net_device *net = hv_get_drvdata(dev);
1006 struct net_device_context *net_device_ctx = netdev_priv(net);
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;
e01ec219 1016 u32 num_rss_qs;
b3e6b82a 1017 u32 sc_delta;
e01ec219
KS
1018 const struct cpumask *node_cpu_mask;
1019 u32 num_possible_rss_qs;
b3e6b82a 1020 unsigned long flags;
fceaf24a 1021
b13cc345
S
1022 rndis_device = get_rndis_device();
1023 if (!rndis_device)
327efbae 1024 return -ENODEV;
fceaf24a 1025
0120ee0d
GKH
1026 /*
1027 * Let the inner driver handle this first to create the netvsc channel
1028 * NOTE! Once the channel is created, we may get a receive callback
1029 * (RndisFilterOnReceive()) before this call is completed
1030 */
ce5bf661 1031 ret = netvsc_device_add(dev, additional_info);
0120ee0d 1032 if (ret != 0) {
b13cc345 1033 kfree(rndis_device);
fceaf24a
HJ
1034 return ret;
1035 }
1036
454f18a9 1037 /* Initialize the rndis device */
3d541ac5 1038 net_device = net_device_ctx->nvdev;
59995370 1039 net_device->max_chn = 1;
5b54dac8 1040 net_device->num_chn = 1;
fceaf24a 1041
b3e6b82a
KS
1042 spin_lock_init(&net_device->sc_lock);
1043
b13cc345 1044 net_device->extension = rndis_device;
3d541ac5 1045 rndis_device->ndev = net;
fceaf24a 1046
454f18a9 1047 /* Send the rndis initialization message */
b13cc345 1048 ret = rndis_filter_init_device(rndis_device);
0120ee0d 1049 if (ret != 0) {
5243e7bd
HZ
1050 rndis_filter_device_remove(dev);
1051 return ret;
fceaf24a
HJ
1052 }
1053
4d3c9d37
HZ
1054 /* Get the MTU from the host */
1055 size = sizeof(u32);
1056 ret = rndis_filter_query_device(rndis_device,
1057 RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
1058 &mtu, &size);
0a1275ca
VK
1059 if (ret == 0 && size == sizeof(u32) && mtu < net->mtu)
1060 net->mtu = mtu;
4d3c9d37 1061
454f18a9 1062 /* Get the mac address */
b13cc345 1063 ret = rndis_filter_query_device_mac(rndis_device);
0120ee0d 1064 if (ret != 0) {
5243e7bd
HZ
1065 rndis_filter_device_remove(dev);
1066 return ret;
fceaf24a
HJ
1067 }
1068
3c4debad 1069 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
fceaf24a 1070
4a0e70ae
KS
1071 /* Turn on the offloads; the host supports all of the relevant
1072 * offloads.
1073 */
1074 memset(&offloads, 0, sizeof(struct ndis_offload_params));
1075 /* A value of zero means "no change"; now turn on what we
1076 * want.
1077 */
1078 offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1079 offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1080 offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1081 offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1082 offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1083 offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1084
1085
1086 ret = rndis_filter_set_offload_params(dev, &offloads);
1087 if (ret)
1088 goto err_dev_remv;
1089
b13cc345 1090 rndis_filter_query_device_link_status(rndis_device);
fceaf24a 1091
6f27457b 1092 device_info->link_state = rndis_device->link_state;
eb335bc4 1093
6f27457b 1094 dev_info(&dev->device, "Device MAC %pM link state %s\n",
b13cc345 1095 rndis_device->hw_mac_adr,
6f27457b 1096 device_info->link_state ? "down" : "up");
fceaf24a 1097
5b54dac8
HZ
1098 if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
1099 return 0;
1100
1101 /* vRSS setup */
1102 memset(&rsscap, 0, rsscap_size);
1103 ret = rndis_filter_query_device(rndis_device,
1104 OID_GEN_RECEIVE_SCALE_CAPABILITIES,
1105 &rsscap, &rsscap_size);
1106 if (ret || rsscap.num_recv_que < 2)
1107 goto out;
1108
9efc2f7d 1109 net_device->max_chn = min_t(u32, VRSS_CHANNEL_MAX, rsscap.num_recv_que);
e01ec219 1110
9efc2f7d 1111 num_rss_qs = min(device_info->max_num_vrss_chns, net_device->max_chn);
e01ec219
KS
1112
1113 /*
1114 * We will limit the VRSS channels to the number CPUs in the NUMA node
1115 * the primary channel is currently bound to.
1116 */
1117 node_cpu_mask = cpumask_of_node(cpu_to_node(dev->channel->target_cpu));
1118 num_possible_rss_qs = cpumask_weight(node_cpu_mask);
8ebdcc52
AS
1119
1120 /* We will use the given number of channels if available. */
1121 if (device_info->num_chn && device_info->num_chn < net_device->max_chn)
1122 net_device->num_chn = device_info->num_chn;
1123 else
1124 net_device->num_chn = min(num_possible_rss_qs, num_rss_qs);
e01ec219 1125
b3e6b82a
KS
1126 num_rss_qs = net_device->num_chn - 1;
1127 net_device->num_sc_offered = num_rss_qs;
1128
5b54dac8
HZ
1129 if (net_device->num_chn == 1)
1130 goto out;
1131
1132 net_device->sub_cb_buf = vzalloc((net_device->num_chn - 1) *
1133 NETVSC_PACKET_SIZE);
1134 if (!net_device->sub_cb_buf) {
1135 net_device->num_chn = 1;
1136 dev_info(&dev->device, "No memory for subchannels.\n");
1137 goto out;
1138 }
1139
1140 vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
1141
1142 init_packet = &net_device->channel_init_pkt;
1143 memset(init_packet, 0, sizeof(struct nvsp_message));
1144 init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL;
1145 init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE;
1146 init_packet->msg.v5_msg.subchn_req.num_subchannels =
1147 net_device->num_chn - 1;
1148 ret = vmbus_sendpacket(dev->channel, init_packet,
1149 sizeof(struct nvsp_message),
1150 (unsigned long)init_packet,
1151 VM_PKT_DATA_INBAND,
1152 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1153 if (ret)
1154 goto out;
1155 t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
1156 if (t == 0) {
1157 ret = -ETIMEDOUT;
1158 goto out;
1159 }
1160 if (init_packet->msg.v5_msg.subchn_comp.status !=
1161 NVSP_STAT_SUCCESS) {
1162 ret = -ENODEV;
1163 goto out;
1164 }
1165 net_device->num_chn = 1 +
1166 init_packet->msg.v5_msg.subchn_comp.num_subchannels;
1167
5b54dac8
HZ
1168 ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn);
1169
b3e6b82a 1170 /*
d66ab514 1171 * Set the number of sub-channels to be received.
b3e6b82a
KS
1172 */
1173 spin_lock_irqsave(&net_device->sc_lock, flags);
1174 sc_delta = num_rss_qs - (net_device->num_chn - 1);
1175 net_device->num_sc_offered -= sc_delta;
1176 spin_unlock_irqrestore(&net_device->sc_lock, flags);
1177
5b54dac8 1178out:
59995370
AS
1179 if (ret) {
1180 net_device->max_chn = 1;
5b54dac8 1181 net_device->num_chn = 1;
d66ab514 1182 net_device->num_sc_offered = 0;
59995370 1183 }
b3e6b82a 1184
5b54dac8 1185 return 0; /* return 0 because primary channel can be used alone */
4a0e70ae
KS
1186
1187err_dev_remv:
1188 rndis_filter_device_remove(dev);
1189 return ret;
fceaf24a
HJ
1190}
1191
df06bcff 1192void rndis_filter_device_remove(struct hv_device *dev)
fceaf24a 1193{
2625466d 1194 struct netvsc_device *net_dev = hv_device_to_netvsc_device(dev);
53d21fdb 1195 struct rndis_device *rndis_dev = net_dev->extension;
d66ab514
HZ
1196 unsigned long t;
1197
1198 /* If not all subchannel offers are complete, wait for them until
1199 * completion to avoid race.
1200 */
1201 while (net_dev->num_sc_offered > 0) {
1202 t = wait_for_completion_timeout(&net_dev->channel_init_wait,
1203 10 * HZ);
1204 if (t == 0)
1205 WARN(1, "Netvsc: Waiting for sub-channel processing");
1206 }
fceaf24a 1207
454f18a9 1208 /* Halt and release the rndis device */
9c26aa0d 1209 rndis_filter_halt_device(rndis_dev);
fceaf24a 1210
c2a4efdd 1211 kfree(rndis_dev);
53d21fdb 1212 net_dev->extension = NULL;
fceaf24a 1213
3fae5c8f 1214 netvsc_device_remove(dev);
fceaf24a
HJ
1215}
1216
fceaf24a 1217
2f5fa6c8 1218int rndis_filter_open(struct netvsc_device *nvdev)
fceaf24a 1219{
2f5fa6c8 1220 if (!nvdev)
8a62d716
BP
1221 return -EINVAL;
1222
2f5fa6c8 1223 if (atomic_inc_return(&nvdev->open_cnt) != 1)
84bf9cef
KS
1224 return 0;
1225
2f5fa6c8 1226 return rndis_filter_open_device(nvdev->extension);
fceaf24a
HJ
1227}
1228
2f5fa6c8 1229int rndis_filter_close(struct netvsc_device *nvdev)
fceaf24a 1230{
5fccab3b 1231 if (!nvdev)
8a62d716
BP
1232 return -EINVAL;
1233
84bf9cef
KS
1234 if (atomic_dec_return(&nvdev->open_cnt) != 0)
1235 return 0;
1236
5fccab3b 1237 return rndis_filter_close_device(nvdev->extension);
fceaf24a 1238}