channel.c 24.9 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 75
	int ret, err = 0;
	unsigned long t;
76

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

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

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

93 94 95 96
	if (!out) {
		err = -ENOMEM;
		goto error0;
	}
97

98
	in = (void *)((unsigned long)out + send_ringbuffer_size);
99

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

104 105 106
	ret = hv_ringbuffer_init(
		&newchannel->outbound, out, send_ringbuffer_size);

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

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


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

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

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

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

143
	init_completion(&open_info->waitevent);
144

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

154
	if (userdatalen > MAX_USER_DEFINED_BYTES) {
155
		err = -EINVAL;
156
		goto error_gpadl;
157 158
	}

159
	if (userdatalen)
160
		memcpy(open_msg->userdata, userdata, userdatalen);
161

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

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

170 171
	if (ret != 0) {
		err = ret;
172
		goto error1;
173
	}
174

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

181

182 183
	if (open_info->response.open_result.status)
		err = open_info->response.open_result.status;
184

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

189 190 191
	if (err == 0)
		newchannel->state = CHANNEL_OPENED_STATE;

192
	kfree(open_info);
193
	return err;
194

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

200 201 202
error_gpadl:
	vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);

203
error0:
204 205
	free_pages((unsigned long)out,
		get_order(send_ringbuffer_size + recv_ringbuffer_size));
206
	kfree(open_info);
207
	newchannel->state = CHANNEL_OPEN_STATE;
208
	return err;
209
}
210
EXPORT_SYMBOL_GPL(vmbus_open);
211

212
/*
213
 * create_gpadl_header - Creates a gpadl for the specified buffer
214
 */
215
static int create_gpadl_header(void *kbuffer, u32 size,
216 217
					 struct vmbus_channel_msginfo **msginfo,
					 u32 *messagecount)
218 219
{
	int i;
220 221 222 223 224 225
	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;
226

227
	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
228

229
	pagecount = size >> PAGE_SHIFT;
230

231
	/* do we need a gpadl body msg */
232
	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
233 234
		  sizeof(struct vmbus_channel_gpadl_header) -
		  sizeof(struct gpa_range);
235
	pfncount = pfnsize / sizeof(u64);
236

237
	if (pagecount > pfncount) {
238
		/* we need a gpadl body */
239
		/* fill in the header */
240
		msgsize = sizeof(struct vmbus_channel_msginfo) +
241
			  sizeof(struct vmbus_channel_gpadl_header) +
242 243 244
			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
		msgheader =  kzalloc(msgsize, GFP_KERNEL);
		if (!msgheader)
245
			goto nomem;
246

247 248
		INIT_LIST_HEAD(&msgheader->submsglist);
		msgheader->msgsize = msgsize;
249

250
		gpadl_header = (struct vmbus_channel_gpadl_header *)
251 252 253
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
254
					 pagecount * sizeof(u64);
255 256
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
257
		for (i = 0; i < pfncount; i++)
258 259
			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
260 261
		*msginfo = msgheader;
		*messagecount = 1;
262

263 264
		pfnsum = pfncount;
		pfnleft = pagecount - pfncount;
265

266
		/* how many pfns can we fit */
267
		pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
268
			  sizeof(struct vmbus_channel_gpadl_body);
269
		pfncount = pfnsize / sizeof(u64);
270

271
		/* fill in the body */
272 273 274
		while (pfnleft) {
			if (pfnleft > pfncount)
				pfncurr = pfncount;
275
			else
276
				pfncurr = pfnleft;
277

278
			msgsize = sizeof(struct vmbus_channel_msginfo) +
279
				  sizeof(struct vmbus_channel_gpadl_body) +
280 281
				  pfncurr * sizeof(u64);
			msgbody = kzalloc(msgsize, GFP_KERNEL);
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296

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

297
				goto nomem;
298 299
			}

300
			msgbody->msgsize = msgsize;
301 302
			(*messagecount)++;
			gpadl_body =
303
				(struct vmbus_channel_gpadl_body *)msgbody->msg;
304 305 306 307

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

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

		gpadl_header = (struct vmbus_channel_gpadl_header *)
333 334 335
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
336
					 pagecount * sizeof(u64);
337 338
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
339
		for (i = 0; i < pagecount; i++)
340 341
			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
342 343 344

		*msginfo = msgheader;
		*messagecount = 1;
345 346 347
	}

	return 0;
348
nomem:
349 350
	kfree(msgheader);
	kfree(msgbody);
351
	return -ENOMEM;
352 353
}

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

