rndis_filter.c 31.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Copyright (c) 2009, Microsoft Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
14
 * this program; if not, see <http://www.gnu.org/licenses/>.
15 16 17 18 19
 *
 * Authors:
 *   Haiyang Zhang <haiyangz@microsoft.com>
 *   Hank Janssen  <hjanssen@microsoft.com>
 */
20
#include <linux/kernel.h>
21 22
#include <linux/sched.h>
#include <linux/wait.h>
23
#include <linux/highmem.h>
24
#include <linux/slab.h>
25
#include <linux/io.h>
26
#include <linux/if_ether.h>
27
#include <linux/netdevice.h>
28
#include <linux/if_vlan.h>
29
#include <linux/nls.h>
30
#include <linux/vmalloc.h>
31

32
#include "hyperv_net.h"
33 34


35
#define RNDIS_EXT_LEN PAGE_SIZE
36
struct rndis_request {
37
	struct list_head list_ent;
38
	struct completion  wait_event;
39

40
	struct rndis_message response_msg;
41
	/*
42 43 44 45
	 * The buffer for extended info after the RNDIS response message. It's
	 * referenced based on the data offset in the RNDIS message. Its size
	 * is enough for current needs, and should be sufficient for the near
	 * future.
46
	 */
47
	u8 response_ext[RNDIS_EXT_LEN];
48

49
	/* Simplify allocation by having a netvsc packet inline */
50
	struct hv_netvsc_packet	pkt;
51

52
	struct rndis_message request_msg;
53
	/*
54 55
	 * The buffer for the extended info after the RNDIS request message.
	 * It is referenced and sized in a similar way as response_ext.
56
	 */
57
	u8 request_ext[RNDIS_EXT_LEN];
58
};
59

60
static struct rndis_device *get_rndis_device(void)
61
{
62
	struct rndis_device *device;
63

64
	device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
65 66 67
	if (!device)
		return NULL;

68
	spin_lock_init(&device->request_lock);
69

70
	INIT_LIST_HEAD(&device->req_list);
71

72
	device->state = RNDIS_DEV_UNINITIALIZED;
73 74 75 76

	return device;
}

77
static struct rndis_request *get_rndis_request(struct rndis_device *dev,
78 79
					     u32 msg_type,
					     u32 msg_len)
80
{
81
	struct rndis_request *request;
82
	struct rndis_message *rndis_msg;
83
	struct rndis_set_request *set;
84
	unsigned long flags;
85

86
	request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
87 88 89
	if (!request)
		return NULL;

90
	init_completion(&request->wait_event);
91

92
	rndis_msg = &request->request_msg;
93 94
	rndis_msg->ndis_msg_type = msg_type;
	rndis_msg->msg_len = msg_len;
95

96 97
	request->pkt.q_idx = 0;

98 99 100 101 102
	/*
	 * Set the request id. This field is always after the rndis header for
	 * request/response packet types so we just used the SetRequest as a
	 * template
	 */
103 104
	set = &rndis_msg->msg.set_req;
	set->req_id = atomic_inc_return(&dev->new_req_id);
105

106
	/* Add to the request list */
107 108 109
	spin_lock_irqsave(&dev->request_lock, flags);
	list_add_tail(&request->list_ent, &dev->req_list);
	spin_unlock_irqrestore(&dev->request_lock, flags);
110 111 112 113

	return request;
}

114
static void put_rndis_request(struct rndis_device *dev,
115
			    struct rndis_request *req)
116
{
117 118
	unsigned long flags;

119 120 121
	spin_lock_irqsave(&dev->request_lock, flags);
	list_del(&req->list_ent);
	spin_unlock_irqrestore(&dev->request_lock, flags);
122

123
	kfree(req);
124 125
}

126 127
static void dump_rndis_message(struct hv_device *hv_dev,
			struct rndis_message *rndis_msg)
