Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Oct 2016 07:47:35 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r307301 - in stable/11/sys/dev/hyperv: include vmbus
Message-ID:  <201610140747.u9E7lZKa074108@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Fri Oct 14 07:47:35 2016
New Revision: 307301
URL: https://svnweb.freebsd.org/changeset/base/307301

Log:
  MFC 302607-302612
  
  302607
      hyperv/vmbus: Use post message Hypercall APIs for channel open
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D6876
  
  302608
      hyperv/vmbus: Remove unnecessary check and unapplied comment
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D6877
  
  302609
      hyperv/vmbus: Use post message Hypercall APIs for GPADL connect.
  
      This also fixes memory leakge if sub-connect messages are needed.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D6878
  
  302610
      hyperv/vmbus: Use post message Hypercall APIs for channel close
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D6906
  
  302611
      hyperv/vmbus: Use post message Hypercall APIs for GPA disconnect
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D6912
  
  302612
      hyperv: Nuke unused stuffs
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D6913

Modified:
  stable/11/sys/dev/hyperv/include/hyperv.h
  stable/11/sys/dev/hyperv/vmbus/hv_channel.c
  stable/11/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
  stable/11/sys/dev/hyperv/vmbus/hv_connection.c
  stable/11/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
  stable/11/sys/dev/hyperv/vmbus/hyperv.c
  stable/11/sys/dev/hyperv/vmbus/vmbus.c
  stable/11/sys/dev/hyperv/vmbus/vmbus_reg.h
  stable/11/sys/dev/hyperv/vmbus/vmbus_var.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/11/sys/dev/hyperv/include/hyperv.h	Fri Oct 14 07:47:07 2016	(r307300)
+++ stable/11/sys/dev/hyperv/include/hyperv.h	Fri Oct 14 07:47:35 2016	(r307301)
@@ -179,8 +179,6 @@ typedef struct hv_vmbus_channel_offer {
 
 } __packed hv_vmbus_channel_offer;
 
