rndis_filter.c 31.3 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

31
#include "hyperv_net.h"
32 33


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

39
	struct rndis_message response_msg;
40
	/*
41 42 43 44
	 * 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.
45
	 */
46
	u8 response_ext[RNDIS_EXT_LEN];
47

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

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

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

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

67
	spin_lock_init(&device->request_lock);
68

69
	INIT_LIST_HEAD(&device->req_list);
70

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

	return device;
}

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

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

89
	init_completion(&request->wait_event);
90

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

95 96
	request->pkt.q_idx = 0;

97 98 99 100 101
	/*
	 * 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
	 */
102 103
	set = &rndis_msg->msg.set_req;
	set->req_id = atomic_inc_return(&dev->new_req_id);
104

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

	return request;
}

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

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

122
	kfree(req);
123 124
}

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

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

134
	switch (rndis_msg->ndis_msg_type) {
135 136
	case RNDIS_MSG_PACKET:
		netdev_dbg(netdev, "RNDIS_MSG_PACKET (len %u, "
137 138
			   "data offset %u data len %u, # oob %u, "
			   "oob offset %u, oob len %u, pkt offset %u, "
139
			   "pkt len %u\n",
140 141 142 143 144 145 146 147
			   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);
148 149
		break;

150 151
	case RNDIS_MSG_INIT_C:
		netdev_dbg(netdev, "RNDIS_MSG_INIT_C "
152 153
			"(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
			"device flags %d, max xfer size 0x%x, max pkts %u, "
154
			"pkt aligned %u)\n",
155 156 157 158 159 160 161 162 163 164 165
			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);
166 167
		break;

168 169
	case RNDIS_MSG_QUERY_C:
		netdev_dbg(netdev, "RNDIS_MSG_QUERY_C "
170
			"(len %u, id 0x%x, status 0x%x, buf len %u, "
171
			"buf offset %u)\n",
172 173 174 175 176 177 178
			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);
179 180
		break;

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

189 190
	case RNDIS_MSG_INDICATE:
		netdev_dbg(netdev, "RNDIS_MSG_INDICATE "
191
			"(len %u, status 0x%x, buf len %u, buf offset %u)\n",
192 193 194 195
			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);
196 197 198
		break;

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

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

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

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

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

227 228 229 230 231 232 233 234 235 236 237 238
	/* 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;
	}

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

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

246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
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;
	}
}

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

	ndev = dev->net_dev->ndev;
271

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

286
	if (found) {
287 288
		if (resp->msg_len <=
		    sizeof(struct rndis_message) + RNDIS_EXT_LEN) {
289
			memcpy(&request->response_msg, resp,
290
			       resp->msg_len);
291 292 293 294
			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);
295
		} else {
296
			netdev_err(ndev,
297 298 299
				"rndis response buffer overflow "
				"detected (size %u max %zu)\n",
				resp->msg_len,
300
				sizeof(struct rndis_message));
301

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

314
		complete(&request->wait_event);
315
	} else {
316
		netdev_err(ndev,
317 318 319 320
			"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);
321 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
/*
 * 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;
}

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

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

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

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

	/*
	 * 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;
384
	pkt->data = (void *)((unsigned long)pkt->data + data_offset);
385

386 387 388 389 390 391 392 393
	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;
	}

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

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

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

412 413
	ndev = net_dev->ndev;

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

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

430
	rndis_msg = pkt->data;
431

432
	dump_rndis_message(dev, rndis_msg);
433

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

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

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

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

	return ret;
464 465
}

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

476
	if (!result)
477
		return -EINVAL;
478

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

487
	/* Setup the rndis query */
488 489 490 491 492
	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;
493

494 495 496 497 498 499 500 501 502 503 504 505 506
	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);
	}

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

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

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

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

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

530
	*result_size = query_complete->info_buflen;
531

532
cleanup:
533
	if (request)
534
		put_rndis_request(dev, request);
535 536 537 538

	return ret;
}

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

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

548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
#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;
564 565
	int ret;
	unsigned long t;
566 567 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

	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;
616 617 618
		if (set_complete->status != RNDIS_STATUS_SUCCESS) {
			netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
				   set_complete->status);
619
			ret = -EINVAL;
620
		}
621 622 623 624 625 626 627
	}

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

L
Lad, Prabhakar 已提交
628 629
static int
rndis_filter_set_offload_params(struct hv_device *hdev,
630 631 632 633 634 635 636 637 638 639
				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);
640 641
	int ret;
	unsigned long t;
642 643 644 645 646 647 648 649 650 651
	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;
	}
652 653 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

	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) {
685
			netdev_err(ndev, "Fail to set offload on host side:0x%x\n",
686 687 688 689 690 691 692 693 694
				   set_complete->status);
			ret = -EINVAL;
		}
	}

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

696 697 698 699 700 701 702 703
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 已提交
704
static int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
705 706 707 708 709 710 711 712 713 714
{
	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;
715 716
	int i, ret;
	unsigned long t;
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735

	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 |
736 737
			 NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
			 NDIS_HASH_TCP_IPV6;
738 739 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
	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;
}


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

787
	ret = rndis_filter_query_device(dev,
788
				      RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
789 790 791
				      &link_status, &size);

	return ret;
792 793
}

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

	ndev = dev->net_dev->ndev;
805

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