128
{
129 130 131 132 133
	struct net_device *netdev;
	struct netvsc_device *net_device;

	net_device = hv_get_drvdata(hv_dev);
	netdev = net_device->ndev;
134

135
	switch (rndis_msg->ndis_msg_type) {
136 137
	case RNDIS_MSG_PACKET:
		netdev_dbg(netdev, "RNDIS_MSG_PACKET (len %u, "
138 139
			   "data offset %u data len %u, # oob %u, "
			   "oob offset %u, oob len %u, pkt offset %u, "
140
			   "pkt len %u\n",
141 142 143 144 145 146 147 148
			   rndis_msg->msg_len,
			   rndis_msg->msg.pkt.data_offset,
			   rndis_msg->msg.pkt.data_len,
			   rndis_msg->msg.pkt.num_oob_data_elements,
			   rndis_msg->msg.pkt.oob_data_offset,
			   rndis_msg->msg.pkt.oob_data_len,
			   rndis_msg->msg.pkt.per_pkt_info_offset,
			   rndis_msg->msg.pkt.per_pkt_info_len);
149 150
		break;

151 152
	case RNDIS_MSG_INIT_C:
		netdev_dbg(netdev, "RNDIS_MSG_INIT_C "
153 154
			"(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
			"device flags %d, max xfer size 0x%x, max pkts %u, "
155
			"pkt aligned %u)\n",
156 157 158 159 160 161 162 163 164 165 166
			rndis_msg->msg_len,
			rndis_msg->msg.init_complete.req_id,
			rndis_msg->msg.init_complete.status,
			rndis_msg->msg.init_complete.major_ver,
			rndis_msg->msg.init_complete.minor_ver,
			rndis_msg->msg.init_complete.dev_flags,
			rndis_msg->msg.init_complete.max_xfer_size,
			rndis_msg->msg.init_complete.
			   max_pkt_per_msg,
			rndis_msg->msg.init_complete.
			   pkt_alignment_factor);
167 168
		break;

169 170
	case RNDIS_MSG_QUERY_C:
		netdev_dbg(netdev, "RNDIS_MSG_QUERY_C "
171
			"(len %u, id 0x%x, status 0x%x, buf len %u, "
172
			"buf offset %u)\n",
173 174 175 176 177 178 179
			rndis_msg->msg_len,
			rndis_msg->msg.query_complete.req_id,
			rndis_msg->msg.query_complete.status,
			rndis_msg->msg.query_complete.
			   info_buflen,
			rndis_msg->msg.query_complete.
			   info_buf_offset);
180 181
		break;

182
	case RNDIS_MSG_SET_C:
183
		netdev_dbg(netdev,
184
			"RNDIS_MSG_SET_C (len %u, id 0x%x, status 0x%x)\n",
185 186 187
			rndis_msg->msg_len,
			rndis_msg->msg.set_complete.req_id,
			rndis_msg->msg.set_complete.status);
188 189
		break;

190 191
	case RNDIS_MSG_INDICATE:
		netdev_dbg(netdev, "RNDIS_MSG_INDICATE "
192
			"(len %u, status 0x%x, buf len %u, buf offset %u)\n",
193 194 195 196
			rndis_msg->msg_len,
			rndis_msg->msg.indicate_status.status,
			rndis_msg->msg.indicate_status.status_buflen,
			rndis_msg->msg.indicate_status.status_buf_offset);
197 198 199
		break;

	default:
200
		netdev_dbg(netdev, "0x%x (len %u)\n",
201 202
			rndis_msg->ndis_msg_type,
			rndis_msg->msg_len);
203 204 205 206
		break;
	}
}

207
static int rndis_filter_send_request(struct rndis_device *dev,
208
				  struct rndis_request *req)
209
{
210
	int ret;
211
	struct hv_netvsc_packet *packet;
212
	struct hv_page_buffer page_buf[2];
213

214
	/* Setup the packet to send it */
215
	packet = &req->pkt;
216

217
	packet->is_data_pkt = false;
218
	packet->total_data_buflen = req->request_msg.msg_len;
219
	packet->page_buf_cnt = 1;
220
	packet->page_buf = page_buf;
221

222
	packet->page_buf[0].pfn = virt_to_phys(&req->request_msg) >>
223
					PAGE_SHIFT;
224 225
	packet->page_buf[0].len = req->request_msg.msg_len;
	packet->page_buf[0].offset =
226
		(unsigned long)&req->request_msg & (PAGE_SIZE - 1);
227

228 229 230 231 232 233 234 235 236 237 238 239
	/* Add one page_buf when request_msg crossing page boundary */
	if (packet->page_buf[0].offset + packet->page_buf[0].len > PAGE_SIZE) {
		packet->page_buf_cnt++;
		packet->page_buf[0].len = PAGE_SIZE -
			packet->page_buf[0].offset;
		packet->page_buf[1].pfn = virt_to_phys((void *)&req->request_msg
			+ packet->page_buf[0].len) >> PAGE_SHIFT;
		packet->page_buf[1].offset = 0;
		packet->page_buf[1].len = req->request_msg.msg_len -
			packet->page_buf[0].len;
	}

240
	packet->send_completion = NULL;
241
	packet->xmit_more = false;
242

243
	ret = netvsc_send(dev->net_dev->dev, packet);
244 245 246
	return ret;
}

247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
static void rndis_set_link_state(struct rndis_device *rdev,
				 struct rndis_request *request)
{
	u32 link_status;
	struct rndis_query_complete *query_complete;

	query_complete = &request->response_msg.msg.query_complete;

	if (query_complete->status == RNDIS_STATUS_SUCCESS &&
	    query_complete->info_buflen == sizeof(u32)) {
		memcpy(&link_status, (void *)((unsigned long)query_complete +
		       query_complete->info_buf_offset), sizeof(u32));
		rdev->link_state = link_status != 0;
	}
}

263
static void rndis_filter_receive_response(struct rndis_device *dev,
264
				       struct rndis_message *resp)
