channel.c 23.6 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
	spin_lock_irqsave(&newchannel->lock, flags);
77 78 79
	if (newchannel->state == CHANNEL_OPEN_STATE) {
		newchannel->state = CHANNEL_OPENING_STATE;
	} else {
80
		spin_unlock_irqrestore(&newchannel->lock, flags);
81 82
		return -EINVAL;
	}
83
	spin_unlock_irqrestore(&newchannel->lock, flags);
84

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_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
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 int 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
	if (channel->target_cpu != get_cpu()) {
		put_cpu();
491 492
		smp_call_function_single(channel->target_cpu, reset_channel_cb,
					 channel, true);
493
	} else {
494
		reset_channel_cb(channel);
495 496
		put_cpu();
	}
497

498
	/* Send a closing message */
499

500
	msg = &channel->close_msg.msg;
501

502 503
	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
	msg->child_relid = channel->offermsg.child_relid;
504

505
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
506

507 508 509 510 511 512 513 514 515
	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;
	}

516
	/* Tear down the gpadl for the channel's ring buffer */
517 518 519 520 521 522 523 524 525 526 527 528
	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;
		}
	}
529

530
	/* Cleanup the ring buffers for this channel */
531 532
	hv_ringbuffer_cleanup(&channel->outbound);
	hv_ringbuffer_cleanup(&channel->inbound);
533

534 535
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
536

537
	return ret;
538
}
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

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

572
/**
573
 * vmbus_sendpacket() - Send the specified buffer on the given channel
574 575 576 577 578
 * @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
579 580
 * packet etc.
 *
581
 * Sends data in @buffer directly to hyper-v via the vmbus
582 583 584
 * This will send the data unparsed to hyper-v.
 *
 * Mainly used by Hyper-V drivers.
585
 */
586
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
587 588
			   u32 bufferlen, u64 requestid,
			   enum vmbus_packet_type type, u32 flags)
589
{
590
	struct vmpacket_descriptor desc;
591
	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
592
	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
593
	struct kvec bufferlist[3];
594
	u64 aligned_data = 0;
595
	int ret;
596
	bool signal = false;
597 598


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

607 608 609 610 611 612
	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);
613

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

616
	if (ret == 0 && signal)
617
		vmbus_setevent(channel);
618 619 620

	return ret;
}
621
EXPORT_SYMBOL(vmbus_sendpacket);
622

623
/*
624
 * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
625
 * packets using a GPADL Direct packet type.
626
 */
627
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
628 629 630
				     struct hv_page_buffer pagebuffers[],
				     u32 pagecount, void *buffer, u32 bufferlen,
				     u64 requestid)
631
{
632 633
	int ret;
	int i;
634
	struct vmbus_channel_packet_page_buffer desc;
635 636 637
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
638
	struct kvec bufferlist[3];
639
	u64 aligned_data = 0;
640
	bool signal = false;
641

642
	if (pagecount > MAX_PAGE_BUFFER_COUNT)
643
		return -EINVAL;
644 645


646
	/*
647
	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
648 649
	 * largest size we support
	 */
650 651
	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
652
			  sizeof(struct hv_page_buffer));
653
	packetlen = descsize + bufferlen;
654
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
655

656
	/* Setup the descriptor */
657
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
658
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
659 660 661 662 663 664
	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++) {
665 666 667
		desc.range[i].len = pagebuffers[i].len;
		desc.range[i].offset = pagebuffers[i].offset;
		desc.range[i].pfn	 = pagebuffers[i].pfn;
668 669
	}

670 671 672 673 674 675
	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);
676

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

679
	if (ret == 0 && signal)
680
		vmbus_setevent(channel);
681 682 683

	return ret;
}
684
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
685

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
/*
 * 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);

730
/*
731
 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
732
 * using a GPADL Direct packet type.
733
 */
734
int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
735 736
				struct hv_multipage_buffer *multi_pagebuffer,
				void *buffer, u32 bufferlen, u64 requestid)
737
{
738
	int ret;
739
	struct vmbus_channel_packet_multipage_buffer desc;
740 741 742
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
743
	struct kvec bufferlist[3];
744
	u64 aligned_data = 0;
745
	bool signal = false;
746 747
	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
					 multi_pagebuffer->len);
748

749
	if (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)
750
		return -EINVAL;
751

752
	/*
753
	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
754 755
	 * the largest size we support
	 */
756 757
	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
758
			  sizeof(u64));
759
	packetlen = descsize + bufferlen;
760
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
761 762


763
	/* Setup the descriptor */
764
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
765
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
766 767 768
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
769
	desc.rangecount = 1;
770

771 772
	desc.range.len = multi_pagebuffer->len;
	desc.range.offset = multi_pagebuffer->offset;
773

774
	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
775
	       pfncount * sizeof(u64));
776

777 778 779 780 781 782
	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);
783

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

786
	if (ret == 0 && signal)
787
		vmbus_setevent(channel);
788 789 790

	return ret;
}
791
EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
792 793

/**
794
 * vmbus_recvpacket() - Retrieve the user packet on the specified channel
795 796 797 798 799
 * @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
800 801 802 803 804
 *
 * 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.
805
 */
806
int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
807
			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
808
{
809
	struct vmpacket_descriptor desc;
810 811
	u32 packetlen;
	u32 userlen;
812
	int ret;
813
	bool signal = false;
814

815 816
	*buffer_actual_len = 0;
	*requestid = 0;
817 818


819
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
820
			     sizeof(struct vmpacket_descriptor));
821
	if (ret != 0)
822 823
		return 0;

824 825
	packetlen = desc.len8 << 3;
	userlen = packetlen - (desc.offset8 << 3);
826

827
	*buffer_actual_len = userlen;
828

829
	if (userlen > bufferlen) {
830

831
		pr_err("Buffer too small - got %d needs %d\n",
832
			   bufferlen, userlen);
833
		return -ETOOSMALL;
834 835
	}

836
	*requestid = desc.trans_id;
837

838
	/* Copy over the packet to the user buffer */
839
	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
840
			     (desc.offset8 << 3), &signal);
841

842 843
	if (signal)
		vmbus_setevent(channel);
844 845 846

	return 0;
}
847
EXPORT_SYMBOL(vmbus_recvpacket);
848

849
/*
850
 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
851
 */
852
int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
853 854
			      u32 bufferlen, u32 *buffer_actual_len,
			      u64 *requestid)
855
{
856
	struct vmpacket_descriptor desc;
857
	u32 packetlen;
858
	int ret;
859
	bool signal = false;
860

861 862
	*buffer_actual_len = 0;
	*requestid = 0;
863 864


865
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
866
			     sizeof(struct vmpacket_descriptor));
867
	if (ret != 0)
868 869 870
		return 0;


871
	packetlen = desc.len8 << 3;
872

873
	*buffer_actual_len = packetlen;
874

875
	if (packetlen > bufferlen)
876
		return -ENOBUFS;
877

878
	*requestid = desc.trans_id;
879

880
	/* Copy over the entire packet to the user buffer */
881 882 883 884 885
	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0,
				 &signal);

	if (signal)
		vmbus_setevent(channel);
886

887
	return ret;
888
}
889
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);