channel.c 22.4 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 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 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 505 506 507 508 509 510 511 512
	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;
	}

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

527
	/* Cleanup the ring buffers for this channel */
528 529
	hv_ringbuffer_cleanup(&channel->outbound);
	hv_ringbuffer_cleanup(&channel->inbound);
530

531 532
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
533

534
	return ret;
535
}
536 537 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

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

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


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

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

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

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

	return ret;
}
618
EXPORT_SYMBOL(vmbus_sendpacket);
619

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

639
	if (pagecount > MAX_PAGE_BUFFER_COUNT)
640
		return -EINVAL;
641 642


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

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

667 668 669 670 671 672
	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);
673

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

676
	if (ret == 0 && signal)
677
		vmbus_setevent(channel);
678 679 680

	return ret;
}
681
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
682

683
/*
684
 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
685
 * using a GPADL Direct packet type.
686
 */
687
int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
688 689
				struct hv_multipage_buffer *multi_pagebuffer,
				void *buffer, u32 bufferlen, u64 requestid)
690
{
691
	int ret;
692
	struct vmbus_channel_packet_multipage_buffer desc;
693 694 695
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
696
	struct kvec bufferlist[3];
697
	u64 aligned_data = 0;
698
	bool signal = false;
699 700
	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
					 multi_pagebuffer->len);
701

702
	if (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)
703
		return -EINVAL;
704

705
	/*
706
	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
707 708
	 * the largest size we support
	 */
709 710
	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
711
			  sizeof(u64));
712
	packetlen = descsize + bufferlen;
713
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
714 715


716
	/* Setup the descriptor */
717
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
718
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
719 720 721
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
722
	desc.rangecount = 1;
723

724 725
	desc.range.len = multi_pagebuffer->len;
	desc.range.offset = multi_pagebuffer->offset;
726

727
	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
728
	       pfncount * sizeof(u64));
729

730 731 732 733 734 735
	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);
736

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

739
	if (ret == 0 && signal)
740
		vmbus_setevent(channel);
741 742 743

	return ret;
}
744
EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
745 746

/**
747
 * vmbus_recvpacket() - Retrieve the user packet on the specified channel
748 749 750 751 752
 * @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
753 754 755 756 757
 *
 * 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.
758
 */
759
int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
760
			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
761
{
762
	struct vmpacket_descriptor desc;
763 764
	u32 packetlen;
	u32 userlen;
765
	int ret;
766
	bool signal = false;
767

768 769
	*buffer_actual_len = 0;
	*requestid = 0;
770 771


772
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
773
			     sizeof(struct vmpacket_descriptor));
774
	if (ret != 0)
775 776
		return 0;

777 778
	packetlen = desc.len8 << 3;
	userlen = packetlen - (desc.offset8 << 3);
779

780
	*buffer_actual_len = userlen;
781

782
	if (userlen > bufferlen) {
783

784
		pr_err("Buffer too small - got %d needs %d\n",
785
			   bufferlen, userlen);
786
		return -ETOOSMALL;
787 788
	}

789
	*requestid = desc.trans_id;
790

791
	/* Copy over the packet to the user buffer */
792
	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
793
			     (desc.offset8 << 3), &signal);
794

795 796
	if (signal)
		vmbus_setevent(channel);
797 798 799

	return 0;
}
800
EXPORT_SYMBOL(vmbus_recvpacket);
801

802
/*
803
 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
804
 */
805
int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
806 807
			      u32 bufferlen, u32 *buffer_actual_len,
			      u64 *requestid)
808
{
809
	struct vmpacket_descriptor desc;
810
	u32 packetlen;
811
	int ret;
812
	bool signal = false;
813

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


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


824
	packetlen = desc.len8 << 3;
825

826
	*buffer_actual_len = packetlen;
827

828
	if (packetlen > bufferlen)
829
		return -ENOBUFS;
830

831
	*requestid = desc.trans_id;
832

833
	/* Copy over the entire packet to the user buffer */
834 835 836 837 838
	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0,
				 &signal);

	if (signal)
		vmbus_setevent(channel);
839

840
	return ret;
841
}
842
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);