Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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