channel.c 23.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307 USA.
 *
 * Authors:
 *   Haiyang Zhang <haiyangz@microsoft.com>
 *   Hank Janssen  <hjanssen@microsoft.com>
 */
21 22
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

23
#include <linux/kernel.h>
24 25
#include <linux/sched.h>
#include <linux/wait.h>
26
#include <linux/mm.h>
27
#include <linux/slab.h>
28
#include <linux/module.h>
29
#include <linux/hyperv.h>
30
#include <linux/uio.h>
31
#include <linux/interrupt.h>
32

33
#include "hyperv_vmbus.h"
34

K
K. Y. Srinivasan 已提交
35 36 37
#define NUM_PAGES_SPANNED(addr, len) \
((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))

38
/*
39
 * vmbus_setevent- Trigger an event notification on the specified
40
 * channel.
41
 */
42
void vmbus_setevent(struct vmbus_channel *channel)
43
{
44
	struct hv_monitor_page *monitorpage;
45

46 47 48 49
	/*
	 * For channels marked as in "low latency" mode
	 * bypass the monitor page mechanism.
	 */
50 51
	if (channel->offermsg.monitor_allocated && !channel->low_latency) {
		vmbus_send_interrupt(channel->offermsg.child_relid);
52

53 54
		/* Get the child to parent monitor page */
		monitorpage = vmbus_connection.monitor_pages[1];
55

56
		sync_set_bit(channel->monitor_bit,
57 58
			(unsigned long *)&monitorpage->trigger_group
					[channel->monitor_grp].pending);
59

60
	} else {
61
		vmbus_set_event(channel);
62 63
	}
}
64
EXPORT_SYMBOL_GPL(vmbus_setevent);
65

66
/*
67
 * vmbus_open - Open the specified channel.
68
 */
69
int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
70 71
		     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
		     void (*onchannelcallback)(void *context), void *context)
72
{
73
	struct vmbus_channel_open_channel *open_msg;
74
	struct vmbus_channel_msginfo *open_info = NULL;
75
	unsigned long flags;
76
	int ret, err = 0;
77
	struct page *page;
78

79 80 81 82
	if (send_ringbuffer_size % PAGE_SIZE ||
	    recv_ringbuffer_size % PAGE_SIZE)
		return -EINVAL;

83
	spin_lock_irqsave(&newchannel->lock, flags);
84 85 86
	if (newchannel->state == CHANNEL_OPEN_STATE) {
		newchannel->state = CHANNEL_OPENING_STATE;
	} else {
87
		spin_unlock_irqrestore(&newchannel->lock, flags);
88 89
		return -EINVAL;
	}
90
	spin_unlock_irqrestore(&newchannel->lock, flags);
91

92 93
	newchannel->onchannel_callback = onchannelcallback;
	newchannel->channel_callback_context = context;
94

95
	/* Allocate the ring buffer */
96 97 98 99 100 101
	page = alloc_pages_node(cpu_to_node(newchannel->target_cpu),
				GFP_KERNEL|__GFP_ZERO,
				get_order(send_ringbuffer_size +
				recv_ringbuffer_size));

	if (!page)
102 103 104
		page = alloc_pages(GFP_KERNEL|__GFP_ZERO,
				   get_order(send_ringbuffer_size +
					     recv_ringbuffer_size));
105

106
	if (!page) {
107
		err = -ENOMEM;
108
		goto error_set_chnstate;
109
	}
110

111
	newchannel->ringbuffer_pages = page_address(page);
112
	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
113
					   recv_ringbuffer_size) >> PAGE_SHIFT;
114

115 116
	ret = hv_ringbuffer_init(&newchannel->outbound, page,
				 send_ringbuffer_size >> PAGE_SHIFT);
117

118
	if (ret != 0) {
119
		err = ret;
120
		goto error_free_pages;
121 122
	}

123 124 125
	ret = hv_ringbuffer_init(&newchannel->inbound,
				 &page[send_ringbuffer_size >> PAGE_SHIFT],
				 recv_ringbuffer_size >> PAGE_SHIFT);
