Index: head/sys/dev/hyperv/vmbus/hv_channel.c =================================================================== --- head/sys/dev/hyperv/vmbus/hv_channel.c +++ head/sys/dev/hyperv/vmbus/hv_channel.c @@ -182,11 +182,21 @@ hv_vmbus_pfn_channel_callback pfn_on_channel_callback, void* context) { - + struct vmbus_softc *sc = new_channel->vmbus_sc; + const struct vmbus_chanmsg_chopen_resp *resp; + const struct vmbus_message *msg; + struct vmbus_chanmsg_chopen *req; + struct vmbus_msghc *mh; + uint32_t status; int ret = 0; void *in, *out; - hv_vmbus_channel_open_channel* open_msg; - hv_vmbus_channel_msg_info* open_info; + + if (user_data_len > VMBUS_CHANMSG_CHOPEN_UDATA_SIZE) { + device_printf(sc->vmbus_dev, + "invalid udata len %u for chan%u\n", + user_data_len, new_channel->offer_msg.child_rel_id); + return EINVAL; + } mtx_lock(&new_channel->sc_lock); if (new_channel->state == HV_CHANNEL_OPEN_STATE) { @@ -248,76 +258,53 @@ send_ring_buffer_size + recv_ring_buffer_size, &new_channel->ring_buffer_gpadl_handle); - /** - * Create and init the channel open message + /* + * Open channel w/ the bufring GPADL on the target CPU. */ - open_info = (hv_vmbus_channel_msg_info*) malloc( - sizeof(hv_vmbus_channel_msg_info) + - sizeof(hv_vmbus_channel_open_channel), - M_DEVBUF, - M_NOWAIT); - KASSERT(open_info != NULL, - ("Error VMBUS: malloc failed to allocate Open Channel message!")); - - if (open_info == NULL) - return (ENOMEM); - - sema_init(&open_info->wait_sema, 0, "Open Info Sema"); - - open_msg = (hv_vmbus_channel_open_channel*) open_info->msg; - open_msg->header.message_type = HV_CHANNEL_MESSAGE_OPEN_CHANNEL; - open_msg->open_id = new_channel->offer_msg.child_rel_id; - open_msg->child_rel_id = new_channel->offer_msg.child_rel_id; - open_msg->ring_buffer_gpadl_handle = - new_channel->ring_buffer_gpadl_handle; - open_msg->downstream_ring_buffer_page_offset = send_ring_buffer_size - >> PAGE_SHIFT; - open_msg->target_vcpu = new_channel->target_vcpu; - + mh = vmbus_msghc_get(sc, sizeof(*req)); + if (mh == NULL) { + device_printf(sc->vmbus_dev, + "can not get msg hypercall for chopen(chan%u)\n", + new_channel->offer_msg.child_rel_id); + return ENXIO; + } + + req = vmbus_msghc_dataptr(mh); + req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHOPEN; + req->chm_chanid = new_channel->offer_msg.child_rel_id; + req->chm_openid = new_channel->offer_msg.child_rel_id; + req->chm_gpadl = new_channel->ring_buffer_gpadl_handle; + req->chm_vcpuid = new_channel->target_vcpu; + req->chm_rxbr_pgofs = send_ring_buffer_size >> PAGE_SHIFT; if (user_data_len) - memcpy(open_msg->user_data, user_data, user_data_len); - - mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); - TAILQ_INSERT_TAIL( - &hv_vmbus_g_connection.channel_msg_anchor, - open_info, - msg_list_entry); - mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); - - ret = hv_vmbus_post_message( - open_msg, sizeof(hv_vmbus_channel_open_channel)); - - if (ret != 0) - goto cleanup; - - ret = sema_timedwait(&open_info->wait_sema, 5 * hz); /* KYS 5 seconds */ + memcpy(req->chm_udata, user_data, user_data_len); - if (ret) { - if(bootverbose) - printf("VMBUS: channel <%p> open timeout.\n", new_channel); - goto cleanup; + ret = vmbus_msghc_exec(sc, mh); + if (ret != 0) { + device_printf(sc->vmbus_dev, + "chopen(chan%u) msg hypercall exec failed: %d\n", + new_channel->offer_msg.child_rel_id, ret); + vmbus_msghc_put(sc, mh); + return ret; } - if (open_info->response.open_result.status == 0) { - new_channel->state = HV_CHANNEL_OPENED_STATE; - if(bootverbose) - printf("VMBUS: channel <%p> open success.\n", new_channel); + msg = vmbus_msghc_wait_result(sc, mh); + resp = (const struct vmbus_chanmsg_chopen_resp *)msg->msg_data; + status = resp->chm_status; + + vmbus_msghc_put(sc, mh); + + if (status == 0) { + new_channel->state = HV_CHANNEL_OPENED_STATE; + if (bootverbose) { + device_printf(sc->vmbus_dev, "chan%u opened\n", + new_channel->offer_msg.child_rel_id); + } } else { - if(bootverbose) - printf("Error VMBUS: channel <%p> open failed - %d!\n", - new_channel, open_info->response.open_result.status); + device_printf(sc->vmbus_dev, "failed to open chan%u\n", + new_channel->offer_msg.child_rel_id); + ret = ENXIO; } - - cleanup: - mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); - TAILQ_REMOVE( - &hv_vmbus_g_connection.channel_msg_anchor, - open_info, - msg_list_entry); - mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); - sema_destroy(&open_info->wait_sema); - free(open_info, M_DEVBUF); - return (ret); } Index: head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c =================================================================== --- head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c +++ head/sys/dev/hyperv/vmbus/hv_channel_mgmt.c @@ -418,46 +418,13 @@ * @brief Open result handler. * * This is invoked when we received a response - * to our channel open request. Find the matching request, copy the - * response and signal the requesting thread. + * to our channel open request. */ static void vmbus_channel_on_open_result(struct vmbus_softc *sc, const struct vmbus_message *msg) { - const hv_vmbus_channel_msg_header *hdr = - (const hv_vmbus_channel_msg_header *)msg->msg_data; - - const hv_vmbus_channel_open_result *result; - hv_vmbus_channel_msg_info* msg_info; - hv_vmbus_channel_msg_header* requestHeader; - hv_vmbus_channel_open_channel* openMsg; - - result = (const hv_vmbus_channel_open_result *)hdr; - - /* - * Find the open msg, copy the result and signal/unblock the wait event - */ - mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); - - TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor, - msg_list_entry) { - requestHeader = (hv_vmbus_channel_msg_header*) msg_info->msg; - - if (requestHeader->message_type == - HV_CHANNEL_MESSAGE_OPEN_CHANNEL) { - openMsg = (hv_vmbus_channel_open_channel*) msg_info->msg; - if (openMsg->child_rel_id == result->child_rel_id - && openMsg->open_id == result->open_id) { - memcpy(&msg_info->response.open_result, result, - sizeof(hv_vmbus_channel_open_result)); - sema_post(&msg_info->wait_sema); - break; - } - } - } - mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); - + vmbus_msghc_wakeup(sc, msg); } /** Index: head/sys/dev/hyperv/vmbus/vmbus_reg.h =================================================================== --- head/sys/dev/hyperv/vmbus/vmbus_reg.h +++ head/sys/dev/hyperv/vmbus/vmbus_reg.h @@ -84,6 +84,8 @@ */ #define VMBUS_CHANMSG_TYPE_CHANNEL_REQ 3 /* REQ */ +#define VMBUS_CHANMSG_TYPE_CHOPEN 5 /* REQ */ +#define VMBUS_CHANMSG_TYPE_CHOPEN_RESP 6 /* RESP */ #define VMBUS_CHANMSG_TYPE_INIT_CONTACT 14 /* REQ */ #define VMBUS_CHANMSG_TYPE_VERSION_RESP 15 /* RESP */ #define VMBUS_CHANMSG_TYPE_UNLOAD 16 /* REQ */ @@ -119,4 +121,24 @@ struct vmbus_chanmsg_hdr chm_hdr; } __packed; +/* VMBUS_CHANMSG_TYPE_CHOPEN */ +struct vmbus_chanmsg_chopen { + struct vmbus_chanmsg_hdr chm_hdr; + uint32_t chm_chanid; + uint32_t chm_openid; + uint32_t chm_gpadl; + uint32_t chm_vcpuid; + uint32_t chm_rxbr_pgofs; +#define VMBUS_CHANMSG_CHOPEN_UDATA_SIZE 120 + uint8_t chm_udata[VMBUS_CHANMSG_CHOPEN_UDATA_SIZE]; +} __packed; + +/* VMBUS_CHANMSG_TYPE_CHOPEN_RESP */ +struct vmbus_chanmsg_chopen_resp { + struct vmbus_chanmsg_hdr chm_hdr; + uint32_t chm_chanid; + uint32_t chm_openid; + uint32_t chm_status; +} __packed; + #endif /* !_VMBUS_REG_H_ */