13e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*
23e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Copyright (c) 2009, Microsoft Corporation.
33e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen *
43e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * This program is free software; you can redistribute it and/or modify it
53e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * under the terms and conditions of the GNU General Public License,
63e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * version 2, as published by the Free Software Foundation.
73e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen *
83e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * This program is distributed in the hope it will be useful, but WITHOUT
93e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
103e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * more details.
123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen *
133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * You should have received a copy of the GNU General Public License along with
143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
153e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Place - Suite 330, Boston, MA 02111-1307 USA.
163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen *
173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Authors:
183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen *   Haiyang Zhang <haiyangz@microsoft.com>
193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen *   Hank Janssen  <hjanssen@microsoft.com>
203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen */
210a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
220a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen
235654e932262840f853233317689fc59536226d76Greg Kroah-Hartman#include <linux/kernel.h>
240c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan#include <linux/sched.h>
250c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan#include <linux/wait.h>
26a0086dc512ba6c2161dcf48195daf177ad0c3615Greg Kroah-Hartman#include <linux/mm.h>
275a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
28c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen#include <linux/module.h>
2946a971913611a23478283931460a95be962ce329Greg Kroah-Hartman#include <linux/hyperv.h>
303f335ea2131b14bca2333b4316c8d4dd737e30dbK. Y. Srinivasan
310f2a6619eeef158d11832436ce151987f18cb08dK. Y. Srinivasan#include "hyperv_vmbus.h"
323e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
33e3fe0bb65b2686aa83dabdb1ecc22f5d80c536f8K. Y. Srinivasan#define NUM_PAGES_SPANNED(addr, len) \
34e3fe0bb65b2686aa83dabdb1ecc22f5d80c536f8K. Y. Srinivasan((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
35e3fe0bb65b2686aa83dabdb1ecc22f5d80c536f8K. Y. Srinivasan
36454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* Internal routines */
37fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangstatic int create_gpadl_header(
3839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	void *kbuffer,	/* must be phys and virt contiguous */
3939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 size,	/* page-size multiple */
4039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_msginfo **msginfo,
4139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 *messagecount);
42fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangstatic void vmbus_setevent(struct vmbus_channel *channel);
433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
443e18951955797872558dad615851a4ca63b2770eHank Janssen/*
45fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_setevent- Trigger an event notification on the specified
463e18951955797872558dad615851a4ca63b2770eHank Janssen * channel.
47f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
48fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangstatic void vmbus_setevent(struct vmbus_channel *channel)
493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
5039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct hv_monitor_page *monitorpage;
513e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
52c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	if (channel->offermsg.monitor_allocated) {
53454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* Each u32 represents 32 channels */
5422356585712d1ff08fbfed152edd8b386873b238Olaf Hering		sync_set_bit(channel->offermsg.child_relid & 31,
55da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang			(unsigned long *) vmbus_connection.send_int_page +
56c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang			(channel->offermsg.child_relid >> 5));
573e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
58da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang		monitorpage = vmbus_connection.monitor_pages;
5939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		monitorpage++; /* Get the child to parent monitor page */
603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
6122356585712d1ff08fbfed152edd8b386873b238Olaf Hering		sync_set_bit(channel->monitor_bit,
62f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang			(unsigned long *)&monitorpage->trigger_group
63f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang					[channel->monitor_grp].pending);
647c369f405bc918f3245c7ee0b0ad6c6b6c750166Bill Pemberton
65f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	} else {
66c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang		vmbus_set_event(channel->offermsg.child_relid);
673e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	}
683e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
703e18951955797872558dad615851a4ca63b2770eHank Janssen/*
71fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_get_debug_info -Retrieve various channel debug info
72f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
73fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangvoid vmbus_get_debug_info(struct vmbus_channel *channel,
7439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			      struct vmbus_channel_debug_info *debuginfo)
753e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
7639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct hv_monitor_page *monitorpage;
77c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
78c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
793e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
80c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->relid = channel->offermsg.child_relid;
81c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->state = channel->state;
82c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	memcpy(&debuginfo->interfacetype,
83358d2ee2e8f5c25f1661e94c206102c88fdee370K. Y. Srinivasan	       &channel->offermsg.offer.if_type, sizeof(uuid_le));
84c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	memcpy(&debuginfo->interface_instance,
85767dff6853ae0f68438e623199cc7137441a286dHaiyang Zhang	       &channel->offermsg.offer.if_instance,
86358d2ee2e8f5c25f1661e94c206102c88fdee370K. Y. Srinivasan	       sizeof(uuid_le));
873e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
88da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang	monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
893e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
90c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->monitorid = channel->offermsg.monitorid;
913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
92c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->servermonitor_pending =
93f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang			monitorpage->trigger_group[monitor_group].pending;
94c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->servermonitor_latency =
95f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang			monitorpage->latency[monitor_group][monitor_offset];
96c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->servermonitor_connectionid =
97f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang			monitorpage->parameter[monitor_group]
98f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang					[monitor_offset].connectionid.u.id;
993e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
10039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	monitorpage++;
1013e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
102c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->clientmonitor_pending =
103f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang			monitorpage->trigger_group[monitor_group].pending;
104c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->clientmonitor_latency =
105f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang			monitorpage->latency[monitor_group][monitor_offset];
106c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	debuginfo->clientmonitor_connectionid =
107f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang			monitorpage->parameter[monitor_group]
108f6feebe073db4c97dc10f6fab54f9d4b5816886bHaiyang Zhang					[monitor_offset].connectionid.u.id;
1093e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
110a75b61d528906fc6bf94226be2cce87e31cd18ffK. Y. Srinivasan	hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
111a75b61d528906fc6bf94226be2cce87e31cd18ffK. Y. Srinivasan	hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
1123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
1133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
1143e18951955797872558dad615851a4ca63b2770eHank Janssen/*
115fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_open - Open the specified channel.
116f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
117fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangint vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
11839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
11939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		     void (*onchannelcallback)(void *context), void *context)
1203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
1210987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan	struct vmbus_channel_open_channel *open_msg;
122176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	struct vmbus_channel_msginfo *open_info = NULL;
1233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	void *in, *out;
124dd0813b6f51b33529f37ba43334ac65e82d772e8Greg Kroah-Hartman	unsigned long flags;
1259568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan	int ret, t, err = 0;
1263e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
127c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	newchannel->onchannel_callback = onchannelcallback;
128c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	newchannel->channel_callback_context = context;
1293e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
130454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Allocate the ring buffer */
131df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan	out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
132df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan		get_order(send_ringbuffer_size + recv_ringbuffer_size));
133df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan
1347e052d98f2bbcaaaa6d509081d78e600927cfe60Bill Pemberton	if (!out)
1357e052d98f2bbcaaaa6d509081d78e600927cfe60Bill Pemberton		return -ENOMEM;
1367e052d98f2bbcaaaa6d509081d78e600927cfe60Bill Pemberton
1373e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
13839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	in = (void *)((unsigned long)out + send_ringbuffer_size);
1393e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
140c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	newchannel->ringbuffer_pages = out;
141c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
14239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang					   recv_ringbuffer_size) >> PAGE_SHIFT;
1433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
14472a95cbcbc24a464f3a51e610bd444fde2c73bbdK. Y. Srinivasan	ret = hv_ringbuffer_init(
14572a95cbcbc24a464f3a51e610bd444fde2c73bbdK. Y. Srinivasan		&newchannel->outbound, out, send_ringbuffer_size);
14672a95cbcbc24a464f3a51e610bd444fde2c73bbdK. Y. Srinivasan
147fd4dc88e46c4d9dd845ffef50a975ceea110fd85Haiyang Zhang	if (ret != 0) {
1483324fb405340cf52fe361697a86d235587402d9cBill Pemberton		err = ret;
1493324fb405340cf52fe361697a86d235587402d9cBill Pemberton		goto errorout;
1503324fb405340cf52fe361697a86d235587402d9cBill Pemberton	}
1513324fb405340cf52fe361697a86d235587402d9cBill Pemberton
15272a95cbcbc24a464f3a51e610bd444fde2c73bbdK. Y. Srinivasan	ret = hv_ringbuffer_init(
15372a95cbcbc24a464f3a51e610bd444fde2c73bbdK. Y. Srinivasan		&newchannel->inbound, in, recv_ringbuffer_size);
154fd4dc88e46c4d9dd845ffef50a975ceea110fd85Haiyang Zhang	if (ret != 0) {
1553324fb405340cf52fe361697a86d235587402d9cBill Pemberton		err = ret;
1563324fb405340cf52fe361697a86d235587402d9cBill Pemberton		goto errorout;
1573324fb405340cf52fe361697a86d235587402d9cBill Pemberton	}
1583e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
1593e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
160454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Establish the gpadl for the ring buffer */
161c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	newchannel->ringbuffer_gpadlhandle = 0;
1623e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
163fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang	ret = vmbus_establish_gpadl(newchannel,
16482f8bd40a017716bfadcf074b4c6110ebe4c7ba6Haiyang Zhang					 newchannel->outbound.ring_buffer,
16539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang					 send_ringbuffer_size +
16639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang					 recv_ringbuffer_size,
167c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang					 &newchannel->ringbuffer_gpadlhandle);
168b94ef345b26b4d75e5028617e43fb51d7dd0162bBill Pemberton
169fd4dc88e46c4d9dd845ffef50a975ceea110fd85Haiyang Zhang	if (ret != 0) {
170b94ef345b26b4d75e5028617e43fb51d7dd0162bBill Pemberton		err = ret;
171b94ef345b26b4d75e5028617e43fb51d7dd0162bBill Pemberton		goto errorout;
172b94ef345b26b4d75e5028617e43fb51d7dd0162bBill Pemberton	}
173f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman
174454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Create and init the channel open message */
175176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	open_info = kmalloc(sizeof(*open_info) +
176f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			   sizeof(struct vmbus_channel_open_channel),
177f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			   GFP_KERNEL);
178176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	if (!open_info) {
179c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton		err = -ENOMEM;
180c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton		goto errorout;
181c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton	}
1823e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
183176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	init_completion(&open_info->waitevent);
1843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
185176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
1860987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan	open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
1870987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan	open_msg->openid = newchannel->offermsg.child_relid;
1880987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan	open_msg->child_relid = newchannel->offermsg.child_relid;
1890987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan	open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
1900987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan	open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
191f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman						  PAGE_SHIFT;
1920987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan	open_msg->server_contextarea_gpadlhandle = 0;
1933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
19439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	if (userdatalen > MAX_USER_DEFINED_BYTES) {
195c827f944f51e02894d68f036da843783e622ec2aBill Pemberton		err = -EINVAL;
196c827f944f51e02894d68f036da843783e622ec2aBill Pemberton		goto errorout;
197c827f944f51e02894d68f036da843783e622ec2aBill Pemberton	}
198c827f944f51e02894d68f036da843783e622ec2aBill Pemberton
19939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	if (userdatalen)
2000987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan		memcpy(open_msg->userdata, userdata, userdatalen);
2013e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
20215b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
203176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	list_add_tail(&open_info->msglistentry,
204da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang		      &vmbus_connection.chn_msg_list);
20515b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
2063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
2070987ff696d55ad4454211d0b72615fb52b05aa77K. Y. Srinivasan	ret = vmbus_post_msg(open_msg,
208f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			       sizeof(struct vmbus_channel_open_channel));
20998e087022b611c6f748c74d952193ccf69280f52Hank Janssen
21098e087022b611c6f748c74d952193ccf69280f52Hank Janssen	if (ret != 0)
21100d760b057e0fb1e5fb515071af2cc87d15439f8K. Y. Srinivasan		goto cleanup;
2123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
213176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
2149568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan	if (t == 0) {
2150c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		err = -ETIMEDOUT;
2160c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto errorout;
2170c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan	}
2180c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan
2193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
220176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	if (open_info->response.open_result.status)
221176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan		err = open_info->response.open_result.status;
2223e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
22300d760b057e0fb1e5fb515071af2cc87d15439f8K. Y. Srinivasancleanup:
22415b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
225176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	list_del(&open_info->msglistentry);
22615b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
2273e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
228176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	kfree(open_info);
22998e087022b611c6f748c74d952193ccf69280f52Hank Janssen	return err;
230c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton
231c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pembertonerrorout:
2322dba688ba4238066400d5b6b35d5b4ce9484b4b1K. Y. Srinivasan	hv_ringbuffer_cleanup(&newchannel->outbound);
2332dba688ba4238066400d5b6b35d5b4ce9484b4b1K. Y. Srinivasan	hv_ringbuffer_cleanup(&newchannel->inbound);
234df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan	free_pages((unsigned long)out,
235df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan		get_order(send_ringbuffer_size + recv_ringbuffer_size));
236176fb9e3f1c145c502dfcd88b2800039aa5e2a24K. Y. Srinivasan	kfree(open_info);
237c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton	return err;
2383e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
23936ceadfc65a78822dfb8e87fc9daab6be3ac3994Greg Kroah-HartmanEXPORT_SYMBOL_GPL(vmbus_open);
2403e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
2413e18951955797872558dad615851a4ca63b2770eHank Janssen/*
242fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * create_gpadl_header - Creates a gpadl for the specified buffer
243f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
244fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangstatic int create_gpadl_header(void *kbuffer, u32 size,
24539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang					 struct vmbus_channel_msginfo **msginfo,
24639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang					 u32 *messagecount)
2473e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
2483e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	int i;
24939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	int pagecount;
250f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	unsigned long long pfn;
25139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_gpadl_header *gpadl_header;
25239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_gpadl_body *gpadl_body;
25339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_msginfo *msgheader;
25439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_msginfo *msgbody = NULL;
25539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 msgsize;
2563e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
25739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
2583e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
25939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	pagecount = size >> PAGE_SHIFT;
26039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
2613e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
262454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* do we need a gpadl body msg */
26339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
264f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman		  sizeof(struct vmbus_channel_gpadl_header) -
265f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman		  sizeof(struct gpa_range);
26639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	pfncount = pfnsize / sizeof(u64);
2673e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
26839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	if (pagecount > pfncount) {
269f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman		/* we need a gpadl body */
270454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* fill in the header */
27139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		msgsize = sizeof(struct vmbus_channel_msginfo) +
272f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			  sizeof(struct vmbus_channel_gpadl_header) +
27339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
27439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		msgheader =  kzalloc(msgsize, GFP_KERNEL);
27539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		if (!msgheader)
276d1c250bb5df9afb5af3f290d1006dfe601a51e2eBill Pemberton			goto nomem;
2773e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
278c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang		INIT_LIST_HEAD(&msgheader->submsglist);
279c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang		msgheader->msgsize = msgsize;
2803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
28139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		gpadl_header = (struct vmbus_channel_gpadl_header *)
282c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang			msgheader->msg;
283c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang		gpadl_header->rangecount = 1;
284c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang		gpadl_header->range_buflen = sizeof(struct gpa_range) +
28539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang					 pagecount * sizeof(u64);
286415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang		gpadl_header->range[0].byte_offset = 0;
287415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang		gpadl_header->range[0].byte_count = size;
28839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		for (i = 0; i < pfncount; i++)
289415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			gpadl_header->range[0].pfn_array[i] = pfn+i;
29039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		*msginfo = msgheader;
29139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		*messagecount = 1;
2923e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
29339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		pfnsum = pfncount;
29439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		pfnleft = pagecount - pfncount;
2953e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
296454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* how many pfns can we fit */
29739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
298f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			  sizeof(struct vmbus_channel_gpadl_body);
29939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		pfncount = pfnsize / sizeof(u64);
3003e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
301454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* fill in the body */
30239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		while (pfnleft) {
30339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			if (pfnleft > pfncount)
30439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang				pfncurr = pfncount;
3053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen			else
30639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang				pfncurr = pfnleft;
3073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
30839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			msgsize = sizeof(struct vmbus_channel_msginfo) +
309f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman				  sizeof(struct vmbus_channel_gpadl_body) +
31039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang				  pfncurr * sizeof(u64);
31139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			msgbody = kzalloc(msgsize, GFP_KERNEL);
312f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan
313f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan			if (!msgbody) {
314f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan				struct vmbus_channel_msginfo *pos = NULL;
315f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan				struct vmbus_channel_msginfo *tmp = NULL;
316f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan				/*
317f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan				 * Free up all the allocated messages.
318f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan				 */
319f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan				list_for_each_entry_safe(pos, tmp,
320f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan					&msgheader->submsglist,
321f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan					msglistentry) {
322f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan
323f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan					list_del(&pos->msglistentry);
324f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan					kfree(pos);
325f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan				}
326f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan
327d1c250bb5df9afb5af3f290d1006dfe601a51e2eBill Pemberton				goto nomem;
328f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan			}
329f38cf9ccd61d2acd5bc9121fabf2f6e77d74b885K. Y. Srinivasan
330c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang			msgbody->msgsize = msgsize;
33139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			(*messagecount)++;
33239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			gpadl_body =
333c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang				(struct vmbus_channel_gpadl_body *)msgbody->msg;
334f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman
335f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			/*
336f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			 * Gpadl is u32 and we are using a pointer which could
337f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			 * be 64-bit
338f27df643d045c146f3233b67ad7d161d1aa1e730K. Y. Srinivasan			 * This is governed by the guest/host protocol and
339f27df643d045c146f3233b67ad7d161d1aa1e730K. Y. Srinivasan			 * so the hypervisor gurantees that this is ok.
340f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			 */
34139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			for (i = 0; i < pfncurr; i++)
342c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang				gpadl_body->pfn[i] = pfn + pfnsum + i;
3433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
344454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton			/* add to msg header */
345c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang			list_add_tail(&msgbody->msglistentry,
346c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang				      &msgheader->submsglist);
34739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			pfnsum += pfncurr;
34839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			pfnleft -= pfncurr;
3493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen		}
350f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	} else {
351454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* everything fits in a header */
35239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		msgsize = sizeof(struct vmbus_channel_msginfo) +
353f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			  sizeof(struct vmbus_channel_gpadl_header) +
35439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			  sizeof(struct gpa_range) + pagecount * sizeof(u64);
35539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		msgheader = kzalloc(msgsize, GFP_KERNEL);
35639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		if (msgheader == NULL)
357e3eb7cdd111eec56d201c4a2b20b743c746b6d99Kulikov Vasiliy			goto nomem;
358c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang		msgheader->msgsize = msgsize;
35939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang
36039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		gpadl_header = (struct vmbus_channel_gpadl_header *)
361c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang			msgheader->msg;
362c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang		gpadl_header->rangecount = 1;
363c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang		gpadl_header->range_buflen = sizeof(struct gpa_range) +
36439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang					 pagecount * sizeof(u64);
365415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang		gpadl_header->range[0].byte_offset = 0;
366415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang		gpadl_header->range[0].byte_count = size;
36739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		for (i = 0; i < pagecount; i++)
368415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			gpadl_header->range[0].pfn_array[i] = pfn+i;
36939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang
37039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		*msginfo = msgheader;
37139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		*messagecount = 1;
3723e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	}
3733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
3743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	return 0;
375d1c250bb5df9afb5af3f290d1006dfe601a51e2eBill Pembertonnomem:
37639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	kfree(msgheader);
37739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	kfree(msgbody);
378d1c250bb5df9afb5af3f290d1006dfe601a51e2eBill Pemberton	return -ENOMEM;
3793e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
3803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
3813e18951955797872558dad615851a4ca63b2770eHank Janssen/*
382fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
383f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman *
38439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @channel: a channel
38539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @kbuffer: from kmalloc
38639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @size: page-size multiple
38739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @gpadl_handle: some funky thing
388f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
389fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangint vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
39039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			       u32 size, u32 *gpadl_handle)
3913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
39239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_gpadl_header *gpadlmsg;
39339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_gpadl_body *gpadl_body;
39439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_msginfo *msginfo = NULL;
39539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct vmbus_channel_msginfo *submsginfo;
39639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 msgcount;
39753af545b277508d6b4829e90546cbd1beef536a9Bill Pemberton	struct list_head *curr;
39839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 next_gpadl_handle;
399dd0813b6f51b33529f37ba43334ac65e82d772e8Greg Kroah-Hartman	unsigned long flags;
400c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton	int ret = 0;
4019568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan	int t;
4023e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
403da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
404da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang	atomic_inc(&vmbus_connection.next_gpadl_handle);
4053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
406fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
407c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton	if (ret)
408c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton		return ret;
4093e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
4109568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan	init_completion(&msginfo->waitevent);
411c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton
412c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
413c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
414c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	gpadlmsg->child_relid = channel->offermsg.child_relid;
415c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	gpadlmsg->gpadl = next_gpadl_handle;
4163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
4173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
41815b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
419c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	list_add_tail(&msginfo->msglistentry,
420da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang		      &vmbus_connection.chn_msg_list);
4213e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
42215b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
4233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
424c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
42539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			       sizeof(*msginfo));
42698e087022b611c6f748c74d952193ccf69280f52Hank Janssen	if (ret != 0)
42700d760b057e0fb1e5fb515071af2cc87d15439f8K. Y. Srinivasan		goto cleanup;
4283e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
42939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	if (msgcount > 1) {
430c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang		list_for_each(curr, &msginfo->submsglist) {
43153af545b277508d6b4829e90546cbd1beef536a9Bill Pemberton
43239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			submsginfo = (struct vmbus_channel_msginfo *)curr;
43339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			gpadl_body =
434c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang			     (struct vmbus_channel_gpadl_body *)submsginfo->msg;
4353e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
436c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang			gpadl_body->header.msgtype =
437c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang				CHANNELMSG_GPADL_BODY;
438c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang			gpadl_body->gpadl = next_gpadl_handle;
4393e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
440c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang			ret = vmbus_post_msg(gpadl_body,
441c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang					       submsginfo->msgsize -
44239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang					       sizeof(*submsginfo));
443fd4dc88e46c4d9dd845ffef50a975ceea110fd85Haiyang Zhang			if (ret != 0)
44400d760b057e0fb1e5fb515071af2cc87d15439f8K. Y. Srinivasan				goto cleanup;
44599259159c0eb58a539ed399677c8294e3792722bBill Pemberton
4463e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen		}
4473e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	}
44840961de3350b99cfa93cd80437cb39ec287f839aK. Y. Srinivasan	t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
4499568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan	BUG_ON(t == 0);
4500c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan
4513e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
452454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* At this point, we received the gpadl created msg */
453c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	*gpadl_handle = gpadlmsg->gpadl;
4543e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
45500d760b057e0fb1e5fb515071af2cc87d15439f8K. Y. Srinivasancleanup:
45615b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
457c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	list_del(&msginfo->msglistentry);
45815b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
4593e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
46039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	kfree(msginfo);
4613e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	return ret;
4623e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
46398873724aa3957f27f35a82f20c85262fae42f0dGreg Kroah-HartmanEXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
4643e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
4653e18951955797872558dad615851a4ca63b2770eHank Janssen/*
466fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_teardown_gpadl -Teardown the specified GPADL handle
467f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
468fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangint vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
4693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
47082250213d08689ab34589923be3064bb8f4c1964Greg Kroah-Hartman	struct vmbus_channel_gpadl_teardown *msg;
471aded7165f262e0f018b23a6cd5cba6e33fd6efd1Greg Kroah-Hartman	struct vmbus_channel_msginfo *info;
472dd0813b6f51b33529f37ba43334ac65e82d772e8Greg Kroah-Hartman	unsigned long flags;
4739568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan	int ret, t;
4743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
475f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	info = kmalloc(sizeof(*info) +
476f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
477c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton	if (!info)
478c3bf2e26b30f4ea54f3825e8ebda7cb10ec204deBill Pemberton		return -ENOMEM;
4793e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
4809568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan	init_completion(&info->waitevent);
4813e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
482c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
4833e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
484c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
485c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	msg->child_relid = channel->offermsg.child_relid;
486c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	msg->gpadl = gpadl_handle;
4873e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
48815b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
489c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	list_add_tail(&info->msglistentry,
490da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang		      &vmbus_connection.chn_msg_list);
49115b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
492c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang	ret = vmbus_post_msg(msg,
493f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			       sizeof(struct vmbus_channel_gpadl_teardown));
4943e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
4950c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan	BUG_ON(ret != 0);
49640961de3350b99cfa93cd80437cb39ec287f839aK. Y. Srinivasan	t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
4979568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan	BUG_ON(t == 0);
4983e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
499454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Received a torndown response */
50015b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
501c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	list_del(&info->msglistentry);
50215b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
5033e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
5048c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman	kfree(info);
5053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	return ret;
5063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
50718726d7a60fdced593b94ff7cc5264ba753ef656Greg Kroah-HartmanEXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
5083e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
5093e18951955797872558dad615851a4ca63b2770eHank Janssen/*
510fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_close - Close the specified channel
511f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
512fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangvoid vmbus_close(struct vmbus_channel *channel)
5133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
51482250213d08689ab34589923be3064bb8f4c1964Greg Kroah-Hartman	struct vmbus_channel_close_channel *msg;
515f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	int ret;
516dad76bf73fc20b42d020fe5a93dbe4b4868e7681K. Y. Srinivasan	unsigned long flags;
5173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
518454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Stop callback and cancel the timer asap */
519dad76bf73fc20b42d020fe5a93dbe4b4868e7681K. Y. Srinivasan	spin_lock_irqsave(&channel->inbound_lock, flags);
520c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	channel->onchannel_callback = NULL;
521dad76bf73fc20b42d020fe5a93dbe4b4868e7681K. Y. Srinivasan	spin_unlock_irqrestore(&channel->inbound_lock, flags);
5223e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
523454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Send a closing message */
5243e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
525e9a27a9f9ef18826030f6d50efde0dc68b7d1be2K. Y. Srinivasan	msg = &channel->close_msg.msg;
5263e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
527c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
528c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	msg->child_relid = channel->offermsg.child_relid;
5293e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
530c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
5313e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
5320c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan	BUG_ON(ret != 0);
533454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Tear down the gpadl for the channel's ring buffer */
534c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang	if (channel->ringbuffer_gpadlhandle)
535fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang		vmbus_teardown_gpadl(channel,
536c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang					  channel->ringbuffer_gpadlhandle);
5373e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
538454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Cleanup the ring buffers for this channel */
5392dba688ba4238066400d5b6b35d5b4ce9484b4b1K. Y. Srinivasan	hv_ringbuffer_cleanup(&channel->outbound);
5402dba688ba4238066400d5b6b35d5b4ce9484b4b1K. Y. Srinivasan	hv_ringbuffer_cleanup(&channel->inbound);
5413e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
542df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan	free_pages((unsigned long)channel->ringbuffer_pages,
543df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
5443e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
5453e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
5463e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
54770bfa307861c8790ce72ae92c4e173c898cc8ff3Greg Kroah-HartmanEXPORT_SYMBOL_GPL(vmbus_close);
5483e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
549c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen/**
550fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_sendpacket() - Send the specified buffer on the given channel
55139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @channel: Pointer to vmbus_channel structure.
55239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @buffer: Pointer to the buffer you want to receive the data into.
55339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @bufferlen: Maximum size of what the the buffer will hold
55439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @requestid: Identifier of the request
55539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @type: Type of packet that is being send e.g. negotiate, time
556c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen * packet etc.
557c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen *
55839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * Sends data in @buffer directly to hyper-v via the vmbus
559c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen * This will send the data unparsed to hyper-v.
560c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen *
561c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen * Mainly used by Hyper-V drivers.
562f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
563fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangint vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
56439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			   u32 bufferlen, u64 requestid,
56539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			   enum vmbus_packet_type type, u32 flags)
5663e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
5678dc0a06ad1f192ea0c8dbe4d2090206c7d880281Greg Kroah-Hartman	struct vmpacket_descriptor desc;
56839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
5697350968193f9b94c4a4b7d14d7a44333a322c5d7Uwe Kleine-König	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
57039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct scatterlist bufferlist[3];
57139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u64 aligned_data = 0;
572f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	int ret;
5733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
5743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
575454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Setup the descriptor */
576415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	desc.type = type; /* VmbusPacketTypeDataInBand; */
577415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
578f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	/* in 8-bytes granularity */
579415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
580415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	desc.len8 = (u16)(packetlen_aligned >> 3);
581415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	desc.trans_id = requestid;
5823e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
58339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_init_table(bufferlist, 3);
58439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
58539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[1], buffer, bufferlen);
58639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[2], &aligned_data,
58739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		   packetlen_aligned - packetlen);
5883e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
589633c4dce4e822be6155a78cec488e8bde521e908K. Y. Srinivasan	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
5903e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
591decc49dacba39354ee705ea8bec12d9ae1f63774K. Y. Srinivasan	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
592fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang		vmbus_setevent(channel);
5933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
5943e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	return ret;
5953e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
596fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang ZhangEXPORT_SYMBOL(vmbus_sendpacket);
5973e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
5983e18951955797872558dad615851a4ca63b2770eHank Janssen/*
599fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
6003e18951955797872558dad615851a4ca63b2770eHank Janssen * packets using a GPADL Direct packet type.
601f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
602fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangint vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
60339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang				     struct hv_page_buffer pagebuffers[],
60439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang				     u32 pagecount, void *buffer, u32 bufferlen,
60539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang				     u64 requestid)
6063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
607f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	int ret;
608f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	int i;
609430a8e9a3325e303f092a371b9d2e45a715b26d7Haiyang Zhang	struct vmbus_channel_packet_page_buffer desc;
61039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 descsize;
61139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 packetlen;
61239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 packetlen_aligned;
61339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct scatterlist bufferlist[3];
61439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u64 aligned_data = 0;
6153e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
61639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	if (pagecount > MAX_PAGE_BUFFER_COUNT)
617002b53ea5713910daf215037b72c5820413e2f95Bill Pemberton		return -EINVAL;
6183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
6193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
620f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	/*
621430a8e9a3325e303f092a371b9d2e45a715b26d7Haiyang Zhang	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
622f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	 * largest size we support
623f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	 */
62439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
62539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
626f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			  sizeof(struct hv_page_buffer));
62739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	packetlen = descsize + bufferlen;
6287350968193f9b94c4a4b7d14d7a44333a322c5d7Uwe Kleine-König	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
6293e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
630454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Setup the descriptor */
631415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
632430a8e9a3325e303f092a371b9d2e45a715b26d7Haiyang Zhang	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
63339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
63439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	desc.length8 = (u16)(packetlen_aligned >> 3);
63539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	desc.transactionid = requestid;
63639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	desc.rangecount = pagecount;
63739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang
63839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	for (i = 0; i < pagecount; i++) {
639ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang		desc.range[i].len = pagebuffers[i].len;
640ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang		desc.range[i].offset = pagebuffers[i].offset;
641ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang		desc.range[i].pfn	 = pagebuffers[i].pfn;
6423e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	}
6433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
64439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_init_table(bufferlist, 3);
64539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[0], &desc, descsize);
64639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[1], buffer, bufferlen);
64739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[2], &aligned_data,
64839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		packetlen_aligned - packetlen);
6493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
650633c4dce4e822be6155a78cec488e8bde521e908K. Y. Srinivasan	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
6513e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
652decc49dacba39354ee705ea8bec12d9ae1f63774K. Y. Srinivasan	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
653fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang		vmbus_setevent(channel);
6543e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
6553e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	return ret;
6563e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
657713efeb4dbc07f76f06581eba18ff29f704fc250Greg Kroah-HartmanEXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
6583e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
6593e18951955797872558dad615851a4ca63b2770eHank Janssen/*
660fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
6613e18951955797872558dad615851a4ca63b2770eHank Janssen * using a GPADL Direct packet type.
662f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
663fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangint vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
66439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang				struct hv_multipage_buffer *multi_pagebuffer,
66539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang				void *buffer, u32 bufferlen, u64 requestid)
6663e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
667f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	int ret;
668430a8e9a3325e303f092a371b9d2e45a715b26d7Haiyang Zhang	struct vmbus_channel_packet_multipage_buffer desc;
66939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 descsize;
67039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 packetlen;
67139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 packetlen_aligned;
67239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	struct scatterlist bufferlist[3];
67339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u64 aligned_data = 0;
674ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
675ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang					 multi_pagebuffer->len);
6763e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
6773e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
67839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
679002b53ea5713910daf215037b72c5820413e2f95Bill Pemberton		return -EINVAL;
6803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
681f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	/*
682430a8e9a3325e303f092a371b9d2e45a715b26d7Haiyang Zhang	 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
683f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	 * the largest size we support
684f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman	 */
68539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
68639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
687f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			  sizeof(u64));
68839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	packetlen = descsize + bufferlen;
6897350968193f9b94c4a4b7d14d7a44333a322c5d7Uwe Kleine-König	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
6903e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
6913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
692454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Setup the descriptor */
693415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
694430a8e9a3325e303f092a371b9d2e45a715b26d7Haiyang Zhang	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
69539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
69639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	desc.length8 = (u16)(packetlen_aligned >> 3);
69739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	desc.transactionid = requestid;
698430a8e9a3325e303f092a371b9d2e45a715b26d7Haiyang Zhang	desc.rangecount = 1;
6993e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
700ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang	desc.range.len = multi_pagebuffer->len;
701ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang	desc.range.offset = multi_pagebuffer->offset;
7023e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
703ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
70439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	       pfncount * sizeof(u64));
7053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
70639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_init_table(bufferlist, 3);
70739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[0], &desc, descsize);
70839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[1], buffer, bufferlen);
70939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	sg_set_buf(&bufferlist[2], &aligned_data,
71039d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang		packetlen_aligned - packetlen);
7113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
712633c4dce4e822be6155a78cec488e8bde521e908K. Y. Srinivasan	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
7133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
714decc49dacba39354ee705ea8bec12d9ae1f63774K. Y. Srinivasan	if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
715fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang		vmbus_setevent(channel);
7163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
7173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	return ret;
7183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
7194cb106faf1e1d5566eded521d14e141b5eac36e2Greg Kroah-HartmanEXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
720c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen
721c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen/**
722fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_recvpacket() - Retrieve the user packet on the specified channel
72339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @channel: Pointer to vmbus_channel structure.
72439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @buffer: Pointer to the buffer you want to receive the data into.
72539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @bufferlen: Maximum size of what the the buffer will hold
72639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @buffer_actual_len: The actual size of the data after it was received
72739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang * @requestid: Identifier of the request
728c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen *
729c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen * Receives directly from the hyper-v vmbus and puts the data it received
730c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen * into Buffer. This will receive the data unparsed from hyper-v.
731c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen *
732c88c4e4c7a427ee65556f33e6327b604ec209ec3Hank Janssen * Mainly used by Hyper-V drivers.
733f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
734fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangint vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
73539d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
7363e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
7378dc0a06ad1f192ea0c8dbe4d2090206c7d880281Greg Kroah-Hartman	struct vmpacket_descriptor desc;
73839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 packetlen;
73939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 userlen;
7403e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	int ret;
7413e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
74239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	*buffer_actual_len = 0;
74339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	*requestid = 0;
7443e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
7453e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
746a89186c21ccea2f06014b26463a39a1eea1efdf7K. Y. Srinivasan	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
747f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			     sizeof(struct vmpacket_descriptor));
748dad76bf73fc20b42d020fe5a93dbe4b4868e7681K. Y. Srinivasan	if (ret != 0)
7493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen		return 0;
7503e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
751415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	packetlen = desc.len8 << 3;
752415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	userlen = packetlen - (desc.offset8 << 3);
7533e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
75439d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	*buffer_actual_len = userlen;
7553e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
75639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	if (userlen > bufferlen) {
7573e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
7580a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen		pr_err("Buffer too small - got %d needs %d\n",
75939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			   bufferlen, userlen);
760926ae5262171b2b23c94bc5cbd8dbb9d32152419K. Y. Srinivasan		return -ETOOSMALL;
7613e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	}
7623e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
763415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	*requestid = desc.trans_id;
7643e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
765454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Copy over the packet to the user buffer */
76638397c8abe5596d8942a453468bec935964d1c75K. Y. Srinivasan	ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
767415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			     (desc.offset8 << 3));
7683e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
7693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
7703e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	return 0;
7713e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
772fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang ZhangEXPORT_SYMBOL(vmbus_recvpacket);
7733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
7743e18951955797872558dad615851a4ca63b2770eHank Janssen/*
775fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhang * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
776f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman */
777fff41b2e30c54c35933e6e51f775fe03c73fc572Haiyang Zhangint vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
77839d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			      u32 bufferlen, u32 *buffer_actual_len,
77939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang			      u64 *requestid)
7803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{
7818dc0a06ad1f192ea0c8dbe4d2090206c7d880281Greg Kroah-Hartman	struct vmpacket_descriptor desc;
78239d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 packetlen;
78339d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	u32 userlen;
7843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	int ret;
7853e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
78639d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	*buffer_actual_len = 0;
78739d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	*requestid = 0;
7883e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
7893e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
790a89186c21ccea2f06014b26463a39a1eea1efdf7K. Y. Srinivasan	ret = hv_ringbuffer_peek(&channel->inbound, &desc,
791f4266e342527b4309119edde777bb9fbb4e0ef33Greg Kroah-Hartman			     sizeof(struct vmpacket_descriptor));
792dad76bf73fc20b42d020fe5a93dbe4b4868e7681K. Y. Srinivasan	if (ret != 0)
7933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen		return 0;
7943e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
7953e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
796415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	packetlen = desc.len8 << 3;
797415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	userlen = packetlen - (desc.offset8 << 3);
7983e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
79939d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	*buffer_actual_len = packetlen;
8003e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
80139d70a4ab178e0a44e9f31c9dd5b9555347018ecHaiyang Zhang	if (packetlen > bufferlen) {
8020a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen		pr_err("Buffer too small - needed %d bytes but "
8030a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen			"got space for only %d bytes\n",
8040a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen			packetlen, bufferlen);
8053d5cad97c4be2bfc5cb4e52a0972c6e3bf8c278dK. Y. Srinivasan		return -ENOBUFS;
8063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	}
8073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
808415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	*requestid = desc.trans_id;
8093e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
810454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Copy over the entire packet to the user buffer */
81138397c8abe5596d8942a453468bec935964d1c75K. Y. Srinivasan	ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
8123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen
8133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen	return 0;
8143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}
815adaee6bd45f6e172cde0a98461e4e1ba19284373Greg Kroah-HartmanEXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
816