linux/drivers/hv/channel.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2009, Microsoft Corporation.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms and conditions of the GNU General Public License,
   6 * version 2, as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License along with
  14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  15 * Place - Suite 330, Boston, MA 02111-1307 USA.
  16 *
  17 * Authors:
  18 *   Haiyang Zhang <haiyangz@microsoft.com>
  19 *   Hank Janssen  <hjanssen@microsoft.com>
  20 */
  21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  22
  23#include <linux/kernel.h>
  24#include <linux/sched.h>
  25#include <linux/wait.h>
  26#include <linux/mm.h>
  27#include <linux/slab.h>
  28#include <linux/module.h>
  29#include <linux/hyperv.h>
  30
  31#include "hyperv_vmbus.h"
  32
  33#define NUM_PAGES_SPANNED(addr, len) \
  34((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
  35
  36/* Internal routines */
  37static int create_gpadl_header(
  38        void *kbuffer,  /* must be phys and virt contiguous */
  39        u32 size,       /* page-size multiple */
  40        struct vmbus_channel_msginfo **msginfo,
  41        u32 *messagecount);
  42static void vmbus_setevent(struct vmbus_channel *channel);
  43
  44/*
  45 * vmbus_setevent- Trigger an event notification on the specified
  46 * channel.
  47 */
  48static void vmbus_setevent(struct vmbus_channel *channel)
  49{
  50        struct hv_monitor_page *monitorpage;
  51
  52        if (channel->offermsg.monitor_allocated) {
  53                /* Each u32 represents 32 channels */
  54                sync_set_bit(channel->offermsg.child_relid & 31,
  55                        (unsigned long *) vmbus_connection.send_int_page +
  56                        (channel->offermsg.child_relid >> 5));
  57
  58                monitorpage = vmbus_connection.monitor_pages;
  59                monitorpage++; /* Get the child to parent monitor page */
  60
  61                sync_set_bit(channel->monitor_bit,
  62                        (unsigned long *)&monitorpage->trigger_group
  63                                        [channel->monitor_grp].pending);
  64
  65        } else {
  66                vmbus_set_event(channel->offermsg.child_relid);
  67        }
  68}
  69
  70/*
  71 * vmbus_get_debug_info -Retrieve various channel debug info
  72 */
  73void vmbus_get_debug_info(struct vmbus_channel *channel,
  74                              struct vmbus_channel_debug_info *debuginfo)
  75{
  76        struct hv_monitor_page *monitorpage;
  77        u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
  78        u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
  79
  80        debuginfo->relid = channel->offermsg.child_relid;
  81        debuginfo->state = channel->state;
  82        memcpy(&debuginfo->interfacetype,
  83               &channel->offermsg.offer.if_type, sizeof(uuid_le));
  84        memcpy(&debuginfo->interface_instance,
  85               &channel->offermsg.offer.if_instance,
  86               sizeof(uuid_le));
  87
  88        monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
  89
  90        debuginfo->monitorid = channel->offermsg.monitorid;
  91
  92        debuginfo->servermonitor_pending =
  93                        monitorpage->trigger_group[monitor_group].pending;
  94        debuginfo->servermonitor_latency =
  95                        monitorpage->latency[monitor_group][monitor_offset];
  96        debuginfo->servermonitor_connectionid =
  97                        monitorpage->parameter[monitor_group]
  98                                        [monitor_offset].connectionid.u.id;
  99
 100        monitorpage++;
 101
 102        debuginfo->clientmonitor_pending =
 103                        monitorpage->trigger_group[monitor_group].pending;
 104        debuginfo->clientmonitor_latency =
 105                        monitorpage->latency[monitor_group][monitor_offset];
 106        debuginfo->clientmonitor_connectionid =
 107                        monitorpage->parameter[monitor_group]
 108                                        [monitor_offset].connectionid.u.id;
 109
 110        hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
 111        hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
 112}
 113
 114/*
 115 * vmbus_open - Open the specified channel.
 116 */
 117int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 118                     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
 119                     void (*onchannelcallback)(void *context), void *context)
 120{
 121        struct vmbus_channel_open_channel *open_msg;
 122        struct vmbus_channel_msginfo *open_info = NULL;
 123        void *in, *out;
 124        unsigned long flags;
 125        int ret, t, err = 0;
 126
 127        newchannel->onchannel_callback = onchannelcallback;
 128        newchannel->channel_callback_context = context;
 129
 130        /* Allocate the ring buffer */
 131        out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
 132                get_order(send_ringbuffer_size + recv_ringbuffer_size));
 133
 134        if (!out)
 135                return -ENOMEM;
 136
 137
 138        in = (void *)((unsigned long)out + send_ringbuffer_size);
 139
 140        newchannel->ringbuffer_pages = out;
 141        newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
 142                                           recv_ringbuffer_size) >> PAGE_SHIFT;
 143
 144        ret = hv_ringbuffer_init(
 145                &newchannel->outbound, out, send_ringbuffer_size);
 146
 147        if (ret != 0) {
 148                err = ret;
 149                goto error0;
 150        }
 151
 152        ret = hv_ringbuffer_init(
 153                &newchannel->inbound, in, recv_ringbuffer_size);
 154        if (ret != 0) {
 155                err = ret;
 156                goto error0;
 157        }
 158
 159
 160        /* Establish the gpadl for the ring buffer */
 161        newchannel->ringbuffer_gpadlhandle = 0;
 162
 163        ret = vmbus_establish_gpadl(newchannel,
 164                                         newchannel->outbound.ring_buffer,
 165                                         send_ringbuffer_size +
 166                                         recv_ringbuffer_size,
 167                                         &newchannel->ringbuffer_gpadlhandle);
 168
 169        if (ret != 0) {
 170                err = ret;
 171                goto error0;
 172        }
 173
 174        /* Create and init the channel open message */
 175        open_info = kmalloc(sizeof(*open_info) +
 176                           sizeof(struct vmbus_channel_open_channel),
 177                           GFP_KERNEL);
 178        if (!open_info) {
 179                err = -ENOMEM;
 180                goto error0;
 181        }
 182
 183        init_completion(&open_info->waitevent);
 184
 185        open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
 186        open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
 187        open_msg->openid = newchannel->offermsg.child_relid;
 188        open_msg->child_relid = newchannel->offermsg.child_relid;
 189        open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
 190        open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
 191                                                  PAGE_SHIFT;
 192        open_msg->server_contextarea_gpadlhandle = 0;
 193
 194        if (userdatalen > MAX_USER_DEFINED_BYTES) {
 195                err = -EINVAL;
 196                goto error0;
 197        }
 198
 199        if (userdatalen)
 200                memcpy(open_msg->userdata, userdata, userdatalen);
 201
 202        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 203        list_add_tail(&open_info->msglistentry,
 204                      &vmbus_connection.chn_msg_list);
 205        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 206
 207        ret = vmbus_post_msg(open_msg,
 208                               sizeof(struct vmbus_channel_open_channel));
 209
 210        if (ret != 0)
 211                goto error1;
 212
 213        t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
 214        if (t == 0) {
 215                err = -ETIMEDOUT;
 216                goto error1;
 217        }
 218
 219
 220        if (open_info->response.open_result.status)
 221                err = open_info->response.open_result.status;
 222
 223        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 224        list_del(&open_info->msglistentry);
 225        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 226
 227        kfree(open_info);
 228        return err;
 229
 230error1:
 231        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 232        list_del(&open_info->msglistentry);
 233        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 234
 235error0:
 236        free_pages((unsigned long)out,
 237                get_order(send_ringbuffer_size + recv_ringbuffer_size));
 238        kfree(open_info);
 239        return err;
 240}
 241EXPORT_SYMBOL_GPL(vmbus_open);
 242
 243/*
 244 * create_gpadl_header - Creates a gpadl for the specified buffer
 245 */
 246static int create_gpadl_header(void *kbuffer, u32 size,
 247                                         struct vmbus_channel_msginfo **msginfo,
 248                                         u32 *messagecount)
 249{
 250        int i;
 251        int pagecount;
 252        unsigned long long pfn;
 253        struct vmbus_channel_gpadl_header *gpadl_header;
 254        struct vmbus_channel_gpadl_body *gpadl_body;
 255        struct vmbus_channel_msginfo *msgheader;
 256        struct vmbus_channel_msginfo *msgbody = NULL;
 257        u32 msgsize;
 258
 259        int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
 260
 261        pagecount = size >> PAGE_SHIFT;
 262        pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
 263
 264        /* do we need a gpadl body msg */
 265        pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
 266                  sizeof(struct vmbus_channel_gpadl_header) -
 267                  sizeof(struct gpa_range);
 268        pfncount = pfnsize / sizeof(u64);
 269
.        if (pagecount > pfncount) {
 271                /* we need a gpadl body */
 272                /* fill in the header */
 273                msgsize = sizeof(struct vmbus_channel_msginfo) +
 274                          sizeof(struct vmbus_channel_gpadl_header) +
 275                          sizeof(struct gpa_range) + pfncount * sizeof(u64);
 276                msgheader =  kzalloc(msgsize, GFP_KERNEL);
 277                if (!msgheader)
 278                        goto nomem;
 279
 280                INIT_LIST_HEAD(&msgheader->submsglist);
 281                msgheader->msgsize = msgsize;
 282
 283                gpadl_header = (struct vmbus_channel_gpadl_header *)
 284                        msgheader->msg;
 285                gpadl_header->rangecount = 1;
 286                gpadl_header->range_buflen = sizeof(struct gpa_range) +
 287                                         pagecount * sizeof(u64);
 288                gpadl_header->range[0].byte_offset = 0;
 289                gpadl_header->range[0].byte_count = size;
 290                for (i = 0; i < pfncount; i++)
 291                        gpadl_header->range[0].pfn_array[i] = pfn+i;
 292                *msginfo = msgheader;
 293                *messagecount = 1;
 294
 295                pfnsum = pfncount;
 296                pfnleft = pagecount - pfncount;
 297
 298                /* how many pfns can we fit */
 299                pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
 300                          sizeof(struct vmbus_channel_gpadl_body);
 301                pfncount = pfnsize / sizeof(u64);
 302
 303                /* fill in the body */
 304                while (pfnleft) {
 305                        if (pfnleft > pfncount)
 306                                pfncurr = pfncount;
 307                        else
 308                                pfncurr = pfnleft;
 309
 310                        msgsize = sizeof(struct vmbus_channel_msginfo) +
 311                                  sizeof(struct vmbus_channel_gpadl_body) +
 312                                  pfncurr * sizeof(u64);
 313                        msgbody = kzalloc(msgsize, GFP_KERNEL);
 314
 315                        if (!msgbody) {
 316                                struct vmbus_channel_msginfo *pos = NULL;
 317                                struct vmbus_channel_msginfo *tmp = NULL;
 318                                /*
 319                                 * Free up all the allocated messages.
 320                                 */
 321                                list_for_each_entry_safe(pos, tmp,
 322                                        &msgheader->submsglist,
 323                                        msglistentry) {
 324
 325                                        list_del(&pos->msglistentry);
 326                                        kfree(pos);
 327                                }
 328
 329                                goto nomem;
 330                        }
 331
 332                        msgbody->msgsize = msgsize;
 333                        (*messagecount)++;
 334                        gpadl_body =
 335                                (struct vmbus_channel_gpadl_body *)msgbody->msg;
 336
 337                        /*
 338                         * Gpadl is u32 and we are using a pointer which could
 339                         * be 64-bit
 340                         * This is governed by the guest/host protocol and
 341                         * so the hypervisor gurantees that this is ok.
 342                         */
 343                        for (i = 0; i < pfncurr; i++)
 344                                gpadl_body->pfn[i] = pfn + pfnsum + i;
 345
 346                        /* add to msg header */
 347                        list_add_tail(&msgbody->msglistentry,
 348                                      &msgheader->submsglist);
 349                        pfnsum += pfncurr;
 350                        pfnleft -= pfncurr;
 351                }
 352        } else {
 353                /* everything fits in a header */
 354                msgsize = sizeof(struct vmbus_channel_msginfo) +
 355                          sizeof(struct vmbus_channel_gpadl_header) +
 356                          sizeof(struct gpa_range) + pagecount * sizeof(u64);
 357                msgheader = kzalloc(msgsize, GFP_KERNEL);
 358                if (msgheader == NULL)
 359                        goto nomem;
 360                msgheader->msgsize = msgsize;
 361
 362                gpadl_header = (struct vmbus_channel_gpadl_header *)
 363                        msgheader->msg;
 364                gpadl_header->rangecount = 1;
 365                gpadl_header->range_buflen = sizeof(struct gpa_range) +
 366                                         pagecount * sizeof(u64);
 367                gpadl_header->range[0].byte_offset = 0;
 368                gpadl_header->range[0].byte_count = size;
 369                for (i = 0; i < pagecount; i++)
.                        gpadl_header->range[0].pfn_array[i] = pfn+i;
 371
 372                *msginfo = msgheader;
 373                *messagecount = 1;
 374        }
 375
 376        return 0;
 377nomem:
 378        kfree(msgheader);
 379        kfree(msgbody);
 380        return -ENOMEM;
 381}
 382
 383/*
 384 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
 385 *
 386 * @channel: a channel
 387 * @kbuffer: from kmalloc
 388 * @size: page-size multiple
 389 * @gpadl_handle: some funky thing
 390 */
 391int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 392                               u32 size, u32 *gpadl_handle)
 393{
 394        struct vmbus_channel_gpadl_header *gpadlmsg;
 395        struct vmbus_channel_gpadl_body *gpadl_body;
 396        struct vmbus_channel_msginfo *msginfo = NULL;
 397        struct vmbus_channel_msginfo *submsginfo;
 398        u32 msgcount;
 399        struct list_head *curr;
 400        u32 next_gpadl_handle;
 401        unsigned long flags;
 402        int ret = 0;
 403        int t;
 404
 405        next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
 406        atomic_inc(&vmbus_connection.next_gpadl_handle);
 407
 408        ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
 409        if (ret)
 410                return ret;
 411
 412        init_completion(&msginfo->waitevent);
 413
 414        gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
 415        gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
 416        gpadlmsg->child_relid = channel->offermsg.child_relid;
 417        gpadlmsg->gpadl = next_gpadl_handle;
 418
 419
 420        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 421        list_add_tail(&msginfo->msglistentry,
 422                      &vmbus_connection.chn_msg_list);
 423
 424        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 425
 426        ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
 427                               sizeof(*msginfo));
 428        if (ret != 0)
 429                goto cleanup;
 430
 431        if (msgcount > 1) {
 432                list_for_each(curr, &msginfo->submsglist) {
 433
 434                        submsginfo = (struct vmbus_channel_msginfo *)curr;
 435                        gpadl_body =
 436                             (struct vmbus_channel_gpadl_body *)submsginfo->msg;
 437
 438                        gpadl_body->header.msgtype =
 439                                CHANNELMSG_GPADL_BODY;
 440                        gpadl_body->gpadl = next_gpadl_handle;
 441
 442                        ret = vmbus_post_msg(gpadl_body,
 443                                               submsginfo->msgsize -
 444                                               sizeof(*submsginfo));
 445                        if (ret != 0)
 446                                goto cleanup;
 447
 448                }
 449        }
 450        t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
 451        BUG_ON(t == 0);
 452
 453
 454        /* At this point, we received the gpadl created msg */
 455        *gpadl_handle = gpadlmsg->gpadl;
 456
 457cleanup:
 458        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 459        list_del(&msginfo->msglistentry);
 460        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 461
 462        kfree(msginfo);
 463        return ret;
 464}
 465EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
 466
 467/*
 468 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
 469 */
