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/list.h> 29 #include <linux/module.h> 30 #include <linux/completion.h> 31 #include <linux/hyperv.h> 32 33 #include "hyperv_vmbus.h" 34 35 struct vmbus_channel_message_table_entry { 36 enum vmbus_channel_message_type message_type; 37 void (*message_handler)(struct vmbus_channel_message_header *msg); 38 }; 39 40 41 /** 42 * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message 43 * @icmsghdrp: Pointer to msg header structure 44 * @icmsg_negotiate: Pointer to negotiate message structure 45 * @buf: Raw buffer channel data 46 * 47 * @icmsghdrp is of type &struct icmsg_hdr. 48 * @negop is of type &struct icmsg_negotiate. 49 * Set up and fill in default negotiate response message. 50 * 51 * The max_fw_version specifies the maximum framework version that 52 * we can support and max _srv_version specifies the maximum service 53 * version we can support. A special value MAX_SRV_VER can be 54 * specified to indicate that we can handle the maximum version 55 * exposed by the host. 56 * 57 * Mainly used by Hyper-V drivers. 58 */ 59 void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, 60 struct icmsg_negotiate *negop, u8 *buf, 61 int max_fw_version, int max_srv_version) 62 { 63 int icframe_vercnt; 64 int icmsg_vercnt; 65 int i; 66 67 icmsghdrp->icmsgsize = 0x10; 68 69 negop = (struct icmsg_negotiate *)&buf[ 70 sizeof(struct vmbuspipe_hdr) + 71 sizeof(struct icmsg_hdr)]; 72 73 icframe_vercnt = negop->icframe_vercnt; 74 icmsg_vercnt = negop->icmsg_vercnt; 75 76 /* 77 * Select the framework version number we will 78 * support. 79 */ 80 81 for (i = 0; i < negop->icframe_vercnt; i++) { 82 if (negop->icversion_data[i].major <= max_fw_version) 83 icframe_vercnt = negop->icversion_data[i].major; 84 } 85 86 for (i = negop->icframe_vercnt; 87 (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { 88 if (negop->icversion_data[i].major <= max_srv_version) 89 icmsg_vercnt = negop->icversion_data[i].major; 90 } 91 92 /* 93 * Respond with the maximum framework and service 94 * version numbers we can support. 95 */ 96 negop->icframe_vercnt = 1; 97 negop->icmsg_vercnt = 1; 98 negop->icversion_data[0].major = icframe_vercnt; 99 negop->icversion_data[0].minor = 0; 100 negop->icversion_data[1].major = icmsg_vercnt; 101 negop->icversion_data[1].minor = 0; 102 } 103 104 EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); 105 106 /* 107 * alloc_channel - Allocate and initialize a vmbus channel object 108 */ 109 static struct vmbus_channel *alloc_channel(void) 110 { 111 struct vmbus_channel *channel; 112 113 channel = kzalloc(sizeof(*channel), GFP_ATOMIC); 114 if (!channel) 115 return NULL; 116 117 spin_lock_init(&channel->inbound_lock); 118 119 channel->controlwq = create_workqueue("hv_vmbus_ctl"); 120 if (!channel->controlwq) { 121 kfree(channel); 122 return NULL; 123 } 124 125 return channel; 126 } 127 128 /* 129 * release_hannel - Release the vmbus channel object itself 130 */ 131 static void release_channel(struct work_struct *work) 132 { 133 struct vmbus_channel *channel = container_of(work, 134 struct vmbus_channel, 135 work); 136 137 destroy_workqueue(channel->controlwq); 138 139 kfree(channel); 140 } 141 142 /* 143 * free_channel - Release the resources used by the vmbus channel object 144 */ 145 static void free_channel(struct vmbus_channel *channel) 146 { 147 148 /* 149 * We have to release the channel's workqueue/thread in the vmbus's 150 * workqueue/thread context 151 * ie we can't destroy ourselves. 152 */ 153 INIT_WORK(&channel->work, release_channel); 154 queue_work(vmbus_connection.work_queue, &channel->work); 155 } 156 157 158 159 /* 160 * vmbus_process_rescind_offer - 161 * Rescind the offer by initiating a device removal 162 */ 163 static void vmbus_process_rescind_offer(struct work_struct *work) 164 { 165 struct vmbus_channel *channel = container_of(work, 166 struct vmbus_channel, 167 work); 168 169 vmbus_device_unregister(channel->device_obj); 170 } 171 172 void vmbus_free_channels(void) 173 { 174 struct vmbus_channel *channel; 175 176 list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { 177 vmbus_device_unregister(channel->device_obj); 178 kfree(channel->device_obj); 179 free_channel(channel); 180 } 181 } 182 183 /* 184 * vmbus_process_offer - Process the offer by creating a channel/device 185 * associated with this offer 186 */ 187 static void vmbus_process_offer(struct work_struct *work) 188 { 189 struct vmbus_channel *newchannel = container_of(work, 190 struct vmbus_channel, 191 work); 192 struct vmbus_channel *channel; 193 bool fnew = true; 194 int ret; 195 unsigned long flags; 196 197 /* The next possible work is rescind handling */ 198 INIT_WORK(&newchannel->work, vmbus_process_rescind_offer); 199 200 /* Make sure this is a new offer */ 201 spin_lock_irqsave(&vmbus_connection.channel_lock, flags); 202 203 list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { 204 if (!uuid_le_cmp(channel->offermsg.offer.if_type, 205 newchannel->offermsg.offer.if_type) && 206 !uuid_le_cmp(channel->offermsg.offer.if_instance, 207 newchannel->offermsg.offer.if_instance)) { 208 fnew = false; 209 break; 210 } 211 } 212 213 if (fnew) 214 list_add_tail(&newchannel->listentry, 215 &vmbus_connection.chn_list); 216 217 spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); 218 219 if (!fnew) { 220 free_channel(newchannel); 221 return; 222 } 223 224 /* 225 * Start the process of binding this offer to the driver 226 * We need to set the DeviceObject field before calling 227 * vmbus_child_dev_add() 228 */ 229 newchannel->device_obj = vmbus_device_create( 230 &newchannel->offermsg.offer.if_type, 231 &newchannel->offermsg.offer.if_instance, 232 newchannel); 233 234 /* 235 * Add the new device to the bus. This will kick off device-driver 236 * binding which eventually invokes the device driver's AddDevice() 237 * method. 238 */ 239 ret = vmbus_device_register(newchannel->device_obj); 240 if (ret != 0) { 241 pr_err("unable to add child device object (relid %d)\n", 242 newchannel->offermsg.child_relid); 243 244 spin_lock_irqsave(&vmbus_connection.channel_lock, flags); 245 list_del(&newchannel->listentry); 246 spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); 247 kfree(newchannel->device_obj); 248 249 free_channel(newchannel); 250 } else { 251 /* 252 * This state is used to indicate a successful open 253 * so that when we do close the channel normally, we 254 * can cleanup properly 255 */ 256 newchannel->state = CHANNEL_OPEN_STATE; 257 } 258 } 259 260 /* 261 * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. 262 * 263 */ 264 static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) 265 { 266 struct vmbus_channel_offer_channel *offer; 267 struct vmbus_channel *newchannel; 268 269 offer = (struct vmbus_channel_offer_channel *)hdr; 270 271 /* Allocate the channel object and save this offer. */ 272 newchannel = alloc_channel(); 273 if (!newchannel) { 274 pr_err("Unable to allocate channel object\n"); 275 return; 276 } 277 278 memcpy(&newchannel->offermsg, offer, 279 sizeof(struct vmbus_channel_offer_channel)); 280 newchannel->monitor_grp = (u8)offer->monitorid / 32; 281 newchannel->monitor_bit = (u8)offer->monitorid % 32; 282 283 INIT_WORK(&newchannel->work, vmbus_process_offer); 284 queue_work(newchannel->controlwq, &newchannel->work); 285 } 286 287 /* 288 * vmbus_onoffer_rescind - Rescind offer handler. 289 * 290 * We queue a work item to process this offer synchronously 291 */ 292 static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) 293 { 294 struct vmbus_channel_rescind_offer *rescind; 295 struct vmbus_channel *channel; 296 297 rescind = (struct vmbus_channel_rescind_offer *)hdr; 298 channel = relid2channel(rescind->child_relid); 299 300 if (channel == NULL) 301 /* Just return here, no channel found */ 302 return; 303 304 /* work is initialized for vmbus_process_rescind_offer() from 305 * vmbus_process_offer() where the channel got created */ 306 queue_work(channel->controlwq, &channel->work); 307 } 308 309 /* 310 * vmbus_onoffers_delivered - 311 * This is invoked when all offers have been delivered. 312 * 313 * Nothing to do here. 314 */ 315 static void vmbus_onoffers_delivered( 316 struct vmbus_channel_message_header *hdr) 317 { 318 } 319 320 /* 321 * vmbus_onopen_result - Open result handler. 322 * 323 * This is invoked when we received a response to our channel open request. 324 * Find the matching request, copy the response and signal the requesting 325 * thread. 326 */ 327 static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr) 328 { 329 struct vmbus_channel_open_result *result; 330 struct vmbus_channel_msginfo *msginfo; 331 struct vmbus_channel_message_header *requestheader; 332 struct vmbus_channel_open_channel *openmsg; 333 unsigned long flags; 334 335 result = (struct vmbus_channel_open_result *)hdr; 336 337 /* 338 * Find the open msg, copy the result and signal/unblock the wait event 339 */ 340 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 341 342 list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, 343 msglistentry) { 344 requestheader = 345 (struct vmbus_channel_message_header *)msginfo->msg; 346 347 if (requestheader->msgtype == CHANNELMSG_OPENCHANNEL) { 348 openmsg = 349 (struct vmbus_channel_open_channel *)msginfo->msg; 350 if (openmsg->child_relid == result->child_relid && 351 openmsg->openid == result->openid) { 352 memcpy(&msginfo->response.open_result, 353 result, 354 sizeof( 355 struct vmbus_channel_open_result)); 356 complete(&msginfo->waitevent); 357 break; 358 } 359 } 360 } 361 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 362 } 363 364 /* 365 * vmbus_ongpadl_created - GPADL created handler. 366 * 367 * This is invoked when we received a response to our gpadl create request. 368 * Find the matching request, copy the response and signal the requesting 369 * thread. 370 */ 371 static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr) 372 { 373 struct vmbus_channel_gpadl_created *gpadlcreated; 374 struct vmbus_channel_msginfo *msginfo; 375 struct vmbus_channel_message_header *requestheader; 376 struct vmbus_channel_gpadl_header *gpadlheader; 377 unsigned long flags; 378 379 gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr; 380 381 /* 382 * Find the establish msg, copy the result and signal/unblock the wait 383 * event 384 */ 385 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 386 387 list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, 388 msglistentry) { 389 requestheader = 390 (struct vmbus_channel_message_header *)msginfo->msg; 391 392 if (requestheader->msgtype == CHANNELMSG_GPADL_HEADER) { 393 gpadlheader = 394 (struct vmbus_channel_gpadl_header *)requestheader; 395 396 if ((gpadlcreated->child_relid == 397 gpadlheader->child_relid) && 398 (gpadlcreated->gpadl == gpadlheader->gpadl)) { 399 memcpy(&msginfo->response.gpadl_created, 400 gpadlcreated, 401 sizeof( 402 struct vmbus_channel_gpadl_created)); 403 complete(&msginfo->waitevent); 404 break; 405 } 406 } 407 } 408 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 409 } 410 411 /* 412 * vmbus_ongpadl_torndown - GPADL torndown handler. 413 * 414 * This is invoked when we received a response to our gpadl teardown request. 415 * Find the matching request, copy the response and signal the requesting 416 * thread. 417 */ 418 static void vmbus_ongpadl_torndown( 419 struct vmbus_channel_message_header *hdr) 420 { 421 struct vmbus_channel_gpadl_torndown *gpadl_torndown; 422 struct vmbus_channel_msginfo *msginfo; 423 struct vmbus_channel_message_header *requestheader; 424 struct vmbus_channel_gpadl_teardown *gpadl_teardown; 425 unsigned long flags; 426 427 gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr; 428 429 /* 430 * Find the open msg, copy the result and signal/unblock the wait event 431 */ 432 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 433 434 list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, 435 msglistentry) { 436 requestheader = 437 (struct vmbus_channel_message_header *)msginfo->msg; 438 439 if (requestheader->msgtype == CHANNELMSG_GPADL_TEARDOWN) { 440 gpadl_teardown = 441 (struct vmbus_channel_gpadl_teardown *)requestheader; 442 443 if (gpadl_torndown->gpadl == gpadl_teardown->gpadl) { 444 memcpy(&msginfo->response.gpadl_torndown, 445 gpadl_torndown, 446 sizeof( 447 struct vmbus_channel_gpadl_torndown)); 448 complete(&msginfo->waitevent); 449 break; 450 } 451 } 452 } 453 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 454 } 455 456 /* 457 * vmbus_onversion_response - Version response handler 458 * 459 * This is invoked when we received a response to our initiate contact request. 460 * Find the matching request, copy the response and signal the requesting 461 * thread. 462 */ 463 static void vmbus_onversion_response( 464 struct vmbus_channel_message_header *hdr) 465 { 466 struct vmbus_channel_msginfo *msginfo; 467 struct vmbus_channel_message_header *requestheader; 468 struct vmbus_channel_version_response *version_response; 469 unsigned long flags; 470 471 version_response = (struct vmbus_channel_version_response *)hdr; 472 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 473 474 list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, 475 msglistentry) { 476 requestheader = 477 (struct vmbus_channel_message_header *)msginfo->msg; 478 479 if (requestheader->msgtype == 480 CHANNELMSG_INITIATE_CONTACT) { 481 memcpy(&msginfo->response.version_response, 482 version_response, 483 sizeof(struct vmbus_channel_version_response)); 484 complete(&msginfo->waitevent); 485 } 486 } 487 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 488 } 489 490 /* Channel message dispatch table */ 491 static struct vmbus_channel_message_table_entry 492 channel_message_table[CHANNELMSG_COUNT] = { 493 {CHANNELMSG_INVALID, NULL}, 494 {CHANNELMSG_OFFERCHANNEL, vmbus_onoffer}, 495 {CHANNELMSG_RESCIND_CHANNELOFFER, vmbus_onoffer_rescind}, 496 {CHANNELMSG_REQUESTOFFERS, NULL}, 497 {CHANNELMSG_ALLOFFERS_DELIVERED, vmbus_onoffers_delivered}, 498 {CHANNELMSG_OPENCHANNEL, NULL}, 499 {CHANNELMSG_OPENCHANNEL_RESULT, vmbus_onopen_result}, 500 {CHANNELMSG_CLOSECHANNEL, NULL}, 501 {CHANNELMSG_GPADL_HEADER, NULL}, 502 {CHANNELMSG_GPADL_BODY, NULL}, 503 {CHANNELMSG_GPADL_CREATED, vmbus_ongpadl_created}, 504 {CHANNELMSG_GPADL_TEARDOWN, NULL}, 505 {CHANNELMSG_GPADL_TORNDOWN, vmbus_ongpadl_torndown}, 506 {CHANNELMSG_RELID_RELEASED, NULL}, 507 {CHANNELMSG_INITIATE_CONTACT, NULL}, 508 {CHANNELMSG_VERSION_RESPONSE, vmbus_onversion_response}, 509 {CHANNELMSG_UNLOAD, NULL}, 510 }; 511 512 /* 513 * vmbus_onmessage - Handler for channel protocol messages. 514 * 515 * This is invoked in the vmbus worker thread context. 516 */ 517 void vmbus_onmessage(void *context) 518 { 519 struct hv_message *msg = context; 520 struct vmbus_channel_message_header *hdr; 521 int size; 522 523 hdr = (struct vmbus_channel_message_header *)msg->u.payload; 524 size = msg->header.payload_size; 525 526 if (hdr->msgtype >= CHANNELMSG_COUNT) { 527 pr_err("Received invalid channel message type %d size %d\n", 528 hdr->msgtype, size); 529 print_hex_dump_bytes("", DUMP_PREFIX_NONE, 530 (unsigned char *)msg->u.payload, size); 531 return; 532 } 533 534 if (channel_message_table[hdr->msgtype].message_handler) 535 channel_message_table[hdr->msgtype].message_handler(hdr); 536 else 537 pr_err("Unhandled channel message type %d\n", hdr->msgtype); 538 } 539 540 /* 541 * vmbus_request_offers - Send a request to get all our pending offers. 542 */ 543 int vmbus_request_offers(void) 544 { 545 struct vmbus_channel_message_header *msg; 546 struct vmbus_channel_msginfo *msginfo; 547 int ret, t; 548 549 msginfo = kmalloc(sizeof(*msginfo) + 550 sizeof(struct vmbus_channel_message_header), 551 GFP_KERNEL); 552 if (!msginfo) 553 return -ENOMEM; 554 555 init_completion(&msginfo->waitevent); 556 557 msg = (struct vmbus_channel_message_header *)msginfo->msg; 558 559 msg->msgtype = CHANNELMSG_REQUESTOFFERS; 560 561 562 ret = vmbus_post_msg(msg, 563 sizeof(struct vmbus_channel_message_header)); 564 if (ret != 0) { 565 pr_err("Unable to request offers - %d\n", ret); 566 567 goto cleanup; 568 } 569 570 t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); 571 if (t == 0) { 572 ret = -ETIMEDOUT; 573 goto cleanup; 574 } 575 576 577 578 cleanup: 579 kfree(msginfo); 580 581 return ret; 582 } 583 584 /* eof */ 585