126
	if (ret != 0) {
127
		err = ret;
128
		goto error_free_pages;
129
	}
130 131


132
	/* Establish the gpadl for the ring buffer */
133
	newchannel->ringbuffer_gpadlhandle = 0;
134

135
	ret = vmbus_establish_gpadl(newchannel,
136 137 138 139
				    page_address(page),
				    send_ringbuffer_size +
				    recv_ringbuffer_size,
				    &newchannel->ringbuffer_gpadlhandle);
140

141
	if (ret != 0) {
142
		err = ret;
143
		goto error_free_pages;
144
	}
145

146
	/* Create and init the channel open message */
147
	open_info = kmalloc(sizeof(*open_info) +
148 149
			   sizeof(struct vmbus_channel_open_channel),
			   GFP_KERNEL);
150
	if (!open_info) {
151
		err = -ENOMEM;
152
		goto error_free_gpadl;
153
	}
154

155
	init_completion(&open_info->waitevent);
156
	open_info->waiting_channel = newchannel;
157

158
	open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
159 160 161 162 163
	open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
	open_msg->openid = newchannel->offermsg.child_relid;
	open_msg->child_relid = newchannel->offermsg.child_relid;
	open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
	open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
164
						  PAGE_SHIFT;
165
	open_msg->target_vp = newchannel->target_vp;
166

167
	if (userdatalen > MAX_USER_DEFINED_BYTES) {
168
		err = -EINVAL;
169
		goto error_free_gpadl;
170 171
	}

172
	if (userdatalen)
173
		memcpy(open_msg->userdata, userdata, userdatalen);
174

175
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
176
	list_add_tail(&open_info->msglistentry,
177
		      &vmbus_connection.chn_msg_list);
178
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
179

180 181 182 183 184
	if (newchannel->rescind) {
		err = -ENODEV;
		goto error_free_gpadl;
	}

185
	ret = vmbus_post_msg(open_msg,
186
			     sizeof(struct vmbus_channel_open_channel), true);
187

188 189
	if (ret != 0) {
		err = ret;
190
		goto error_clean_msglist;
191
	}
192

193
	wait_for_completion(&open_info->waitevent);
194

195
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
196
	list_del(&open_info->msglistentry);
197
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
198

199 200 201 202 203
	if (newchannel->rescind) {
		err = -ENODEV;
		goto error_free_gpadl;
	}

204 205
	if (open_info->response.open_result.status) {
		err = -EAGAIN;
206
		goto error_free_gpadl;
207
	}
208

209
	newchannel->state = CHANNEL_OPENED_STATE;
210
	kfree(open_info);
211
	return 0;
212

213
error_clean_msglist:
214 215 216 217
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
	list_del(&open_info->msglistentry);
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);

218
error_free_gpadl:
219
	vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
220 221
	kfree(open_info);
error_free_pages:
222 223 224 225
	hv_ringbuffer_cleanup(&newchannel->outbound);
	hv_ringbuffer_cleanup(&newchannel->inbound);
	__free_pages(page,
		     get_order(send_ringbuffer_size + recv_ringbuffer_size));
226
error_set_chnstate:
227
	newchannel->state = CHANNEL_OPEN_STATE;
228
	return err;
229
}
230
EXPORT_SYMBOL_GPL(vmbus_open);
231

232 233 234 235 236 237 238 239 240 241 242
/* Used for Hyper-V Socket: a guest client's connect() to the host */
int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
				  const uuid_le *shv_host_servie_id)
{
	struct vmbus_channel_tl_connect_request conn_msg;

	memset(&conn_msg, 0, sizeof(conn_msg));
	conn_msg.header.msgtype = CHANNELMSG_TL_CONNECT_REQUEST;
	conn_msg.guest_endpoint_id = *shv_guest_servie_id;
	conn_msg.host_service_id = *shv_host_servie_id;

243
	return vmbus_post_msg(&conn_msg, sizeof(conn_msg), true);
244 245 246
}
EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request);

