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