channel.c 22.1 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, t;
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
	BUG_ON(ret != 0);
461
	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
462
	BUG_ON(t == 0);
463

464
	/* Received a torndown response */
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
static void vmbus_close_internal(struct vmbus_channel *channel)
475
{
476
	struct vmbus_channel_close_channel *msg;
477
	int ret;
478
	unsigned long flags;
479

480 481
	channel->state = CHANNEL_OPEN_STATE;
	channel->sc_creation_callback = NULL;
482
	/* Stop callback and cancel the timer asap */
483
	spin_lock_irqsave(&channel->inbound_lock, flags);
484
	channel->onchannel_callback = NULL;
485
	spin_unlock_irqrestore(&channel->inbound_lock, flags);
486

487
	/* Send a closing message */
488

489
	msg = &channel->close_msg.msg;
490

491 492
	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
	msg->child_relid = channel->offermsg.child_relid;
493

494
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
495

496
	BUG_ON(ret != 0);
497
	/* Tear down the gpadl for the channel's ring buffer */
498
	if (channel->ringbuffer_gpadlhandle)
499
		vmbus_teardown_gpadl(channel,
500
					  channel->ringbuffer_gpadlhandle);
501

502
	/* Cleanup the ring buffers for this channel */
503 504
	hv_ringbuffer_cleanup(&channel->outbound);
	hv_ringbuffer_cleanup(&channel->inbound);
505

506 507
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
508 509 510


}
511 512 513 514 515 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

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

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


571
	/* Setup the descriptor */
572 573
	desc.type = type; /* VmbusPacketTypeDataInBand; */
	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
574
	/* in 8-bytes granularity */
575 576 577
	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
	desc.len8 = (u16)(packetlen_aligned >> 3);
	desc.trans_id = requestid;
578

579 580 581 582 583 584
	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);
585

586
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
587

588
	if (ret == 0 && signal)
589
		vmbus_setevent(channel);
590 591 592

	return ret;
}
593
EXPORT_SYMBOL(vmbus_sendpacket);
594

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

614
	if (pagecount > MAX_PAGE_BUFFER_COUNT)
615
		return -EINVAL;
616 617


618
	/*
619
	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
620 621
	 * largest size we support
	 */
622 623
	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
624
			  sizeof(struct hv_page_buffer));
625
	packetlen = descsize + bufferlen;
626
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
627

628
	/* Setup the descriptor */
629
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
630
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
631 632 633 634 635 636
	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++) {
637 638 639
		desc.range[i].len = pagebuffers[i].len;
		desc.range[i].offset = pagebuffers[i].offset;
		desc.range[i].pfn	 = pagebuffers[i].pfn;
640 641
	}

642 643 644 645 646 647
	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);
648

649
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
650

651
	if (ret == 0 && signal)
652
		vmbus_setevent(channel);
653 654 655

	return ret;
}
656
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
657

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


678
	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
679
		return -EINVAL;
680

681
	/*
682
	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
683 684
	 * the largest size we support
	 */
685 686
	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
687
			  sizeof(u64));
688
	packetlen = descsize + bufferlen;
689
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
690 691


692
	/* Setup the descriptor */
693
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
694
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
695 696 697
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
698
	desc.rangecount = 1;
699

700 701
	desc.range.len = multi_pagebuffer->len;
	desc.range.offset = multi_pagebuffer->offset;
702

703
	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
704
	       pfncount * sizeof(u64));
705

706 707 708 709 710 711
	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);
712

713
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
714

715
	if (ret == 0 && signal)
716
		vmbus_setevent(channel);
717 718 719

	return ret;
}
720
EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
721 722

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

744 745
	*buffer_actual_len = 0;
	*requestid = 0;
746 747


748
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
749
			     sizeof(struct vmpacket_descriptor));
750
	if (ret != 0)
751 752
		return 0;

753 754
	packetlen = desc.len8 << 3;
	userlen = packetlen - (desc.offset8 << 3);
755

756
	*buffer_actual_len = userlen;
757

758
	if (userlen > bufferlen) {
759

760
		pr_err("Buffer too small - got %d needs %d\n",
761
			   bufferlen, userlen);
762
		return -ETOOSMALL;
763 764
	}

765
	*requestid = desc.trans_id;
766

767
	/* Copy over the packet to the user buffer */
768
	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
769
			     (desc.offset8 << 3), &signal);
770

771 772
	if (signal)
		vmbus_setevent(channel);
773 774 775

	return 0;
}
776
EXPORT_SYMBOL(vmbus_recvpacket);
777

778
/*
779
 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
780
 */
781
int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
782 783
			      u32 bufferlen, u32 *buffer_actual_len,
			      u64 *requestid)
784
{
785
	struct vmpacket_descriptor desc;
786
	u32 packetlen;
787
	int ret;
788
	bool signal = false;
789

790 791
	*buffer_actual_len = 0;
	*requestid = 0;
792 793


794
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
795
			     sizeof(struct vmpacket_descriptor));
796
	if (ret != 0)
797 798 799
		return 0;


800
	packetlen = desc.len8 << 3;
801

802
	*buffer_actual_len = packetlen;
803

804
	if (packetlen > bufferlen) {
805 806 807
		pr_err("Buffer too small - needed %d bytes but "
			"got space for only %d bytes\n",
			packetlen, bufferlen);
808
		return -ENOBUFS;
809 810
	}

811
	*requestid = desc.trans_id;
812

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

	if (signal)
		vmbus_setevent(channel);
819

820
	return ret;
821
}
822
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);