265
{
266
	struct rndis_request *request = NULL;
267
	bool found = false;
268
	unsigned long flags;
269 270 271
	struct net_device *ndev;

	ndev = dev->net_dev->ndev;
272

273 274
	spin_lock_irqsave(&dev->request_lock, flags);
	list_for_each_entry(request, &dev->req_list, list_ent) {
275 276 277 278
		/*
		 * All request/response message contains RequestId as the 1st
		 * field
		 */
279 280
		if (request->request_msg.msg.init_req.req_id
		    == resp->msg.init_complete.req_id) {
281
			found = true;
282 283 284
			break;
		}
	}
285
	spin_unlock_irqrestore(&dev->request_lock, flags);
286

287
	if (found) {
288 289
		if (resp->msg_len <=
		    sizeof(struct rndis_message) + RNDIS_EXT_LEN) {
290
			memcpy(&request->response_msg, resp,
291
			       resp->msg_len);
292 293 294 295
			if (request->request_msg.ndis_msg_type ==
			    RNDIS_MSG_QUERY && request->request_msg.msg.
			    query_req.oid == RNDIS_OID_GEN_MEDIA_CONNECT_STATUS)
				rndis_set_link_state(dev, request);
296
		} else {
297
			netdev_err(ndev,
298 299 300
				"rndis response buffer overflow "
				"detected (size %u max %zu)\n",
				resp->msg_len,
301
				sizeof(struct rndis_message));
302

303
			if (resp->ndis_msg_type ==
304
			    RNDIS_MSG_RESET_C) {
305
				/* does not have a request id field */
306
				request->response_msg.msg.reset_complete.
307
					status = RNDIS_STATUS_BUFFER_OVERFLOW;
308
			} else {
309 310
				request->response_msg.msg.
				init_complete.status =
311
					RNDIS_STATUS_BUFFER_OVERFLOW;
312 313 314
			}
		}

315
		complete(&request->wait_event);
316
	} else {
317
		netdev_err(ndev,
318 319 320 321
			"no rndis request found for this response "
			"(id 0x%x res type 0x%x)\n",
			resp->msg.init_complete.req_id,
			resp->ndis_msg_type);
322 323 324
	}
}

325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
/*
 * Get the Per-Packet-Info with the specified type
 * return NULL if not found.
 */
static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type)
{
	struct rndis_per_packet_info *ppi;
	int len;

	if (rpkt->per_pkt_info_offset == 0)
		return NULL;

	ppi = (struct rndis_per_packet_info *)((ulong)rpkt +
		rpkt->per_pkt_info_offset);
	len = rpkt->per_pkt_info_len;

	while (len > 0) {
		if (ppi->type == type)
			return (void *)((ulong)ppi + ppi->ppi_offset);
		len -= ppi->size;
		ppi = (struct rndis_per_packet_info *)((ulong)ppi + ppi->size);
	}

	return NULL;
}

351
static void rndis_filter_receive_data(struct rndis_device *dev,
352 353
				   struct rndis_message *msg,
				   struct hv_netvsc_packet *pkt)
354
{
355 356
	struct rndis_packet *rndis_pkt;
	u32 data_offset;
357
	struct ndis_pkt_8021q_info *vlan;
358
	struct ndis_tcp_ip_checksum_info *csum_info;
359

360
	rndis_pkt = &msg->msg.pkt;
361

362
	/* Remove the rndis header and pass it back up the stack */
363
	data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
364

365
	pkt->total_data_buflen -= data_offset;
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384

	/*
	 * Make sure we got a valid RNDIS message, now total_data_buflen
	 * should be the data packet size plus the trailer padding size
	 */
	if (pkt->total_data_buflen < rndis_pkt->data_len) {
		netdev_err(dev->net_dev->ndev, "rndis message buffer "
			   "overflow detected (got %u, min %u)"
			   "...dropping this message!\n",
			   pkt->total_data_buflen, rndis_pkt->data_len);
		return;
	}

	/*
	 * Remove the rndis trailer padding from rndis packet message
	 * rndis_pkt->data_len tell us the real data length, we only copy
	 * the data packet to the stack, without the rndis trailer padding
	 */
	pkt->total_data_buflen = rndis_pkt->data_len;
385
	pkt->data = (void *)((unsigned long)pkt->data + data_offset);
386

387 388 389 390 391 392 393 394
	vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO);
	if (vlan) {
		pkt->vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid |
			(vlan->pri << VLAN_PRIO_SHIFT);
	} else {
		pkt->vlan_tci = 0;
	}

395 396
	csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO);
	netvsc_recv_callback(dev->net_dev->dev, pkt, csum_info);
397 398
}

399
int rndis_filter_receive(struct hv_device *dev,
400
				struct hv_netvsc_packet	*pkt)
401
{
402
	struct netvsc_device *net_dev = hv_get_drvdata(dev);
403
	struct rndis_device *rndis_dev;
404
	struct rndis_message *rndis_msg;
405
	struct net_device *ndev;
406
	int ret = 0;
407

408 409 410 411
	if (!net_dev) {
		ret = -EINVAL;
		goto exit;
	}
412

413 414
	ndev = net_dev->ndev;

415
	/* Make sure the rndis device state is initialized */
416
	if (!net_dev->extension) {
417
		netdev_err(ndev, "got rndis message but no rndis device - "
418
			  "dropping this message!\n");
419 420
		ret = -ENODEV;
		goto exit;
421 422
	}

423
	rndis_dev = (struct rndis_device *)net_dev->extension;
424
	if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
425
		netdev_err(ndev, "got rndis message but rndis device "
426
			   "uninitialized...dropping this message!\n");
427 428
		ret = -ENODEV;
		goto exit;
429 430
	}

431
	rndis_msg = pkt->data;
