hv_netvsc: pass struct net_device to rndis_filter_set_offload_params()
[deliverable/linux.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 622static int
426d9541 623rndis_filter_set_offload_params(struct net_device *ndev,
4a0e70ae
KS
624 struct ndis_offload_params *req_offloads)
625{
2625466d 626 struct netvsc_device *nvdev = net_device_to_netvsc_device(ndev);
4a0e70ae 627 struct rndis_device *rdev = nvdev->extension;
4a0e70ae
KS
628 struct rndis_request *request;
629 struct rndis_set_request *set;
630 struct ndis_offload_params *offload_params;
631 struct rndis_set_complete *set_complete;
632 u32 extlen = sizeof(struct ndis_offload_params);
999028cc
NMG
633 int ret;
634 unsigned long t;
af9893a3
KS
635 u32 vsp_version = nvdev->nvsp_version;
636
637 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
638 extlen = VERSION_4_OFFLOAD_SIZE;
639 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
640 * UDP checksum offload.
641 */
642 req_offloads->udp_ip_v4_csum = 0;
643 req_offloads->udp_ip_v6_csum = 0;
644 }
4a0e70ae
KS
645
646 request = get_rndis_request(rdev, RNDIS_MSG_SET,
647 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
648 if (!request)
649 return -ENOMEM;
650
651 set = &request->request_msg.msg.set_req;
652 set->oid = OID_TCP_OFFLOAD_PARAMETERS;
653 set->info_buflen = extlen;
654 set->info_buf_offset = sizeof(struct rndis_set_request);
655 set->dev_vc_handle = 0;
656
657 offload_params = (struct ndis_offload_params *)((ulong)set +
658 set->info_buf_offset);
659 *offload_params = *req_offloads;
660 offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
661 offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
662 offload_params->header.size = extlen;
663
664 ret = rndis_filter_send_request(rdev, request);
665 if (ret != 0)
666 goto cleanup;
667
668 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
669 if (t == 0) {
670 netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n");
671 /* can't put_rndis_request, since we may still receive a
672 * send-completion.
673 */
674 return -EBUSY;
675 } else {
676 set_complete = &request->response_msg.msg.set_complete;
677 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
af9893a3 678 netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
4a0e70ae
KS
679 set_complete->status);
680 ret = -EINVAL;
681 }
682 }
683
684cleanup:
685 put_rndis_request(rdev, request);
686 return ret;
687}
1ce09e89 688
5b54dac8
HZ
689u8 netvsc_hash_key[HASH_KEYLEN] = {
690 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
691 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
692 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
693 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
694 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
695};
696
da19fcd0 697static int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
5b54dac8 698{
3d541ac5 699 struct net_device *ndev = rdev->ndev;
5b54dac8
HZ
700 struct rndis_request *request;
701 struct rndis_set_request *set;
702 struct rndis_set_complete *set_complete;
703 u32 extlen = sizeof(struct ndis_recv_scale_param) +
704 4*ITAB_NUM + HASH_KEYLEN;
705 struct ndis_recv_scale_param *rssp;
706 u32 *itab;
707 u8 *keyp;
999028cc
NMG
708 int i, ret;
709 unsigned long t;
5b54dac8
HZ
710
711 request = get_rndis_request(
712 rdev, RNDIS_MSG_SET,
713 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
714 if (!request)
715 return -ENOMEM;
716
717 set = &request->request_msg.msg.set_req;
718 set->oid = OID_GEN_RECEIVE_SCALE_PARAMETERS;
719 set->info_buflen = extlen;
720 set->info_buf_offset = sizeof(struct rndis_set_request);
721 set->dev_vc_handle = 0;
722
723 rssp = (struct ndis_recv_scale_param *)(set + 1);
724 rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
725 rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
726 rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
727 rssp->flag = 0;
728 rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
4c87454a
HZ
729 NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
730 NDIS_HASH_TCP_IPV6;
5b54dac8
HZ
731 rssp->indirect_tabsize = 4*ITAB_NUM;
732 rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
733 rssp->hashkey_size = HASH_KEYLEN;
734 rssp->kashkey_offset = rssp->indirect_taboffset +
735 rssp->indirect_tabsize;
736
737 /* Set indirection table entries */
738 itab = (u32 *)(rssp + 1);
739 for (i = 0; i < ITAB_NUM; i++)
740 itab[i] = i % num_queue;
741
742 /* Set hask key values */
743 keyp = (u8 *)((unsigned long)rssp + rssp->kashkey_offset);
744 for (i = 0; i < HASH_KEYLEN; i++)
745 keyp[i] = netvsc_hash_key[i];
746
747
748 ret = rndis_filter_send_request(rdev, request);
749 if (ret != 0)
750 goto cleanup;
751
752 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
753 if (t == 0) {
754 netdev_err(ndev, "timeout before we got a set response...\n");
755 /* can't put_rndis_request, since we may still receive a
756 * send-completion.
757 */
758 return -ETIMEDOUT;
759 } else {
760 set_complete = &request->response_msg.msg.set_complete;
761 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
762 netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
763 set_complete->status);
764 ret = -EINVAL;
765 }
766 }
767
768cleanup:
769 put_rndis_request(rdev, request);
770 return ret;
771}
772
773
9c26aa0d 774static int rndis_filter_query_device_link_status(struct rndis_device *dev)
fceaf24a 775{
0120ee0d 776 u32 size = sizeof(u32);
6f27457b
S
777 u32 link_status;
778 int ret;
fceaf24a 779
6f27457b 780 ret = rndis_filter_query_device(dev,
0120ee0d 781 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
6f27457b 782 &link_status, &size);
6f27457b
S
783
784 return ret;
fceaf24a
HJ
785}
786
d426b2e3 787int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
fceaf24a 788{
e681b954 789 struct rndis_request *request;
9f33d054 790 struct rndis_set_request *set;
c2a4efdd 791 struct rndis_set_complete *set_complete;
4d643114 792 u32 status;
999028cc
NMG
793 int ret;
794 unsigned long t;
3d541ac5 795 struct net_device *ndev = dev->ndev;
fceaf24a 796
51491167 797 request = get_rndis_request(dev, RNDIS_MSG_SET,
0120ee0d
GKH
798 RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
799 sizeof(u32));
800 if (!request) {
58ef3977 801 ret = -ENOMEM;
1c627870 802 goto cleanup;
fceaf24a
HJ
803 }
804
454f18a9 805 /* Setup the rndis set */
a388eb17
HZ
806 set = &request->request_msg.msg.set_req;
807 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
808 set->info_buflen = sizeof(u32);
809 set->info_buf_offset = sizeof(struct rndis_set_request);
fceaf24a 810
0120ee0d 811 memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
c2a4efdd 812 &new_filter, sizeof(u32));
fceaf24a 813
9c26aa0d 814 ret = rndis_filter_send_request(dev, request);
fceaf24a 815 if (ret != 0)
1c627870 816 goto cleanup;
fceaf24a 817
5c5781b3 818 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
98d79690
S
819
820 if (t == 0) {
d9871158 821 netdev_err(ndev,
eb335bc4 822 "timeout before we got a set response...\n");
ea496374 823 ret = -ETIMEDOUT;
0120ee0d 824 /*
25985edc 825 * We can't deallocate the request since we may still receive a
0120ee0d
GKH
826 * send completion for it.
827 */
5585d81e 828 goto exit;
0120ee0d 829 } else {
a388eb17
HZ
830 set_complete = &request->response_msg.msg.set_complete;
831 status = set_complete->status;
fceaf24a
HJ
832 }
833
1c627870 834cleanup:
fceaf24a 835 if (request)
9c26aa0d 836 put_rndis_request(dev, request);
5585d81e 837exit:
fceaf24a
HJ
838 return ret;
839}
840
fceaf24a 841
9c26aa0d 842static int rndis_filter_init_device(struct rndis_device *dev)
fceaf24a 843{
e681b954 844 struct rndis_request *request;
9f33d054 845 struct rndis_initialize_request *init;
c2a4efdd 846 struct rndis_initialize_complete *init_complete;
4d643114 847 u32 status;
999028cc
NMG
848 int ret;
849 unsigned long t;
2625466d 850 struct netvsc_device *nvdev = net_device_to_netvsc_device(dev->ndev);
fceaf24a 851
51491167 852 request = get_rndis_request(dev, RNDIS_MSG_INIT,
0120ee0d
GKH
853 RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
854 if (!request) {
bc49b926 855 ret = -ENOMEM;
1c627870 856 goto cleanup;
fceaf24a
HJ
857 }
858
454f18a9 859 /* Setup the rndis set */
a388eb17
HZ
860 init = &request->request_msg.msg.init_req;
861 init->major_ver = RNDIS_MAJOR_VERSION;
862 init->minor_ver = RNDIS_MINOR_VERSION;
fb1d074e 863 init->max_xfer_size = 0x4000;
fceaf24a 864
c2a4efdd 865 dev->state = RNDIS_DEV_INITIALIZING;
fceaf24a 866
9c26aa0d 867 ret = rndis_filter_send_request(dev, request);
0120ee0d 868 if (ret != 0) {
c2a4efdd 869 dev->state = RNDIS_DEV_UNINITIALIZED;
1c627870 870 goto cleanup;
fceaf24a
HJ
871 }
872
5c5781b3 873 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
98d79690
S
874
875 if (t == 0) {
0c3b7b2f 876 ret = -ETIMEDOUT;
1c627870 877 goto cleanup;
0c3b7b2f 878 }
fceaf24a 879
a388eb17
HZ
880 init_complete = &request->response_msg.msg.init_complete;
881 status = init_complete->status;
0120ee0d 882 if (status == RNDIS_STATUS_SUCCESS) {
c2a4efdd 883 dev->state = RNDIS_DEV_INITIALIZED;
7c3877f2
HZ
884 nvdev->max_pkt = init_complete->max_pkt_per_msg;
885 nvdev->pkt_align = 1 << init_complete->pkt_alignment_factor;
fceaf24a 886 ret = 0;
0120ee0d 887 } else {
c2a4efdd 888 dev->state = RNDIS_DEV_UNINITIALIZED;
bc49b926 889 ret = -EINVAL;
fceaf24a
HJ
890 }
891
1c627870 892cleanup:
fceaf24a 893 if (request)
9c26aa0d 894 put_rndis_request(dev, request);
fceaf24a
HJ
895
896 return ret;
897}
898
9c26aa0d 899static void rndis_filter_halt_device(struct rndis_device *dev)
fceaf24a 900{
e681b954 901 struct rndis_request *request;
9f33d054 902 struct rndis_halt_request *halt;
3d541ac5
VK
903 struct net_device_context *net_device_ctx = netdev_priv(dev->ndev);
904 struct netvsc_device *nvdev = net_device_ctx->nvdev;
905 struct hv_device *hdev = net_device_ctx->device_ctx;
ae9e63bb 906 ulong flags;
fceaf24a 907
454f18a9 908 /* Attempt to do a rndis device halt */
51491167 909 request = get_rndis_request(dev, RNDIS_MSG_HALT,
0120ee0d 910 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
fceaf24a 911 if (!request)
1c627870 912 goto cleanup;
fceaf24a 913
454f18a9 914 /* Setup the rndis set */
a388eb17
HZ
915 halt = &request->request_msg.msg.halt_req;
916 halt->req_id = atomic_inc_return(&dev->new_req_id);
fceaf24a 917
454f18a9 918 /* Ignore return since this msg is optional. */
9c26aa0d 919 rndis_filter_send_request(dev, request);
fceaf24a 920
c2a4efdd 921 dev->state = RNDIS_DEV_UNINITIALIZED;
fceaf24a 922
1c627870 923cleanup:
ae9e63bb
HZ
924 spin_lock_irqsave(&hdev->channel->inbound_lock, flags);
925 nvdev->destroy = true;
926 spin_unlock_irqrestore(&hdev->channel->inbound_lock, flags);
927
928 /* Wait for all send completions */
929 wait_event(nvdev->wait_drain,
930 atomic_read(&nvdev->num_outstanding_sends) == 0);
931
fceaf24a 932 if (request)
9c26aa0d 933 put_rndis_request(dev, request);
fceaf24a
HJ
934 return;
935}
936
9c26aa0d 937static int rndis_filter_open_device(struct rndis_device *dev)
fceaf24a 938{
0120ee0d 939 int ret;
fceaf24a 940
c2a4efdd 941 if (dev->state != RNDIS_DEV_INITIALIZED)
fceaf24a
HJ
942 return 0;
943
9c26aa0d 944 ret = rndis_filter_set_packet_filter(dev,
0120ee0d 945 NDIS_PACKET_TYPE_BROADCAST |
95beae90 946 NDIS_PACKET_TYPE_ALL_MULTICAST |
0120ee0d 947 NDIS_PACKET_TYPE_DIRECTED);
fceaf24a 948 if (ret == 0)
c2a4efdd 949 dev->state = RNDIS_DEV_DATAINITIALIZED;
fceaf24a 950
fceaf24a
HJ
951 return ret;
952}
953
9c26aa0d 954static int rndis_filter_close_device(struct rndis_device *dev)
fceaf24a
HJ
955{
956 int ret;
957
c2a4efdd 958 if (dev->state != RNDIS_DEV_DATAINITIALIZED)
fceaf24a
HJ
959 return 0;
960
9c26aa0d 961 ret = rndis_filter_set_packet_filter(dev, 0);
c3582a2c
HZ
962 if (ret == -ENODEV)
963 ret = 0;
964
fceaf24a 965 if (ret == 0)
c2a4efdd 966 dev->state = RNDIS_DEV_INITIALIZED;
fceaf24a 967
fceaf24a
HJ
968 return ret;
969}
970
5b54dac8
HZ
971static void netvsc_sc_open(struct vmbus_channel *new_sc)
972{
3d541ac5
VK
973 struct net_device *ndev =
974 hv_get_drvdata(new_sc->primary_channel->device_obj);
2625466d 975 struct netvsc_device *nvscdev = net_device_to_netvsc_device(ndev);
5b54dac8
HZ
976 u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
977 int ret;
b3e6b82a 978 unsigned long flags;
5b54dac8 979
5b54dac8
HZ
980 if (chn_index >= nvscdev->num_chn)
981 return;
982
983 set_per_channel_state(new_sc, nvscdev->sub_cb_buf + (chn_index - 1) *
984 NETVSC_PACKET_SIZE);
985
986 ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
987 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
988 netvsc_channel_cb, new_sc);
989
990 if (ret == 0)
991 nvscdev->chn_table[chn_index] = new_sc;
3f735131
HZ
992
993 spin_lock_irqsave(&nvscdev->sc_lock, flags);
994 nvscdev->num_sc_offered--;
995 spin_unlock_irqrestore(&nvscdev->sc_lock, flags);
996 if (nvscdev->num_sc_offered == 0)
997 complete(&nvscdev->channel_init_wait);
5b54dac8
HZ
998}
999
bdbad576 1000int rndis_filter_device_add(struct hv_device *dev,
c2a4efdd 1001 void *additional_info)
fceaf24a
HJ
1002{
1003 int ret;
3d541ac5
VK
1004 struct net_device *net = hv_get_drvdata(dev);
1005 struct net_device_context *net_device_ctx = netdev_priv(net);
86c921af 1006 struct netvsc_device *net_device;
b13cc345 1007 struct rndis_device *rndis_device;
3c4debad 1008 struct netvsc_device_info *device_info = additional_info;
4a0e70ae 1009 struct ndis_offload_params offloads;
5b54dac8 1010 struct nvsp_message *init_packet;
999028cc 1011 unsigned long t;
5b54dac8
HZ
1012 struct ndis_recv_scale_cap rsscap;
1013 u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
4d3c9d37 1014 u32 mtu, size;
e01ec219 1015 u32 num_rss_qs;
b3e6b82a 1016 u32 sc_delta;
e01ec219
KS
1017 const struct cpumask *node_cpu_mask;
1018 u32 num_possible_rss_qs;
b3e6b82a 1019 unsigned long flags;
fceaf24a 1020
b13cc345
S
1021 rndis_device = get_rndis_device();
1022 if (!rndis_device)
327efbae 1023 return -ENODEV;
fceaf24a 1024
0120ee0d
GKH
1025 /*
1026 * Let the inner driver handle this first to create the netvsc channel
1027 * NOTE! Once the channel is created, we may get a receive callback
1028 * (RndisFilterOnReceive()) before this call is completed
1029 */
ce5bf661 1030 ret = netvsc_device_add(dev, additional_info);
0120ee0d 1031 if (ret != 0) {
b13cc345 1032 kfree(rndis_device);
fceaf24a
HJ
1033 return ret;
1034 }
1035
454f18a9 1036 /* Initialize the rndis device */
3d541ac5 1037 net_device = net_device_ctx->nvdev;
59995370 1038 net_device->max_chn = 1;
5b54dac8 1039 net_device->num_chn = 1;
fceaf24a 1040
b3e6b82a
KS
1041 spin_lock_init(&net_device->sc_lock);
1042
b13cc345 1043 net_device->extension = rndis_device;
3d541ac5 1044 rndis_device->ndev = net;
fceaf24a 1045
454f18a9 1046 /* Send the rndis initialization message */
b13cc345 1047 ret = rndis_filter_init_device(rndis_device);
0120ee0d 1048 if (ret != 0) {
5243e7bd
HZ
1049 rndis_filter_device_remove(dev);
1050 return ret;
fceaf24a
HJ
1051 }
1052
4d3c9d37
HZ
1053 /* Get the MTU from the host */
1054 size = sizeof(u32);
1055 ret = rndis_filter_query_device(rndis_device,
1056 RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
1057 &mtu, &size);
0a1275ca
VK
1058 if (ret == 0 && size == sizeof(u32) && mtu < net->mtu)
1059 net->mtu = mtu;
4d3c9d37 1060
454f18a9 1061 /* Get the mac address */
b13cc345 1062 ret = rndis_filter_query_device_mac(rndis_device);
0120ee0d 1063 if (ret != 0) {
5243e7bd
HZ
1064 rndis_filter_device_remove(dev);
1065 return ret;
fceaf24a
HJ
1066 }
1067
3c4debad 1068 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
fceaf24a 1069
4a0e70ae
KS
1070 /* Turn on the offloads; the host supports all of the relevant
1071 * offloads.
1072 */
1073 memset(&offloads, 0, sizeof(struct ndis_offload_params));
1074 /* A value of zero means "no change"; now turn on what we
1075 * want.
1076 */
1077 offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1078 offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1079 offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1080 offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1081 offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1082 offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1083
1084
426d9541 1085 ret = rndis_filter_set_offload_params(net, &offloads);
4a0e70ae
KS
1086 if (ret)
1087 goto err_dev_remv;
1088
b13cc345 1089 rndis_filter_query_device_link_status(rndis_device);
fceaf24a 1090
6f27457b 1091 device_info->link_state = rndis_device->link_state;
eb335bc4 1092
6f27457b 1093 dev_info(&dev->device, "Device MAC %pM link state %s\n",
b13cc345 1094 rndis_device->hw_mac_adr,
6f27457b 1095 device_info->link_state ? "down" : "up");
fceaf24a 1096
5b54dac8
HZ
1097 if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
1098 return 0;
1099
1100 /* vRSS setup */
1101 memset(&rsscap, 0, rsscap_size);
1102 ret = rndis_filter_query_device(rndis_device,
1103 OID_GEN_RECEIVE_SCALE_CAPABILITIES,
1104 &rsscap, &rsscap_size);
1105 if (ret || rsscap.num_recv_que < 2)
1106 goto out;
1107
9efc2f7d 1108 net_device->max_chn = min_t(u32, VRSS_CHANNEL_MAX, rsscap.num_recv_que);
e01ec219 1109
9efc2f7d 1110 num_rss_qs = min(device_info->max_num_vrss_chns, net_device->max_chn);
e01ec219
KS
1111
1112 /*
1113 * We will limit the VRSS channels to the number CPUs in the NUMA node
1114 * the primary channel is currently bound to.
1115 */
1116 node_cpu_mask = cpumask_of_node(cpu_to_node(dev->channel->target_cpu));
1117 num_possible_rss_qs = cpumask_weight(node_cpu_mask);
8ebdcc52
AS
1118
1119 /* We will use the given number of channels if available. */
1120 if (device_info->num_chn && device_info->num_chn < net_device->max_chn)
1121 net_device->num_chn = device_info->num_chn;
1122 else
1123 net_device->num_chn = min(num_possible_rss_qs, num_rss_qs);
e01ec219 1124
b3e6b82a
KS
1125 num_rss_qs = net_device->num_chn - 1;
1126 net_device->num_sc_offered = num_rss_qs;
1127
5b54dac8
HZ
1128 if (net_device->num_chn == 1)
1129 goto out;
1130
1131 net_device->sub_cb_buf = vzalloc((net_device->num_chn - 1) *
1132 NETVSC_PACKET_SIZE);
1133 if (!net_device->sub_cb_buf) {
1134 net_device->num_chn = 1;
1135 dev_info(&dev->device, "No memory for subchannels.\n");
1136 goto out;
1137 }
1138
1139 vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
1140
1141 init_packet = &net_device->channel_init_pkt;
1142 memset(init_packet, 0, sizeof(struct nvsp_message));
1143 init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL;
1144 init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE;
1145 init_packet->msg.v5_msg.subchn_req.num_subchannels =
1146 net_device->num_chn - 1;
1147 ret = vmbus_sendpacket(dev->channel, init_packet,
1148 sizeof(struct nvsp_message),
1149 (unsigned long)init_packet,
1150 VM_PKT_DATA_INBAND,
1151 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1152 if (ret)
1153 goto out;
1154 t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
1155 if (t == 0) {
1156 ret = -ETIMEDOUT;
1157 goto out;
1158 }
1159 if (init_packet->msg.v5_msg.subchn_comp.status !=
1160 NVSP_STAT_SUCCESS) {
1161 ret = -ENODEV;
1162 goto out;
1163 }
1164 net_device->num_chn = 1 +
1165 init_packet->msg.v5_msg.subchn_comp.num_subchannels;
1166
5b54dac8
HZ
1167 ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn);
1168
b3e6b82a 1169 /*
d66ab514 1170 * Set the number of sub-channels to be received.
b3e6b82a
KS
1171 */
1172 spin_lock_irqsave(&net_device->sc_lock, flags);
1173 sc_delta = num_rss_qs - (net_device->num_chn - 1);
1174 net_device->num_sc_offered -= sc_delta;
1175 spin_unlock_irqrestore(&net_device->sc_lock, flags);
1176
5b54dac8 1177out:
59995370
AS
1178 if (ret) {
1179 net_device->max_chn = 1;
5b54dac8 1180 net_device->num_chn = 1;
d66ab514 1181 net_device->num_sc_offered = 0;
59995370 1182 }
b3e6b82a 1183
5b54dac8 1184 return 0; /* return 0 because primary channel can be used alone */
4a0e70ae
KS
1185
1186err_dev_remv:
1187 rndis_filter_device_remove(dev);
1188 return ret;
fceaf24a
HJ
1189}
1190
df06bcff 1191void rndis_filter_device_remove(struct hv_device *dev)
fceaf24a 1192{
2625466d 1193 struct netvsc_device *net_dev = hv_device_to_netvsc_device(dev);
53d21fdb 1194 struct rndis_device *rndis_dev = net_dev->extension;
d66ab514
HZ
1195 unsigned long t;
1196
1197 /* If not all subchannel offers are complete, wait for them until
1198 * completion to avoid race.
1199 */
1200 while (net_dev->num_sc_offered > 0) {
1201 t = wait_for_completion_timeout(&net_dev->channel_init_wait,
1202 10 * HZ);
1203 if (t == 0)
1204 WARN(1, "Netvsc: Waiting for sub-channel processing");
1205 }
fceaf24a 1206
454f18a9 1207 /* Halt and release the rndis device */
9c26aa0d 1208 rndis_filter_halt_device(rndis_dev);
fceaf24a 1209
c2a4efdd 1210 kfree(rndis_dev);
53d21fdb 1211 net_dev->extension = NULL;
fceaf24a 1212
3fae5c8f 1213 netvsc_device_remove(dev);
fceaf24a
HJ
1214}
1215
fceaf24a 1216
2f5fa6c8 1217int rndis_filter_open(struct netvsc_device *nvdev)
fceaf24a 1218{
2f5fa6c8 1219 if (!nvdev)
8a62d716
BP
1220 return -EINVAL;
1221
2f5fa6c8 1222 if (atomic_inc_return(&nvdev->open_cnt) != 1)
84bf9cef
KS
1223 return 0;
1224
2f5fa6c8 1225 return rndis_filter_open_device(nvdev->extension);
fceaf24a
HJ
1226}
1227
2f5fa6c8 1228int rndis_filter_close(struct netvsc_device *nvdev)
fceaf24a 1229{
5fccab3b 1230 if (!nvdev)
8a62d716
BP
1231 return -EINVAL;
1232
84bf9cef
KS
1233 if (atomic_dec_return(&nvdev->open_cnt) != 0)
1234 return 0;
1235
5fccab3b 1236 return rndis_filter_close_device(nvdev->extension);
fceaf24a 1237}
This page took 0.95019 seconds and 5 git commands to generate.