channel.c 22.0 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

32
#include "hyperv_vmbus.h"
33

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

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

45
	if (channel->offermsg.monitor_allocated) {
46
		/* Each u32 represents 32 channels */
47
		sync_set_bit(channel->offermsg.child_relid & 31,
48
			(unsigned long *) vmbus_connection.send_int_page +
49
			(channel->offermsg.child_relid >> 5));
50

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

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

58
	} else {
59
		vmbus_set_event(channel);
60 61 62
	}
}

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

76 77 78 79 80 81 82 83 84
	spin_lock_irqsave(&newchannel->sc_lock, flags);
	if (newchannel->state == CHANNEL_OPEN_STATE) {
		newchannel->state = CHANNEL_OPENING_STATE;
	} else {
		spin_unlock_irqrestore(&newchannel->sc_lock, flags);
		return -EINVAL;
	}
	spin_unlock_irqrestore(&newchannel->sc_lock, flags);

85 86
	newchannel->onchannel_callback = onchannelcallback;
	newchannel->channel_callback_context = context;
87

88
	/* Allocate the ring buffer */
89 90 91
	out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
		get_order(send_ringbuffer_size + recv_ringbuffer_size));

92 93 94
	if (!out)
		return -ENOMEM;

95

96
	in = (void *)((unsigned long)out + send_ringbuffer_size);
97

98 99
	newchannel->ringbuffer_pages = out;
	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
100
					   recv_ringbuffer_size) >> PAGE_SHIFT;
101

102 103 104
	ret = hv_ringbuffer_init(
		&newchannel->outbound, out, send_ringbuffer_size);

105
	if (ret != 0) {
106
		err = ret;
107
		goto error0;
108 109
	}

110 111
	ret = hv_ringbuffer_init(
		&newchannel->inbound, in, recv_ringbuffer_size);
112
	if (ret != 0) {
113
		err = ret;
114
		goto error0;
115
	}
116 117


118
	/* Establish the gpadl for the ring buffer */
119
	newchannel->ringbuffer_gpadlhandle = 0;
120

121
	ret = vmbus_establish_gpadl(newchannel,
122
					 newchannel->outbound.ring_buffer,
123 124
					 send_ringbuffer_size +
					 recv_ringbuffer_size,
125
					 &newchannel->ringbuffer_gpadlhandle);
126

127
	if (ret != 0) {
128
		err = ret;
129
		goto error0;
130
	}
131

132
	/* Create and init the channel open message */
133
	open_info = kmalloc(sizeof(*open_info) +
134 135
			   sizeof(struct vmbus_channel_open_channel),
			   GFP_KERNEL);
136
	if (!open_info) {
137
		err = -ENOMEM;
138
		goto error0;
139
	}
140

141
	init_completion(&open_info->waitevent);
142

143
	open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
144 145 146 147 148
	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 >>
149
						  PAGE_SHIFT;
150
	open_msg->target_vp = newchannel->target_vp;
151

152
	if (userdatalen > MAX_USER_DEFINED_BYTES) {
153
		err = -EINVAL;
154
		goto error0;
155 156
	}

157
	if (userdatalen)
158
		memcpy(open_msg->userdata, userdata, userdatalen);
159

160
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
161
	list_add_tail(&open_info->msglistentry,
162
		      &vmbus_connection.chn_msg_list);
163
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
164

165
	ret = vmbus_post_msg(open_msg,
166
			       sizeof(struct vmbus_channel_open_channel));
167 168

	if (ret != 0)
169
		goto error1;
170

171
	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
172
	if (t == 0) {
173
		err = -ETIMEDOUT;
174
		goto error1;
175 176
	}

177

178 179
	if (open_info->response.open_result.status)
		err = open_info->response.open_result.status;
180

181
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
182
	list_del(&open_info->msglistentry);
183
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
184

185 186 187
	if (err == 0)
		newchannel->state = CHANNEL_OPENED_STATE;

188
	kfree(open_info);
189
	return err;
190