432

433 434
	if (netif_msg_rx_err(net_dev->nd_ctx))
		dump_rndis_message(dev, rndis_msg);
435

436
	switch (rndis_msg->ndis_msg_type) {
437
	case RNDIS_MSG_PACKET:
438
		/* data msg */
439
		rndis_filter_receive_data(rndis_dev, rndis_msg, pkt);
440 441
		break;

442 443 444
	case RNDIS_MSG_INIT_C:
	case RNDIS_MSG_QUERY_C:
	case RNDIS_MSG_SET_C:
445
		/* completion msgs */
446
		rndis_filter_receive_response(rndis_dev, rndis_msg);
447 448
		break;

449
	case RNDIS_MSG_INDICATE:
450
		/* notification msgs */
451
		netvsc_linkstatus_callback(dev, rndis_msg);
452 453
		break;
	default:
454
		netdev_err(ndev,
455
			"unhandled rndis message (type %u len %u)\n",
456 457
			   rndis_msg->ndis_msg_type,
			   rndis_msg->msg_len);
458 459 460
		break;
	}

461 462 463 464 465
exit:
	if (ret != 0)
		pkt->status = NVSP_STAT_FAIL;

	return ret;
466 467
}

468
static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
469
				  void *result, u32 *result_size)
470
{
471
	struct rndis_request *request;
472
	u32 inresult_size = *result_size;
473
	struct rndis_query_request *query;
474
	struct rndis_query_complete *query_complete;
475
	int ret = 0;
476
	unsigned long t;
477

478
	if (!result)
479
		return -EINVAL;
480

481
	*result_size = 0;
482
	request = get_rndis_request(dev, RNDIS_MSG_QUERY,
483 484
			RNDIS_MESSAGE_SIZE(struct rndis_query_request));
	if (!request) {
485
		ret = -ENOMEM;
486
		goto cleanup;
487 488
	}

489
	/* Setup the rndis query */
490 491 492 493 494
	query = &request->request_msg.msg.query_req;
	query->oid = oid;
	query->info_buf_offset = sizeof(struct rndis_query_request);
	query->info_buflen = 0;
	query->dev_vc_handle = 0;
495

496 497 498 499 500 501 502 503 504 505 506 507 508
	if (oid == OID_GEN_RECEIVE_SCALE_CAPABILITIES) {
		struct ndis_recv_scale_cap *cap;

		request->request_msg.msg_len +=
			sizeof(struct ndis_recv_scale_cap);
		query->info_buflen = sizeof(struct ndis_recv_scale_cap);
		cap = (struct ndis_recv_scale_cap *)((unsigned long)query +
						     query->info_buf_offset);
		cap->hdr.type = NDIS_OBJECT_TYPE_RSS_CAPABILITIES;
		cap->hdr.rev = NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
		cap->hdr.size = sizeof(struct ndis_recv_scale_cap);
	}

509
	ret = rndis_filter_send_request(dev, request);
510
	if (ret != 0)
511
		goto cleanup;
512

513
	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
514
	if (t == 0) {
515
		ret = -ETIMEDOUT;
516
		goto cleanup;
517
	}
518

519
	/* Copy the response back */
520
	query_complete = &request->response_msg.msg.query_complete;
521

522
	if (query_complete->info_buflen > inresult_size) {
523
		ret = -1;
524
		goto cleanup;
525 526
	}

527 528
	memcpy(result,
	       (void *)((unsigned long)query_complete +
529 530
			 query_complete->info_buf_offset),
	       query_complete->info_buflen);
531

532
	*result_size = query_complete->info_buflen;
533

534
cleanup:
535
	if (request)
536
		put_rndis_request(dev, request);
537 538 539 540

	return ret;
}

541
static int rndis_filter_query_device_mac(struct rndis_device *dev)
542
{
543
	u32 size = ETH_ALEN;
544

545
	return rndis_filter_query_device(dev,
546
				      RNDIS_OID_802_3_PERMANENT_ADDRESS,
547
				      dev->hw_mac_adr, &size);
548 549
}

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
#define NWADR_STR "NetworkAddress"
#define NWADR_STRLEN 14