247
/*
248
 * create_gpadl_header - Creates a gpadl for the specified buffer
249
 */
250
static int create_gpadl_header(void *kbuffer, u32 size,
251
			       struct vmbus_channel_msginfo **msginfo)
252 253
{
	int i;
254 255 256 257 258 259
	int pagecount;
	struct vmbus_channel_gpadl_header *gpadl_header;
	struct vmbus_channel_gpadl_body *gpadl_body;
	struct vmbus_channel_msginfo *msgheader;
	struct vmbus_channel_msginfo *msgbody = NULL;
	u32 msgsize;
260

261
	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
262

263
	pagecount = size >> PAGE_SHIFT;
264

265
	/* do we need a gpadl body msg */
266
	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
267 268
		  sizeof(struct vmbus_channel_gpadl_header) -
		  sizeof(struct gpa_range);
269
	pfncount = pfnsize / sizeof(u64);
270

271
	if (pagecount > pfncount) {
272
		/* we need a gpadl body */
273
		/* fill in the header */
274
		msgsize = sizeof(struct vmbus_channel_msginfo) +
275
			  sizeof(struct vmbus_channel_gpadl_header) +
276 277 278
			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
		msgheader =  kzalloc(msgsize, GFP_KERNEL);
		if (!msgheader)
279
			goto nomem;
280

281 282
		INIT_LIST_HEAD(&msgheader->submsglist);
		msgheader->msgsize = msgsize;
283

284
		gpadl_header = (struct vmbus_channel_gpadl_header *)
285 286 287
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
288
					 pagecount * sizeof(u64);
289 290
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
291
		for (i = 0; i < pfncount; i++)
292 293
			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
294
		*msginfo = msgheader;
295

296 297
		pfnsum = pfncount;
		pfnleft = pagecount - pfncount;
298

299
		/* how many pfns can we fit */
300
		pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
301
			  sizeof(struct vmbus_channel_gpadl_body);
302
		pfncount = pfnsize / sizeof(u64);
303

304
		/* fill in the body */
305 306 307
		while (pfnleft) {
			if (pfnleft > pfncount)
				pfncurr = pfncount;
308
			else
309
				pfncurr = pfnleft;
310

311
			msgsize = sizeof(struct vmbus_channel_msginfo) +
312
				  sizeof(struct vmbus_channel_gpadl_body) +
313 314
				  pfncurr * sizeof(u64);
			msgbody = kzalloc(msgsize, GFP_KERNEL);
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

			if (!msgbody) {
				struct vmbus_channel_msginfo *pos = NULL;
				struct vmbus_channel_msginfo *tmp = NULL;
				/*
				 * Free up all the allocated messages.
				 */
				list_for_each_entry_safe(pos, tmp,
					&msgheader->submsglist,
					msglistentry) {

					list_del(&pos->msglistentry);
					kfree(pos);
				}

330
				goto nomem;
331 332
			}

333
			msgbody->msgsize = msgsize;
334
			gpadl_body =
335
				(struct vmbus_channel_gpadl_body *)msgbody->msg;
336 337 338 339

			/*
			 * Gpadl is u32 and we are using a pointer which could
			 * be 64-bit
340
			 * This is governed by the guest/host protocol and
S
Stephen Hemminger 已提交
341
			 * so the hypervisor guarantees that this is ok.
342
			 */
343
			for (i = 0; i < pfncurr; i++)
344 345 346
				gpadl_body->pfn[i] = slow_virt_to_phys(
					kbuffer + PAGE_SIZE * (pfnsum + i)) >>
					PAGE_SHIFT;
347

348
			/* add to msg header */
349 350
			list_add_tail(&msgbody->msglistentry,
				      &msgheader->submsglist);
351 352
			pfnsum += pfncurr;
			pfnleft -= pfncurr;
353
		}
354
	} else {
355
		/* everything fits in a header */
356
		msgsize = sizeof(struct vmbus_channel_msginfo) +
357
			  sizeof(struct vmbus_channel_gpadl_header) +
358 359 360
			  sizeof(struct gpa_range) + pagecount * sizeof(u64);
		msgheader = kzalloc(msgsize, GFP_KERNEL);
		if (msgheader == NULL)
361
			goto nomem;
362 363

		INIT_LIST_HEAD(&msgheader->submsglist);
364
		msgheader->msgsize = msgsize;
365 366

		gpadl_header = (struct vmbus_channel_gpadl_header *)
367 368 369
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
370
					 pagecount * sizeof(u64);
371 372
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
373
		for (i = 0; i < pagecount; i++)
374 375
			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
376 377

		*msginfo = msgheader;
378 379 380
	}

	return 0;
381
nomem:
382 383
	kfree(msgheader);
	kfree(msgbody);
384
	return -ENOMEM;
385 386
}