-typedef uint32_t hv_gpadl_handle;
-
 typedef struct {
 	uint16_t type;
 	uint16_t data_offset8;
@@ -352,14 +350,6 @@ typedef struct {
 } __packed hv_vmbus_channel_query_vmbus_version;
 
 /*
- * VMBus Version Supported parameters
- */
-typedef struct {
-	hv_vmbus_channel_msg_header	header;
-	hv_bool_uint8_t			version_supported;
-} __packed hv_vmbus_channel_version_supported;
-
-/*
  * Channel Offer parameters
  */
 typedef struct {
@@ -397,171 +387,13 @@ typedef struct
     uint32_t			child_rel_id;
 } __packed hv_vmbus_channel_rescind_offer;
 
-
-/*
- * Request Offer -- no parameters, SynIC message contains the partition ID
- *
- * Set Snoop -- no parameters, SynIC message contains the partition ID
- *
- * Clear Snoop -- no parameters, SynIC message contains the partition ID
- *
- * All Offers Delivered -- no parameters, SynIC message contains the
- * partition ID
- *
- * Flush Client -- no parameters, SynIC message contains the partition ID
- */
-
-
-/*
- * Open Channel parameters
- */
-typedef struct
-{
-    hv_vmbus_channel_msg_header header;
-
-    /*
-     * Identifies the specific VMBus channel that is being opened.
-     */
-    uint32_t		child_rel_id;
-
-    /*
-     * ID making a particular open request at a channel offer unique.
-     */
-    uint32_t		open_id;
-
-    /*
-     * GPADL for the channel's ring buffer.
-     */
-    hv_gpadl_handle	ring_buffer_gpadl_handle;
-
-    /*
-     * Before win8, all incoming channel interrupts are only
-     * delivered on cpu 0. Setting this value to 0 would
-     * preserve the earlier behavior.
-     */
-    uint32_t		target_vcpu;
-
-    /*
-     * The upstream ring buffer begins at offset zero in the memory described
-     * by ring_buffer_gpadl_handle. The downstream ring buffer follows it at
-     * this offset (in pages).
-     */
-    uint32_t		downstream_ring_buffer_page_offset;
-
-    /*
-     * User-specific data to be passed along to the server endpoint.
-     */
-    uint8_t		user_data[HV_MAX_USER_DEFINED_BYTES];
-
-} __packed hv_vmbus_channel_open_channel;
-
-typedef uint32_t hv_nt_status;
-
-/*
- * Open Channel Result parameters
- */
-typedef struct
-{
-	hv_vmbus_channel_msg_header	header;
-	uint32_t			child_rel_id;
-	uint32_t			open_id;
-	hv_nt_status			status;
-} __packed hv_vmbus_channel_open_result;
-
-/*
- * Close channel parameters
- */
-typedef struct
-{
-	hv_vmbus_channel_msg_header	header;
-	uint32_t			child_rel_id;
-} __packed hv_vmbus_channel_close_channel;
-
-/*
- * Channel Message GPADL
- */
-#define HV_GPADL_TYPE_RING_BUFFER	1
-#define HV_GPADL_TYPE_SERVER_SAVE_AREA	2
-#define HV_GPADL_TYPE_TRANSACTION	8
-
-/*
- * The number of PFNs in a GPADL message is defined by the number of pages
- * that would be spanned by byte_count and byte_offset.  If the implied number
- * of PFNs won't fit in this packet, there will be a follow-up packet that
- * contains more
- */
-
-typedef struct {
-	hv_vmbus_channel_msg_header	header;
-	uint32_t			child_rel_id;
-	uint32_t			gpadl;
-	uint16_t			range_buf_len;
-	uint16_t			range_count;
-	hv_gpa_range			range[0];
-} __packed hv_vmbus_channel_gpadl_header;
-
-/*
- * This is the follow-up packet that contains more PFNs
- */
-typedef struct {
-	hv_vmbus_channel_msg_header	header;
-	uint32_t			message_number;
-	uint32_t 			gpadl;
-	uint64_t 			pfn[0];
-} __packed hv_vmbus_channel_gpadl_body;
-
-typedef struct {
-	hv_vmbus_channel_msg_header	header;
-	uint32_t			child_rel_id;
-	uint32_t			gpadl;
-	uint32_t			creation_status;
-} __packed hv_vmbus_channel_gpadl_created;
-
-typedef struct {
-	hv_vmbus_channel_msg_header	header;
-	uint32_t			child_rel_id;
-	uint32_t			gpadl;
-} __packed hv_vmbus_channel_gpadl_teardown;
-
-typedef struct {
-	hv_vmbus_channel_msg_header	header;
-	uint32_t			gpadl;
-} __packed hv_vmbus_channel_gpadl_torndown;
-
 typedef struct {
 	hv_vmbus_channel_msg_header	header;
 	uint32_t			child_rel_id;
 } __packed hv_vmbus_channel_relid_released;
 
-typedef hv_vmbus_channel_msg_header hv_vmbus_channel_unload;
-
 #define HW_MACADDR_LEN	6
 
-/*
- * Fixme:  Added to quiet "typeof" errors involving hv_vmbus.h when
- * the including C file was compiled with "-std=c99".
- */
-#ifndef typeof
-#define typeof __typeof
-#endif
-
-#ifndef NULL
-#define NULL  (void *)0
-#endif
-
-typedef void *hv_vmbus_handle;
-
-#ifndef CONTAINING_RECORD
-#define CONTAINING_RECORD(address, type, field) ((type *)(	\
-		(uint8_t *)(address) -				\
-		(uint8_t *)(&((type *)0)->field)))
-#endif /* CONTAINING_RECORD */
-
-
-#define container_of(ptr, type, member) ({				\
-		__typeof__( ((type *)0)->member ) *__mptr = (ptr);	\
-		(type *)( (char *)__mptr - offsetof(type,member) );})
-
 enum {
 	HV_VMBUS_IVAR_TYPE,
 	HV_VMBUS_IVAR_INSTANCE,

Modified: stable/11/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/11/sys/dev/hyperv/vmbus/hv_channel.c	Fri Oct 14 07:47:07 2016	(r307300)
+++ stable/11/sys/dev/hyperv/vmbus/hv_channel.c	Fri Oct 14 07:47:35 2016	(r307301)
@@ -49,14 +49,6 @@ __FBSDID("$FreeBSD$");
 #include <dev/hyperv/vmbus/vmbus_reg.h>
 #include <dev/hyperv/vmbus/vmbus_var.h>
 
-static int 	vmbus_channel_create_gpadl_header(
-			/* must be phys and virt contiguous*/
-			void*				contig_buffer,
-			/* page-size multiple */
-			uint32_t 			size,
-			hv_vmbus_channel_msg_info**	msg_info,
-			uint32_t*			message_count);
-
 static void 	vmbus_channel_set_event(hv_vmbus_channel* channel);
 static void	VmbusProcessChannelEvent(void* channel, int pending);
 
@@ -182,11 +174,21 @@ hv_vmbus_channel_open(
 	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,381 +250,231 @@ hv_vmbus_channel_open(
 		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));
+		memcpy(req->chm_udata, user_data, user_data_len);
 
-	if (ret != 0)
-	    goto cleanup;
-
-	ret = sema_timedwait(&open_info->wait_sema, 5 * hz); /* KYS 5 seconds */
-
-	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);
 }
 
 /**
- * @brief Create a gpadl for the specified buffer
- */
-static int
-vmbus_channel_create_gpadl_header(
-	void*				contig_buffer,
-	uint32_t			size,	/* page-size multiple */
-	hv_vmbus_channel_msg_info**	msg_info,
-	uint32_t*			message_count)
-{
-	int				i;
-	int				page_count;
-	unsigned long long 		pfn;
-	uint32_t			msg_size;
-	hv_vmbus_channel_gpadl_header*	gpa_header;
-	hv_vmbus_channel_gpadl_body*	gpadl_body;
-	hv_vmbus_channel_msg_info*	msg_header;
-	hv_vmbus_channel_msg_info*	msg_body;
-
-	int pfnSum, pfnCount, pfnLeft, pfnCurr, pfnSize;
-
-	page_count = size >> PAGE_SHIFT;
-	pfn = hv_get_phys_addr(contig_buffer) >> PAGE_SHIFT;
-
-	/*do we need a gpadl body msg */
-	pfnSize = HV_MAX_SIZE_CHANNEL_MESSAGE
-	    - sizeof(hv_vmbus_channel_gpadl_header)
-	    - sizeof(hv_gpa_range);
-	pfnCount = pfnSize / sizeof(uint64_t);
-
-	if (page_count > pfnCount) { /* if(we need a gpadl body)	*/
-	    /* fill in the header		*/
-	    msg_size = sizeof(hv_vmbus_channel_msg_info)
-		+ sizeof(hv_vmbus_channel_gpadl_header)
-		+ sizeof(hv_gpa_range)
-		+ pfnCount * sizeof(uint64_t);
-	    msg_header = malloc(msg_size, M_DEVBUF, M_NOWAIT | M_ZERO);
-	    KASSERT(
-		msg_header != NULL,
-		("Error VMBUS: malloc failed to allocate Gpadl Message!"));
-	    if (msg_header == NULL)
-		return (ENOMEM);
-
-	    TAILQ_INIT(&msg_header->sub_msg_list_anchor);
-	    msg_header->message_size = msg_size;
-
-	    gpa_header = (hv_vmbus_channel_gpadl_header*) msg_header->msg;
-	    gpa_header->range_count = 1;
-	    gpa_header->range_buf_len = sizeof(hv_gpa_range)
-		+ page_count * sizeof(uint64_t);
-	    gpa_header->range[0].byte_offset = 0;
-	    gpa_header->range[0].byte_count = size;
-	    for (i = 0; i < pfnCount; i++) {
-		gpa_header->range[0].pfn_array[i] = pfn + i;
-	    }
-	    *msg_info = msg_header;
-	    *message_count = 1;
-
-	    pfnSum = pfnCount;
-	    pfnLeft = page_count - pfnCount;
-
-	    /*
-	     *  figure out how many pfns we can fit
-	     */
-	    pfnSize = HV_MAX_SIZE_CHANNEL_MESSAGE
-		- sizeof(hv_vmbus_channel_gpadl_body);
-	    pfnCount = pfnSize / sizeof(uint64_t);
-
-	    /*
-	     * fill in the body
-	     */
-	    while (pfnLeft) {
-		if (pfnLeft > pfnCount) {
-		    pfnCurr = pfnCount;
-		} else {
-		    pfnCurr = pfnLeft;
-		}
-
-		msg_size = sizeof(hv_vmbus_channel_msg_info) +
-		    sizeof(hv_vmbus_channel_gpadl_body) +
-		    pfnCurr * sizeof(uint64_t);
-		msg_body = malloc(msg_size, M_DEVBUF, M_NOWAIT | M_ZERO);
-		KASSERT(
-		    msg_body != NULL,
-		    ("Error VMBUS: malloc failed to allocate Gpadl msg_body!"));
-		if (msg_body == NULL)
-		    return (ENOMEM);
-
-		msg_body->message_size = msg_size;
-		(*message_count)++;
-		gpadl_body =
-		    (hv_vmbus_channel_gpadl_body*) msg_body->msg;
-		/*
-		 * gpadl_body->gpadl = kbuffer;
-		 */
-		for (i = 0; i < pfnCurr; i++) {
-		    gpadl_body->pfn[i] = pfn + pfnSum + i;
-		}
-
-		TAILQ_INSERT_TAIL(
-		    &msg_header->sub_msg_list_anchor,
-		    msg_body,
-		    msg_list_entry);
-		pfnSum += pfnCurr;
-		pfnLeft -= pfnCurr;
-	    }
-	} else { /* else everything fits in a header */
-
-	    msg_size = sizeof(hv_vmbus_channel_msg_info) +
-		sizeof(hv_vmbus_channel_gpadl_header) +
-		sizeof(hv_gpa_range) +
-		page_count * sizeof(uint64_t);
-	    msg_header = malloc(msg_size, M_DEVBUF, M_NOWAIT | M_ZERO);
-	    KASSERT(
-		msg_header != NULL,
-		("Error VMBUS: malloc failed to allocate Gpadl Message!"));
-	    if (msg_header == NULL)
-		return (ENOMEM);
-
-	    msg_header->message_size = msg_size;
-
-	    gpa_header = (hv_vmbus_channel_gpadl_header*) msg_header->msg;
-	    gpa_header->range_count = 1;
-	    gpa_header->range_buf_len = sizeof(hv_gpa_range) +
-		page_count * sizeof(uint64_t);
-	    gpa_header->range[0].byte_offset = 0;
-	    gpa_header->range[0].byte_count = size;
-	    for (i = 0; i < page_count; i++) {
-		gpa_header->range[0].pfn_array[i] = pfn + i;
-	    }
-
-	    *msg_info = msg_header;
-	    *message_count = 1;
-	}
-
-	return (0);
-}
-
-/**
  * @brief Establish a GPADL for the specified buffer
  */
 int