191 192 193 194 195 196
error1:
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
	list_del(&open_info->msglistentry);
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);

error0:
197 198
	free_pages((unsigned long)out,
		get_order(send_ringbuffer_size + recv_ringbuffer_size));
199
	kfree(open_info);
200
	return err;
201
}
202
EXPORT_SYMBOL_GPL(vmbus_open);
203

204
/*
205
 * create_gpadl_header - Creates a gpadl for the specified buffer
206
 */
207
static int create_gpadl_header(void *kbuffer, u32 size,
208 209
					 struct vmbus_channel_msginfo **msginfo,
					 u32 *messagecount)
210 211
{
	int i;
212 213 214 215 216 217
	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;
218

219
	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
220

221
	pagecount = size >> PAGE_SHIFT;
222

223
	/* do we need a gpadl body msg */
224
	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
225 226
		  sizeof(struct vmbus_channel_gpadl_header) -
		  sizeof(struct gpa_range);
227
	pfncount = pfnsize / sizeof(u64);
228

229
	if (pagecount > pfncount) {
230
		/* we need a gpadl body */
231
		/* fill in the header */
232
		msgsize = sizeof(struct vmbus_channel_msginfo) +
233
			  sizeof(struct vmbus_channel_gpadl_header) +
234 235 236
			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
		msgheader =  kzalloc(msgsize, GFP_KERNEL);
		if (!msgheader)
237
			goto nomem;
238

239 240
		INIT_LIST_HEAD(&msgheader->submsglist);
		msgheader->msgsize = msgsize;
241

242
		gpadl_header = (struct vmbus_channel_gpadl_header *)
243 244 245
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
246
					 pagecount * sizeof(u64);
247 248
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
249
		for (i = 0; i < pfncount; i++)
250 251
			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
252 253
		*msginfo = msgheader;
		*messagecount = 1;
254

255 256
		pfnsum = pfncount;
		pfnleft = pagecount - pfncount;
257

258
		/* how many pfns can we fit */
259
		pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
260
			  sizeof(struct vmbus_channel_gpadl_body);
261
		pfncount = pfnsize / sizeof(u64);
262

263
		/* fill in the body */
264 265 266
		while (pfnleft) {
			if (pfnleft > pfncount)
				pfncurr = pfncount;
267
			else
268
				pfncurr = pfnleft;
269

270
			msgsize = sizeof(struct vmbus_channel_msginfo) +
271
				  sizeof(struct vmbus_channel_gpadl_body) +
272 273
				  pfncurr * sizeof(u64);
			msgbody = kzalloc(msgsize, GFP_KERNEL);
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288

			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);
				}

289
				goto nomem;
290 291
			}

292
			msgbody->msgsize = msgsize;
293 294
			(*messagecount)++;
			gpadl_body =
295
				(struct vmbus_channel_gpadl_body *)msgbody->msg;
296 297 298 299

			/*
			 * Gpadl is u32 and we are using a pointer which could
			 * be 64-bit
300 301
			 * This is governed by the guest/host protocol and
			 * so the hypervisor gurantees that this is ok.
302
			 */
303
			for (i = 0; i < pfncurr; i++)
304 305 306
				gpadl_body->pfn[i] = slow_virt_to_phys(
					kbuffer + PAGE_SIZE * (pfnsum + i)) >>
					PAGE_SHIFT;
307

308
			/* add to msg header */
309 310
			list_add_tail(&msgbody->msglistentry,
				      &msgheader->submsglist);
311 312
			pfnsum += pfncurr;
			pfnleft -= pfncurr;
313
		}