387
/*
S
Stephen Hemminger 已提交
388
 * vmbus_establish_gpadl - Establish a GPADL for the specified buffer
389
 *
390
 * @channel: a channel
391
 * @kbuffer: from kmalloc or vmalloc
392 393
 * @size: page-size multiple
 * @gpadl_handle: some funky thing
394
 */
395
int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
396
			       u32 size, u32 *gpadl_handle)
397
{
398 399 400
	struct vmbus_channel_gpadl_header *gpadlmsg;
	struct vmbus_channel_gpadl_body *gpadl_body;
	struct vmbus_channel_msginfo *msginfo = NULL;
401
	struct vmbus_channel_msginfo *submsginfo, *tmp;
402
	struct list_head *curr;
403
	u32 next_gpadl_handle;
404
	unsigned long flags;
405
	int ret = 0;
406

407 408
	next_gpadl_handle =
		(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
409

410
	ret = create_gpadl_header(kbuffer, size, &msginfo);
411 412
	if (ret)
		return ret;
413

414
	init_completion(&msginfo->waitevent);
415
	msginfo->waiting_channel = channel;
416

417 418 419 420
	gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
	gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
	gpadlmsg->child_relid = channel->offermsg.child_relid;
	gpadlmsg->gpadl = next_gpadl_handle;
421 422


423
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
424
	list_add_tail(&msginfo->msglistentry,
425
		      &vmbus_connection.chn_msg_list);
426

427
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
428

429 430 431 432 433
	if (channel->rescind) {
		ret = -ENODEV;
		goto cleanup;
	}

434
	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
435
			     sizeof(*msginfo), true);
436
	if (ret != 0)
437
		goto cleanup;
438

439 440 441 442
	list_for_each(curr, &msginfo->submsglist) {
		submsginfo = (struct vmbus_channel_msginfo *)curr;
		gpadl_body =
			(struct vmbus_channel_gpadl_body *)submsginfo->msg;
443

444 445 446
		gpadl_body->header.msgtype =
			CHANNELMSG_GPADL_BODY;
		gpadl_body->gpadl = next_gpadl_handle;
447

448
		ret = vmbus_post_msg(gpadl_body,
449 450
				     submsginfo->msgsize - sizeof(*submsginfo),
				     true);
451 452
		if (ret != 0)
			goto cleanup;
453 454

	}
455
	wait_for_completion(&msginfo->waitevent);
456

457 458 459 460 461
	if (channel->rescind) {
		ret = -ENODEV;
		goto cleanup;
	}

462
	/* At this point, we received the gpadl created msg */
463
	*gpadl_handle = gpadlmsg->gpadl;
464

465
cleanup:
466
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
467
	list_del(&msginfo->msglistentry);
468
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
469 470 471 472
	list_for_each_entry_safe(submsginfo, tmp, &msginfo->submsglist,
				 msglistentry) {
		kfree(submsginfo);
	}
473

474
	kfree(msginfo);
475 476
	return ret;
}
477
EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
478

479
/*
480
 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
481
 */