-hv_vmbus_channel_establish_gpadl(
-	hv_vmbus_channel*	channel,
-	void*			contig_buffer,
-	uint32_t		size, /* page-size multiple */
-	uint32_t*		gpadl_handle)
-
+hv_vmbus_channel_establish_gpadl(struct hv_vmbus_channel *channel,
+    void *contig_buffer, uint32_t size, uint32_t *gpadl0)
 {
-	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);
+	struct vmbus_softc *sc = channel->vmbus_sc;
+	struct vmbus_msghc *mh;
+	struct vmbus_chanmsg_gpadl_conn *req;
+	const struct vmbus_message *msg;
+	size_t reqsz;
+	uint32_t gpadl, status;
+	int page_count, range_len, i, cnt, error;
+	uint64_t page_id, paddr;
 
-	if(ret != 0) {
-		/*
-		 * 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 ...
-		 */
-		return ret;
-	}
+	/*
+	 * Preliminary checks.
+	 */
 
-	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));
+	KASSERT((size & PAGE_MASK) == 0,
+	    ("invalid GPA size %u, not multiple page size", size));
+	page_count = size >> PAGE_SHIFT;
 
-	if (ret != 0)
-	    goto cleanup;
+	paddr = hv_get_phys_addr(contig_buffer);
+	KASSERT((paddr & PAGE_MASK) == 0,
+	    ("GPA is not page aligned %jx", (uintmax_t)paddr));
+	page_id = paddr >> PAGE_SHIFT;
 