314
	} else {
315
		/* everything fits in a header */
316
		msgsize = sizeof(struct vmbus_channel_msginfo) +
317
			  sizeof(struct vmbus_channel_gpadl_header) +
318 319 320
			  sizeof(struct gpa_range) + pagecount * sizeof(u64);
		msgheader = kzalloc(msgsize, GFP_KERNEL);
		if (msgheader == NULL)
321
			goto nomem;
322
		msgheader->msgsize = msgsize;
323 324

		gpadl_header = (struct vmbus_channel_gpadl_header *)
325 326 327
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
328
					 pagecount * sizeof(u64);
329 330
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
331
		for (i = 0; i < pagecount; i++)
332 333
			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
334 335 336

		*msginfo = msgheader;
		*messagecount = 1;
337 338 339
	}

	return 0;
340
nomem:
341 342
	kfree(msgheader);
	kfree(msgbody);
343
	return -ENOMEM;
344 345
}

346
/*
347
 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
348
 *
349
 * @channel: a channel
350
 * @kbuffer: from kmalloc or vmalloc
351 352
 * @size: page-size multiple
 * @gpadl_handle: some funky thing
353
 */
354
int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
355
			       u32 size, u32 *gpadl_handle)
356
{
357 358 359 360 361
	struct vmbus_channel_gpadl_header *gpadlmsg;
	struct vmbus_channel_gpadl_body *gpadl_body;
	struct vmbus_channel_msginfo *msginfo = NULL;
	struct vmbus_channel_msginfo *submsginfo;
	u32 msgcount;
362
	struct list_head *curr;
363
	u32 next_gpadl_handle;
364
	unsigned long flags;
365
	int ret = 0;
366
	int t;
367

368 369
	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
	atomic_inc(&vmbus_connection.next_gpadl_handle);
370

371
	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
372 373
	if (ret)
		return ret;
374

375
	init_completion(&msginfo->waitevent);
376

377 378 379 380
	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;
381 382


383
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
384
	list_add_tail(&msginfo->msglistentry,
385
		      &vmbus_connection.chn_msg_list);
386

387
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
388

389
	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
390
			       sizeof(*msginfo));
391
	if (ret != 0)
392
		goto cleanup;
393

394
	if (msgcount > 1) {
395
		list_for_each(curr, &msginfo->submsglist) {
396

397 398
			submsginfo = (struct vmbus_channel_msginfo *)curr;
			gpadl_body =
399
			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
400

401 402 403
			gpadl_body->header.msgtype =
				CHANNELMSG_GPADL_BODY;
			gpadl_body->gpadl = next_gpadl_handle;
404

405
			ret = vmbus_post_msg(gpadl_body,
406
					       submsginfo->msgsize -
407
					       sizeof(*submsginfo));
408
			if (ret != 0)
409
				goto cleanup;
410

411 412
		}
	}
413
	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
414
	BUG_ON(t == 0);
415

416

417
	/* At this point, we received the gpadl created msg */
418
	*gpadl_handle = gpadlmsg->gpadl;
419

420
cleanup:
421
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
422
	list_del(&msginfo->msglistentry);
423
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
424

425
	kfree(msginfo);
426 427
	return ret;
}
428
EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
429

430
/*
431
 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
432
 */