int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac)
{
	struct netvsc_device *nvdev = hv_get_drvdata(hdev);
	struct rndis_device *rdev = nvdev->extension;
	struct net_device *ndev = nvdev->ndev;
	struct rndis_request *request;
	struct rndis_set_request *set;
	struct rndis_config_parameter_info *cpi;
	wchar_t *cfg_nwadr, *cfg_mac;
	struct rndis_set_complete *set_complete;
	char macstr[2*ETH_ALEN+1];
	u32 extlen = sizeof(struct rndis_config_parameter_info) +
		2*NWADR_STRLEN + 4*ETH_ALEN;
566 567
	int ret;
	unsigned long t;
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617

	request = get_rndis_request(rdev, RNDIS_MSG_SET,
		RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
	if (!request)
		return -ENOMEM;

	set = &request->request_msg.msg.set_req;
	set->oid = RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER;
	set->info_buflen = extlen;
	set->info_buf_offset = sizeof(struct rndis_set_request);
	set->dev_vc_handle = 0;

	cpi = (struct rndis_config_parameter_info *)((ulong)set +
		set->info_buf_offset);
	cpi->parameter_name_offset =
		sizeof(struct rndis_config_parameter_info);
	/* Multiply by 2 because host needs 2 bytes (utf16) for each char */
	cpi->parameter_name_length = 2*NWADR_STRLEN;
	cpi->parameter_type = RNDIS_CONFIG_PARAM_TYPE_STRING;
	cpi->parameter_value_offset =
		cpi->parameter_name_offset + cpi->parameter_name_length;
	/* Multiply by 4 because each MAC byte displayed as 2 utf16 chars */
	cpi->parameter_value_length = 4*ETH_ALEN;

	cfg_nwadr = (wchar_t *)((ulong)cpi + cpi->parameter_name_offset);
	cfg_mac = (wchar_t *)((ulong)cpi + cpi->parameter_value_offset);
	ret = utf8s_to_utf16s(NWADR_STR, NWADR_STRLEN, UTF16_HOST_ENDIAN,
			      cfg_nwadr, NWADR_STRLEN);
	if (ret < 0)
		goto cleanup;
	snprintf(macstr, 2*ETH_ALEN+1, "%pm", mac);
	ret = utf8s_to_utf16s(macstr, 2*ETH_ALEN, UTF16_HOST_ENDIAN,
			      cfg_mac, 2*ETH_ALEN);
	if (ret < 0)
		goto cleanup;

	ret = rndis_filter_send_request(rdev, request);
	if (ret != 0)
		goto cleanup;

	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
	if (t == 0) {
		netdev_err(ndev, "timeout before we got a set response...\n");
		/*
		 * can't put_rndis_request, since we may still receive a
		 * send-completion.
		 */
		return -EBUSY;
	} else {
		set_complete = &request->response_msg.msg.set_complete;
618 619 620
		if (set_complete->status != RNDIS_STATUS_SUCCESS) {
			netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
				   set_complete->status);
621
			ret = -EINVAL;
622
		}
623 624 625 626 627 628 629
	}

cleanup:
	put_rndis_request(rdev, request);
	return ret;
}

L
Lad, Prabhakar 已提交
630 631
static int
rndis_filter_set_offload_params(struct hv_device *hdev,
632 633 634 635 636 637 638 639 640 641
				struct ndis_offload_params *req_offloads)
{
	struct netvsc_device *nvdev = hv_get_drvdata(hdev);
	struct rndis_device *rdev = nvdev->extension;
	struct net_device *ndev = nvdev->ndev;
	struct rndis_request *request;
	struct rndis_set_request *set;
	struct ndis_offload_params *offload_params;
	struct rndis_set_complete *set_complete;
	u32 extlen = sizeof(struct ndis_offload_params);
642 643
	int ret;
	unsigned long t;
644 645 646 647 648 649 650 651 652 653
	u32 vsp_version = nvdev->nvsp_version;

	if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
		extlen = VERSION_4_OFFLOAD_SIZE;
		/* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
		 * UDP checksum offload.
		 */
		req_offloads->udp_ip_v4_csum = 0;
		req_offloads->udp_ip_v6_csum = 0;
	}
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686

	request = get_rndis_request(rdev, RNDIS_MSG_SET,
		RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
	if (!request)
		return -ENOMEM;

	set = &request->request_msg.msg.set_req;
	set->oid = OID_TCP_OFFLOAD_PARAMETERS;
	set->info_buflen = extlen;
	set->info_buf_offset = sizeof(struct rndis_set_request);
	set->dev_vc_handle = 0;

	offload_params = (struct ndis_offload_params *)((ulong)set +
				set->info_buf_offset);
	*offload_params = *req_offloads;
	offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
	offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
	offload_params->header.size = extlen;

	ret = rndis_filter_send_request(rdev, request);
	if (ret != 0)
		goto cleanup;

	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
	if (t == 0) {
		netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n");
		/* can't put_rndis_request, since we may still receive a
		 * send-completion.
		 */
		return -EBUSY;
	} else {
		set_complete = &request->response_msg.msg.set_complete;
		if (set_complete->status != RNDIS_STATUS_SUCCESS) {
687
			netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
688 689 690 691 692 693 694 695 696
				   set_complete->status);
			ret = -EINVAL;
		}
	}

cleanup:
	put_rndis_request(rdev, request);
	return ret;
}
697

698 699 700 701 702 703 704 705
u8 netvsc_hash_key[HASH_KEYLEN] = {
	0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
	0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
	0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
	0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
	0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
};