-	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 (the post message failed) give up and clean up */
-		if(ret != 0)
-		    goto cleanup;
-	    }
+	range_len = __offsetof(struct vmbus_gpa_range, gpa_page[page_count]);
+	/*
+	 * We don't support multiple GPA ranges.
+	 */
+	if (range_len > UINT16_MAX) {
+		device_printf(sc->vmbus_dev, "GPA too large, %d pages\n",
+		    page_count);
+		return EOPNOTSUPP;
 	}
 
-	ret = sema_timedwait(&msg_info->wait_sema, 5 * hz); /* KYS 5 seconds*/
-	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);
+	/*
+	 * Allocate GPADL id.
+	 */
+	gpadl = atomic_fetchadd_int(
+	    &hv_vmbus_g_connection.next_gpadl_handle, 1);
+	*gpadl0 = gpadl;
 
-	return (ret);
+	/*
+	 * Connect this GPADL to the target channel.
+	 *
+	 * NOTE:
+	 * Since each message can only hold small set of page
+	 * addresses, several messages may be required to
+	 * complete the connection.
+	 */
+	if (page_count > VMBUS_CHANMSG_GPADL_CONN_PGMAX)
+		cnt = VMBUS_CHANMSG_GPADL_CONN_PGMAX;
+	else
+		cnt = page_count;
+	page_count -= cnt;
+
+	reqsz = __offsetof(struct vmbus_chanmsg_gpadl_conn,
+	    chm_range.gpa_page[cnt]);
+	mh = vmbus_msghc_get(sc, reqsz);
+	if (mh == NULL) {
+		device_printf(sc->vmbus_dev,
+		    "can not get msg hypercall for gpadl->chan%u\n",
+		    channel->offer_msg.child_rel_id);
+		return EIO;
+	}
+
+	req = vmbus_msghc_dataptr(mh);
+	req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_CONN;
+	req->chm_chanid = channel->offer_msg.child_rel_id;
+	req->chm_gpadl = gpadl;
+	req->chm_range_len = range_len;
+	req->chm_range_cnt = 1;
+	req->chm_range.gpa_len = size;
+	req->chm_range.gpa_ofs = 0;
+	for (i = 0; i < cnt; ++i)
+		req->chm_range.gpa_page[i] = page_id++;
+
+	error = vmbus_msghc_exec(sc, mh);
+	if (error) {
+		device_printf(sc->vmbus_dev,
+		    "gpadl->chan%u msg hypercall exec failed: %d\n",
+		    channel->offer_msg.child_rel_id, error);
+		vmbus_msghc_put(sc, mh);
+		return error;
+	}
+
+	while (page_count > 0) {
+		struct vmbus_chanmsg_gpadl_subconn *subreq;
+
+		if (page_count > VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX)
+			cnt = VMBUS_CHANMSG_GPADL_SUBCONN_PGMAX;
+		else
+			cnt = page_count;
+		page_count -= cnt;
+
+		reqsz = __offsetof(struct vmbus_chanmsg_gpadl_subconn,
+		    chm_gpa_page[cnt]);
+		vmbus_msghc_reset(mh, reqsz);
+
+		subreq = vmbus_msghc_dataptr(mh);
+		subreq->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_SUBCONN;
+		subreq->chm_gpadl = gpadl;
+		for (i = 0; i < cnt; ++i)
+			subreq->chm_gpa_page[i] = page_id++;
+
+		vmbus_msghc_exec_noresult(mh);
+	}
+	KASSERT(page_count == 0, ("invalid page count %d", page_count));
+
+	msg = vmbus_msghc_wait_result(sc, mh);
+	status = ((const struct vmbus_chanmsg_gpadl_connresp *)
+	    msg->msg_data)->chm_status;
+
+	vmbus_msghc_put(sc, mh);
+
+	if (status != 0) {
+		device_printf(sc->vmbus_dev, "gpadl->chan%u failed: "
+		    "status %u\n", channel->offer_msg.child_rel_id, status);
+		return EIO;
+	}
+	return 0;
 }
 