.int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
 471{
 472        struct vmbus_channel_gpadl_teardown *msg;
 473        struct vmbus_channel_msginfo *info;
 474        unsigned long flags;
 475        int ret, t;
 476
 477        info = kmalloc(sizeof(*info) +
 478                       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
 479        if (!info)
 480                return -ENOMEM;
 481
 482        init_completion(&info->waitevent);
 483
 484        msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
 485
 486        msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
 487        msg->child_relid = channel->offermsg.child_relid;
 488        msg->gpadl = gpadl_handle;
 489
 490        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 491        list_add_tail(&info->msglistentry,
 492                      &vmbus_connection.chn_msg_list);
 493        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 494        ret = vmbus_post_msg(msg,
 495                               sizeof(struct vmbus_channel_gpadl_teardown));
 4rs/hv/channel.c#L396" id="L396" 7l.c#L397"4id="L397" class="line" n4me="L497"> 487        BUG_ON(ret));
 398        t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
 459        BUG_ON(t == 0);
 430
 401         */
 482        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 493        list_del(&info->msglistentgs);
 424        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 485
 406        kfree(infs);
 487        return ret;
 464}
 465EXPORT_SYMBOL_GPL(vmbus_teardown_gpafs);
 430
 467/*
 468 * closem- Closemrdown the specsref">cha">/*
 383 */
 4,(&vlose_gpadl(struct vmbus_channel *channfo)
 471{
 396        struct vmbus_chvlose=vmbus_cardown *msg;
 417        int rsg;
 398        unsigned long flags;
 419
 420         */
 421        spin_lock_irqsave(&channel->flags);
 482        channel->t = NULL;
 493        spin_unlock_irqrestore(&channel->flags);
 404
 420        mment"> */
 4rs/hv/channel.c#L396" id="L396" 5l.c#L427"5id="L427" class="line" n5me="L527"> 487        m>t(&channel->msg;
 418
 459        msg->header.msgtype = CHANNCLOSE+code=Cf">msg;
 490        msg->child_relid = channel->offermsg.child_relid;
 481
 482        ret = vmbus_post_msg(ms       sizeof(struct vmbus_chvlose=vmbus_cardown));
 433
 424        BUG_ON(ret));
 420        kment"> */
 436        if (channel->kardowngpadl_handle" class="rineref">kardowngpadl_hannfo)
 367                vmbus_teardown_gpad  if (channsg,
 438                                      if (channel->kardowngpadl_handle" class="rineref">kardowngpadl_hannf));
 419
 420        cDL forinedref">ks_GPADL isors/hv/cment"> */
 421        ka+code=cleanup" class="hv_rineref">ka+code=cestore(&channel-> 482        ka+code=cleanup" class="hv_rineref">ka+code=cestore(&channel-> 433
 424         *)channel->kasizee=flags" class="rineref">kasizeehannsg,
 445          >->channel->kasizede=msgcount" class="rineref">kasizede=msardown >-> 4rs/hv/channel.c#L396" id="L396" 5l.c#L447"5id="L447" class="line" n5me="L547"> 447
 464}
 465EXPORT_SYMBOL_GPL(vlose_gpan));
 430
 467/*
 468 * sendpacket() -nSenecL for the specified  oeardowref=ncsref">cha">/*
 383 * @chaPthisd  to sref">vmbus_c       ure.ha">/*
 384/*
 385/*
 386/*
 387m: T">m of packet L atmisobeinedsend e.g. negotiate,wetioha">/*
 468/*
 469/*
 390mr-v via L fosref"ha">/*
 467mr-v.ha">/*
 468/*
 383mr-V href="d.ha">/*
 384 */
 470int sendpacket_gpadl(struct vmbus_channel *chann, const ,l *kbuffe/span>
 446                      *u32 kleng_lock,  3        427                     enum /a> =  3        3el, u32 flag/span>
 471{
 399        struct u32 .<5 hres570"> 400        u32 ret<      sizeof(struct u) +32 kleng_loid;
 421        u32 ret = rs       s,  3wn));
 472        struct u32 u[3]));
 493         3       ret<0));
 474        int rsg;
 485
 476
 477         */
 398         3et =  3;       mDataInBand;ment"> */
 459        flaet = flag        */
 420         */
 421        ret<      sizeof(struct u) l3sg;
 482        ret,  3)PL(rel3n));
 493         404
 415        (u,>3n));
 486         * @klubmsglist" class="> * @klubmf">u[0]rr, &u)n));
 487         * @klubmsglist" class="> * @klubmf">u[1]el, kbuffe32 kleng_lon));
 488         * @klubmsglist" class="> * @klubmf">u[2]rr, &re/span>
 439             L(re-32 rn));
 430
 491        ret = kawritrestore" class="hv_rineref">kawritrestore(&channel-> * @klubmsglist" class="> * @klubmf">u,>3n));
 452
 493        if (ret,,   if (!kahisd rupt_massg_lock" class="97"4id="L397" class="line" n4me=estore(&f5ags);
(&545"> 445          >-> * @klid="L484"="+code=msg" class="sref5>msg<59>;
5mbus_channel_gpadl_teard5wn 487        retu id="L4ch5nnel.c#L395" id="L3954965> 4rs5hv/cha href="drivers/hv/chann5l.c#L448"5href="+co5e=ret" class="sref">ret<5a> 465 sutboundhanne32 t<6a> ==60n>
u,6*/
 383 * @chaPth6 href="+c6de=flags" class="sref">f6ags
msgliste6tgs);
chan60" cld="L465" class="line" n5me="L56>chan60" cl5"> 470int sendpacket_gpadl(struct int ,.-&,f">vmbus_channel * 446                      * * @klenbuffer" class="ref">kleng_lock,  474        6adl" clas6="sref">vmbus_teardown_g6afs 474        6aid="L4006 class="line" n5me="L5106> 43061a>
vmbus_post_msg(chan_60" cld="L465" class=g(chan_60" cl  struct u32 4676/a>;
 446      aderu32cha"6/*.<5 hres570"> 400        u326*/
 421        u32ch6nnfo<615>
vmbus_post_ms72"5id="L472" class="line" n5me="L572"> 472        struct u32  493         3       -&3)PL6lags<61n>
u326*/;
f6ags);

(chan_60" clline5mel.c#L411"5id="L411" class="line" n5me="6 glistent6de=flags" class="sref">f6ags
 386mment">6*/chan_60" cld="L465" class=g(chan_60" cl  st) -"5id="L413" class="line" n5me="L6c *(-&) *"5id="L413" class="line" n5me="L6ct , 400        u) +32 CHANNCLOSE+code=Cf6>msg<6a>;
 421        u32 ret = rs       s6e=child_r6lid" class="sref">child_6elid<6a>;
 477         398        u) +32  459        flode=channel" clVM> = flcket_descripto_f">u) +32 ret<6a>
 421         421de=u32"rivers/hv/channader 420        kment">6*/ret,  3)PL(kardowngpadl_h6nnfo<63);
 4airqre3        .ch6nnsg<63n>
-&ss="drans_id>flaet = kardowngpadl_ha6nf44"5id="L474" cis="lass="ers/hv/chann5l.ci44"5id="L474" cis="l &lL-&sers/hv/chann5l.ci44"5id="L474" cis="l++)  href="drivers/hv/chann5l.c#L448"6inedref">6s_GPADL isors/hv/cment">6*/
.flaet =  4244"5id="L474" c1"> 42de=u32"rivers/hv/channvare60" cl_relsg. 4244"5id="L474" c1"> 42de=uss="drans_id>flaet = .flaet = kasizeeh6nnsg<64>;
 415        ( 487         * @klubmsglist" clasrivers/hv/channader( 488         * @klubmsglist" class="> * @klubmf">u[1]el, kbuffe32 
 488         * @klubmsglist" class="> * @klubmf">u[2]rr, &vlose_g6an 439             L(re-32  467<6a>
 491        ret = kawritrestore" class="hv_rineref">kawritrestore(&channel-> * "6/s="sref"6 oeardowref=ncsref">cha"6/*vmbus_c       ure.ha"6/* 493        if (ret,,   if (!kahisd rupt_massg_lock" class="97"4id="L397" class="line" n4me=estore(&,
(&545"> 445          >-> * @6f whatmrd6wedowified  will holdha"6/*
 487        ret6beinedsen6 e.g. negotiate,wetioha"6/*
}
 465chan60" cld="L465" class="line" n5me="L56>chan60" cl5"> sutboundhanne32  4696/a>mr-v via L fosref"ha"6/*
mr-v.ha"6/*

 383 * @chaPth6Mainly us6ecby H">mr-V href="d.ha"6/*
 384<6a>6*/
multichan60" cld="L465" class="line" n5me="L56>multichan60" cl549">70int sendpacket_gpadl(struct kb6ffe/s6an>
.,,(struct multi>chan60" cld="L465" class=multi>chan60" cl clas"5id="L413" class="line" n5me="L6htid: Id=6e=ret" class="srquestidb6ffe/s6an>
vmbus_channel * 446                      * * @klenbuffer" class="ref">kleng_lock, 6lag/s6an>
 474        6 multichan_60" cld="L465" class=hr/a>(multichan_60" cl@klenbuffer" class="vacket_descripto_header" class="srvacket_descripto_f">u32 * @klen6uffer" class="ref">kleng6loid<6a>;
u32 6wn;
 446      570"> 400        u32u63] 421        u32re6<0vmbus_post_ms72"5id="L472" class="line" n5me="L572"> 472        struct u32  493         3       6485 = de=channel" clVMNUMss="BS_SP> = d9"> 465chan60" cl clas"s="sref">child_relid 42de=uss5id="L413" class="line" n5me="L6htd="L476" 6lass="line" n5me="L576">6476chan60" cld="L465" class=multi>chan60" cl clas"s="sref">child_relidU482          *6mDataInBand;ment"> *6 *6
 *6u32u) l6sgrel36)6;
(chltichan_60" cl@k in class="commenSeneswdata   n@> * @k dit6d="L484" 6lass="line" n5me="L584">6404 386u,>36n68>
u)6)6;
chltichan_60" cld="L465" class=hr/a>(multichan_60" cl@klenb-"5id="L413" class="line" n5me="L6c  @klenbuf6er" class="ref">kleng_lo6)68
6e/spa6>
(rs       s6e=ketlenbuf6er" class="vacketlenf">r6)69
 421        u) +32 6430
 421        u32 ret = rs       s6e=bmsglist"6class="> * @klubmf">u,>36)6;
6452f5a6s6;
 477        u) +32 5m6us_channel_gpadl_teard5w6flode=channel" clVM> = flcket_descripto_f">u) +32  421         421de=u32"rivers/hv/channader 420        ret<5a6ret,  3)PL( 4airqre3        .t<6a7 ==6070