375 376
	next_gpadl_handle =
		(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
377

378
	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
379 380
	if (ret)
		return ret;
381

382
	init_completion(&msginfo->waitevent);
383

384 385 386 387
	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;
388 389


390
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
391
	list_add_tail(&msginfo->msglistentry,
392
		      &vmbus_connection.chn_msg_list);
393

394
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
395

396
	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
397
			       sizeof(*msginfo));
398
	if (ret != 0)
399
		goto cleanup;
400

401
	if (msgcount > 1) {
402
		list_for_each(curr, &msginfo->submsglist) {
403

404 405
			submsginfo = (struct vmbus_channel_msginfo *)curr;
			gpadl_body =
406
			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
407

408 409 410
			gpadl_body->header.msgtype =
				CHANNELMSG_GPADL_BODY;
			gpadl_body->gpadl = next_gpadl_handle;
411

412
			ret = vmbus_post_msg(gpadl_body,
413
					       submsginfo->msgsize -
414
					       sizeof(*submsginfo));
415
			if (ret != 0)
416
				goto cleanup;
417

418 419
		}
	}
420
	wait_for_completion(&msginfo->waitevent);
421

422
	/* At this point, we received the gpadl created msg */
423
	*gpadl_handle = gpadlmsg->gpadl;
424

425
cleanup:
426
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
427
	list_del(&msginfo->msglistentry);
428
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
429

430
	kfree(msginfo);
431 432
	return ret;
}
433
EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
434

435
/*
436
 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
437
 */
438
int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
439
{
440
	struct vmbus_channel_gpadl_teardown *msg;
441
	struct vmbus_channel_msginfo *info;
442
	unsigned long flags;
443
	int ret;
444

445 446
	info = kmalloc(sizeof(*info) +
		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
447 448
	if (!info)
		return -ENOMEM;
449

450
	init_completion(&info->waitevent);
451

452
	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
453

454 455 456
	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
	msg->child_relid = channel->offermsg.child_relid;
	msg->gpadl = gpadl_handle;
457

458
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
459
	list_add_tail(&info->msglistentry,
460
		      &vmbus_connection.chn_msg_list);
461
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
462
	ret = vmbus_post_msg(msg,
463
			       sizeof(struct vmbus_channel_gpadl_teardown));
464

465 466 467 468
	if (ret)
		goto post_msg_err;

	wait_for_completion(&info->waitevent);
469

470
post_msg_err:
471
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
472
	list_del(&info->msglistentry);
473
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
474

475
	kfree(info);
476 477
	return ret;
}
478
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
479

480 481 482 483 484 485 486
static void reset_channel_cb(void *arg)
{
	struct vmbus_channel *channel = arg;

	channel->onchannel_callback = NULL;
}

487
static int vmbus_close_internal(struct vmbus_channel *channel)
488
{
489
	struct vmbus_channel_close_channel *msg;
490
	int ret;
491

492 493
	channel->state = CHANNEL_OPEN_STATE;
	channel->sc_creation_callback = NULL;
494
	/* Stop callback and cancel the timer asap */
495 496
	if (channel->target_cpu != get_cpu()) {
		put_cpu();
497 498
		smp_call_function_single(channel->target_cpu, reset_channel_cb,
					 channel, true);
499
	} else {
500
		reset_channel_cb(channel);
501 502
		put_cpu();
	}
503

504
	/* Send a closing message */
505

506
	msg = &channel->close_msg.msg;
507

508 509
	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
	msg->child_relid = channel->offermsg.child_relid;
510

511
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
512

513 514 515 516 517 518 519 520 521
	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.
		 */
		return ret;
	}

522
	/* Tear down the gpadl for the channel's ring buffer */
523 524 525 526 527 528 529 530 531 532 533 534
	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.
			 */
			return ret;
		}
	}
