channel.c 21.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

31
#include "hyperv_vmbus.h"
32

K
K. Y. Srinivasan 已提交
33 34 35
#define NUM_PAGES_SPANNED(addr, len) \
((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))

36
/*
37
 * vmbus_setevent- Trigger an event notification on the specified
38
 * channel.
39
 */
40
static void vmbus_setevent(struct vmbus_channel *channel)
41
{
42
	struct hv_monitor_page *monitorpage;
43

44
	if (channel->offermsg.monitor_allocated) {
45
		/* Each u32 represents 32 channels */
46
		sync_set_bit(channel->offermsg.child_relid & 31,
47
			(unsigned long *) vmbus_connection.send_int_page +
48
			(channel->offermsg.child_relid >> 5));
49

50 51
		/* Get the child to parent monitor page */
		monitorpage = vmbus_connection.monitor_pages[1];
52

53
		sync_set_bit(channel->monitor_bit,
54 55
			(unsigned long *)&monitorpage->trigger_group
					[channel->monitor_grp].pending);
56

57
	} else {
58
		vmbus_set_event(channel);
59 60 61
	}
}

62
/*
63
 * vmbus_open - Open the specified channel.
64
 */
65
int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
66 67
		     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
		     void (*onchannelcallback)(void *context), void *context)
68
{
69
	struct vmbus_channel_open_channel *open_msg;
70
	struct vmbus_channel_msginfo *open_info = NULL;
71
	void *in, *out;
72
	unsigned long flags;
73
	int ret, t, err = 0;
74

75 76 77 78 79 80 81 82 83
	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);

84 85
	newchannel->onchannel_callback = onchannelcallback;
	newchannel->channel_callback_context = context;
86

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

91 92 93
	if (!out)
		return -ENOMEM;

94

95
	in = (void *)((unsigned long)out + send_ringbuffer_size);
96

97 98
	newchannel->ringbuffer_pages = out;
	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
99
					   recv_ringbuffer_size) >> PAGE_SHIFT;
100

101 102 103
	ret = hv_ringbuffer_init(
		&newchannel->outbound, out, send_ringbuffer_size);

104
	if (ret != 0) {
105
		err = ret;
106
		goto error0;
107 108
	}

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


117
	/* Establish the gpadl for the ring buffer */
118
	newchannel->ringbuffer_gpadlhandle = 0;
119

120
	ret = vmbus_establish_gpadl(newchannel,
121
					 newchannel->outbound.ring_buffer,
122 123
					 send_ringbuffer_size +
					 recv_ringbuffer_size,
124
					 &newchannel->ringbuffer_gpadlhandle);
125

126
	if (ret != 0) {
127
		err = ret;
128
		goto error0;
129
	}
130

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

140
	init_completion(&open_info->waitevent);
141

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

151
	if (userdatalen > MAX_USER_DEFINED_BYTES) {
152
		err = -EINVAL;
153
		goto error0;
154 155
	}

156
	if (userdatalen)
157
		memcpy(open_msg->userdata, userdata, userdatalen);
158

159
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
160
	list_add_tail(&open_info->msglistentry,
161
		      &vmbus_connection.chn_msg_list);
162
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
163

164
	ret = vmbus_post_msg(open_msg,
165
			       sizeof(struct vmbus_channel_open_channel));
166 167

	if (ret != 0)
168
		goto error1;
169

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

176

177 178
	if (open_info->response.open_result.status)
		err = open_info->response.open_result.status;
179

180
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
181
	list_del(&open_info->msglistentry);
182
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
183

184 185 186
	if (err == 0)
		newchannel->state = CHANNEL_OPENED_STATE;

187
	kfree(open_info);
188
	return err;
189

190 191 192 193 194 195
error1:
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
	list_del(&open_info->msglistentry);
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);

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

203
/*
204
 * create_gpadl_header - Creates a gpadl for the specified buffer
205
 */
206
static int create_gpadl_header(void *kbuffer, u32 size,
207 208
					 struct vmbus_channel_msginfo **msginfo,
					 u32 *messagecount)
209 210
{
	int i;
211
	int pagecount;
212
	unsigned long long pfn;
213 214 215 216 217
	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 222
	pagecount = size >> PAGE_SHIFT;
	pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
223

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

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

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

243
		gpadl_header = (struct vmbus_channel_gpadl_header *)
244 245 246
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
247
					 pagecount * sizeof(u64);
248 249
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
250
		for (i = 0; i < pfncount; i++)
251
			gpadl_header->range[0].pfn_array[i] = pfn+i;
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
				gpadl_body->pfn[i] = pfn + pfnsum + i;
305

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

		gpadl_header = (struct vmbus_channel_gpadl_header *)
323 324 325
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
326
					 pagecount * sizeof(u64);
327 328
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
329
		for (i = 0; i < pagecount; i++)
330
			gpadl_header->range[0].pfn_array[i] = pfn+i;
331 332 333

		*msginfo = msgheader;
		*messagecount = 1;
334 335 336
	}

	return 0;
337
nomem:
338 339
	kfree(msgheader);
	kfree(msgbody);
340
	return -ENOMEM;
341 342
}

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

365 366
	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
	atomic_inc(&vmbus_connection.next_gpadl_handle);
367

368
	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
369 370
	if (ret)
		return ret;
371

372
	init_completion(&msginfo->waitevent);
373

374 375 376 377
	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;
378 379


380
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
381
	list_add_tail(&msginfo->msglistentry,
382
		      &vmbus_connection.chn_msg_list);
383

384
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
385

386
	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
387
			       sizeof(*msginfo));
388
	if (ret != 0)
389
		goto cleanup;
390

