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 169
	if (ret != 0) {
		err = ret;
170
		goto error1;
171
	}
172

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

179

180 181
	if (open_info->response.open_result.status)
		err = open_info->response.open_result.status;
182

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

187 188 189
	if (err == 0)
		newchannel->state = CHANNEL_OPENED_STATE;

190
	kfree(open_info);
191
	return err;
192

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

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

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

221
	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
222

223
	pagecount = size >> PAGE_SHIFT;
224

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

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

241 242
		INIT_LIST_HEAD(&msgheader->submsglist);
		msgheader->msgsize = msgsize;
243

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

257 258
		pfnsum = pfncount;
		pfnleft = pagecount - pfncount;
259

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

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

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

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

291
				goto nomem;
292 293
			}

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

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

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

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

		*msginfo = msgheader;
		*messagecount = 1;
339 340 341
	}

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

348
/*
349
 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
350
 *
351
 * @channel: a channel
352
 * @kbuffer: from kmalloc or vmalloc
353 354
 * @size: page-size multiple
 * @gpadl_handle: some funky thing
355
 */
356
int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
357
			       u32 size, u32 *gpadl_handle)
358
{
359 360 361 362 363
	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;
364
	struct list_head *curr;
365
	u32 next_gpadl_handle;
366
	unsigned long flags;
367
	int ret = 0;
368

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

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

376
	init_completion(&msginfo->waitevent);
377

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


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

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

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

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

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

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

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

412 413
		}
	}
414
	wait_for_completion(&msginfo->waitevent);
415

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

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

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

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

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

444
	init_completion(&info->waitevent);
445

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

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

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

459 460 461 462
	if (ret)
		goto post_msg_err;

	wait_for_completion(&info->waitevent);
463

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

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

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

	channel->onchannel_callback = NULL;
}

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

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

495
	/* Send a closing message */
496

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

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

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

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

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

514 515
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
516 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

/*
 * 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);
}
550
EXPORT_SYMBOL_GPL(vmbus_close);
551

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


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

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

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

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

	return ret;
}
601
EXPORT_SYMBOL(vmbus_sendpacket);
602

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

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


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

636
	/* Setup the descriptor */
637
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
638
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
639 640 641 642 643 644
	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++) {
645 646 647
		desc.range[i].len = pagebuffers[i].len;
		desc.range[i].offset = pagebuffers[i].offset;
		desc.range[i].pfn	 = pagebuffers[i].pfn;
648 649
	}

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

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

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

	return ret;
}
664
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
665

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

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

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


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

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

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

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

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

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

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

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

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


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

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

763
	*buffer_actual_len = userlen;
764

765
	if (userlen > bufferlen) {
766

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

772
	*requestid = desc.trans_id;
773

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

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

	return 0;
}
783
EXPORT_SYMBOL(vmbus_recvpacket);
784

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

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


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


807
	packetlen = desc.len8 << 3;
808

809
	*buffer_actual_len = packetlen;
810

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

814
	*requestid = desc.trans_id;
815

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

	if (signal)
		vmbus_setevent(channel);
822

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