Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Copyright (c) 2009, Microsoft Corporation.
  3 *
  4 * This program is free software; you can redistribute it and/or modify it
  5 * under the terms and conditions of the GNU General Public License,
  6 * version 2, as published by the Free Software Foundation.
  7 *
  8 * This program is distributed in the hope it will be useful, but WITHOUT
  9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 11 * more details.
 12 *
 13 * You should have received a copy of the GNU General Public License along with
 14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 15 * Place - Suite 330, Boston, MA 02111-1307 USA.
 16 *
 17 * Authors:
 18 *   Haiyang Zhang <haiyangz@microsoft.com>
 19 *   Hank Janssen  <hjanssen@microsoft.com>
 20 */
 21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 22
 23#include <linux/kernel.h>
 24#include <linux/sched.h>
 25#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
 34#define NUM_PAGES_SPANNED(addr, len) \
 35((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
 36
 37/*
 38 * vmbus_setevent- Trigger an event notification on the specified
 39 * channel.
 40 */
 41static 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		/* Get the child to parent monitor page */
 52		monitorpage = vmbus_connection.monitor_pages[1];
 53
 54		sync_set_bit(channel->monitor_bit,
 55			(unsigned long *)&monitorpage->trigger_group
 56					[channel->monitor_grp].pending);
 57
 58	} else {
 59		vmbus_set_event(channel);
 60	}
 61}
 62
 63/*
 64 * vmbus_open - Open the specified channel.
 65 */
 66int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 67		     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
 68		     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->sc_lock, flags);
 77	if (newchannel->state == CHANNEL_OPEN_STATE) {
 78		newchannel->state = CHANNEL_OPENING_STATE;
 79	} else {
 80		spin_unlock_irqrestore(&newchannel->sc_lock, flags);
 81		return -EINVAL;
 82	}
 83	spin_unlock_irqrestore(&newchannel->sc_lock, flags);
 84
 85	newchannel->onchannel_callback = onchannelcallback;
 86	newchannel->channel_callback_context = context;
 87
 88	/* Allocate the ring buffer */
 89	out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
 90		get_order(send_ringbuffer_size + recv_ringbuffer_size));
 91
 92	if (!out)
 93		return -ENOMEM;
 94
 95
 96	in = (void *)((unsigned long)out + send_ringbuffer_size);
 97
 98	newchannel->ringbuffer_pages = out;
 99	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