482
int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
483
{
484
	struct vmbus_channel_gpadl_teardown *msg;
485
	struct vmbus_channel_msginfo *info;
486
	unsigned long flags;
487
	int ret;
488

489 490
	info = kmalloc(sizeof(*info) +
		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
491 492
	if (!info)
		return -ENOMEM;
493

494
	init_completion(&info->waitevent);
495
	info->waiting_channel = channel;
496

497
	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
498

499 500 501
	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
	msg->child_relid = channel->offermsg.child_relid;
	msg->gpadl = gpadl_handle;
502

503
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
504
	list_add_tail(&info->msglistentry,
505
		      &vmbus_connection.chn_msg_list);
506
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
507 508 509 510

	if (channel->rescind)
		goto post_msg_err;

511 512
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown),
			     true);
513

514 515 516 517
	if (ret)
		goto post_msg_err;

	wait_for_completion(&info->waitevent);
518

519
post_msg_err:
520 521 522 523 524 525 526 527
	/*
	 * If the channel has been rescinded;
	 * we will be awakened by the rescind
	 * handler; set the error code to zero so we don't leak memory.
	 */
	if (channel->rescind)
		ret = 0;

528
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
529
	list_del(&info->msglistentry);
530
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
531

532
	kfree(info);
533 534
	return ret;
}
535
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
536

537 538 539 540 541 542 543
static void reset_channel_cb(void *arg)
{
	struct vmbus_channel *channel = arg;

	channel->onchannel_callback = NULL;
}

544
static int vmbus_close_internal(struct vmbus_channel *channel)
545
{
546
	struct vmbus_channel_close_channel *msg;
547
	int ret;
548

549
	/*
550
	 * vmbus_on_event(), running in the per-channel tasklet, can race
551 552
	 * with vmbus_close_internal() in the case of SMP guest, e.g., when
	 * the former is accessing channel->inbound.ring_buffer, the latter
553 554
	 * could be freeing the ring_buffer pages, so here we must stop it
	 * first.
555
	 */
556
	tasklet_disable(&channel->callback_event);
557

558 559 560
	/*
	 * In case a device driver's probe() fails (e.g.,
	 * util_probe() -> vmbus_open() returns -ENOMEM) and the device is
561
	 * rescinded later (e.g., we dynamically disable an Integrated Service
562 563 564 565 566 567 568 569
	 * in Hyper-V Manager), the driver's remove() invokes vmbus_close():
	 * here we should skip most of the below cleanup work.
	 */
	if (channel->state != CHANNEL_OPENED_STATE) {
		ret = -EINVAL;
		goto out;
	}

570 571
	channel->state = CHANNEL_OPEN_STATE;
	channel->sc_creation_callback = NULL;
572
	/* Stop callback and cancel the timer asap */
573 574
	if (channel->target_cpu != get_cpu()) {
		put_cpu();
575 576
		smp_call_function_single(channel->target_cpu, reset_channel_cb,
					 channel, true);
577
	} else {
578
		reset_channel_cb(channel);
579 580
		put_cpu();
	}
581

582
	/* Send a closing message */
583

584
	msg = &channel->close_msg.msg;
585

586 587
	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
	msg->child_relid = channel->offermsg.child_relid;
588

589 590
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel),
			     true);
591

592 593 594 595 596 597
	if (ret) {
		pr_err("Close failed: close post msg return is %d\n", ret);
		/*
		 * If we failed to post the close msg,
		 * it is perhaps better to leak memory.
		 */
598
		goto out;
599 600
	}

601
	/* Tear down the gpadl for the channel's ring buffer */
602 603 604 605 606 607 608 609 610
	if (channel->ringbuffer_gpadlhandle) {
		ret = vmbus_teardown_gpadl(channel,
					   channel->ringbuffer_gpadlhandle);
		if (ret) {
			pr_err("Close failed: teardown gpadl return %d\n", ret);
			/*
			 * If we failed to teardown gpadl,
			 * it is perhaps better to leak memory.
			 */
611
			goto out;
612 613
		}
	}