535

536
	/* Cleanup the ring buffers for this channel */
537 538
	hv_ringbuffer_cleanup(&channel->outbound);
	hv_ringbuffer_cleanup(&channel->inbound);
539

540 541
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
542

543 544 545 546 547 548
	/*
	 * If the channel has been rescinded; process device removal.
	 */
	if (channel->rescind)
		hv_process_channel_removal(channel,
					   channel->offermsg.child_relid);
549
	return ret;
550
}
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

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

584
int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
585
			   u32 bufferlen, u64 requestid,
586
			   enum vmbus_packet_type type, u32 flags, bool kick_q)
587
{
588
	struct vmpacket_descriptor desc;
589
	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
590
	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
591
	struct kvec bufferlist[3];
592
	u64 aligned_data = 0;
593
	int ret;
594
	bool signal = false;
595 596


597
	/* Setup the descriptor */
598 599
	desc.type = type; /* VmbusPacketTypeDataInBand; */
	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
600
	/* in 8-bytes granularity */
601 602 603
	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
	desc.len8 = (u16)(packetlen_aligned >> 3);
	desc.trans_id = requestid;
604

605 606 607 608 609 610
	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);
611

612
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
613

614
	if ((ret == 0) && kick_q && signal)
615
		vmbus_setevent(channel);
616 617 618

	return ret;
}
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
EXPORT_SYMBOL(vmbus_sendpacket_ctl);

/**
 * 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)
{
	return vmbus_sendpacket_ctl(channel, buffer, bufferlen, requestid,
				    type, flags, true);
}
642
EXPORT_SYMBOL(vmbus_sendpacket);
643

644
/*
645 646 647 648 649
 * vmbus_sendpacket_pagebuffer_ctl - Send a range of single-page buffer
 * 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.
650
 */
651
int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
652 653
				     struct hv_page_buffer pagebuffers[],
				     u32 pagecount, void *buffer, u32 bufferlen,
654 655 656
				     u64 requestid,
				     u32 flags,
				     bool kick_q)
657
{
658 659
	int ret;
	int i;
660
	struct vmbus_channel_packet_page_buffer desc;
661 662 663
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
664
	struct kvec bufferlist[3];
665
	u64 aligned_data = 0;
666
	bool signal = false;
667

668
	if (pagecount > MAX_PAGE_BUFFER_COUNT)
669
		return -EINVAL;
670 671


672
	/*
673
	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
674 675
	 * largest size we support
	 */
676 677
	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
678
			  sizeof(struct hv_page_buffer));
679
	packetlen = descsize + bufferlen;
680
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
681

682
	/* Setup the descriptor */
683
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
684
	desc.flags = flags;
685 686 687 688 689 690
	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++) {
691 692 693
		desc.range[i].len = pagebuffers[i].len;
		desc.range[i].offset = pagebuffers[i].offset;
		desc.range[i].pfn	 = pagebuffers[i].pfn;
694 695
	}

696 697 698 699 700 701
	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);
702

703
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
704

705
	if ((ret == 0) && kick_q && signal)
706
		vmbus_setevent(channel);
707 708 709

	return ret;
}
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725

/*
 * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
 * packets using a GPADL Direct packet type.
 */
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
				     struct hv_page_buffer pagebuffers[],
				     u32 pagecount, void *buffer, u32 bufferlen,
				     u64 requestid)
{
	u32 flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
	return vmbus_sendpacket_pagebuffer_ctl(channel, pagebuffers, pagecount,
					       buffer, bufferlen, requestid,
					       flags, true);

}
726
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
727