433
int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
434
{
435
	struct vmbus_channel_gpadl_teardown *msg;
436
	struct vmbus_channel_msginfo *info;
437
	unsigned long flags;
438
	int ret;
439

440 441
	info = kmalloc(sizeof(*info) +
		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
442 443
	if (!info)
		return -ENOMEM;
444

445
	init_completion(&info->waitevent);
446

447
	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
448

449 450 451
	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
	msg->child_relid = channel->offermsg.child_relid;
	msg->gpadl = gpadl_handle;
452

453
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
454
	list_add_tail(&info->msglistentry,
455
		      &vmbus_connection.chn_msg_list);
456
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
457
	ret = vmbus_post_msg(msg,
458
			       sizeof(struct vmbus_channel_gpadl_teardown));
459

460 461 462 463
	if (ret)
		goto post_msg_err;

	wait_for_completion(&info->waitevent);
464

465
post_msg_err:
466
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
467
	list_del(&info->msglistentry);
468
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
469

470
	kfree(info);
471 472
	return ret;
}
473
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
474

475 476 477 478 479 480 481
static void reset_channel_cb(void *arg)
{
	struct vmbus_channel *channel = arg;

	channel->onchannel_callback = NULL;
}

482
static void vmbus_close_internal(struct vmbus_channel *channel)
483
{
484
	struct vmbus_channel_close_channel *msg;
485
	int ret;
486

487 488
	channel->state = CHANNEL_OPEN_STATE;
	channel->sc_creation_callback = NULL;
489
	/* Stop callback and cancel the timer asap */
490 491 492 493 494
	if (channel->target_cpu != smp_processor_id())
		smp_call_function_single(channel->target_cpu, reset_channel_cb,
					 channel, true);
	else
		reset_channel_cb(channel);
495

496
	/* Send a closing message */
497

498
	msg = &channel->close_msg.msg;
499

500 501
	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
	msg->child_relid = channel->offermsg.child_relid;
502

503
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
504

505
	BUG_ON(ret != 0);
506
	/* Tear down the gpadl for the channel's ring buffer */
507
	if (channel->ringbuffer_gpadlhandle)
508
		vmbus_teardown_gpadl(channel,
509
					  channel->ringbuffer_gpadlhandle);
510

511
	/* Cleanup the ring buffers for this channel */
512 513
	hv_ringbuffer_cleanup(&channel->outbound);
	hv_ringbuffer_cleanup(&channel->inbound);
514

515 516
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
517 518 519


}
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550

/*
 * 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;
	}
	/*
	 * 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);
		if (cur_channel->state != CHANNEL_OPENED_STATE)
			continue;
		vmbus_close_internal(cur_channel);
	}
	/*
	 * Now close the primary.
	 */
	vmbus_close_internal(channel);
}
551
EXPORT_SYMBOL_GPL(vmbus_close);
552

553
/**
554
 * vmbus_sendpacket() - Send the specified buffer on the given channel
555 556 557 558 559
 * @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
560 561
 * packet etc.
 *
562
 * Sends data in @buffer directly to hyper-v via the vmbus
563 564 565
 * This will send the data unparsed to hyper-v.
 *
 * Mainly used by Hyper-V drivers.
566
 */
567
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
568 569
			   u32 bufferlen, u64 requestid,
			   enum vmbus_packet_type type, u32 flags)
570
{
571
	struct vmpacket_descriptor desc;
572
	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
573
	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
574
	struct kvec bufferlist[3];
575
	u64 aligned_data = 0;
576
	int ret;
577
	bool signal = false;
578 579


580
	/* Setup the descriptor */
581 582
	desc.type = type; /* VmbusPacketTypeDataInBand; */
	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
583
	/* in 8-bytes granularity */
584 585 586
	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
	desc.len8 = (u16)(packetlen_aligned >> 3);
	desc.trans_id = requestid;
587

588 589 590 591 592 593
	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);
594

595
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
596

597
	if (ret == 0 && signal)
598
		vmbus_setevent(channel);
599 600 601

	return ret;
}
602
EXPORT_SYMBOL(vmbus_sendpacket);
603

604
/*
605
 * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
606
 * packets using a GPADL Direct packet type.
607
 */
608
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
609 610 611
				     struct hv_page_buffer pagebuffers[],
				     u32 pagecount, void *buffer, u32 bufferlen,
				     u64 requestid)
612
{
613 614
	int ret;
	int i;
615
	struct vmbus_channel_packet_page_buffer desc;
616 617 618
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
619
	struct kvec bufferlist[3];
620
	u64 aligned_data = 0;
621
	bool signal = false;
622

623
	if (pagecount > MAX_PAGE_BUFFER_COUNT)
624
		return -EINVAL;
625 626


627
	/*
628
	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
629 630
	 * largest size we support
	 */
631 632
	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
633
			  sizeof(struct hv_page_buffer));
634
	packetlen = descsize + bufferlen;
635
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
636

637
	/* Setup the descriptor */