614

615
	/* Cleanup the ring buffers for this channel */
616 617
	hv_ringbuffer_cleanup(&channel->outbound);
	hv_ringbuffer_cleanup(&channel->inbound);
618

619 620
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
621

622
out:
623 624
	/* re-enable tasklet for use on re-open */
	tasklet_enable(&channel->callback_event);
625
	return ret;
626
}
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642

/*
 * vmbus_close - Close the specified channel
 */
void vmbus_close(struct vmbus_channel *channel)
{
	struct list_head *cur, *tmp;
	struct vmbus_channel *cur_channel;

	if (channel->primary_channel != NULL) {
		/*
		 * We will only close sub-channels when
		 * the primary is closed.
		 */
		return;
	}
643
	mutex_lock(&vmbus_connection.channel_mutex);
644 645 646 647 648 649 650
	/*
	 * Close all the sub-channels first and then close the
	 * primary channel.
	 */
	list_for_each_safe(cur, tmp, &channel->sc_list) {
		cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
		vmbus_close_internal(cur_channel);
651
		if (cur_channel->rescind) {
652
			hv_process_channel_removal(
653 654
					   cur_channel->offermsg.child_relid);
		}
655 656 657 658 659
	}
	/*
	 * Now close the primary.
	 */
	vmbus_close_internal(channel);
660
	mutex_unlock(&vmbus_connection.channel_mutex);
661
}
662
EXPORT_SYMBOL_GPL(vmbus_close);
663

664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
/**
 * vmbus_sendpacket() - Send the specified buffer on the given channel
 * @channel: Pointer to vmbus_channel structure.
 * @buffer: Pointer to the buffer you want to receive the data into.
 * @bufferlen: Maximum size of what the the buffer will hold
 * @requestid: Identifier of the request
 * @type: Type of packet that is being send e.g. negotiate, time
 * packet etc.
 *
 * Sends data in @buffer directly to hyper-v via the vmbus
 * This will send the data unparsed to hyper-v.
 *
 * Mainly used by Hyper-V drivers.
 */
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
			   u32 bufferlen, u64 requestid,
			   enum vmbus_packet_type type, u32 flags)
681
{
682
	struct vmpacket_descriptor desc;
683
	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
684
	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
685
	struct kvec bufferlist[3];
686
	u64 aligned_data = 0;
687
	int num_vecs = ((bufferlen != 0) ? 3 : 1);
688 689


690
	/* Setup the descriptor */
691 692
	desc.type = type; /* VmbusPacketTypeDataInBand; */
	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
693
	/* in 8-bytes granularity */
694 695 696
	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
	desc.len8 = (u16)(packetlen_aligned >> 3);
	desc.trans_id = requestid;
697

698 699 700 701 702 703
	bufferlist[0].iov_base = &desc;
	bufferlist[0].iov_len = sizeof(struct vmpacket_descriptor);
	bufferlist[1].iov_base = buffer;
	bufferlist[1].iov_len = bufferlen;
	bufferlist[2].iov_base = &aligned_data;
	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
704

705
	return hv_ringbuffer_write(channel, bufferlist, num_vecs);
706
}
707
EXPORT_SYMBOL(vmbus_sendpacket);
708

709
/*
710
 * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
711 712 713 714
 * packets using a GPADL Direct packet type. This interface allows you
 * to control notifying the host. This will be useful for sending
 * batched data. Also the sender can control the send flags
 * explicitly.
715
 */
716 717 718 719
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
				struct hv_page_buffer pagebuffers[],
				u32 pagecount, void *buffer, u32 bufferlen,
				u64 requestid)
720
{
721
	int i;
722
	struct vmbus_channel_packet_page_buffer desc;
723 724 725
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
726
	struct kvec bufferlist[3];
727
	u64 aligned_data = 0;
728

729
	if (pagecount > MAX_PAGE_BUFFER_COUNT)
730
		return -EINVAL;
731

732
	/*
733
	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
734 735
	 * largest size we support
	 */
736 737
	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
738
			  sizeof(struct hv_page_buffer));
