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