814
	/* Setup the rndis set */
815 816 817 818
	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);
819

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

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

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

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

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


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

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

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

874
	dev->state = RNDIS_DEV_INITIALIZING;
875

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

882

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

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

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

902
cleanup:
903
	if (request)
904
		put_rndis_request(dev, request);
905 906 907 908

	return ret;
}

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

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

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

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

930
	dev->state = RNDIS_DEV_UNINITIALIZED;
931

932
cleanup:
933 934 935 936 937 938 939 940
	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);

941
	if (request)
942
		put_rndis_request(dev, request);
943 944 945
	return;
}

946
static int rndis_filter_open_device(struct rndis_device *dev)
947
{
948
	int ret;
949

950
	if (dev->state != RNDIS_DEV_INITIALIZED)
951 952
		return 0;

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

	return ret;
}

963
static int rndis_filter_close_device(struct rndis_device *dev)
964 965 966
{
	int ret;

967
	if (dev->state != RNDIS_DEV_DATAINITIALIZED)
968 969
		return 0;

970
	ret = rndis_filter_set_packet_filter(dev, 0);
971 972 973
	if (ret == -ENODEV)
		ret = 0;

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

	return ret;
}

980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
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;
}

1002
int rndis_filter_device_add(struct hv_device *dev,
1003
				  void *additional_info)
1004 1005
{
	int ret;
1006
	struct netvsc_device *net_device;
1007
	struct rndis_device *rndis_device;
1008
	struct netvsc_device_info *device_info = additional_info;
1009
	struct ndis_offload_params offloads;
1010
	struct nvsp_message *init_packet;
1011
	unsigned long t;
1012 1013
	struct ndis_recv_scale_cap rsscap;
	u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
1014
	u32 mtu, size;
1015

1016 1017
	rndis_device = get_rndis_device();
	if (!rndis_device)
1018
		return -ENODEV;
1019

1020 1021 1022 1023 1024
	/*
	 * 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
	 */
1025
	ret = netvsc_device_add(dev, additional_info);
1026
	if (ret != 0) {
1027
		kfree(rndis_device);
1028 1029 1030
		return ret;
	}

1031 1032

	/* Initialize the rndis device */
1033
	net_device = hv_get_drvdata(dev);
1034
	net_device->max_chn = 1;
1035
	net_device->num_chn = 1;
1036

1037 1038
	net_device->extension = rndis_device;
	rndis_device->net_dev = net_device;
1039

1040
	/* Send the rndis initialization message */
1041
	ret = rndis_filter_init_device(rndis_device);
1042
	if (ret != 0) {
1043 1044
		rndis_filter_device_remove(dev);
		return ret;
1045 1046
	}

1047 1048 1049 1050 1051 1052 1053 1054
	/* Get the MTU from the host */
	size = sizeof(u32);
	ret = rndis_filter_query_device(rndis_device,
					RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
					&mtu, &size);
	if (ret == 0 && size == sizeof(u32))
		net_device->ndev->mtu = mtu;

1055
	/* Get the mac address */
1056
	ret = rndis_filter_query_device_mac(rndis_device);
1057
	if (ret != 0) {
1058 1059
		rndis_filter_device_remove(dev);
		return ret;
1060 1061
	}

1062
	memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
1063

1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
	/* 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;

1083
	rndis_filter_query_device_link_status(rndis_device);
1084

1085
	device_info->link_state = rndis_device->link_state;
1086

1087
	dev_info(&dev->device, "Device MAC %pM link state %s\n",
1088
		 rndis_device->hw_mac_adr,
1089
		 device_info->link_state ? "down" : "up");
1090

1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
	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;

1102
	net_device->max_chn = rsscap.num_recv_que;
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 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
	net_device->num_chn = (num_online_cpus() < rsscap.num_recv_que) ?
			       num_online_cpus() : rsscap.num_recv_que;
	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:
1147 1148
	if (ret) {
		net_device->max_chn = 1;
1149
		net_device->num_chn = 1;
1150
	}
1151
	return 0; /* return 0 because primary channel can be used alone */
1152 1153 1154 1155

err_dev_remv:
	rndis_filter_device_remove(dev);
	return ret;
1156 1157
}

1158
void rndis_filter_device_remove(struct hv_device *dev)
1159
{
1160
	struct netvsc_device *net_dev = hv_get_drvdata(dev);
1161
	struct rndis_device *rndis_dev = net_dev->extension;
1162

1163
	/* Halt and release the rndis device */
1164
	rndis_filter_halt_device(rndis_dev);
1165

1166
	kfree(rndis_dev);
1167
	net_dev->extension = NULL;
1168

1169
	netvsc_device_remove(dev);
1170 1171 1172
}


1173
int rndis_filter_open(struct hv_device *dev)
1174
{
1175
	struct netvsc_device *net_device = hv_get_drvdata(dev);
1176

1177
	if (!net_device)
1178 1179
		return -EINVAL;

1180
	return rndis_filter_open_device(net_device->extension);
1181 1182
}

1183
int rndis_filter_close(struct hv_device *dev)
1184
{
1185
	struct netvsc_device *nvdev = hv_get_drvdata(dev);
1186

1187
	if (!nvdev)
1188 1189
		return -EINVAL;

1190
	return rndis_filter_close_device(nvdev->extension);
1191
}