FreeBSD/sys/dev/hyperv/vmbus/hv_channel.c
/**
 * @brief Establish a GPADL for the specified buffer
 */
@brief Establish a GPADL for the specified buffer
@brief Establish a GPADL for the specified buffer
int
hv_vmbus_channel_establish_gpadl(
	hv_vmbus_channel*	channel,
	void*			contig_buffer,
	uint32_t		size, 
	uint32_t*		gpadl_handle)
{
	int ret = 0;
	hv_vmbus_channel_gpadl_header*	gpadl_msg;
	hv_vmbus_channel_gpadl_body*	gpadl_body;
	hv_vmbus_channel_msg_info*	msg_info;
	hv_vmbus_channel_msg_info*	sub_msg_info;
	uint32_t			msg_count;
	hv_vmbus_channel_msg_info*	curr;
	uint32_t			next_gpadl_handle;
	next_gpadl_handle = atomic_fetchadd_int(
	    &hv_vmbus_g_connection.next_gpadl_handle, 1);
	ret = vmbus_channel_create_gpadl_header(
		contig_buffer, size, &msg_info, &msg_count);
	if(ret != 0) {
		return ret;
	}
	sema_init(&msg_info->wait_sema, 0, "Open Info Sema");
	gpadl_msg = (hv_vmbus_channel_gpadl_header*) msg_info->msg;
	gpadl_msg->header.message_type = HV_CHANNEL_MESSAGEL_GPADL_HEADER;
	gpadl_msg->child_rel_id = channel->offer_msg.child_rel_id;
	gpadl_msg->gpadl = next_gpadl_handle;
	mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
	TAILQ_INSERT_TAIL(
		&hv_vmbus_g_connection.channel_msg_anchor,
		msg_info,
		msg_list_entry);
	mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
	ret = hv_vmbus_post_message(
		gpadl_msg,
		msg_info->message_size -
		    (uint32_t) sizeof(hv_vmbus_channel_msg_info));
	if (ret != 0)
	    goto cleanup;
	if (msg_count > 1) {
	    TAILQ_FOREACH(curr,
		    &msg_info->sub_msg_list_anchor, msg_list_entry) {
		sub_msg_info = curr;
		gpadl_body =
		    (hv_vmbus_channel_gpadl_body*) sub_msg_info->msg;
		gpadl_body->header.message_type =
		    HV_CHANNEL_MESSAGE_GPADL_BODY;
		gpadl_body->gpadl = next_gpadl_handle;
		ret = hv_vmbus_post_message(
			gpadl_body,
			sub_msg_info->message_size
			    - (uint32_t) sizeof(hv_vmbus_channel_msg_info));
		if(ret != 0)
		    goto cleanup;
	    }
	}
	ret = sema_timedwait(&msg_info->wait_sema, 5 * hz); 
	if (ret != 0)
	    goto cleanup;
	*gpadl_handle = gpadl_msg->gpadl;
cleanup:
	mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
	TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor,
		msg_info, msg_list_entry);
	mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
	sema_destroy(&msg_info->wait_sema);
	free(msg_info, M_DEVBUF);
	return (ret);
}
int hv_vmbus_channel_establish_gpadl ( hv_vmbus_channel * channel , void * contig_buffer , uint32_t size , uint32_t * gpadl_handle ) { int ret = 0 ; hv_vmbus_channel_gpadl_header * gpadl_msg ; hv_vmbus_channel_gpadl_body * gpadl_body ; hv_vmbus_channel_msg_info * msg_info ; hv_vmbus_channel_msg_info * sub_msg_info ; uint32_t msg_count ; hv_vmbus_channel_msg_info * curr ; uint32_t next_gpadl_handle ; next_gpadl_handle = atomic_fetchadd_int ( & hv_vmbus_g_connection . next_gpadl_handle , 1 ) ; ret = vmbus_channel_create_gpadl_header ( contig_buffer , size , & msg_info , & msg_count ) ; if ( ret != 0 ) { return ret ; } sema_init ( & msg_info -> wait_sema , 0 , " " ) ; gpadl_msg = ( hv_vmbus_channel_gpadl_header * ) msg_info -> msg ; gpadl_msg -> header . message_type = HV_CHANNEL_MESSAGEL_GPADL_HEADER ; gpadl_msg -> child_rel_id = channel -> offer_msg . child_rel_id ; gpadl_msg -> gpadl = next_gpadl_handle ; mtx_lock ( & hv_vmbus_g_connection . channel_msg_lock ) ; TAILQ_INSERT_TAIL ( & hv_vmbus_g_connection . channel_msg_anchor , msg_info , msg_list_entry ) ; mtx_unlock ( & hv_vmbus_g_connection . channel_msg_lock ) ; ret = hv_vmbus_post_message ( gpadl_msg , msg_info -> message_size - ( uint32_t ) sizeof ( hv_vmbus_channel_msg_info ) ) ; if ( ret != 0 ) goto cleanup ; if ( msg_count > 1 ) { TAILQ_FOREACH ( curr , & msg_info -> sub_msg_list_anchor , msg_list_entry ) { sub_msg_info = curr ; gpadl_body = ( hv_vmbus_channel_gpadl_body * ) sub_msg_info -> msg ; gpadl_body -> header . message_type = HV_CHANNEL_MESSAGE_GPADL_BODY ; gpadl_body -> gpadl = next_gpadl_handle ; ret = hv_vmbus_post_message ( gpadl_body , sub_msg_info -> message_size - ( uint32_t ) sizeof ( hv_vmbus_channel_msg_info ) ) ; if ( ret != 0 ) goto cleanup ; } } ret = sema_timedwait ( & msg_info -> wait_sema , 5 * hz ) ; if ( ret != 0 ) goto cleanup ; * gpadl_handle = gpadl_msg -> gpadl ; cleanup : mtx_lock ( & hv_vmbus_g_connection . channel_msg_lock ) ; TAILQ_REMOVE ( & hv_vmbus_g_connection . channel_msg_anchor , msg_info , msg_list_entry ) ; mtx_unlock ( & hv_vmbus_g_connection . channel_msg_lock ) ; sema_destroy ( & msg_info -> wait_sema ) ; free ( msg_info , M_DEVBUF ) ; return ( ret ) ; }
@brief Establish a GPADL for the specified buffer
@brief Establish a GPADL for the specified buffer
/* page-size multiple */ /*
		 * XXX
		 * We can _not_ even revert the above incremental,
		 * if multiple GPADL establishments are running
		 * parallelly, decrement the global next_gpadl_handle
		 * is calling for _big_ trouble.  A better solution
		 * is to have a 0-based GPADL id bitmap ...
		 */ /* if (the post message failed) give up and clean up */ /* KYS 5 seconds*/