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