L
Lad, Prabhakar 已提交
706
static int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
707 708 709 710 711 712 713 714 715 716
{
	struct net_device *ndev = rdev->net_dev->ndev;
	struct rndis_request *request;
	struct rndis_set_request *set;
	struct rndis_set_complete *set_complete;
	u32 extlen = sizeof(struct ndis_recv_scale_param) +
		     4*ITAB_NUM + HASH_KEYLEN;
	struct ndis_recv_scale_param *rssp;
	u32 *itab;
	u8 *keyp;
717 718
	int i, ret;
	unsigned long t;
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737

	request = get_rndis_request(
			rdev, RNDIS_MSG_SET,
			RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
	if (!request)
		return -ENOMEM;

	set = &request->request_msg.msg.set_req;
	set->oid = OID_GEN_RECEIVE_SCALE_PARAMETERS;
	set->info_buflen = extlen;
	set->info_buf_offset = sizeof(struct rndis_set_request);
	set->dev_vc_handle = 0;

	rssp = (struct ndis_recv_scale_param *)(set + 1);
	rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
	rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
	rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
	rssp->flag = 0;
	rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
738 739
			 NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
			 NDIS_HASH_TCP_IPV6;
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
	rssp->indirect_tabsize = 4*ITAB_NUM;
	rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param);
	rssp->hashkey_size = HASH_KEYLEN;
	rssp->kashkey_offset = rssp->indirect_taboffset +
			       rssp->indirect_tabsize;

	/* Set indirection table entries */
	itab = (u32 *)(rssp + 1);
	for (i = 0; i < ITAB_NUM; i++)
		itab[i] = i % num_queue;

	/* Set hask key values */
	keyp = (u8 *)((unsigned long)rssp + rssp->kashkey_offset);
	for (i = 0; i < HASH_KEYLEN; i++)
		keyp[i] = netvsc_hash_key[i];


	ret = rndis_filter_send_request(rdev, request);
	if (ret != 0)
		goto cleanup;

	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
	if (t == 0) {
		netdev_err(ndev, "timeout before we got a set response...\n");
		/* can't put_rndis_request, since we may still receive a
		 * send-completion.
		 */
		return -ETIMEDOUT;
	} else {
		set_complete = &request->response_msg.msg.set_complete;
		if (set_complete->status != RNDIS_STATUS_SUCCESS) {
			netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
				   set_complete->status);
			ret = -EINVAL;
		}
	}

cleanup:
	put_rndis_request(rdev, request);
	return ret;
}


783
static int rndis_filter_query_device_link_status(struct rndis_device *dev)
784
{
785
	u32 size = sizeof(u32);
786 787
	u32 link_status;
	int ret;
788

789
	ret = rndis_filter_query_device(dev,
790
				      RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
791 792 793
				      &link_status, &size);

	return ret;
794 795
}

796
int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
797
{
798
	struct rndis_request *request;
799
	struct rndis_set_request *set;
800
	struct rndis_set_complete *set_complete;
801
	u32 status;
802 803
	int ret;
	unsigned long t;
804 805 806
	struct net_device *ndev;

	ndev = dev->net_dev->ndev;
807

808
	request = get_rndis_request(dev, RNDIS_MSG_SET,
809 810 811
			RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
			sizeof(u32));
	if (!request) {
812
		ret = -ENOMEM;
813
		goto cleanup;
814 815
	}

816
	/* Setup the rndis set */
817 818 819 820
	set = &request->request_msg.msg.set_req;
	set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
	set->info_buflen = sizeof(u32);
	set->info_buf_offset = sizeof(struct rndis_set_request);
821

822
	memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
823
	       &new_filter, sizeof(u32));
824

825
	ret = rndis_filter_send_request(dev, request);
826
	if (ret != 0)
827
		goto cleanup;
828

829
	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
830 831

	if (t == 0) {
832
		netdev_err(ndev,
833
			"timeout before we got a set response...\n");
834
		ret = -ETIMEDOUT;
835
		/*
L
Lucas De Marchi 已提交
836
		 * We can't deallocate the request since we may still receive a
837 838
		 * send completion for it.
		 */
839
		goto exit;
840
	} else {
841 842
		set_complete = &request->response_msg.msg.set_complete;
		status = set_complete->status;
843 844
	}

845
cleanup:
846
	if (request)
847
		put_rndis_request(dev, request);
848
exit:
849 850 851 852
	return ret;
}