638
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
639
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
640 641 642 643 644 645
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
	desc.rangecount = pagecount;

	for (i = 0; i < pagecount; i++) {
646 647 648
		desc.range[i].len = pagebuffers[i].len;
		desc.range[i].offset = pagebuffers[i].offset;
		desc.range[i].pfn	 = pagebuffers[i].pfn;
649 650
	}

651 652 653 654 655 656
	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);
657

658
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
659

660
	if (ret == 0 && signal)
661
		vmbus_setevent(channel);
662 663 664

	return ret;
}
665
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
666

667
/*
668
 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
669
 * using a GPADL Direct packet type.
670
 */
671
int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
672 673
				struct hv_multipage_buffer *multi_pagebuffer,
				void *buffer, u32 bufferlen, u64 requestid)
674
{
675
	int ret;
676
	struct vmbus_channel_packet_multipage_buffer desc;
677 678 679
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
680
	struct kvec bufferlist[3];
681
	u64 aligned_data = 0;
682
	bool signal = false;
683 684
	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
					 multi_pagebuffer->len);
685

686
	if (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)
687
		return -EINVAL;
688

689
	/*
690
	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
691 692
	 * the largest size we support
	 */
693 694
	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
695
			  sizeof(u64));
696
	packetlen = descsize + bufferlen;
697
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
698 699


700
	/* Setup the descriptor */
701
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
702
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
703 704 705
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
706
	desc.rangecount = 1;
707

708 709
	desc.range.len = multi_pagebuffer->len;
	desc.range.offset = multi_pagebuffer->offset;
710

711
	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
712
	       pfncount * sizeof(u64));
713

714 715 716 717 718 719
	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);
720

721
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
722

723
	if (ret == 0 && signal)
724
		vmbus_setevent(channel);
725 726 727

	return ret;
}
728
EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
729 730

/**
731
 * vmbus_recvpacket() - Retrieve the user packet on the specified channel
732 733 734 735 736
 * @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
737 738 739 740 741
 *
 * 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.
742
 */
743
int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
744
			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
745
{
746
	struct vmpacket_descriptor desc;
747 748
	u32 packetlen;
	u32 userlen;
749
	int ret;
750
	bool signal = false;
751

752 753
	*buffer_actual_len = 0;
	*requestid = 0;
754 755


756
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
757
			     sizeof(struct vmpacket_descriptor));
758
	if (ret != 0)
759 760
		return 0;

761 762
	packetlen = desc.len8 << 3;
	userlen = packetlen - (desc.offset8 << 3);
763

764
	*buffer_actual_len = userlen;
765

766
	if (userlen > bufferlen) {
767

768
		pr_err("Buffer too small - got %d needs %d\n",
769
			   bufferlen, userlen);
770
		return -ETOOSMALL;
771 772
	}

773
	*requestid = desc.trans_id;
774

775
	/* Copy over the packet to the user buffer */
776
	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
777
			     (desc.offset8 << 3), &signal);
778

779 780
	if (signal)
		vmbus_setevent(channel);
781 782 783

	return 0;
}
784
EXPORT_SYMBOL(vmbus_recvpacket);
785

786
/*
787
 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
788
 */
789
int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
790 791
			      u32 bufferlen, u32 *buffer_actual_len,
			      u64 *requestid)
792
{
793
	struct vmpacket_descriptor desc;
794
	u32 packetlen;
795
	int ret;
796
	bool signal = false;
797

798 799
	*buffer_actual_len = 0;
	*requestid = 0;
800 801


802
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
803
			     sizeof(struct vmpacket_descriptor));
804
	if (ret != 0)
805 806 807
		return 0;


808
	packetlen = desc.len8 << 3;
809

810
	*buffer_actual_len = packetlen;
811

812
	if (packetlen > bufferlen)
813
		return -ENOBUFS;
814

815
	*requestid = desc.trans_id;
816

817
	/* Copy over the entire packet to the user buffer */
818 819 820 821 822
	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0,
				 &signal);

	if (signal)
		vmbus_setevent(channel);
823

824
	return ret;
825
}
826
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);