100					   recv_ringbuffer_size) >> PAGE_SHIFT;
101
102	ret = hv_ringbuffer_init(
103		&newchannel->outbound, out, send_ringbuffer_size);
104
105	if (ret != 0) {
106		err = ret;
107		goto error0;
108	}
109
110	ret = hv_ringbuffer_init(
111		&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					 send_ringbuffer_size +
124					 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			   sizeof(struct vmbus_channel_open_channel),
135			   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	open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
145	open_msg->openid = newchannel->offermsg.child_relid;
146	open_msg->child_relid = newchannel->offermsg.child_relid;
147	open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
148	open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
149						  PAGE_SHIFT;
150	open_msg->target_vp = newchannel->target_vp;
151
152	if (userdatalen > MAX_USER_DEFINED_BYTES) {
153		err = -EINVAL;
154		goto error0;
155	}
156
157	if (userdatalen)
158		memcpy(open_msg->userdata, userdata, userdatalen);
159
160	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
161	list_add_tail(&open_info->msglistentry,
162		      &vmbus_connection.chn_msg_list);
163	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
164
165	ret = vmbus_post_msg(open_msg,
166			       sizeof(struct vmbus_channel_open_channel));
167
168	if (ret != 0)
169		goto error1;
170
171	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
172	if (t == 0) {
173		err = -ETIMEDOUT;
174		goto error1;
175	}
176
177
178	if (open_info->response.open_result.status)
179		err = open_info->response.open_result.status;
180
181	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
182	list_del(&open_info->msglistentry);
183	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
184
185	if (err == 0)
186		newchannel->state = CHANNEL_OPENED_STATE;
187
188	kfree(open_info);
189	return err;
190
191error1:
192	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
193	list_del(&open_info->msglistentry);
194	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
195
196error0:
197	free_pages((unsigned long)out,
198		get_order(send_ringbuffer_size + recv_ringbuffer_size));
199	kfree(open_info);
200	return err;
201}
202EXPORT_SYMBOL_GPL(vmbus_open);
203
204/*
205 * create_gpadl_header - Creates a gpadl for the specified buffer
206 */
207static int create_gpadl_header(void *kbuffer, u32 size,
208					 struct vmbus_channel_msginfo **msginfo,
209					 u32 *messagecount)
210{
211	int i;
212	int pagecount;
213	struct vmbus_channel_gpadl_header *gpadl_header;
214	struct vmbus_channel_gpadl_body *gpadl_body;
215	struct vmbus_channel_msginfo *msgheader;
216	struct vmbus_channel_msginfo *msgbody = NULL;
217	u32 msgsize;
218
219	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
220
221	pagecount = size >> PAGE_SHIFT;
222
223	/* do we need a gpadl body msg */
224	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
225		  sizeof(struct vmbus_channel_gpadl_header) -
226		  sizeof(struct gpa_range);
227	pfncount = pfnsize / sizeof(u64);
228
229	if (pagecount > pfncount) {
230		/* we need a gpadl body */
231		/* fill in the header */
232		msgsize = sizeof(struct vmbus_channel_msginfo) +
233			  sizeof(struct vmbus_channel_gpadl_header) +
234			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
235		msgheader =  kzalloc(msgsize, GFP_KERNEL);
236		if (!msgheader)
237			goto nomem;
238
239		INIT_LIST_HEAD(&msgheader->submsglist);
240		msgheader->msgsize = msgsize;
241
242		gpadl_header = (struct vmbus_channel_gpadl_header *)
243			msgheader->msg;
244		gpadl_header->rangecount = 1;
245		gpadl_header->range_buflen = sizeof(struct gpa_range) +
246					 pagecount * sizeof(u64);
247		gpadl_header->range[0].byte_offset = 0;
248		gpadl_header->range[0].byte_count = size;
249		for (i = 0; i < pfncount; i++)
250			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
251				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
252		*msginfo = msgheader;
253		*messagecount = 1;
254
255		pfnsum = pfncount;
256		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		while (pfnleft) {
265			if (pfnleft > pfncount)
266				pfncurr = pfncount;
267			else
268				pfncurr = pfnleft;
269
270			msgsize = sizeof(struct vmbus_channel_msginfo) +
271				  sizeof(struct vmbus_channel_gpadl_body) +
272				  pfncurr * sizeof(u64);
273			msgbody = kzalloc(msgsize, GFP_KERNEL);
274
275			if (!msgbody) {
276				struct vmbus_channel_msginfo *pos = NULL;
277				struct vmbus_channel_msginfo *tmp = NULL;
278				/*
279				 * Free up all the allocated messages.
280				 */
281				list_for_each_entry_safe(pos, tmp,
282					&msgheader->submsglist,
283					msglistentry) {
284
285					list_del(&pos->msglistentry);
286					kfree(pos);
287				}
288
289				goto nomem;
290			}
291
292			msgbody->msgsize = msgsize;
293			(*messagecount)++;
294			gpadl_body =
295				(struct vmbus_channel_gpadl_body *)msgbody->msg;
296
297			/*
298			 * Gpadl is u32 and we are using a pointer which could
299			 * be 64-bit
300			 * This is governed by the guest/host protocol and
301			 * so the hypervisor gurantees that this is ok.
302			 */
303			for (i = 0; i < pfncurr; i++)
304				gpadl_body->pfn[i] = slow_virt_to_phys(
305					kbuffer + PAGE_SIZE * (pfnsum + i)) >>
306					PAGE_SHIFT;
307
308			/* add to msg header */
309			list_add_tail(&msgbody->msglistentry,
310				      &msgheader->submsglist);
311			pfnsum += pfncurr;
312			pfnleft -= pfncurr;
313		}
314	} else {
315		/* everything fits in a header */
316		msgsize = sizeof(struct vmbus_channel_msginfo) +
317			  sizeof(struct vmbus_channel_gpadl_header) +
318			  sizeof(struct gpa_range) + pagecount * sizeof(u64);
319		msgheader = kzalloc(msgsize, GFP_KERNEL);
320		if (msgheader == NULL)
321			goto nomem;
322		msgheader->msgsize = msgsize;
323
324		gpadl_header = (struct vmbus_channel_gpadl_header *)
325			msgheader->msg;
326		gpadl_header->rangecount = 1;
327		gpadl_header->range_buflen = sizeof(struct gpa_range) +
328					 pagecount * sizeof(u64);
329		gpadl_header->range[0].byte_offset = 0;
330		gpadl_header->range[0].byte_count = size;
331		for (i = 0; i < pagecount; i++)
332			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
333				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
334
335		*msginfo = msgheader;
336		*messagecount = 1;
337	}
338
339	return 0;
340nomem:
341	kfree(msgheader);
342	kfree(msgbody);
343	return -ENOMEM;
344}
345
346/*
347 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
348 *
349 * @channel: a channel
350 * @kbuffer: from kmalloc or vmalloc
351 * @size: page-size multiple
352 * @gpadl_handle: some funky thing
353 */
354int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
355			       u32 size, u32 *gpadl_handle)
356{
357	struct vmbus_channel_gpadl_header *gpadlmsg;
358	struct vmbus_channel_gpadl_body *gpadl_body;
359	struct vmbus_channel_msginfo *msginfo = NULL;
360	struct vmbus_channel_msginfo *submsginfo;
361	u32 msgcount;
362	struct list_head *curr;
363	u32 next_gpadl_handle;
364	unsigned long flags;
365	int ret = 0;
366	int t;
367
368	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
369	atomic_inc(&vmbus_connection.next_gpadl_handle);
370
371	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
372	if (ret)
373		return ret;
374
375	init_completion(&msginfo->waitevent);
376
377	gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
378	gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
379	gpadlmsg->child_relid = channel->offermsg.child_relid;
380	gpadlmsg->gpadl = next_gpadl_handle;
381
382
383	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
384	list_add_tail(&msginfo->msglistentry,
385		      &vmbus_connection.chn_msg_list);
386
387	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
388
389	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
390			       sizeof(*msginfo));
391	if (ret != 0)
392		goto cleanup;
393
394	if (msgcount > 1) {
395		list_for_each(curr, &msginfo->submsglist) {
396
397			submsginfo = (struct vmbus_channel_msginfo *)curr;
398			gpadl_body =
399			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
400
401			gpadl_body->header.msgtype =
402				CHANNELMSG_GPADL_BODY;
403			gpadl_body->gpadl = next_gpadl_handle;
404
405			ret = vmbus_post_msg(gpadl_body,
406					       submsginfo->msgsize -
407					       sizeof(*submsginfo));
408			if (ret != 0)
409				goto cleanup;
410
411		}
412	}
413	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
414	BUG_ON(t == 0);
415
416
417	/* At this point, we received the gpadl created msg */
418	*gpadl_handle = gpadlmsg->gpadl;
419
420cleanup:
421	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
422	list_del(&msginfo->msglistentry);
423	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
424
425	kfree(msginfo);
426	return ret;
427}
428EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
429
430/*
431 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
432 */
433int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
434{
435	struct vmbus_channel_gpadl_teardown *msg;
436	struct vmbus_channel_msginfo *info;
437	unsigned long flags;
438	int ret, t;
439
440	info = kmalloc(sizeof(*info) +
441		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
442	if (!info)
443		return -ENOMEM;
444
445	init_completion(&info->waitevent);
446
447	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
448
449	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
450	msg->child_relid = channel->offermsg.child_relid;
451	msg->gpadl = gpadl_handle;
452
453	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
454	list_add_tail(&info->msglistentry,
455		      &vmbus_connection.chn_msg_list);
456	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
457	ret = vmbus_post_msg(msg,
458			       sizeof(struct vmbus_channel_gpadl_teardown));
459
460	BUG_ON(ret != 0);
461	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
462	BUG_ON(t == 0);
463
464	/* Received a torndown response */
465	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
466	list_del(&info->msglistentry);
467	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
468
469	kfree(info);
470	return ret;
471}
472EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
473
474static void vmbus_close_internal(struct vmbus_channel *channel)
475{
476	struct vmbus_channel_close_channel *msg;
477	int ret;
478	unsigned long flags;
479
480	channel->state = CHANNEL_OPEN_STATE;
481	channel->sc_creation_callback = NULL;
482	/* Stop callback and cancel the timer asap */
483	spin_lock_irqsave(&channel->inbound_lock, flags);
484	channel->onchannel_callback = NULL;
485	spin_unlock_irqrestore(&channel->inbound_lock, flags);
486
487	/* Send a closing message */
488
489	msg = &channel->close_msg.msg;
490
491	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
492	msg->child_relid = channel->offermsg.child_relid;
493
494	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
495
496	BUG_ON(ret != 0);
497	/* Tear down the gpadl for the channel's ring buffer */
498	if (channel->ringbuffer_gpadlhandle)
499		vmbus_teardown_gpadl(channel,
500					  channel->ringbuffer_gpadlhandle);
501
502	/* Cleanup the ring buffers for this channel */
503	hv_ringbuffer_cleanup(&channel->outbound);
504	hv_ringbuffer_cleanup(&channel->inbound);
505
506	free_pages((unsigned long)channel->ringbuffer_pages,
507		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
508
509
510}
511
512/*
513 * vmbus_close - Close the specified channel
514 */
515void vmbus_close(struct vmbus_channel *channel)
516{
517	struct list_head *cur, *tmp;
518	struct vmbus_channel *cur_channel;
519
520	if (channel->primary_channel != NULL) {
521		/*
522		 * We will only close sub-channels when
523		 * the primary is closed.
524		 */
525		return;
526	}
527	/*
528	 * Close all the sub-channels first and then close the
529	 * primary channel.
530	 */
531	list_for_each_safe(cur, tmp, &channel->sc_list) {
532		cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
533		if (cur_channel->state != CHANNEL_OPENED_STATE)
534			continue;
535		vmbus_close_internal(cur_channel);
536	}
537	/*
538	 * Now close the primary.
539	 */
540	vmbus_close_internal(channel);
541}
542EXPORT_SYMBOL_GPL(vmbus_close);
543
544/**
545 * vmbus_sendpacket() - Send the specified buffer on the given channel
546 * @channel: Pointer to vmbus_channel structure.
547 * @buffer: Pointer to the buffer you want to receive the data into.
548 * @bufferlen: Maximum size of what the the buffer will hold
549 * @requestid: Identifier of the request
550 * @type: Type of packet that is being send e.g. negotiate, time
551 * packet etc.
552 *
553 * Sends data in @buffer directly to hyper-v via the vmbus
554 * This will send the data unparsed to hyper-v.
555 *
556 * Mainly used by Hyper-V drivers.
557 */
558int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
559			   u32 bufferlen, u64 requestid,
560			   enum vmbus_packet_type type, u32 flags)
561{
562	struct vmpacket_descriptor desc;
563	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
564	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
565	struct kvec bufferlist[3];
566	u64 aligned_data = 0;
567	int ret;
568	bool signal = false;
569
570
571	/* Setup the descriptor */
572	desc.type = type; /* VmbusPacketTypeDataInBand; */
573	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
574	/* in 8-bytes granularity */
575	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
576	desc.len8 = (u16)(packetlen_aligned >> 3);
577	desc.trans_id = requestid;
578
579	bufferlist[0].iov_base = &desc;
580	bufferlist[0].iov_len = sizeof(struct vmpacket_descriptor);
581	bufferlist[1].iov_base = buffer;
582	bufferlist[1].iov_len = bufferlen;
583	bufferlist[2].iov_base = &aligned_data;
584	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
585
586	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
587
588	if (ret == 0 && signal)
589		vmbus_setevent(channel);
590
591	return ret;
592}
593EXPORT_SYMBOL(vmbus_sendpacket);
594
595/*
596 * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
597 * packets using a GPADL Direct packet type.
598 */
599int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
600				     struct hv_page_buffer pagebuffers[],
601				     u32 pagecount, void *buffer, u32 bufferlen,
602				     u64 requestid)
603{
604	int ret;
605	int i;
606	struct vmbus_channel_packet_page_buffer desc;
607	u32 descsize;
608	u32 packetlen;
609	u32 packetlen_aligned;
610	struct kvec bufferlist[3];
611	u64 aligned_data = 0;
612	bool signal = false;
613
614	if (pagecount > MAX_PAGE_BUFFER_COUNT)
615		return -EINVAL;
616
617
618	/*
619	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
620	 * largest size we support
621	 */
622	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
623			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
624			  sizeof(struct hv_page_buffer));
625	packetlen = descsize + bufferlen;
626	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
627
628	/* Setup the descriptor */
629	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
630	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
631	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
632	desc.length8 = (u16)(packetlen_aligned >> 3);
633	desc.transactionid = requestid;
634	desc.rangecount = pagecount;
635
636	for (i = 0; i < pagecount; i++) {
637		desc.range[i].len = pagebuffers[i].len;
638		desc.range[i].offset = pagebuffers[i].offset;
639		desc.range[i].pfn	 = pagebuffers[i].pfn;
640	}
641
642	bufferlist[0].iov_base = &desc;
643	bufferlist[0].iov_len = descsize;
644	bufferlist[1].iov_base = buffer;
645	bufferlist[1].iov_len = bufferlen;
646	bufferlist[2].iov_base = &aligned_data;
647	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
648
649	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
650
651	if (ret == 0 && signal)
652		vmbus_setevent(channel);
653
654	return ret;
655}
656EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
657
658/*
659 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
660 * using a GPADL Direct packet type.
661 */
662int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
663				struct hv_multipage_buffer *multi_pagebuffer,
664				void *buffer, u32 bufferlen, u64 requestid)
665{
666	int ret;
667	struct vmbus_channel_packet_multipage_buffer desc;
668	u32 descsize;
669	u32 packetlen;
670	u32 packetlen_aligned;
671	struct kvec bufferlist[3];
672	u64 aligned_data = 0;
673	bool signal = false;
674	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
675					 multi_pagebuffer->len);
676
677
678	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
679		return -EINVAL;
680
681	/*
682	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
683	 * the largest size we support
684	 */
685	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
686			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
687			  sizeof(u64));
688	packetlen = descsize + bufferlen;
689	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
690
691
692	/* Setup the descriptor */
693	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
694	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
695	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
696	desc.length8 = (u16)(packetlen_aligned >> 3);
697	desc.transactionid = requestid;
698	desc.rangecount = 1;
699
700	desc.range.len = multi_pagebuffer->len;
701	desc.range.offset = multi_pagebuffer->offset;
702
703	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
704	       pfncount * sizeof(u64));
705
706	bufferlist[0].iov_base = &desc;
707	bufferlist[0].iov_len = descsize;
708	bufferlist[1].iov_base = buffer;
709	bufferlist[1].iov_len = bufferlen;
710	bufferlist[2].iov_base = &aligned_data;
711	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
712
713	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
714
715	if (ret == 0 && signal)
716		vmbus_setevent(channel);
717
718	return ret;
719}
720EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
721
722/**
723 * vmbus_recvpacket() - Retrieve the user packet on the specified channel
724 * @channel: Pointer to vmbus_channel structure.
725 * @buffer: Pointer to the buffer you want to receive the data into.
726 * @bufferlen: Maximum size of what the the buffer will hold
727 * @buffer_actual_len: The actual size of the data after it was received
728 * @requestid: Identifier of the request
729 *
730 * Receives directly from the hyper-v vmbus and puts the data it received
731 * into Buffer. This will receive the data unparsed from hyper-v.
732 *
733 * Mainly used by Hyper-V drivers.
734 */
735int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
736			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
737{
738	struct vmpacket_descriptor desc;
739	u32 packetlen;
740	u32 userlen;
741	int ret;
742	bool signal = false;
743
744	*buffer_actual_len = 0;
745	*requestid = 0;
746
747
748	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
749			     sizeof(struct vmpacket_descriptor));
750	if (ret != 0)
751		return 0;
752
753	packetlen = desc.len8 << 3;
754	userlen = packetlen - (desc.offset8 << 3);
755
756	*buffer_actual_len = userlen;
757
758	if (userlen > bufferlen) {
759
760		pr_err("Buffer too small - got %d needs %d\n",
761			   bufferlen, userlen);
762		return -ETOOSMALL;
763	}
764
765	*requestid = desc.trans_id;
766
767	/* Copy over the packet to the user buffer */
768	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
769			     (desc.offset8 << 3), &signal);
770
771	if (signal)
772		vmbus_setevent(channel);
773
774	return 0;
775}
776EXPORT_SYMBOL(vmbus_recvpacket);
777
778/*
779 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
780 */
781int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
782			      u32 bufferlen, u32 *buffer_actual_len,
783			      u64 *requestid)
784{
785	struct vmpacket_descriptor desc;
786	u32 packetlen;
787	int ret;
788	bool signal = false;
789
790	*buffer_actual_len = 0;
791	*requestid = 0;
792
793
794	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
795			     sizeof(struct vmpacket_descriptor));
796	if (ret != 0)
797		return 0;
798
799
800	packetlen = desc.len8 << 3;
801
802	*buffer_actual_len = packetlen;
803
804	if (packetlen > bufferlen) {
805		pr_err("Buffer too small - needed %d bytes but "
806			"got space for only %d bytes\n",
807			packetlen, bufferlen);
808		return -ENOBUFS;
809	}
810
811	*requestid = desc.trans_id;
812
813	/* Copy over the entire packet to the user buffer */
814	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0,
815				 &signal);
816
817	if (signal)
818		vmbus_setevent(channel);
819
820	return ret;
821}
822EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);