Merge remote-tracking branch 'mfd/for-mfd-next'
[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;
fceaf24a 469
c2a4efdd 470 if (!result)
8a62d716 471 return -EINVAL;
fceaf24a 472
c2a4efdd 473 *result_size = 0;
51491167 474 request = get_rndis_request(dev, RNDIS_MSG_QUERY,
0120ee0d
GKH
475 RNDIS_MESSAGE_SIZE(struct rndis_query_request));
476 if (!request) {
de6e0580 477 ret = -ENOMEM;
1c627870 478 goto cleanup;
fceaf24a
HJ
479 }
480
454f18a9 481 /* Setup the rndis query */
a388eb17
HZ
482 query = &request->request_msg.msg.query_req;
483 query->oid = oid;
484 query->info_buf_offset = sizeof(struct rndis_query_request);
485 query->info_buflen = 0;
486 query->dev_vc_handle = 0;
fceaf24a 487
5b54dac8
HZ
488 if (oid == OID_GEN_RECEIVE_SCALE_CAPABILITIES) {
489 struct ndis_recv_scale_cap *cap;
490
491 request->request_msg.msg_len +=
492 sizeof(struct ndis_recv_scale_cap);
493 query->info_buflen = sizeof(struct ndis_recv_scale_cap);
494 cap = (struct ndis_recv_scale_cap *)((unsigned long)query +
495 query->info_buf_offset);
496 cap->hdr.type = NDIS_OBJECT_TYPE_RSS_CAPABILITIES;
497 cap->hdr.rev = NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
498 cap->hdr.size = sizeof(struct ndis_recv_scale_cap);
499 }
500
9c26aa0d 501 ret = rndis_filter_send_request(dev, request);
fceaf24a 502 if (ret != 0)
1c627870 503 goto cleanup;
fceaf24a 504
5362855a 505 wait_for_completion(&request->wait_event);
fceaf24a 506
454f18a9 507 /* Copy the response back */
a388eb17 508 query_complete = &request->response_msg.msg.query_complete;
fceaf24a 509
a388eb17 510 if (query_complete->info_buflen > inresult_size) {
fceaf24a 511 ret = -1;
1c627870 512 goto cleanup;
fceaf24a
HJ
513 }
514
c2a4efdd
HZ
515 memcpy(result,
516 (void *)((unsigned long)query_complete +
a388eb17
HZ
517 query_complete->info_buf_offset),
518 query_complete->info_buflen);
fceaf24a 519
a388eb17 520 *result_size = query_complete->info_buflen;
fceaf24a 521
1c627870 522cleanup:
fceaf24a 523 if (request)
9c26aa0d 524 put_rndis_request(dev, request);
fceaf24a
HJ
525
526 return ret;
527}
528
9c26aa0d 529static int rndis_filter_query_device_mac(struct rndis_device *dev)
fceaf24a 530{
9f8bd8ba 531 u32 size = ETH_ALEN;
fceaf24a 532
9c26aa0d 533 return rndis_filter_query_device(dev,
0120ee0d 534 RNDIS_OID_802_3_PERMANENT_ADDRESS,
c2a4efdd 535 dev->hw_mac_adr, &size);
fceaf24a
HJ
536}
537
1ce09e89
HZ
538#define NWADR_STR "NetworkAddress"
539#define NWADR_STRLEN 14
540
e834da9a 541int rndis_filter_set_device_mac(struct net_device *ndev, char *mac)
1ce09e89 542{
2625466d 543 struct netvsc_device *nvdev = net_device_to_netvsc_device(ndev);
1ce09e89 544 struct rndis_device *rdev = nvdev->extension;
1ce09e89
HZ
545 struct rndis_request *request;
546 struct rndis_set_request *set;
547 struct rndis_config_parameter_info *cpi;
548 wchar_t *cfg_nwadr, *cfg_mac;
549 struct rndis_set_complete *set_complete;
550 char macstr[2*ETH_ALEN+1];
551 u32 extlen = sizeof(struct rndis_config_parameter_info) +
552 2*NWADR_STRLEN + 4*ETH_ALEN;
999028cc 553 int ret;
1ce09e89
HZ
554
555 request = get_rndis_request(rdev, RNDIS_MSG_SET,
556 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
557 if (!request)
558 return -ENOMEM;
559
560 set = &request->request_msg.msg.set_req;
561 set->oid = RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER;
562 set->info_buflen = extlen;
563 set->info_buf_offset = sizeof(struct rndis_set_request);
564 set->dev_vc_handle = 0;
565
566 cpi = (struct rndis_config_parameter_info *)((ulong)set +
567 set->info_buf_offset);
568 cpi->parameter_name_offset =
569 sizeof(struct rndis_config_parameter_info);
570 /* Multiply by 2 because host needs 2 bytes (utf16) for each char */
571 cpi->parameter_name_length = 2*NWADR_STRLEN;
572 cpi->parameter_type = RNDIS_CONFIG_PARAM_TYPE_STRING;
573 cpi->parameter_value_offset =
574 cpi->parameter_name_offset + cpi->parameter_name_length;
575 /* Multiply by 4 because each MAC byte displayed as 2 utf16 chars */
576 cpi->parameter_value_length = 4*ETH_ALEN;
577
578 cfg_nwadr = (wchar_t *)((ulong)cpi + cpi->parameter_name_offset);
579 cfg_mac = (wchar_t *)((ulong)cpi + cpi->parameter_value_offset);
580 ret = utf8s_to_utf16s(NWADR_STR, NWADR_STRLEN, UTF16_HOST_ENDIAN,
581 cfg_nwadr, NWADR_STRLEN);
582 if (ret < 0)
583 goto cleanup;
584 snprintf(macstr, 2*ETH_ALEN+1, "%pm", mac);
585 ret = utf8s_to_utf16s(macstr, 2*ETH_ALEN, UTF16_HOST_ENDIAN,
586 cfg_mac, 2*ETH_ALEN);
587 if (ret < 0)
588 goto cleanup;
589
590 ret = rndis_filter_send_request(rdev, request);
591 if (ret != 0)
592 goto cleanup;
593
5362855a
VK
594 wait_for_completion(&request->wait_event);
595
596 set_complete = &request->response_msg.msg.set_complete;
597 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
598 netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
599 set_complete->status);
600 ret = -EINVAL;
1ce09e89
HZ
601 }
602
603cleanup:
604 put_rndis_request(rdev, request);
605 return ret;
606}
607
da19fcd0 608static int
426d9541 609rndis_filter_set_offload_params(struct net_device *ndev,
4a0e70ae
KS
610 struct ndis_offload_params *req_offloads)
611{
2625466d 612 struct netvsc_device *nvdev = net_device_to_netvsc_device(ndev);
4a0e70ae 613 struct rndis_device *rdev = nvdev->extension;
4a0e70ae
KS
614 struct rndis_request *request;
615 struct rndis_set_request *set;
616 struct ndis_offload_params *offload_params;
617 struct rndis_set_complete *set_complete;
618 u32 extlen = sizeof(struct ndis_offload_params);
999028cc 619 int ret;
af9893a3
KS
620 u32 vsp_version = nvdev->nvsp_version;
621
622 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
623 extlen = VERSION_4_OFFLOAD_SIZE;
624 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
625 * UDP checksum offload.
626 */
627 req_offloads->udp_ip_v4_csum = 0;
628 req_offloads->udp_ip_v6_csum = 0;
629 }
4a0e70ae
KS
630
631 request = get_rndis_request(rdev, RNDIS_MSG_SET,
632 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
633 if (!request)
634 return -ENOMEM;
635
636 set = &request->request_msg.msg.set_req;
637 set->oid = OID_TCP_OFFLOAD_PARAMETERS;
638 set->info_buflen = extlen;
639 set->info_buf_offset = sizeof(struct rndis_set_request);
640 set->dev_vc_handle = 0;
641
642 offload_params = (struct ndis_offload_params *)((ulong)set +
643 set->info_buf_offset);
644 *offload_params = *req_offloads;
645 offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
646 offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
647 offload_params->header.size = extlen;
648
649 ret = rndis_filter_send_request(rdev, request);
650 if (ret != 0)
651 goto cleanup;
652
5362855a
VK
653 wait_for_completion(&request->wait_event);
654 set_complete = &request->response_msg.msg.set_complete;
655 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
656 netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
657 set_complete->status);
658 ret = -EINVAL;
4a0e70ae
KS
659 }
660
661cleanup:
662 put_rndis_request(rdev, request);
663 return ret;
664}
1ce09e89 665
94773866 666static const u8 netvsc_hash_key[] = {
5b54dac8
HZ
667 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
668 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
669 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
670 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
671 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
672};
94773866 673#define HASH_KEYLEN ARRAY_SIZE(netvsc_hash_key)
5b54dac8 674
da19fcd0 675static int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
5b54dac8 676{
3d541ac5 677 struct net_device *ndev = rdev->ndev;
5b54dac8
HZ
678 struct rndis_request *request;
679 struct rndis_set_request *set;
680 struct rndis_set_complete *set_complete;
681 u32 extlen = sizeof(struct ndis_recv_scale_param) +
682 4*ITAB_NUM + HASH_KEYLEN;
683 struct ndis_recv_scale_param *rssp;
684 u32 *itab;
685 u8 *keyp;
999028cc 686 int i, ret;
5b54dac8
HZ
687
688 request = get_rndis_request(
689 rdev, RNDIS_MSG_SET,
690 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
691 if (!request)
692 return -ENOMEM;
693
694 set = &request->request_msg.msg.set_req;
695 set->oid = OID_GEN_RECEIVE_SCALE_PARAMETERS;
696 set->info_buflen = extlen;
697 set->info_buf_offset = sizeof(struct rndis_set_request);
698 set->dev_vc_handle = 0;
699
700 rssp = (struct ndis_recv_scale_param *)(set + 1);
701 rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
702 rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
703 rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
704 rssp->flag = 0;
705 rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
4c87454a
HZ
706 NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
707 NDIS_HASH_TCP_IPV6;
5b54dac8
HZ
708 rssp->indirect_tabsize = 4*ITAB_NUM;
709 rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
710 rssp->hashkey_size = HASH_KEYLEN;
711 rssp->kashkey_offset = rssp->indirect_taboffset +
712 rssp->indirect_tabsize;
713
714 /* Set indirection table entries */
715 itab = (u32 *)(rssp + 1);
716 for (i = 0; i < ITAB_NUM; i++)
717 itab[i] = i % num_queue;
718
719 /* Set hask key values */
720 keyp = (u8 *)((unsigned long)rssp + rssp->kashkey_offset);
721 for (i = 0; i < HASH_KEYLEN; i++)
722 keyp[i] = netvsc_hash_key[i];
723
5b54dac8
HZ
724 ret = rndis_filter_send_request(rdev, request);
725 if (ret != 0)
726 goto cleanup;
727
5362855a
VK
728 wait_for_completion(&request->wait_event);
729 set_complete = &request->response_msg.msg.set_complete;
730 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
731 netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
732 set_complete->status);
733 ret = -EINVAL;
5b54dac8
HZ
734 }
735
736cleanup:
737 put_rndis_request(rdev, request);
738 return ret;
739}
740
9c26aa0d 741static int rndis_filter_query_device_link_status(struct rndis_device *dev)
fceaf24a 742{
0120ee0d 743 u32 size = sizeof(u32);
6f27457b
S
744 u32 link_status;
745 int ret;
fceaf24a 746
6f27457b 747 ret = rndis_filter_query_device(dev,
0120ee0d 748 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
6f27457b 749 &link_status, &size);
6f27457b
S
750
751 return ret;
fceaf24a
HJ
752}
753
b37879e6
HZ
754static int rndis_filter_query_link_speed(struct rndis_device *dev)
755{
756 u32 size = sizeof(u32);
757 u32 link_speed;
758 struct net_device_context *ndc;
759 int ret;
760
761 ret = rndis_filter_query_device(dev, RNDIS_OID_GEN_LINK_SPEED,
762 &link_speed, &size);
763
764 if (!ret) {
765 ndc = netdev_priv(dev->ndev);
766
767 /* The link speed reported from host is in 100bps unit, so
768 * we convert it to Mbps here.
769 */
770 ndc->speed = link_speed / 10000;
771 }
772
773 return ret;
774}
775
d426b2e3 776int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
fceaf24a 777{
e681b954 778 struct rndis_request *request;
9f33d054 779 struct rndis_set_request *set;
c2a4efdd 780 struct rndis_set_complete *set_complete;
4d643114 781 u32 status;
999028cc 782 int ret;
fceaf24a 783
51491167 784 request = get_rndis_request(dev, RNDIS_MSG_SET,
0120ee0d
GKH
785 RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
786 sizeof(u32));
787 if (!request) {
58ef3977 788 ret = -ENOMEM;
1c627870 789 goto cleanup;
fceaf24a
HJ
790 }
791
454f18a9 792 /* Setup the rndis set */
a388eb17
HZ
793 set = &request->request_msg.msg.set_req;
794 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
795 set->info_buflen = sizeof(u32);
796 set->info_buf_offset = sizeof(struct rndis_set_request);
fceaf24a 797
0120ee0d 798 memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
c2a4efdd 799 &new_filter, sizeof(u32));
fceaf24a 800
9c26aa0d 801 ret = rndis_filter_send_request(dev, request);
fceaf24a 802 if (ret != 0)
1c627870 803 goto cleanup;
fceaf24a 804
5362855a 805 wait_for_completion(&request->wait_event);
98d79690 806
5362855a
VK
807 set_complete = &request->response_msg.msg.set_complete;
808 status = set_complete->status;
fceaf24a 809
1c627870 810cleanup:
fceaf24a 811 if (request)
9c26aa0d 812 put_rndis_request(dev, request);
fceaf24a
HJ
813 return ret;
814}
815
9c26aa0d 816static int rndis_filter_init_device(struct rndis_device *dev)
fceaf24a 817{
e681b954 818 struct rndis_request *request;
9f33d054 819 struct rndis_initialize_request *init;
c2a4efdd 820 struct rndis_initialize_complete *init_complete;
4d643114 821 u32 status;
999028cc 822 int ret;
2625466d 823 struct netvsc_device *nvdev = net_device_to_netvsc_device(dev->ndev);
fceaf24a 824
51491167 825 request = get_rndis_request(dev, RNDIS_MSG_INIT,
0120ee0d
GKH
826 RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
827 if (!request) {
bc49b926 828 ret = -ENOMEM;
1c627870 829 goto cleanup;
fceaf24a
HJ
830 }
831
454f18a9 832 /* Setup the rndis set */
a388eb17
HZ
833 init = &request->request_msg.msg.init_req;
834 init->major_ver = RNDIS_MAJOR_VERSION;
835 init->minor_ver = RNDIS_MINOR_VERSION;
fb1d074e 836 init->max_xfer_size = 0x4000;
fceaf24a 837
c2a4efdd 838 dev->state = RNDIS_DEV_INITIALIZING;
fceaf24a 839
9c26aa0d 840 ret = rndis_filter_send_request(dev, request);
0120ee0d 841 if (ret != 0) {
c2a4efdd 842 dev->state = RNDIS_DEV_UNINITIALIZED;
1c627870 843 goto cleanup;
fceaf24a
HJ
844 }
845
5362855a 846 wait_for_completion(&request->wait_event);
fceaf24a 847
a388eb17
HZ
848 init_complete = &request->response_msg.msg.init_complete;
849 status = init_complete->status;
0120ee0d 850 if (status == RNDIS_STATUS_SUCCESS) {
c2a4efdd 851 dev->state = RNDIS_DEV_INITIALIZED;
7c3877f2
HZ
852 nvdev->max_pkt = init_complete->max_pkt_per_msg;
853 nvdev->pkt_align = 1 << init_complete->pkt_alignment_factor;
fceaf24a 854 ret = 0;
0120ee0d 855 } else {
c2a4efdd 856 dev->state = RNDIS_DEV_UNINITIALIZED;
bc49b926 857 ret = -EINVAL;
fceaf24a
HJ
858 }
859
1c627870 860cleanup:
fceaf24a 861 if (request)
9c26aa0d 862 put_rndis_request(dev, request);
fceaf24a
HJ
863
864 return ret;
865}
866
9c26aa0d 867static void rndis_filter_halt_device(struct rndis_device *dev)
fceaf24a 868{
e681b954 869 struct rndis_request *request;
9f33d054 870 struct rndis_halt_request *halt;
3d541ac5
VK
871 struct net_device_context *net_device_ctx = netdev_priv(dev->ndev);
872 struct netvsc_device *nvdev = net_device_ctx->nvdev;
873 struct hv_device *hdev = net_device_ctx->device_ctx;
ae9e63bb 874 ulong flags;
fceaf24a 875
454f18a9 876 /* Attempt to do a rndis device halt */
51491167 877 request = get_rndis_request(dev, RNDIS_MSG_HALT,
0120ee0d 878 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
fceaf24a 879 if (!request)
1c627870 880 goto cleanup;
fceaf24a 881
454f18a9 882 /* Setup the rndis set */
a388eb17
HZ
883 halt = &request->request_msg.msg.halt_req;
884 halt->req_id = atomic_inc_return(&dev->new_req_id);
fceaf24a 885
454f18a9 886 /* Ignore return since this msg is optional. */
9c26aa0d 887 rndis_filter_send_request(dev, request);
fceaf24a 888
c2a4efdd 889 dev->state = RNDIS_DEV_UNINITIALIZED;
fceaf24a 890
1c627870 891cleanup:
ae9e63bb
HZ
892 spin_lock_irqsave(&hdev->channel->inbound_lock, flags);
893 nvdev->destroy = true;
894 spin_unlock_irqrestore(&hdev->channel->inbound_lock, flags);
895
896 /* Wait for all send completions */
897 wait_event(nvdev->wait_drain,
c0b558e5
HZ
898 atomic_read(&nvdev->num_outstanding_sends) == 0 &&
899 atomic_read(&nvdev->num_outstanding_recvs) == 0);
ae9e63bb 900
fceaf24a 901 if (request)
9c26aa0d 902 put_rndis_request(dev, request);
fceaf24a
HJ
903}
904
9c26aa0d 905static int rndis_filter_open_device(struct rndis_device *dev)
fceaf24a 906{
0120ee0d 907 int ret;
fceaf24a 908
c2a4efdd 909 if (dev->state != RNDIS_DEV_INITIALIZED)
fceaf24a
HJ
910 return 0;
911
9c26aa0d 912 ret = rndis_filter_set_packet_filter(dev,
0120ee0d 913 NDIS_PACKET_TYPE_BROADCAST |
95beae90 914 NDIS_PACKET_TYPE_ALL_MULTICAST |
0120ee0d 915 NDIS_PACKET_TYPE_DIRECTED);
fceaf24a 916 if (ret == 0)
c2a4efdd 917 dev->state = RNDIS_DEV_DATAINITIALIZED;
fceaf24a 918
fceaf24a
HJ
919 return ret;
920}
921
9c26aa0d 922static int rndis_filter_close_device(struct rndis_device *dev)
fceaf24a
HJ
923{
924 int ret;
925
c2a4efdd 926 if (dev->state != RNDIS_DEV_DATAINITIALIZED)
fceaf24a
HJ
927 return 0;
928
9c26aa0d 929 ret = rndis_filter_set_packet_filter(dev, 0);
c3582a2c
HZ
930 if (ret == -ENODEV)
931 ret = 0;
932
fceaf24a 933 if (ret == 0)
c2a4efdd 934 dev->state = RNDIS_DEV_INITIALIZED;
fceaf24a 935
fceaf24a
HJ
936 return ret;
937}
938
5b54dac8
HZ
939static void netvsc_sc_open(struct vmbus_channel *new_sc)
940{
3d541ac5
VK
941 struct net_device *ndev =
942 hv_get_drvdata(new_sc->primary_channel->device_obj);
2625466d 943 struct netvsc_device *nvscdev = net_device_to_netvsc_device(ndev);
5b54dac8
HZ
944 u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
945 int ret;
b3e6b82a 946 unsigned long flags;
5b54dac8 947
5b54dac8
HZ
948 if (chn_index >= nvscdev->num_chn)
949 return;
950
951 set_per_channel_state(new_sc, nvscdev->sub_cb_buf + (chn_index - 1) *
952 NETVSC_PACKET_SIZE);
953
c0b558e5
HZ
954 nvscdev->mrc[chn_index].buf = vzalloc(NETVSC_RECVSLOT_MAX *
955 sizeof(struct recv_comp_data));
956
5b54dac8
HZ
957 ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
958 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
959 netvsc_channel_cb, new_sc);
960
961 if (ret == 0)
962 nvscdev->chn_table[chn_index] = new_sc;
3f735131
HZ
963
964 spin_lock_irqsave(&nvscdev->sc_lock, flags);
965 nvscdev->num_sc_offered--;
966 spin_unlock_irqrestore(&nvscdev->sc_lock, flags);
967 if (nvscdev->num_sc_offered == 0)
968 complete(&nvscdev->channel_init_wait);
5b54dac8
HZ
969}
970
bdbad576 971int rndis_filter_device_add(struct hv_device *dev,
796cc88c 972 void *additional_info)
fceaf24a
HJ
973{
974 int ret;
3d541ac5
VK
975 struct net_device *net = hv_get_drvdata(dev);
976 struct net_device_context *net_device_ctx = netdev_priv(net);
86c921af 977 struct netvsc_device *net_device;
b13cc345 978 struct rndis_device *rndis_device;
3c4debad 979 struct netvsc_device_info *device_info = additional_info;
4a0e70ae 980 struct ndis_offload_params offloads;
5b54dac8 981 struct nvsp_message *init_packet;
5b54dac8
HZ
982 struct ndis_recv_scale_cap rsscap;
983 u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
4d3c9d37 984 u32 mtu, size;
e01ec219 985 u32 num_rss_qs;
b3e6b82a 986 u32 sc_delta;
e01ec219
KS
987 const struct cpumask *node_cpu_mask;
988 u32 num_possible_rss_qs;
b3e6b82a 989 unsigned long flags;
fceaf24a 990
b13cc345
S
991 rndis_device = get_rndis_device();
992 if (!rndis_device)
327efbae 993 return -ENODEV;
fceaf24a 994
0120ee0d
GKH
995 /*
996 * Let the inner driver handle this first to create the netvsc channel
997 * NOTE! Once the channel is created, we may get a receive callback
998 * (RndisFilterOnReceive()) before this call is completed
999 */
ce5bf661 1000 ret = netvsc_device_add(dev, additional_info);
0120ee0d 1001 if (ret != 0) {
b13cc345 1002 kfree(rndis_device);
fceaf24a
HJ
1003 return ret;
1004 }
1005
454f18a9 1006 /* Initialize the rndis device */
3d541ac5 1007 net_device = net_device_ctx->nvdev;
59995370 1008 net_device->max_chn = 1;
5b54dac8 1009 net_device->num_chn = 1;
fceaf24a 1010
b3e6b82a
KS
1011 spin_lock_init(&net_device->sc_lock);
1012
b13cc345 1013 net_device->extension = rndis_device;
3d541ac5 1014 rndis_device->ndev = net;
fceaf24a 1015
454f18a9 1016 /* Send the rndis initialization message */
b13cc345 1017 ret = rndis_filter_init_device(rndis_device);
0120ee0d 1018 if (ret != 0) {
5243e7bd
HZ
1019 rndis_filter_device_remove(dev);
1020 return ret;
fceaf24a
HJ
1021 }
1022
4d3c9d37
HZ
1023 /* Get the MTU from the host */
1024 size = sizeof(u32);
1025 ret = rndis_filter_query_device(rndis_device,
1026 RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
1027 &mtu, &size);
0a1275ca
VK
1028 if (ret == 0 && size == sizeof(u32) && mtu < net->mtu)
1029 net->mtu = mtu;
4d3c9d37 1030
454f18a9 1031 /* Get the mac address */
b13cc345 1032 ret = rndis_filter_query_device_mac(rndis_device);
0120ee0d 1033 if (ret != 0) {
5243e7bd
HZ
1034 rndis_filter_device_remove(dev);
1035 return ret;
fceaf24a
HJ
1036 }
1037
3c4debad 1038 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
fceaf24a 1039
4a0e70ae
KS
1040 /* Turn on the offloads; the host supports all of the relevant
1041 * offloads.
1042 */
1043 memset(&offloads, 0, sizeof(struct ndis_offload_params));
1044 /* A value of zero means "no change"; now turn on what we
1045 * want.
1046 */
1047 offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1048 offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1049 offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1050 offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1051 offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1052 offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1053
426d9541 1054 ret = rndis_filter_set_offload_params(net, &offloads);
4a0e70ae
KS
1055 if (ret)
1056 goto err_dev_remv;
1057
b13cc345 1058 rndis_filter_query_device_link_status(rndis_device);
fceaf24a 1059
6f27457b 1060 device_info->link_state = rndis_device->link_state;
eb335bc4 1061
6f27457b 1062 dev_info(&dev->device, "Device MAC %pM link state %s\n",
b13cc345 1063 rndis_device->hw_mac_adr,
6f27457b 1064 device_info->link_state ? "down" : "up");
fceaf24a 1065
5b54dac8
HZ
1066 if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
1067 return 0;
1068
b37879e6
HZ
1069 rndis_filter_query_link_speed(rndis_device);
1070
5b54dac8
HZ
1071 /* vRSS setup */
1072 memset(&rsscap, 0, rsscap_size);
1073 ret = rndis_filter_query_device(rndis_device,
1074 OID_GEN_RECEIVE_SCALE_CAPABILITIES,
1075 &rsscap, &rsscap_size);
1076 if (ret || rsscap.num_recv_que < 2)
1077 goto out;
1078
9efc2f7d 1079 net_device->max_chn = min_t(u32, VRSS_CHANNEL_MAX, rsscap.num_recv_que);
e01ec219 1080
9efc2f7d 1081 num_rss_qs = min(device_info->max_num_vrss_chns, net_device->max_chn);
e01ec219
KS
1082
1083 /*
1084 * We will limit the VRSS channels to the number CPUs in the NUMA node
1085 * the primary channel is currently bound to.
1086 */
1087 node_cpu_mask = cpumask_of_node(cpu_to_node(dev->channel->target_cpu));
1088 num_possible_rss_qs = cpumask_weight(node_cpu_mask);
8ebdcc52
AS
1089
1090 /* We will use the given number of channels if available. */
1091 if (device_info->num_chn && device_info->num_chn < net_device->max_chn)
1092 net_device->num_chn = device_info->num_chn;
1093 else
1094 net_device->num_chn = min(num_possible_rss_qs, num_rss_qs);
e01ec219 1095
b3e6b82a
KS
1096 num_rss_qs = net_device->num_chn - 1;
1097 net_device->num_sc_offered = num_rss_qs;
1098
5b54dac8
HZ
1099 if (net_device->num_chn == 1)
1100 goto out;
1101
1102 net_device->sub_cb_buf = vzalloc((net_device->num_chn - 1) *
1103 NETVSC_PACKET_SIZE);
1104 if (!net_device->sub_cb_buf) {
1105 net_device->num_chn = 1;
1106 dev_info(&dev->device, "No memory for subchannels.\n");
1107 goto out;
1108 }
1109
1110 vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
1111
1112 init_packet = &net_device->channel_init_pkt;
1113 memset(init_packet, 0, sizeof(struct nvsp_message));
1114 init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL;
1115 init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE;
1116 init_packet->msg.v5_msg.subchn_req.num_subchannels =
1117 net_device->num_chn - 1;
1118 ret = vmbus_sendpacket(dev->channel, init_packet,
1119 sizeof(struct nvsp_message),
1120 (unsigned long)init_packet,
1121 VM_PKT_DATA_INBAND,
1122 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1123 if (ret)
1124 goto out;
5362855a
VK
1125 wait_for_completion(&net_device->channel_init_wait);
1126
5b54dac8
HZ
1127 if (init_packet->msg.v5_msg.subchn_comp.status !=
1128 NVSP_STAT_SUCCESS) {
1129 ret = -ENODEV;
1130 goto out;
1131 }
1132 net_device->num_chn = 1 +
1133 init_packet->msg.v5_msg.subchn_comp.num_subchannels;
1134
5b54dac8
HZ
1135 ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn);
1136
b3e6b82a 1137 /*
d66ab514 1138 * Set the number of sub-channels to be received.
b3e6b82a
KS
1139 */
1140 spin_lock_irqsave(&net_device->sc_lock, flags);
1141 sc_delta = num_rss_qs - (net_device->num_chn - 1);
1142 net_device->num_sc_offered -= sc_delta;
1143 spin_unlock_irqrestore(&net_device->sc_lock, flags);
1144
5b54dac8 1145out:
59995370
AS
1146 if (ret) {
1147 net_device->max_chn = 1;
5b54dac8 1148 net_device->num_chn = 1;
d66ab514 1149 net_device->num_sc_offered = 0;
59995370 1150 }
b3e6b82a 1151
5b54dac8 1152 return 0; /* return 0 because primary channel can be used alone */
4a0e70ae
KS
1153
1154err_dev_remv:
1155 rndis_filter_device_remove(dev);
1156 return ret;
fceaf24a
HJ
1157}
1158
df06bcff 1159void rndis_filter_device_remove(struct hv_device *dev)
fceaf24a 1160{
2625466d 1161 struct netvsc_device *net_dev = hv_device_to_netvsc_device(dev);
53d21fdb 1162 struct rndis_device *rndis_dev = net_dev->extension;
d66ab514
HZ
1163
1164 /* If not all subchannel offers are complete, wait for them until
1165 * completion to avoid race.
1166 */
5362855a
VK
1167 if (net_dev->num_sc_offered > 0)
1168 wait_for_completion(&net_dev->channel_init_wait);
fceaf24a 1169
454f18a9 1170 /* Halt and release the rndis device */
9c26aa0d 1171 rndis_filter_halt_device(rndis_dev);
fceaf24a 1172
c2a4efdd 1173 kfree(rndis_dev);
53d21fdb 1174 net_dev->extension = NULL;
fceaf24a 1175
3fae5c8f 1176 netvsc_device_remove(dev);
fceaf24a
HJ
1177}
1178
2f5fa6c8 1179int rndis_filter_open(struct netvsc_device *nvdev)
fceaf24a 1180{
2f5fa6c8 1181 if (!nvdev)
8a62d716
BP
1182 return -EINVAL;
1183
2f5fa6c8 1184 if (atomic_inc_return(&nvdev->open_cnt) != 1)
84bf9cef
KS
1185 return 0;
1186
2f5fa6c8 1187 return rndis_filter_open_device(nvdev->extension);
fceaf24a
HJ
1188}
1189
2f5fa6c8 1190int rndis_filter_close(struct netvsc_device *nvdev)
fceaf24a 1191{
5fccab3b 1192 if (!nvdev)
8a62d716
BP
1193 return -EINVAL;
1194
84bf9cef
KS
1195 if (atomic_dec_return(&nvdev->open_cnt) != 0)
1196 return 0;
1197
5fccab3b 1198 return rndis_filter_close_device(nvdev->extension);
fceaf24a 1199}
This page took 0.689178 seconds and 5 git commands to generate.