391
	if (msgcount > 1) {
392
		list_for_each(curr, &msginfo->submsglist) {
393

394 395
			submsginfo = (struct vmbus_channel_msginfo *)curr;
			gpadl_body =
396
			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
397

398 399 400
			gpadl_body->header.msgtype =
				CHANNELMSG_GPADL_BODY;
			gpadl_body->gpadl = next_gpadl_handle;
401

402
			ret = vmbus_post_msg(gpadl_body,
403
					       submsginfo->msgsize -
404
					       sizeof(*submsginfo));
405
			if (ret != 0)
406
				goto cleanup;
407

408 409
		}
	}
410
	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
411
	BUG_ON(t == 0);
412

413

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

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

422
	kfree(msginfo);
423 424
	return ret;
}
425
EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
426

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

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

442
	init_completion(&info->waitevent);
443

444
	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
445

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

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

457
	BUG_ON(ret != 0);
458
	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
459
	BUG_ON(t == 0);
460

461
	/* Received a torndown response */
462
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
463
	list_del(&info->msglistentry);
464
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
465

466
	kfree(info);
467 468
	return ret;
}
469
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
470

471
static void vmbus_close_internal(struct vmbus_channel *channel)
472
{
473
	struct vmbus_channel_close_channel *msg;
474
	int ret;
475
	unsigned long flags;
476

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

484
	/* Send a closing message */
485

486
	msg = &channel->close_msg.msg;
487

488 489
	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
	msg->child_relid = channel->offermsg.child_relid;
490

491
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
492

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

499
	/* Cleanup the ring buffers for this channel */
500 501
	hv_ringbuffer_cleanup(&channel->outbound);
	hv_ringbuffer_cleanup(&channel->inbound);
502

503 504
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
505 506 507


}
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

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

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


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

576 577 578 579 580
	sg_init_table(bufferlist, 3);
	sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
	sg_set_buf(&bufferlist[1], buffer, bufferlen);
	sg_set_buf(&bufferlist[2], &aligned_data,
		   packetlen_aligned - packetlen);
581

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

584
	if (ret == 0 && signal)
585
		vmbus_setevent(channel);
586 587 588

	return ret;
}
589
EXPORT_SYMBOL(vmbus_sendpacket);
590

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

610
	if (pagecount > MAX_PAGE_BUFFER_COUNT)
611
		return -EINVAL;
612 613


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

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

638 639 640 641 642
	sg_init_table(bufferlist, 3);
	sg_set_buf(&bufferlist[0], &desc, descsize);
	sg_set_buf(&bufferlist[1], buffer, bufferlen);
	sg_set_buf(&bufferlist[2], &aligned_data,
		packetlen_aligned - packetlen);
643

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

646
	if (ret == 0 && signal)
647
		vmbus_setevent(channel);
648 649 650

	return ret;
}
651
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
652

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


673
	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
674
		return -EINVAL;
675

676
	/*
677
	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
678 679
	 * the largest size we support
	 */
680 681
	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
682
			  sizeof(u64));
683
	packetlen = descsize + bufferlen;
684
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
685 686


687
	/* Setup the descriptor */
688
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
689
	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
690 691 692
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
693
	desc.rangecount = 1;
694

695 696
	desc.range.len = multi_pagebuffer->len;
	desc.range.offset = multi_pagebuffer->offset;
697

698
	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
699
	       pfncount * sizeof(u64));
700

701 702 703 704 705
	sg_init_table(bufferlist, 3);
	sg_set_buf(&bufferlist[0], &desc, descsize);
	sg_set_buf(&bufferlist[1], buffer, bufferlen);
	sg_set_buf(&bufferlist[2], &aligned_data,
		packetlen_aligned - packetlen);
706

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

709
	if (ret == 0 && signal)
710
		vmbus_setevent(channel);
711 712 713

	return ret;
}
714
EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
715 716

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

738 739
	*buffer_actual_len = 0;
	*requestid = 0;
740 741


742
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
743
			     sizeof(struct vmpacket_descriptor));
744
	if (ret != 0)
745 746
		return 0;

747 748
	packetlen = desc.len8 << 3;
	userlen = packetlen - (desc.offset8 << 3);
749

750
	*buffer_actual_len = userlen;
751

752
	if (userlen > bufferlen) {
753

754
		pr_err("Buffer too small - got %d needs %d\n",
755
			   bufferlen, userlen);
756
		return -ETOOSMALL;
757 758
	}

759
	*requestid = desc.trans_id;
760

761
	/* Copy over the packet to the user buffer */
762
	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
763
			     (desc.offset8 << 3), &signal);
764

765 766
	if (signal)
		vmbus_setevent(channel);
767 768 769

	return 0;
}
770
EXPORT_SYMBOL(vmbus_recvpacket);
771

772
/*
773
 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
774
 */
775
int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
776 777
			      u32 bufferlen, u32 *buffer_actual_len,
			      u64 *requestid)
778
{
779
	struct vmpacket_descriptor desc;
780
	u32 packetlen;
781
	int ret;
782
	bool signal = false;
783

784 785
	*buffer_actual_len = 0;
	*requestid = 0;
786 787


788
	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
789
			     sizeof(struct vmpacket_descriptor));
790
	if (ret != 0)
791 792 793
		return 0;


794
	packetlen = desc.len8 << 3;
795

796
	*buffer_actual_len = packetlen;
797

798
	if (packetlen > bufferlen) {
799 800 801
		pr_err("Buffer too small - needed %d bytes but "
			"got space for only %d bytes\n",
			packetlen, bufferlen);
802
		return -ENOBUFS;
803 804
	}

805
	*requestid = desc.trans_id;
806

807
	/* Copy over the entire packet to the user buffer */
808 809 810 811 812
	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0,
				 &signal);

	if (signal)
		vmbus_setevent(channel);
813 814 815

	return 0;
}
816
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);