728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
/*
 * 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)
{
	int ret;
	u32 packetlen;
	u32 packetlen_aligned;
	struct kvec bufferlist[3];
	u64 aligned_data = 0;
	bool signal = false;

	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;
	desc->dataoffset8 = desc_size >> 3; /* in 8-bytes grandularity */
	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);

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

	if (ret == 0 && signal)
		vmbus_setevent(channel);

	return ret;
}
EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);

772
/*
773
 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
774
 * using a GPADL Direct packet type.
775
 */
776
int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
777 778
				struct hv_multipage_buffer *multi_pagebuffer,
				void *buffer, u32 bufferlen, u64 requestid)
779
{
780
	int ret;
781
	struct vmbus_channel_packet_multipage_buffer desc;
782 783 784
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
785
	struct kvec bufferlist[3];
786
	u64 aligned_data = 0;
787
	bool signal = false;
788 789
	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
					 multi_pagebuffer->len);
790

791
	if (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)
792
		return -EINVAL;
793

794
	/*
795
	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
796 797
	 * the largest size we support
	 */
798 799
	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
800
			  sizeof(u64));
801
	packetlen = descsize + bufferlen;
802
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
803 804


805
	/* Setup the descriptor */
806
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
807
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
808 809 810
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
811
	desc.rangecount = 1;
812

813 814
	desc.range.len = multi_pagebuffer->len;
	desc.range.offset = multi_pagebuffer->offset;
815

816
	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
817
	       pfncount * sizeof(u64));
818

819 820 821 822 823 824
	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);
825

826
	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
827

828
	if (ret == 0 && signal)
829
		vmbus_setevent(channel);
830 831 832

	return ret;
}
833
EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
834 835

/**
836
 * vmbus_recvpacket() - Retrieve the user packet on the specified channel
837 838 839 840 841
 * @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
842 843 844 845 846
 *
 * 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.
847
 */
848
int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
849
			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
850
{
851
	struct vmpacket_descriptor desc;
852 853
	u32 packetlen;
	u32 userlen;
854
	int ret;
855
	bool signal = false;
856

857 858
	*buffer_actual_len = 0;
	*requestid = 0;
859 860


861
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
862
			     sizeof(struct vmpacket_descriptor));
863
	if (ret != 0)
864 865
		return 0;

866 867
	packetlen = desc.len8 << 3;
	userlen = packetlen - (desc.offset8 << 3);
868

869
	*buffer_actual_len = userlen;
870

871
	if (userlen > bufferlen) {
872

873
		pr_err("Buffer too small - got %d needs %d\n",
874
			   bufferlen, userlen);
875
		return -ETOOSMALL;
876 877
	}

878
	*requestid = desc.trans_id;
879

880
	/* Copy over the packet to the user buffer */
881
	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
882
			     (desc.offset8 << 3), &signal);
883

884 885
	if (signal)
		vmbus_setevent(channel);
886 887 888

	return 0;
}
889
EXPORT_SYMBOL(vmbus_recvpacket);
890

891
/*
892
 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
893
 */
894
int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
895 896
			      u32 bufferlen, u32 *buffer_actual_len,
			      u64 *requestid)
897
{
898
	struct vmpacket_descriptor desc;
899
	u32 packetlen;
900
	int ret;
901
	bool signal = false;
902

903 904
	*buffer_actual_len = 0;
	*requestid = 0;
905 906


907
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
908
			     sizeof(struct vmpacket_descriptor));
909
	if (ret != 0)
910 911 912
		return 0;


913
	packetlen = desc.len8 << 3;
914

915
	*buffer_actual_len = packetlen;
916

917
	if (packetlen > bufferlen)
918
		return -ENOBUFS;
919

920
	*requestid = desc.trans_id;
921

922
	/* Copy over the entire packet to the user buffer */
923 924 925 926 927
	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0,
				 &signal);

	if (signal)
		vmbus_setevent(channel);
928

929
	return ret;
930
}
931
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);