-/**
- * @brief Teardown the specified GPADL handle
+/*
+ * Disconnect the GPA from the target channel
  */
 int
-hv_vmbus_channel_teardown_gpdal(
-	hv_vmbus_channel*	channel,
-	uint32_t		gpadl_handle)
+hv_vmbus_channel_teardown_gpdal(struct hv_vmbus_channel *chan, uint32_t gpadl)
 {
-	int					ret = 0;
-	hv_vmbus_channel_gpadl_teardown*	msg;
-	hv_vmbus_channel_msg_info*		info;
-
-	info = (hv_vmbus_channel_msg_info *)
-		malloc(	sizeof(hv_vmbus_channel_msg_info) +
-			sizeof(hv_vmbus_channel_gpadl_teardown),
-				M_DEVBUF, M_NOWAIT);
-	KASSERT(info != NULL,
-	    ("Error VMBUS: malloc failed to allocate Gpadl Teardown Msg!"));
-	if (info == NULL) {
-	    ret = ENOMEM;
-	    goto cleanup;
-	}
-
-	sema_init(&info->wait_sema, 0, "Open Info Sema");
-
-	msg = (hv_vmbus_channel_gpadl_teardown*) info->msg;
-
-	msg->header.message_type = HV_CHANNEL_MESSAGE_GPADL_TEARDOWN;
-	msg->child_rel_id = channel->offer_msg.child_rel_id;
-	msg->gpadl = gpadl_handle;
-
-	mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
-	TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_msg_anchor,
-			info, msg_list_entry);
-	mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
-
-	ret = hv_vmbus_post_message(msg,
-			sizeof(hv_vmbus_channel_gpadl_teardown));
-	if (ret != 0) 
-	    goto cleanup;
-	
-	ret = sema_timedwait(&info->wait_sema, 5 * hz); /* KYS 5 seconds */
-
-cleanup:
-	/*
-	 * Received a torndown response
-	 */
-	mtx_lock(&hv_vmbus_g_connection.channel_msg_lock);
-	TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor,
-			info, msg_list_entry);
-	mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
-	sema_destroy(&info->wait_sema);
-	free(info, M_DEVBUF);
+	struct vmbus_softc *sc = chan->vmbus_sc;
+	struct vmbus_msghc *mh;
+	struct vmbus_chanmsg_gpadl_disconn *req;
+	int error;
+
+	mh = vmbus_msghc_get(sc, sizeof(*req));
+	if (mh == NULL) {
+		device_printf(sc->vmbus_dev,
+		    "can not get msg hypercall for gpa x->chan%u\n",
+		    chan->offer_msg.child_rel_id);
+		return EBUSY;
+	}
+
+	req = vmbus_msghc_dataptr(mh);
+	req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_GPADL_DISCONN;
+	req->chm_chanid = chan->offer_msg.child_rel_id;
+	req->chm_gpadl = gpadl;
+
+	error = vmbus_msghc_exec(sc, mh);
+	if (error) {
+		device_printf(sc->vmbus_dev,
+		    "gpa x->chan%u msg hypercall exec failed: %d\n",
+		    chan->offer_msg.child_rel_id, error);
+		vmbus_msghc_put(sc, mh);
+		return error;
+	}
+
+	vmbus_msghc_wait_result(sc, mh);
+	/* Discard result; no useful information */
+	vmbus_msghc_put(sc, mh);
 