739
	packetlen = descsize + bufferlen;
740
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
741

742
	/* Setup the descriptor */
743
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
744
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
S
Stephen Hemminger 已提交
745
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */
746 747 748 749 750
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
	desc.rangecount = pagecount;

	for (i = 0; i < pagecount; i++) {
751 752 753
		desc.range[i].len = pagebuffers[i].len;
		desc.range[i].offset = pagebuffers[i].offset;
		desc.range[i].pfn	 = pagebuffers[i].pfn;
754 755
	}

756 757 758 759 760 761
	bufferlist[0].iov_base = &desc;
	bufferlist[0].iov_len = descsize;
	bufferlist[1].iov_base = buffer;
	bufferlist[1].iov_len = bufferlen;
	bufferlist[2].iov_base = &aligned_data;
	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
762

763
	return hv_ringbuffer_write(channel, bufferlist, 3);
764
}
765
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
766

767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
/*
 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
 * using a GPADL Direct packet type.
 * The buffer includes the vmbus descriptor.
 */
int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
			      struct vmbus_packet_mpb_array *desc,
			      u32 desc_size,
			      void *buffer, u32 bufferlen, u64 requestid)
{
	u32 packetlen;
	u32 packetlen_aligned;
	struct kvec bufferlist[3];
	u64 aligned_data = 0;

	packetlen = desc_size + bufferlen;
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));

	/* Setup the descriptor */
	desc->type = VM_PKT_DATA_USING_GPA_DIRECT;
	desc->flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
S
Stephen Hemminger 已提交
788
	desc->dataoffset8 = desc_size >> 3; /* in 8-bytes granularity */
789 790 791 792 793 794 795 796 797 798 799
	desc->length8 = (u16)(packetlen_aligned >> 3);
	desc->transactionid = requestid;
	desc->rangecount = 1;

	bufferlist[0].iov_base = desc;
	bufferlist[0].iov_len = desc_size;
	bufferlist[1].iov_base = buffer;
	bufferlist[1].iov_len = bufferlen;
	bufferlist[2].iov_base = &aligned_data;
	bufferlist[2].iov_len = (packetlen_aligned - packetlen);

800
	return hv_ringbuffer_write(channel, bufferlist, 3);
801 802 803
}
EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);

804
/**
805
 * vmbus_recvpacket() - Retrieve the user packet on the specified channel
806 807 808 809 810
 * @channel: Pointer to vmbus_channel structure.
 * @buffer: Pointer to the buffer you want to receive the data into.
 * @bufferlen: Maximum size of what the the buffer will hold
 * @buffer_actual_len: The actual size of the data after it was received
 * @requestid: Identifier of the request
811 812 813 814 815
 *
 * Receives directly from the hyper-v vmbus and puts the data it received
 * into Buffer. This will receive the data unparsed from hyper-v.
 *
 * Mainly used by Hyper-V drivers.
816
 */
817 818 819 820
static inline int
__vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
		   u32 bufferlen, u32 *buffer_actual_len, u64 *requestid,
		   bool raw)
821
{
822 823
	return hv_ringbuffer_read(channel, buffer, bufferlen,
				  buffer_actual_len, requestid, raw);
824

825 826 827 828 829 830 831 832
}

int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
		     u32 bufferlen, u32 *buffer_actual_len,
		     u64 *requestid)
{
	return __vmbus_recvpacket(channel, buffer, bufferlen,
				  buffer_actual_len, requestid, false);
833
}
834
EXPORT_SYMBOL(vmbus_recvpacket);
835

836
/*
837
 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
838
 */
839
int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
840 841
			      u32 bufferlen, u32 *buffer_actual_len,
			      u64 *requestid)
842
{
843 844
	return __vmbus_recvpacket(channel, buffer, bufferlen,
				  buffer_actual_len, requestid, true);
845
}
846
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);