void hv_kvp_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; struct hv_kvp_msg *kvp_msg; struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; int util_fw_version; int kvp_srv_version; if (kvp_transaction.active) { /* * We will defer processing this callback once * the current transaction is complete. */ kvp_transaction.kvp_context = context; return; } vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 4, &recvlen, &requestid); if (recvlen > 0) { icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { /* * Based on the host, select appropriate * framework and service versions we will * negotiate. */ switch (vmbus_proto_version) { case (VERSION_WS2008): util_fw_version = UTIL_WS2K8_FW_VERSION; kvp_srv_version = WS2008_SRV_VERSION; break; case (VERSION_WIN7): util_fw_version = UTIL_FW_VERSION; kvp_srv_version = WIN7_SRV_VERSION; break; default: util_fw_version = UTIL_FW_VERSION; kvp_srv_version = WIN8_SRV_VERSION; } vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer, util_fw_version, kvp_srv_version); } else { kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; /* * Stash away this global state for completing the * transaction; note transactions are serialized. */ kvp_transaction.recv_len = recvlen; kvp_transaction.recv_channel = channel; kvp_transaction.recv_req_id = requestid; kvp_transaction.active = true; kvp_transaction.kvp_msg = kvp_msg; /* * Get the information from the * user-mode component. * component. This transaction will be * completed when we get the value from * the user-mode component. * Set a timeout to deal with * user-mode not responding. */ schedule_work(&kvp_sendkey_work); schedule_delayed_work(&kvp_work, 5*HZ); return; } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, VM_PKT_DATA_INBAND, 0); } }
void hv_vss_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; struct hv_vss_msg *vss_msg; struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; if (vss_transaction.state > HVUTIL_READY) return; vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, &requestid); if (recvlen > 0) { icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer, UTIL_FW_VERSION, VSS_VERSION); } else { vss_msg = (struct hv_vss_msg *)&recv_buffer[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; /* * Stash away this global state for completing the * transaction; note transactions are serialized. */ vss_transaction.recv_len = recvlen; vss_transaction.recv_req_id = requestid; vss_transaction.msg = (struct hv_vss_msg *)vss_msg; switch (vss_msg->vss_hdr.operation) { /* * Initiate a "freeze/thaw" * operation in the guest. * We respond to the host once * the operation is complete. * * We send the message to the * user space daemon and the * operation is performed in * the daemon. */ case VSS_OP_FREEZE: case VSS_OP_THAW: if (vss_transaction.state < HVUTIL_READY) { /* Userspace is not registered yet */ vss_respond_to_host(HV_E_FAIL); return; } vss_transaction.state = HVUTIL_HOSTMSG_RECEIVED; schedule_work(&vss_send_op_work); schedule_delayed_work(&vss_timeout_work, VSS_USERSPACE_TIMEOUT); return; case VSS_OP_HOT_BACKUP: vss_msg->vss_cf.flags = VSS_HBU_NO_AUTO_RECOVERY; vss_respond_to_host(0); return; case VSS_OP_GET_DM_INFO: vss_msg->dm_info.flags = 0; vss_respond_to_host(0); return; default: vss_respond_to_host(0); return; } } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, VM_PKT_DATA_INBAND, 0); } }
void hv_kvp_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; struct hv_kvp_msg *kvp_msg; struct hv_kvp_msg_enumerate *kvp_data; struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); if (recvlen > 0) { icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer); } else { kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; kvp_data = &kvp_msg->kvp_data; /* * We only support the "get" operation on * "KVP_POOL_AUTO" pool. */ if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) || (kvp_msg->kvp_hdr.operation != KVP_OP_ENUMERATE)) { icmsghdrp->status = HV_E_FAIL; goto callback_done; } /* * Stash away this global state for completing the * transaction; note transactions are serialized. */ kvp_transaction.recv_len = recvlen; kvp_transaction.recv_channel = channel; kvp_transaction.recv_req_id = requestid; kvp_transaction.active = true; kvp_transaction.index = kvp_data->index; /* * Get the information from the * user-mode component. * component. This transaction will be * completed when we get the value from * the user-mode component. * Set a timeout to deal with * user-mode not responding. */ schedule_work(&kvp_sendkey_work); schedule_delayed_work(&kvp_work, 5*HZ); return; } callback_done: icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, VM_PKT_DATA_INBAND, 0); } }
static void shutdown_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u8 *buf; u32 buflen, recvlen; u64 requestid; u8 execute_shutdown = false; struct shutdown_msg_data *shutdown_msg; struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; buflen = PAGE_SIZE; buf = kmalloc(buflen, GFP_ATOMIC); vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid); if (recvlen > 0) { DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld", recvlen, requestid); icmsghdrp = (struct icmsg_hdr *)&buf[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { prep_negotiate_resp(icmsghdrp, negop, buf); } else { shutdown_msg = (struct shutdown_msg_data *)&buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; switch (shutdown_msg->flags) { case 0: case 1: icmsghdrp->status = HV_S_OK; execute_shutdown = true; DPRINT_INFO(VMBUS, "Shutdown request received -" " gracefull shutdown initiated"); break; default: icmsghdrp->status = HV_E_FAIL; execute_shutdown = false; DPRINT_INFO(VMBUS, "Shutdown request received -" " Invalid request"); break; }; } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, buf, recvlen, requestid, VmbusPacketTypeDataInBand, 0); } kfree(buf); if (execute_shutdown == true) orderly_poweroff(false); }
static void shutdown_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; u8 execute_shutdown = false; u8 *shut_txf_buf = util_shutdown.recv_buffer; struct shutdown_msg_data *shutdown_msg; struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; vmbus_recvpacket(channel, shut_txf_buf, PAGE_SIZE, &recvlen, &requestid); if (recvlen > 0) { icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf, util_fw_version, sd_srv_version); } else { shutdown_msg = (struct shutdown_msg_data *)&shut_txf_buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; switch (shutdown_msg->flags) { case 0: case 1: icmsghdrp->status = HV_S_OK; execute_shutdown = true; pr_info("Shutdown request received -" " graceful shutdown initiated\n"); break; default: icmsghdrp->status = HV_E_FAIL; execute_shutdown = false; pr_info("Shutdown request received -" " Invalid request\n"); break; } } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, shut_txf_buf, recvlen, requestid, VM_PKT_DATA_INBAND, 0); } if (execute_shutdown == true) schedule_work(&shutdown_work); }
void hv_kvp_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; struct hv_kvp_msg *kvp_msg; struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; int util_fw_version; int kvp_srv_version; static enum {NEGO_NOT_STARTED, NEGO_IN_PROGRESS, NEGO_FINISHED } host_negotiatied = NEGO_NOT_STARTED; if (host_negotiatied == NEGO_NOT_STARTED && kvp_transaction.state < HVUTIL_READY) { /* * If userspace daemon is not connected and host is asking * us to negotiate we need to delay to not lose messages. * This is important for Failover IP setting. */ host_negotiatied = NEGO_IN_PROGRESS; schedule_delayed_work(&kvp_host_handshake_work, HV_UTIL_NEGO_TIMEOUT * HZ); return; } if (kvp_transaction.state > HVUTIL_READY) return; vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 4, &recvlen, &requestid); if (recvlen > 0) { icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { /* * Based on the host, select appropriate * framework and service versions we will * negotiate. */ switch (vmbus_proto_version) { case (VERSION_WS2008): util_fw_version = UTIL_WS2K8_FW_VERSION; kvp_srv_version = WS2008_SRV_VERSION; break; case (VERSION_WIN7): util_fw_version = UTIL_FW_VERSION; kvp_srv_version = WIN7_SRV_VERSION; break; default: util_fw_version = UTIL_FW_VERSION; kvp_srv_version = WIN8_SRV_VERSION; } vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer, util_fw_version, kvp_srv_version); } else { kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; /* * Stash away this global state for completing the * transaction; note transactions are serialized. */ kvp_transaction.recv_len = recvlen; kvp_transaction.recv_req_id = requestid; kvp_transaction.kvp_msg = kvp_msg; if (kvp_transaction.state < HVUTIL_READY) { /* Userspace is not registered yet */ kvp_respond_to_host(NULL, HV_E_FAIL); return; } kvp_transaction.state = HVUTIL_HOSTMSG_RECEIVED; /* * Get the information from the * user-mode component. * component. This transaction will be * completed when we get the value from * the user-mode component. * Set a timeout to deal with * user-mode not responding. */ schedule_work(&kvp_sendkey_work); schedule_delayed_work(&kvp_timeout_work, HV_UTIL_TIMEOUT * HZ); return; } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, VM_PKT_DATA_INBAND, 0); host_negotiatied = NEGO_FINISHED; } }
void hv_kvp_onchannelcallback(void *context) { struct vmbus_channel *channel = context; u32 recvlen; u64 requestid; struct hv_kvp_msg *kvp_msg; struct icmsg_hdr *icmsghdrp; struct icmsg_negotiate *negop = NULL; if (kvp_transaction.active) { /* * We will defer processing this callback once * the current transaction is complete. */ kvp_transaction.kvp_context = context; return; } vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen, &requestid); if (recvlen > 0) { icmsghdrp = (struct icmsg_hdr *)&recv_buffer[ sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer, MAX_SRV_VER, MAX_SRV_VER); } else { kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; /* * Stash away this global state for completing the * transaction; note transactions are serialized. */ kvp_transaction.recv_len = recvlen; kvp_transaction.recv_channel = channel; kvp_transaction.recv_req_id = requestid; kvp_transaction.active = true; kvp_transaction.kvp_msg = kvp_msg; /* * Get the information from the * user-mode component. * component. This transaction will be * completed when we get the value from * the user-mode component. * Set a timeout to deal with * user-mode not responding. */ schedule_work(&kvp_sendkey_work); schedule_delayed_work(&kvp_work, 5*HZ); return; } icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; vmbus_sendpacket(channel, recv_buffer, recvlen, requestid, VM_PKT_DATA_INBAND, 0); } }