853
static int rndis_filter_init_device(struct rndis_device *dev)
854
{
855
	struct rndis_request *request;
856
	struct rndis_initialize_request *init;
857
	struct rndis_initialize_complete *init_complete;
858
	u32 status;
859 860
	int ret;
	unsigned long t;
861
	struct netvsc_device *nvdev = dev->net_dev;
862

863
	request = get_rndis_request(dev, RNDIS_MSG_INIT,
864 865
			RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
	if (!request) {
866
		ret = -ENOMEM;
867
		goto cleanup;
868 869
	}

870
	/* Setup the rndis set */
871 872 873
	init = &request->request_msg.msg.init_req;
	init->major_ver = RNDIS_MAJOR_VERSION;
	init->minor_ver = RNDIS_MINOR_VERSION;
874
	init->max_xfer_size = 0x4000;
875

876
	dev->state = RNDIS_DEV_INITIALIZING;
877

878
	ret = rndis_filter_send_request(dev, request);
879
	if (ret != 0) {
880
		dev->state = RNDIS_DEV_UNINITIALIZED;
881
		goto cleanup;
882 883
	}

884

885
	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
886 887

	if (t == 0) {
888
		ret = -ETIMEDOUT;
889
		goto cleanup;
890
	}
891

892 893
	init_complete = &request->response_msg.msg.init_complete;
	status = init_complete->status;
894
	if (status == RNDIS_STATUS_SUCCESS) {
895
		dev->state = RNDIS_DEV_INITIALIZED;
896 897
		nvdev->max_pkt = init_complete->max_pkt_per_msg;
		nvdev->pkt_align = 1 << init_complete->pkt_alignment_factor;
898
		ret = 0;
899
	} else {
900
		dev->state = RNDIS_DEV_UNINITIALIZED;
901
		ret = -EINVAL;
902 903
	}

904
cleanup:
905
	if (request)
906
		put_rndis_request(dev, request);
907 908 909 910

	return ret;
}

911
static void rndis_filter_halt_device(struct rndis_device *dev)
912
{
913
	struct rndis_request *request;
914
	struct rndis_halt_request *halt;
915 916 917
	struct netvsc_device *nvdev = dev->net_dev;
	struct hv_device *hdev = nvdev->dev;
	ulong flags;
918

919
	/* Attempt to do a rndis device halt */
920
	request = get_rndis_request(dev, RNDIS_MSG_HALT,
921
				RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
922
	if (!request)
923
		goto cleanup;
924

925
	/* Setup the rndis set */
926 927
	halt = &request->request_msg.msg.halt_req;
	halt->req_id = atomic_inc_return(&dev->new_req_id);
928

929
	/* Ignore return since this msg is optional. */
930
	rndis_filter_send_request(dev, request);
931

932
	dev->state = RNDIS_DEV_UNINITIALIZED;
933

934
cleanup:
935 936 937 938 939 940 941 942
	spin_lock_irqsave(&hdev->channel->inbound_lock, flags);
	nvdev->destroy = true;
	spin_unlock_irqrestore(&hdev->channel->inbound_lock, flags);

	/* Wait for all send completions */
	wait_event(nvdev->wait_drain,
		atomic_read(&nvdev->num_outstanding_sends) == 0);

943
	if (request)
944
		put_rndis_request(dev, request);
945 946 947
	return;
}

948
static int rndis_filter_open_device(struct rndis_device *dev)
949
{
950
	int ret;
951

952
	if (dev->state != RNDIS_DEV_INITIALIZED)
953 954
		return 0;

955
	ret = rndis_filter_set_packet_filter(dev,
956
					 NDIS_PACKET_TYPE_BROADCAST |
957
					 NDIS_PACKET_TYPE_ALL_MULTICAST |
958
					 NDIS_PACKET_TYPE_DIRECTED);
959
	if (ret == 0)
960
		dev->state = RNDIS_DEV_DATAINITIALIZED;
961 962 963 964

	return ret;
}

965
static int rndis_filter_close_device(struct rndis_device *dev)
966 967 968
{
	int ret;

969
	if (dev->state != RNDIS_DEV_DATAINITIALIZED)
970 971
		return 0;

972
	ret = rndis_filter_set_packet_filter(dev, 0);
973 974 975
	if (ret == -ENODEV)
		ret = 0;

976
	if (ret == 0)
977
		dev->state = RNDIS_DEV_INITIALIZED;
978 979 980 981

	return ret;
}

982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
static void netvsc_sc_open(struct vmbus_channel *new_sc)
{
	struct netvsc_device *nvscdev;
	u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
	int ret;

	nvscdev = hv_get_drvdata(new_sc->primary_channel->device_obj);

	if (chn_index >= nvscdev->num_chn)
		return;

	set_per_channel_state(new_sc, nvscdev->sub_cb_buf + (chn_index - 1) *
			      NETVSC_PACKET_SIZE);

	ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
			 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
			 netvsc_channel_cb, new_sc);

	if (ret == 0)
		nvscdev->chn_table[chn_index] = new_sc;
}

1004
int rndis_filter_device_add(struct hv_device *dev,
1005
				  void *additional_info)
1006 1007
{
	int ret;
1008
	struct netvsc_device *net_device;
1009
	struct rndis_device *rndis_device;
1010
	struct netvsc_device_info *device_info = additional_info;
1011
	struct ndis_offload_params offloads;
1012
	struct nvsp_message *init_packet;
1013
	unsigned long t;
1014 1015
	struct ndis_recv_scale_cap rsscap;
	u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
1016
	u32 mtu, size;
1017 1018 1019
	u32 num_rss_qs;
	const struct cpumask *node_cpu_mask;
	u32 num_possible_rss_qs;
1020

1021 1022
	rndis_device = get_rndis_device();
	if (!rndis_device)
1023
		return -ENODEV;
1024

1025 1026 1027 1028 1029
	/*
	 * Let the inner driver handle this first to create the netvsc channel
	 * NOTE! Once the channel is created, we may get a receive callback
	 * (RndisFilterOnReceive()) before this call is completed
	 */
1030
	ret = netvsc_device_add(dev, additional_info);
1031
	if (ret != 0) {
1032
		kfree(rndis_device);
1033 1034 1035
		return ret;
	}

1036 1037

	/* Initialize the rndis device */
1038
	net_device = hv_get_drvdata(dev);
1039
	net_device->max_chn = 1;
1040
	net_device->num_chn = 1;
1041

1042 1043
	net_device->extension = rndis_device;
	rndis_device->net_dev = net_device;
1044

1045
	/* Send the rndis initialization message */
1046
	ret = rndis_filter_init_device(rndis_device);
1047
	if (ret != 0) {
1048 1049
		rndis_filter_device_remove(dev);
		return ret;
1050 1051
	}

1052 1053 1054 1055 1056
	/* Get the MTU from the host */
	size = sizeof(u32);
	ret = rndis_filter_query_device(rndis_device,
					RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
					&mtu, &size);
1057
	if (ret == 0 && size == sizeof(u32) && mtu < net_device->ndev->mtu)
1058 1059
		net_device->ndev->mtu = mtu;

1060
	/* Get the mac address */
1061
	ret = rndis_filter_query_device_mac(rndis_device);
1062
	if (ret != 0) {
1063 1064
		rndis_filter_device_remove(dev);
		return ret;
1065 1066
	}

1067
	memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
1068

1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
	/* Turn on the offloads; the host supports all of the relevant
	 * offloads.
	 */
	memset(&offloads, 0, sizeof(struct ndis_offload_params));
	/* A value of zero means "no change"; now turn on what we
	 * want.
	 */
	offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;


	ret = rndis_filter_set_offload_params(dev, &offloads);
	if (ret)
		goto err_dev_remv;

1088
	rndis_filter_query_device_link_status(rndis_device);
1089

1090
	device_info->link_state = rndis_device->link_state;
1091

1092
	dev_info(&dev->device, "Device MAC %pM link state %s\n",
1093
		 rndis_device->hw_mac_adr,
1094
		 device_info->link_state ? "down" : "up");
1095

1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
	if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
		return 0;

	/* vRSS setup */
	memset(&rsscap, 0, rsscap_size);
	ret = rndis_filter_query_device(rndis_device,
					OID_GEN_RECEIVE_SCALE_CAPABILITIES,
					&rsscap, &rsscap_size);
	if (ret || rsscap.num_recv_que < 2)
		goto out;

1107 1108
	num_rss_qs = min(device_info->max_num_vrss_chns, rsscap.num_recv_que);

1109
	net_device->max_chn = rsscap.num_recv_que;
1110 1111 1112 1113 1114 1115 1116 1117 1118

	/*
	 * We will limit the VRSS channels to the number CPUs in the NUMA node
	 * the primary channel is currently bound to.
	 */
	node_cpu_mask = cpumask_of_node(cpu_to_node(dev->channel->target_cpu));
	num_possible_rss_qs = cpumask_weight(node_cpu_mask);
	net_device->num_chn = min(num_possible_rss_qs, num_rss_qs);

1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
	if (net_device->num_chn == 1)
		goto out;

	net_device->sub_cb_buf = vzalloc((net_device->num_chn - 1) *
					 NETVSC_PACKET_SIZE);
	if (!net_device->sub_cb_buf) {
		net_device->num_chn = 1;
		dev_info(&dev->device, "No memory for subchannels.\n");
		goto out;
	}

	vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);

	init_packet = &net_device->channel_init_pkt;
	memset(init_packet, 0, sizeof(struct nvsp_message));
	init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL;
	init_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE;
	init_packet->msg.v5_msg.subchn_req.num_subchannels =
						net_device->num_chn - 1;
	ret = vmbus_sendpacket(dev->channel, init_packet,
			       sizeof(struct nvsp_message),
			       (unsigned long)init_packet,
			       VM_PKT_DATA_INBAND,
			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
	if (ret)
		goto out;
	t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
	if (t == 0) {
		ret = -ETIMEDOUT;
		goto out;
	}
	if (init_packet->msg.v5_msg.subchn_comp.status !=
	    NVSP_STAT_SUCCESS) {
		ret = -ENODEV;
		goto out;
	}
	net_device->num_chn = 1 +
		init_packet->msg.v5_msg.subchn_comp.num_subchannels;

	ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn);

out:
1161 1162
	if (ret) {
		net_device->max_chn = 1;
1163
		net_device->num_chn = 1;
1164
	}
1165
	return 0; /* return 0 because primary channel can be used alone */
1166 1167 1168 1169

err_dev_remv:
	rndis_filter_device_remove(dev);
	return ret;
1170 1171
}

1172
void rndis_filter_device_remove(struct hv_device *dev)
1173
{
1174
	struct netvsc_device *net_dev = hv_get_drvdata(dev);
1175
	struct rndis_device *rndis_dev = net_dev->extension;
1176

1177
	/* Halt and release the rndis device */
1178
	rndis_filter_halt_device(rndis_dev);
1179

1180
	kfree(rndis_dev);
1181
	net_dev->extension = NULL;
1182

1183
	netvsc_device_remove(dev);
1184 1185 1186
}


1187
int rndis_filter_open(struct hv_device *dev)
1188
{
1189
	struct netvsc_device *net_device = hv_get_drvdata(dev);
1190

1191
	if (!net_device)
1192 1193
		return -EINVAL;

1194
	return rndis_filter_open_device(net_device->extension);
1195 1196
}

1197
int rndis_filter_close(struct hv_device *dev)
1198
{
1199
	struct netvsc_device *nvdev = hv_get_drvdata(dev);
1200

1201
	if (!nvdev)
1202 1203
		return -EINVAL;

1204
	return rndis_filter_close_device(nvdev->extension);
1205
}