-	return (ret);
+	return 0;
 }
 
 static void
 hv_vmbus_channel_close_internal(hv_vmbus_channel *channel)
 {
-	int ret = 0;
+	struct vmbus_softc *sc = channel->vmbus_sc;
+	struct vmbus_msghc *mh;
+	struct vmbus_chanmsg_chclose *req;
 	struct taskqueue *rxq = channel->rxq;
-	hv_vmbus_channel_close_channel* msg;
-	hv_vmbus_channel_msg_info* info;
+	int error;
 
 	channel->state = HV_CHANNEL_OPEN_STATE;
 
@@ -636,20 +488,31 @@ hv_vmbus_channel_close_internal(hv_vmbus
 	/**
 	 * Send a closing message
 	 */
-	info = (hv_vmbus_channel_msg_info *)
-		malloc(	sizeof(hv_vmbus_channel_msg_info) +
-			sizeof(hv_vmbus_channel_close_channel),
-				M_DEVBUF, M_NOWAIT);
-	KASSERT(info != NULL, ("VMBUS: malloc failed hv_vmbus_channel_close!"));
-	if(info == NULL)
-	    return;
-
-	msg = (hv_vmbus_channel_close_channel*) info->msg;
-	msg->header.message_type = HV_CHANNEL_MESSAGE_CLOSE_CHANNEL;
-	msg->child_rel_id = channel->offer_msg.child_rel_id;
 
-	ret = hv_vmbus_post_message(
-		msg, sizeof(hv_vmbus_channel_close_channel));
+	mh = vmbus_msghc_get(sc, sizeof(*req));
+	if (mh == NULL) {
+		device_printf(sc->vmbus_dev,
+		    "can not get msg hypercall for chclose(chan%u)\n",
+		    channel->offer_msg.child_rel_id);
+		return;
+	}
+
+	req = vmbus_msghc_dataptr(mh);
+	req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHCLOSE;
+	req->chm_chanid = channel->offer_msg.child_rel_id;
+
+	error = vmbus_msghc_exec_noresult(mh);
+	vmbus_msghc_put(sc, mh);
+
+	if (error) {
+		device_printf(sc->vmbus_dev,
+		    "chclose(chan%u) msg hypercall exec failed: %d\n",
+		    channel->offer_msg.child_rel_id, error);
+		return;
+	} else if (bootverbose) {
+		device_printf(sc->vmbus_dev, "close chan%u\n",
+		    channel->offer_msg.child_rel_id);
+	}
 
 	/* Tear down the gpadl for the channel's ring buffer */
 	if (channel->ring_buffer_gpadl_handle) {
@@ -665,8 +528,6 @@ hv_vmbus_channel_close_internal(hv_vmbus
 
 	contigfree(channel->ring_buffer_pages, channel->ring_buffer_size,
 	    M_DEVBUF);
-
-	free(info, M_DEVBUF);
 }
 
 /**
@@ -988,23 +849,6 @@ VmbusProcessChannelEvent(void* context, 
 	hv_vmbus_channel* channel = (hv_vmbus_channel*)context;
 	boolean_t is_batched_reading;
 
-	/**
-	 * Find the channel based on this relid and invokes
-	 * the channel callback to process the event
-	 */
-
-	if (channel == NULL) {
-		return;
-	}
-	/**
-	 * To deal with the race condition where we might
-	 * receive a packet while the relevant driver is
-	 * being unloaded, dispatch the callback while
-	 * holding the channel lock. The unloading driver
-	 * will acquire the same channel lock to set the
-	 * callback to NULL. This closes the window.
-	 */
-
 	if (channel->on_channel_callback != NULL) {
 		arg = channel->channel_callback_context;
 		is_batched_reading = channel->batched_reading;

Modified: stable/11/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
==============================================================================
--- stable/11/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Fri Oct 14 07:47:07 2016	(r307300)
+++ stable/11/sys/dev/hyperv/vmbus/hv_channel_mgmt.c	Fri Oct 14 07:47:35 2016	(r307301)
@@ -418,46 +418,13 @@ vmbus_channel_on_offers_delivered(struct
  * @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);
 }
 
 /**
@@ -471,39 +438,7 @@ static void
 vmbus_channel_on_gpadl_created(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_gpadl_created *gpadl_created;
-	hv_vmbus_channel_msg_info*		msg_info;
-	hv_vmbus_channel_msg_header*		request_header;
-	hv_vmbus_channel_gpadl_header*		gpadl_header;
-
-	gpadl_created = (const hv_vmbus_channel_gpadl_created *)hdr;
-
-	/* Find the establish 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) {
-	    request_header = (hv_vmbus_channel_msg_header*) msg_info->msg;
-	    if (request_header->message_type ==
-		    HV_CHANNEL_MESSAGEL_GPADL_HEADER) {
-		gpadl_header =
-		    (hv_vmbus_channel_gpadl_header*) request_header;
-
-		if ((gpadl_created->child_rel_id == gpadl_header->child_rel_id)
-		    && (gpadl_created->gpadl == gpadl_header->gpadl)) {
-		    memcpy(&msg_info->response.gpadl_created,
-			gpadl_created,
-			sizeof(hv_vmbus_channel_gpadl_created));
-		    sema_post(&msg_info->wait_sema);
-		    break;
-		}
-	    }
-	}
-	mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
+	vmbus_msghc_wakeup(sc, msg);
 }
 
 /**
@@ -517,42 +452,7 @@ static void
 vmbus_channel_on_gpadl_torndown(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_gpadl_torndown *gpadl_torndown;
-	hv_vmbus_channel_msg_info*		msg_info;
-	hv_vmbus_channel_msg_header*		requestHeader;
-	hv_vmbus_channel_gpadl_teardown*	gpadlTeardown;
-
-	gpadl_torndown = (const hv_vmbus_channel_gpadl_torndown *)hdr;
-
-	/*
-	 * Find the open msg, copy the result and signal/unblock the
-	 * wait event.

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610140747.u9E7lZKa074108>