flaet = 74306070
u,6*7chan60" cld="L465" class=multi>chan60" cl clas"s="sref">child_relidU482        flaet = 7s 4244"5id="L474" c1"> 42de=u32"rivers/hv/channvalti>chan60" cld="L465" class=multi>chan60" cl clas"s="sref">child_relid 42de=uss="drans_id>flaet = f5a7s70
chan60" cld="L465" class=multi>chan60" cl clas"s="sref">child_relidafn_array"L465" class=muafn_array=u3drref="drivers/hv/chann5l.c#L444"57l6stent6y7+s_channel_gpadl_teard5w7485607)
(rs       s6e7listent6y7el.c#L395" id="L3954966n7s7et<6070
 415        ( 488         * @klubmsglist" clasrivers/hv/channader(vmbus_teardown_g6a7s 488         * @klubmsglist" class="> * @klubmf">u[1]el, kbuffe32  488         * @klubmsglist" class="> * @klubmf">u[2]rr, & 4676/7> 439             L(re-32 cha"6/76*7
 491        ret = kawritrestore" class="hv_rineref">kawritrestore(&channel->(ch6n7fo<6171
 493        if (ret,,   if (!kahisd rupt_massg_lock" class="97"4id="L397" class="line" n4me=estore(&.((&545"> 445          >-> * @6f7 6l7gs<617>
 487        ret6b7d="L4196 7lass="line" n5me="L5196>7419627;
7 anecsa6c7lmrdowetior asapment">6*7 465chltichan60" cld="L465" class="line" n5me="L56>multichan60" cl549">7tboundhanne32 f6a7s72

f6a7s
m() L77" cus e="L565" onme=laspecified de=headerL411"5id="L411" class="line" n5me="6e7listent6c7lass="line" n5me="L5246>7404627>
 * @chaPth6M7mmenSen6c7 vlosinedsref">mment">6*7
77" cklubivero83 * @chaPth6M7m * @chaPth6M7m * @chaPth6M7mref="+6o7lass="line" n5me="L5286>74186/7>
 * @chaPth6M7 class=6s7ef">CHANNCLOSE+code=Cf6>7sg<6a73
child_6e7id<6a73
s d"li45ly from 7" chyper-v(< and puts77" cklubivtd3 * @chaPth6M7d="L4316 7lass="line" n5me="L5316>74816373
77" cklubiunparsed from hyper-v83 * @chaPth6M7="sref"6v7bus_chvlose=vmbus_card6w7 * @chaPth6M7=istent6d7lass="line" n5me="L5336>74336/73
 * @chaPth6M7=istent6c7ret" class="sref">ret<6a7 420        kment">6*7m"L465" class="line" nrecv"L56>m9"> 4int sendpacket_gpadl(struct vmbus_channel * 420        kardowngpadl_h6n7fo<6373
 446                      * _channel * *kleng_lock, ch6n7sg<6373
kardowngpadl_ha6n7u[0]rr, &u327d="L4396 7lass="line" n5me="L5396>74196/74
 446      570"> 400        u326s7GPADL isors/hv/cment">6*7u32 474        6 7="sref"6g7lock" class="inboundha6n7 * * 3       kasizeeh6n7sg<64745kleng_lock,  3        491     peeef">ret,     peeeeref">kahisd rupt_massg_lock" class="97"4id="L397" class="line" n4me=estore * @klubmsglist" clasrht" class="sreannel-&ss="drans_id>2c#L453"5id="L473"code=nn5l.c#L4336sd  to a91     peeeeref"67
7=rs/hv/6&7t" class="lass=7> * @7567
7tboundhanne32 flaet =    s6e=ketlenbuf6er" class="vacketlenf">r6)69
 t"> *3eh6n7sg<64745cha"7/*6*7 t"> *3rivers/hv/chann5l.c#L468amp7ef="al  ual_vac  /a>(&(6*76*7u[2]rr, &6*7span class="_id5l.">"th6M7d too smalle-vgot %d needs %d\n"@chaPthinamp; 4697/a>6*7
u[2]rr, &amlags" class="sre6 wmmen TOOSMAL"6>7 anecsa6c7lmrTOOSMAL"s/hv/chann5l.c#L451"5id="L471" class="60" cla-"7id="L4multi-chan msglis 7="L5676de=uss="drans n5me="L507"> 487        ret6bchann5lu 7lasa 468 76de=uss="drans_id>flaet = 
 3       kasiz396" id="L396" (str7ct  3       ch7n60" 7l clas"5id="L44641"> 421de=u32"rivers/hCopy ov7d the>re" class="7ef">kleng_lock, 7447647;
 491     peeef">ret,     peeeeref">kahisd rupt_massg_lock" css="line" n5me="L588"> 488        6*767ag/s676" clasrht" class="sreannel-&sse396" id="L396"  t"> *3rrivers/hv/chann5l.c#L468amp7ef="al "drivers/7v/chann5l.c#L444"5id="L474" cl77"> sutboundhanne32  400         487        ret6b21   7    7 anecsa6c7lmrdowetior asat">6*7kment">6*7rivers/hv/chann5l.c#L468amp7ef="al ""6/*( 493<7a>        92"56="vacketl6n_al   unf">rel36<7sref">chi7d_relid 773 * rinedref">kment"_rawd7=flags" class=rawd">f6a7s
m() L * @chaPth6M7=istent6c7ret" class="sref">re55commenS7t6cDL fodescripto_ment">7*6 420        kment"_raw>6*7m"L465" class="line" nrecv"L56>m9"> 4int sendpacket_gpadl(struct vmbu56VcodePa7k6tT">mDataInBand;ment">7*6u[2]rr, &ame=frr, &kardowngpadl_h6n7fo<6373
 446                      *vmbu5lenbuffe7l" clMAX_asMULTIs="BUFFE7_COUN7odcl'  * *u) l6sg<7a68
kardowngpadl_ha6n7u[0]rr, &u326*/ 446(chltichan_60"7cl@k 78="scatsd submf">u32 u326s7GPADL isors/hv/cment">6*7u32multichan_70" cl7klenb-"5id="L4rivers/hv/chann5l.c#L4336s7listent6 7lass="line" n5me="L5436>74336/7>
kasizeeh6n7sg<64745( sutboundhanne32 ( 467<6a>
 491     peeef">ret,     peeeeref">kahisd rupt_massg_lock" class="97"4id="L397" class="line" n4me=estoreu,736flaeeeeeeeeeeeeee="drans_id>2c#L453"5id="L473"code=nn5l.c#L4336sd  to a91     peeeeref"67
 3       7974
 420        6e=ketlenbuf6er" class="vacketlenf">r6)69
 t"> *3eh6n7sg<64745 7)PL(6*7 t"> *3rivers/hv/chann5l.c#L468amp7ef="al8/hv/chann8lsg. sutboundhanne32 6*/ 4468e7a1href=8+7oass="line" n5me="L5908>74308049">7tboundhanne32 child_relidU482   8    <8 de=uss="dransrive396" id="L396" "L  s6e=ketlenbuf6er" class="vacke" clchafn"+codass="L" class="sg_set_> *estore(&chi8d_relid 804cl'     r_erdt">6*7span class="_id5l.">"th6M7d too smalle-vneeded %d nnaderbut "@chaPthvaref="+code=channel" clchannel<8s5ef">chi8dhann5"5id="L477" class=8a7s"got spacedriveoaPth%d nnade\n"@chaPthinamp;u32  4468e7ild_rel8df="+code=flags" class="8lenbu80ss="sc#"> 420    lags" class="sre6 wmmen NOBUFS6>7 anecsa6c7lmrNOBUFS/chann57class="line" n5me="L566"> 4468e8ild_rel8d80"5id="L480" clasds="l8n7s 487        ret68    kasiz396" id="L396" ,  * @8lubmf">u[2]rr<4641"> 421de=u32"rivers/hCopy ov7d the>="+6re>r8a href="v8cketlen_al   unbuffer" c8ass="81de=uss="drans_id>flaet =5l.c#L4476n7="+code6 7lass="line" n5me="L5476>7447647;
 491     peeef">ret,     peeeeref">kahisd rupt_massg_lock" css="line" n5me="L588"> 488        u32  446857ref="+c8r7own the specsref">cha"8/7flaet = -8gt;ch8n7fo<8171
 487        ret68me=estore8/a>(&7 anecsa6c7lmrdowetior asapment">6*7kment"_raw>6*7 nn57class="line" n5me="L566"> 446858ild_rel8     >->>
+codoriginal LXR software>bylass=57class="http://sourcerivge.net/projects/lx">>LXR u32"unitL583"=gt4316experi"rival e" nion>byl57class="mailto:lx"@