Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Oct 2016 02:28:40 +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-10@freebsd.org
Subject:   svn commit: r307164 - in stable/10/sys: conf dev/hyperv/include dev/hyperv/netvsc dev/hyperv/vmbus modules/hyperv/vmbus
Message-ID:  <201610130228.u9D2SeiU099968@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Thu Oct 13 02:28:40 2016
New Revision: 307164
URL: https://svnweb.freebsd.org/changeset/base/307164

Log:
  MFC 303945,303947-303949,303989,303992,303998,304001,304002,304109,304111
  
  303945
      hyperv/vmbus: Add macro to get channel packet data length.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7455
  
  303947
      hyperv/vmbus: Add APIs for various types of transactions.
  
      Reviewed by:    Jun Su <junsu microsoft com>
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7456
  
  303948
      hyperv/hn: Switch to vmbus xact APIs for NVS initialization
  
      Reviewed by:    Jun Su <junsu microsoft com>
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7457
  
  303949
      hyperv/vmbus: Use xact APIs to implement post message Hypercall APIs
  
      Avoid code duplication.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7458
  
  303989
      hyperv/hn: Simplify NDIS configuration.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7466
  
  303992
      hyperv/hn: Simplify NDIS initialization.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7467
  
  303998
      hyperv/hn: Switch to vmbus xact APIs for NVS RXBUF connection.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7469
  
  304001
      hyperv/hn: Switch to vmbus xact APIs for NVS chimney buffer connection.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7470
  
  304002
      hyperv/hn: Simplify RXBUF disconnection.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7472
  
  304109
      hyperv/hn: Simplify chimney sending buffer disconnection.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7479
  
  304111
      hyperv/hn: Switch to vmbus xact APIs for sub-channel alloc request.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7480

Added:
  stable/10/sys/dev/hyperv/include/vmbus_xact.h
     - copied, changed from r303947, head/sys/dev/hyperv/include/vmbus_xact.h
  stable/10/sys/dev/hyperv/netvsc/if_hnreg.h
     - copied, changed from r303948, head/sys/dev/hyperv/netvsc/if_hnreg.h
  stable/10/sys/dev/hyperv/vmbus/vmbus_xact.c
     - copied, changed from r303947, head/sys/dev/hyperv/vmbus/vmbus_xact.c
Modified:
  stable/10/sys/conf/files.amd64
  stable/10/sys/conf/files.i386
  stable/10/sys/dev/hyperv/include/vmbus.h
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/netvsc/hv_rndis.h
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  stable/10/sys/dev/hyperv/netvsc/if_hnvar.h
  stable/10/sys/dev/hyperv/vmbus/vmbus.c
  stable/10/sys/dev/hyperv/vmbus/vmbus_var.h
  stable/10/sys/modules/hyperv/vmbus/Makefile
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/conf/files.amd64
==============================================================================
--- stable/10/sys/conf/files.amd64	Thu Oct 13 02:06:23 2016	(r307163)
+++ stable/10/sys/conf/files.amd64	Thu Oct 13 02:28:40 2016	(r307164)
@@ -278,6 +278,7 @@ dev/hyperv/vmbus/vmbus_br.c				optional	
 dev/hyperv/vmbus/vmbus_chan.c				optional	hyperv
 dev/hyperv/vmbus/vmbus_et.c				optional	hyperv
 dev/hyperv/vmbus/vmbus_if.m				optional	hyperv
+dev/hyperv/vmbus/vmbus_xact.c				optional	hyperv
 dev/hyperv/vmbus/amd64/hyperv_machdep.c			optional	hyperv
 dev/hyperv/vmbus/amd64/vmbus_vector.S			optional	hyperv
 dev/lindev/full.c		optional	lindev

Modified: stable/10/sys/conf/files.i386
==============================================================================
--- stable/10/sys/conf/files.i386	Thu Oct 13 02:06:23 2016	(r307163)
+++ stable/10/sys/conf/files.i386	Thu Oct 13 02:28:40 2016	(r307164)
@@ -255,6 +255,7 @@ dev/hyperv/vmbus/vmbus_br.c				optional	
 dev/hyperv/vmbus/vmbus_chan.c				optional	hyperv
 dev/hyperv/vmbus/vmbus_et.c				optional	hyperv
 dev/hyperv/vmbus/vmbus_if.m				optional	hyperv
+dev/hyperv/vmbus/vmbus_xact.c				optional	hyperv
 dev/hyperv/vmbus/i386/hyperv_machdep.c			optional	hyperv
 dev/hyperv/vmbus/i386/vmbus_vector.S			optional	hyperv
 dev/ichwd/ichwd.c		optional ichwd

Modified: stable/10/sys/dev/hyperv/include/vmbus.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/vmbus.h	Thu Oct 13 02:06:23 2016	(r307163)
+++ stable/10/sys/dev/hyperv/include/vmbus.h	Thu Oct 13 02:28:40 2016	(r307164)
@@ -90,6 +90,11 @@ struct vmbus_chanpkt_hdr {
 	(const void *)((const uint8_t *)(pkt) +	\
 	VMBUS_CHANPKT_GETLEN((pkt)->cph_hlen))
 
+/* Include padding */
+#define VMBUS_CHANPKT_DATALEN(pkt)		\
+	(VMBUS_CHANPKT_GETLEN((pkt)->cph_tlen) -\
+	 VMBUS_CHANPKT_GETLEN((pkt)->cph_hlen))
+
 struct vmbus_rxbuf_desc {
 	uint32_t	rb_len;
 	uint32_t	rb_ofs;

Copied and modified: stable/10/sys/dev/hyperv/include/vmbus_xact.h (from r303947, head/sys/dev/hyperv/include/vmbus_xact.h)
==============================================================================
--- head/sys/dev/hyperv/include/vmbus_xact.h	Thu Aug 11 05:49:49 2016	(r303947, copy source)
+++ stable/10/sys/dev/hyperv/include/vmbus_xact.h	Thu Oct 13 02:28:40 2016	(r307164)
@@ -31,12 +31,14 @@
 
 #include <sys/param.h>
 #include <sys/bus.h>
+#include <machine/bus.h>
 
 struct vmbus_xact;
 struct vmbus_xact_ctx;
 
 struct vmbus_xact_ctx	*vmbus_xact_ctx_create(bus_dma_tag_t dtag,
-			    size_t req_size, size_t resp_size);
+			    size_t req_size, size_t resp_size,
+			    size_t priv_size);
 void			vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx);
 struct vmbus_xact	*vmbus_xact_get(struct vmbus_xact_ctx *ctx,
 			    size_t req_len);
@@ -44,11 +46,15 @@ void			vmbus_xact_put(struct vmbus_xact 
 
 void			*vmbus_xact_req_data(const struct vmbus_xact *xact);
 bus_addr_t		vmbus_xact_req_paddr(const struct vmbus_xact *xact);
+void			*vmbus_xact_priv(const struct vmbus_xact *xact,
+			    size_t priv_len);
 void			vmbus_xact_activate(struct vmbus_xact *xact);
 void			vmbus_xact_deactivate(struct vmbus_xact *xact);
 const void		*vmbus_xact_wait(struct vmbus_xact *xact,
 			    size_t *resp_len);
 void			vmbus_xact_wakeup(struct vmbus_xact *xact,
 			    const void *data, size_t dlen);
+void			vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx,
+			    const void *data, size_t dlen);
 
 #endif	/* !_VMBUS_XACT_H_ */

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Thu Oct 13 02:06:23 2016	(r307163)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Thu Oct 13 02:28:40 2016	(r307164)
@@ -44,9 +44,11 @@
 #include <machine/atomic.h>
 
 #include <dev/hyperv/include/hyperv.h>
-#include "hv_net_vsc.h"
-#include "hv_rndis.h"
-#include "hv_rndis_filter.h"
+#include <dev/hyperv/include/vmbus_xact.h>
+#include <dev/hyperv/netvsc/hv_net_vsc.h>
+#include <dev/hyperv/netvsc/hv_rndis.h>
+#include <dev/hyperv/netvsc/hv_rndis_filter.h>
+#include <dev/hyperv/netvsc/if_hnreg.h>
 
 MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver");
 
@@ -69,7 +71,7 @@ static void hv_nv_on_receive(netvsc_dev 
     const struct vmbus_chanpkt_hdr *pkt);
 static void hn_nvs_sent_none(struct hn_send_ctx *sndc,
     struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
-    const struct nvsp_msg_ *msg);
+    const struct nvsp_msg_ *msg, int);
 
 static struct hn_send_ctx	hn_send_ctx_none =
     HN_SEND_CTX_INITIALIZER(hn_nvs_sent_none, NULL);
@@ -146,10 +148,14 @@ hv_nv_get_next_send_section(netvsc_dev *
 static int 
 hv_nv_init_rx_buffer_with_net_vsp(struct hn_softc *sc)
 {
+	struct vmbus_xact *xact;
+	struct hn_nvs_rxbuf_conn *conn;
+	const struct hn_nvs_rxbuf_connresp *resp;
+	size_t resp_len;
 	struct hn_send_ctx sndc;
 	netvsc_dev *net_dev;
-	nvsp_msg *init_pkt;
-	int ret = 0;
+	uint32_t status;
+	int error;
 
 	net_dev = hv_nv_get_outbound_net_device(sc);
 	if (!net_dev) {
@@ -161,7 +167,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
 	    BUS_DMA_WAITOK | BUS_DMA_ZERO);
 	if (net_dev->rx_buf == NULL) {
 		device_printf(sc->hn_dev, "allocate rxbuf failed\n");
-		return ENOMEM;
+		return (ENOMEM);
 	}
 
 	/*
@@ -171,74 +177,76 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
 	 * Only primary channel has RXBUF connected to it.  Sub-channels
 	 * just share this RXBUF.
 	 */
-	ret = vmbus_chan_gpadl_connect(sc->hn_prichan,
+	error = vmbus_chan_gpadl_connect(sc->hn_prichan,
 	    net_dev->rxbuf_dma.hv_paddr, net_dev->rx_buf_size,
 	    &net_dev->rx_buf_gpadl_handle);
-	if (ret != 0) {
-		device_printf(sc->hn_dev, "rxbuf gpadl connect failed: %d\n",
-		    ret);
+	if (error) {
+		if_printf(sc->hn_ifp, "rxbuf gpadl connect failed: %d\n",
+		    error);
 		goto cleanup;
 	}
-	
-	/* sema_wait(&ext->channel_init_sema); KYS CHECK */
 
-	/* Notify the NetVsp of the gpadl handle */
-	init_pkt = &net_dev->channel_init_packet;
+	/*
+	 * Connect RXBUF to NVS.
+	 */
 
-	memset(init_pkt, 0, sizeof(nvsp_msg));
+	xact = vmbus_xact_get(sc->hn_xact, sizeof(*conn));
+	if (xact == NULL) {
+		if_printf(sc->hn_ifp, "no xact for nvs rxbuf conn\n");
+		error = ENXIO;
+		goto cleanup;
+	}
 
-	init_pkt->hdr.msg_type = nvsp_msg_1_type_send_rx_buf;
-	init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle =
-	    net_dev->rx_buf_gpadl_handle;
-	init_pkt->msgs.vers_1_msgs.send_rx_buf.id =
-	    NETVSC_RECEIVE_BUFFER_ID;
+	conn = vmbus_xact_req_data(xact);
+	conn->nvs_type = HN_NVS_TYPE_RXBUF_CONN;
+	conn->nvs_gpadl = net_dev->rx_buf_gpadl_handle;
+	conn->nvs_sig = HN_NVS_RXBUF_SIG;
 
-	/* Send the gpadl notification request */
+	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+	vmbus_xact_activate(xact);
 
-	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
-	ret = vmbus_chan_send(sc->hn_prichan,
+	error = vmbus_chan_send(sc->hn_prichan,
 	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-	    init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
-	if (ret != 0) {
+	    conn, sizeof(*conn), (uint64_t)(uintptr_t)&sndc);
+	if (error != 0) {
+		if_printf(sc->hn_ifp, "send nvs rxbuf conn failed: %d\n",
+		    error);
+		vmbus_xact_deactivate(xact);
+		vmbus_xact_put(xact);
 		goto cleanup;
 	}
 
-	sema_wait(&net_dev->channel_init_sema);
-
-	/* Check the response */
-	if (init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.status
-	    != nvsp_status_success) {
-		ret = EINVAL;
+	resp = vmbus_xact_wait(xact, &resp_len);
+	if (resp_len < sizeof(*resp)) {
+		if_printf(sc->hn_ifp, "invalid rxbuf conn resp length %zu\n",
+		    resp_len);
+		vmbus_xact_put(xact);
+		error = EINVAL;
+		goto cleanup;
+	}
+	if (resp->nvs_type != HN_NVS_TYPE_RXBUF_CONNRESP) {
+		if_printf(sc->hn_ifp, "not rxbuf conn resp, type %u\n",
+		    resp->nvs_type);
+		vmbus_xact_put(xact);
+		error = EINVAL;
 		goto cleanup;
 	}
 
-	net_dev->rx_section_count =
-	    init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections;
-
-	net_dev->rx_sections = malloc(net_dev->rx_section_count *
-	    sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_WAITOK);
-	memcpy(net_dev->rx_sections, 
-	    init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections,
-	    net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section));
-
+	status = resp->nvs_status;
+	vmbus_xact_put(xact);
 
-	/*
-	 * For first release, there should only be 1 section that represents
-	 * the entire receive buffer
-	 */
-	if (net_dev->rx_section_count != 1
-	    || net_dev->rx_sections->offset != 0) {
-		ret = EINVAL;
+	if (status != HN_NVS_STATUS_OK) {
+		if_printf(sc->hn_ifp, "rxbuf conn failed: %x\n", status);
+		error = EIO;
 		goto cleanup;
 	}
+	net_dev->rx_section_count = 1;
 
-	goto exit;
+	return (0);
 
 cleanup:
 	hv_nv_destroy_rx_buffer(net_dev);
-	
-exit:
-	return (ret);
+	return (error);
 }
 
 /*
@@ -248,9 +256,13 @@ static int 
 hv_nv_init_send_buffer_with_net_vsp(struct hn_softc *sc)
 {
 	struct hn_send_ctx sndc;
+	struct vmbus_xact *xact;
+	struct hn_nvs_chim_conn *chim;
+	const struct hn_nvs_chim_connresp *resp;
+	size_t resp_len;
+	uint32_t status, sectsz;
 	netvsc_dev *net_dev;
-	nvsp_msg *init_pkt;
-	int ret = 0;
+	int error;
 
 	net_dev = hv_nv_get_outbound_net_device(sc);
 	if (!net_dev) {
@@ -262,7 +274,7 @@ hv_nv_init_send_buffer_with_net_vsp(stru
 	    BUS_DMA_WAITOK | BUS_DMA_ZERO);
 	if (net_dev->send_buf == NULL) {
 		device_printf(sc->hn_dev, "allocate chimney txbuf failed\n");
-		return ENOMEM;
+		return (ENOMEM);
 	}
 
 	/*
@@ -272,48 +284,77 @@ hv_nv_init_send_buffer_with_net_vsp(stru
 	 * Only primary channel has chimney sending buffer connected to it.
 	 * Sub-channels just share this chimney sending buffer.
 	 */
-	ret = vmbus_chan_gpadl_connect(sc->hn_prichan,
+	error = vmbus_chan_gpadl_connect(sc->hn_prichan,
   	    net_dev->txbuf_dma.hv_paddr, net_dev->send_buf_size,
 	    &net_dev->send_buf_gpadl_handle);
-	if (ret != 0) {
-		device_printf(sc->hn_dev, "chimney sending buffer gpadl "
-		    "connect failed: %d\n", ret);
+	if (error) {
+		if_printf(sc->hn_ifp, "chimney sending buffer gpadl "
+		    "connect failed: %d\n", error);
 		goto cleanup;
 	}
 
-	/* Notify the NetVsp of the gpadl handle */
-
-	init_pkt = &net_dev->channel_init_packet;
+	/*
+	 * Connect chimney sending buffer to NVS
+	 */
 
-	memset(init_pkt, 0, sizeof(nvsp_msg));
+	xact = vmbus_xact_get(sc->hn_xact, sizeof(*chim));
+	if (xact == NULL) {
+		if_printf(sc->hn_ifp, "no xact for nvs chim conn\n");
+		error = ENXIO;
+		goto cleanup;
+	}
 
-	init_pkt->hdr.msg_type = nvsp_msg_1_type_send_send_buf;
-	init_pkt->msgs.vers_1_msgs.send_rx_buf.gpadl_handle =
-	    net_dev->send_buf_gpadl_handle;
-	init_pkt->msgs.vers_1_msgs.send_rx_buf.id =
-	    NETVSC_SEND_BUFFER_ID;
+	chim = vmbus_xact_req_data(xact);
+	chim->nvs_type = HN_NVS_TYPE_CHIM_CONN;
+	chim->nvs_gpadl = net_dev->send_buf_gpadl_handle;
+	chim->nvs_sig = HN_NVS_CHIM_SIG;
 
-	/* Send the gpadl notification request */
+	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+	vmbus_xact_activate(xact);
 
-	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
-	ret = vmbus_chan_send(sc->hn_prichan,
+	error = vmbus_chan_send(sc->hn_prichan,
 	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-  	    init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
-	if (ret != 0) {
+  	    chim, sizeof(*chim), (uint64_t)(uintptr_t)&sndc);
+	if (error) {
+		if_printf(sc->hn_ifp, "send nvs chim conn failed: %d\n",
+		    error);
+		vmbus_xact_deactivate(xact);
+		vmbus_xact_put(xact);
 		goto cleanup;
 	}
 
-	sema_wait(&net_dev->channel_init_sema);
+	resp = vmbus_xact_wait(xact, &resp_len);
+	if (resp_len < sizeof(*resp)) {
+		if_printf(sc->hn_ifp, "invalid chim conn resp length %zu\n",
+		    resp_len);
+		vmbus_xact_put(xact);
+		error = EINVAL;
+		goto cleanup;
+	}
+	if (resp->nvs_type != HN_NVS_TYPE_CHIM_CONNRESP) {
+		if_printf(sc->hn_ifp, "not chim conn resp, type %u\n",
+		    resp->nvs_type);
+		vmbus_xact_put(xact);
+		error = EINVAL;
+		goto cleanup;
+	}
 
-	/* Check the response */
-	if (init_pkt->msgs.vers_1_msgs.send_send_buf_complete.status
-	    != nvsp_status_success) {
-		ret = EINVAL;
+	status = resp->nvs_status;
+	sectsz = resp->nvs_sectsz;
+	vmbus_xact_put(xact);
+
+	if (status != HN_NVS_STATUS_OK) {
+		if_printf(sc->hn_ifp, "chim conn failed: %x\n", status);
+		error = EIO;
 		goto cleanup;
 	}
+	if (sectsz == 0) {
+		if_printf(sc->hn_ifp, "zero chimney sending buffer "
+		    "section size\n");
+		return 0;
+	}
 
-	net_dev->send_section_size =
-	    init_pkt->msgs.vers_1_msgs.send_send_buf_complete.section_size;
+	net_dev->send_section_size = sectsz;
 	net_dev->send_section_count =
 	    net_dev->send_buf_size / net_dev->send_section_size;
 	net_dev->bitsmap_words = howmany(net_dev->send_section_count,
@@ -322,13 +363,15 @@ hv_nv_init_send_buffer_with_net_vsp(stru
 	    malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC,
 	    M_WAITOK | M_ZERO);
 
-	goto exit;
+	if (bootverbose) {
+		if_printf(sc->hn_ifp, "chimney sending buffer %u/%u\n",
+		    net_dev->send_section_size, net_dev->send_section_count);
+	}
+	return 0;
 
 cleanup:
 	hv_nv_destroy_send_buffer(net_dev);
-	
-exit:
-	return (ret);
+	return (error);
 }
 
 /*
@@ -337,34 +380,27 @@ exit:
 static int
 hv_nv_destroy_rx_buffer(netvsc_dev *net_dev)
 {
-	nvsp_msg *revoke_pkt;
 	int ret = 0;
 
-	/*
-	 * If we got a section count, it means we received a
-	 * send_rx_buf_complete msg 
-	 * (ie sent nvsp_msg_1_type_send_rx_buf msg) therefore,
-	 * we need to send a revoke msg here
-	 */
 	if (net_dev->rx_section_count) {
-		/* Send the revoke receive buffer */
-		revoke_pkt = &net_dev->revoke_packet;
-		memset(revoke_pkt, 0, sizeof(nvsp_msg));
-
-		revoke_pkt->hdr.msg_type = nvsp_msg_1_type_revoke_rx_buf;
-		revoke_pkt->msgs.vers_1_msgs.revoke_rx_buf.id =
-		    NETVSC_RECEIVE_BUFFER_ID;
+		struct hn_nvs_rxbuf_disconn disconn;
 
-		ret = vmbus_chan_send(net_dev->sc->hn_prichan,
-		    VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg),
-		    (uint64_t)(uintptr_t)&hn_send_ctx_none);
 		/*
-		 * If we failed here, we might as well return and have a leak 
-		 * rather than continue and a bugchk
+		 * Disconnect RXBUF from NVS.
 		 */
+		memset(&disconn, 0, sizeof(disconn));
+		disconn.nvs_type = HN_NVS_TYPE_RXBUF_DISCONN;
+		disconn.nvs_sig = HN_NVS_RXBUF_SIG;
+
+		ret = vmbus_chan_send(net_dev->sc->hn_prichan,
+		    VMBUS_CHANPKT_TYPE_INBAND, 0, &disconn, sizeof(disconn),
+		    (uint64_t)(uintptr_t)&hn_send_ctx_none);
 		if (ret != 0) {
+			if_printf(net_dev->sc->hn_ifp,
+			    "send rxbuf disconn failed: %d\n", ret);
 			return (ret);
 		}
+		net_dev->rx_section_count = 0;
 	}
 		
 	/* Tear down the gpadl on the vsp end */
@@ -387,12 +423,6 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_
 		net_dev->rx_buf = NULL;
 	}
 
-	if (net_dev->rx_sections) {
-		free(net_dev->rx_sections, M_NETVSC);
-		net_dev->rx_sections = NULL;
-		net_dev->rx_section_count = 0;
-	}
-
 	return (ret);
 }
 
@@ -402,33 +432,24 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_
 static int
 hv_nv_destroy_send_buffer(netvsc_dev *net_dev)
 {
-	nvsp_msg *revoke_pkt;
 	int ret = 0;
 
-	/*
-	 * If we got a section count, it means we received a
-	 * send_rx_buf_complete msg 
-	 * (ie sent nvsp_msg_1_type_send_rx_buf msg) therefore,
-	 * we need to send a revoke msg here
-	 */
 	if (net_dev->send_section_size) {
-		/* Send the revoke send buffer */
-		revoke_pkt = &net_dev->revoke_packet;
-		memset(revoke_pkt, 0, sizeof(nvsp_msg));
-
-		revoke_pkt->hdr.msg_type =
-		    nvsp_msg_1_type_revoke_send_buf;
-		revoke_pkt->msgs.vers_1_msgs.revoke_send_buf.id =
-		    NETVSC_SEND_BUFFER_ID;
+		struct hn_nvs_chim_disconn disconn;
 
-		ret = vmbus_chan_send(net_dev->sc->hn_prichan,
-		    VMBUS_CHANPKT_TYPE_INBAND, 0, revoke_pkt, sizeof(nvsp_msg),
-		    (uint64_t)(uintptr_t)&hn_send_ctx_none);
 		/*
-		 * If we failed here, we might as well return and have a leak 
-		 * rather than continue and a bugchk
+		 * Disconnect chimney sending buffer from NVS.
 		 */
+		memset(&disconn, 0, sizeof(disconn));
+		disconn.nvs_type = HN_NVS_TYPE_CHIM_DISCONN;
+		disconn.nvs_sig = HN_NVS_CHIM_SIG;
+
+		ret = vmbus_chan_send(net_dev->sc->hn_prichan,
+		    VMBUS_CHANPKT_TYPE_INBAND, 0, &disconn, sizeof(disconn),
+		    (uint64_t)(uintptr_t)&hn_send_ctx_none);
 		if (ret != 0) {
+			if_printf(net_dev->sc->hn_ifp,
+			    "send chim disconn failed: %d\n", ret);
 			return (ret);
 		}
 	}
@@ -461,45 +482,64 @@ hv_nv_destroy_send_buffer(netvsc_dev *ne
 	return (ret);
 }
 
-
-/*
- * Attempt to negotiate the caller-specified NVSP version
- *
- * For NVSP v2, Server 2008 R2 does not set
- * init_pkt->msgs.init_msgs.init_compl.negotiated_prot_vers
- * to the negotiated version, so we cannot rely on that.
- */
 static int
 hv_nv_negotiate_nvsp_protocol(struct hn_softc *sc, netvsc_dev *net_dev,
-    uint32_t nvsp_ver)
+    uint32_t nvs_ver)
 {
 	struct hn_send_ctx sndc;
-	nvsp_msg *init_pkt;
-	int ret;
-
-	init_pkt = &net_dev->channel_init_packet;
-	memset(init_pkt, 0, sizeof(nvsp_msg));
-	init_pkt->hdr.msg_type = nvsp_msg_type_init;
+	struct vmbus_xact *xact;
+	struct hn_nvs_init *init;
+	const struct hn_nvs_init_resp *resp;
+	size_t resp_len;
+	uint32_t status;
+	int error;
+
+	xact = vmbus_xact_get(sc->hn_xact, sizeof(*init));
+	if (xact == NULL) {
+		if_printf(sc->hn_ifp, "no xact for nvs init\n");
+		return (ENXIO);
+	}
+
+	init = vmbus_xact_req_data(xact);
+	init->nvs_type = HN_NVS_TYPE_INIT;
+	init->nvs_ver_min = nvs_ver;
+	init->nvs_ver_max = nvs_ver;
 
-	/*
-	 * Specify parameter as the only acceptable protocol version
-	 */
-	init_pkt->msgs.init_msgs.init.p1.protocol_version = nvsp_ver;
-	init_pkt->msgs.init_msgs.init.protocol_version_2 = nvsp_ver;
+	vmbus_xact_activate(xact);
+	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
 
-	/* Send the init request */
-	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
-	ret = vmbus_chan_send(sc->hn_prichan,
+	error = vmbus_chan_send(sc->hn_prichan,
 	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-	    init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
-	if (ret != 0)
-		return (-1);
-
-	sema_wait(&net_dev->channel_init_sema);
+	    init, sizeof(*init), (uint64_t)(uintptr_t)&sndc);
+	if (error) {
+		if_printf(sc->hn_ifp, "send nvs init failed: %d\n", error);
+		vmbus_xact_deactivate(xact);
+		vmbus_xact_put(xact);
+		return (error);
+	}
 
-	if (init_pkt->msgs.init_msgs.init_compl.status != nvsp_status_success)
+	resp = vmbus_xact_wait(xact, &resp_len);
+	if (resp_len < sizeof(*resp)) {
+		if_printf(sc->hn_ifp, "invalid init resp length %zu\n",
+		    resp_len);
+		vmbus_xact_put(xact);
+		return (EINVAL);
+	}
+	if (resp->nvs_type != HN_NVS_TYPE_INIT_RESP) {
+		if_printf(sc->hn_ifp, "not init resp, type %u\n",
+		    resp->nvs_type);
+		vmbus_xact_put(xact);
 		return (EINVAL);
+	}
+
+	status = resp->nvs_status;
+	vmbus_xact_put(xact);
 
+	if (status != HN_NVS_STATUS_OK) {
+		if_printf(sc->hn_ifp, "nvs init failed for ver 0x%x\n",
+		    nvs_ver);
+		return (EINVAL);
+	}
 	return (0);
 }
 
@@ -511,33 +551,19 @@ hv_nv_negotiate_nvsp_protocol(struct hn_
 static int
 hv_nv_send_ndis_config(struct hn_softc *sc, uint32_t mtu)
 {
-	netvsc_dev *net_dev;
-	nvsp_msg *init_pkt;
-	int ret;
-
-	net_dev = hv_nv_get_outbound_net_device(sc);
-	if (!net_dev)
-		return (-ENODEV);
-
-	/*
-	 * Set up configuration packet, write MTU
-	 * Indicate we are capable of handling VLAN tags
-	 */
-	init_pkt = &net_dev->channel_init_packet;
-	memset(init_pkt, 0, sizeof(nvsp_msg));
-	init_pkt->hdr.msg_type = nvsp_msg_2_type_send_ndis_config;
-	init_pkt->msgs.vers_2_msgs.send_ndis_config.mtu = mtu;
-	init_pkt->
-		msgs.vers_2_msgs.send_ndis_config.capabilities.u1.u2.ieee8021q
-		= 1;
-
-	/* Send the configuration packet */
-	ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0,
-	    init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&hn_send_ctx_none);
-	if (ret != 0)
-		return (-EINVAL);
+	struct hn_nvs_ndis_conf conf;
+	int error;
 
-	return (0);
+	memset(&conf, 0, sizeof(conf));
+	conf.nvs_type = HN_NVS_TYPE_NDIS_CONF;
+	conf.nvs_mtu = mtu;
+	conf.nvs_caps = HN_NVS_NDIS_CONF_VLAN;
+
+	error = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0,
+	    &conf, sizeof(conf), (uint64_t)(uintptr_t)&hn_send_ctx_none);
+	if (error)
+		if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error);
+	return (error);
 }
 
 /*
@@ -547,8 +573,6 @@ static int
 hv_nv_connect_to_vsp(struct hn_softc *sc)
 {
 	netvsc_dev *net_dev;
-	nvsp_msg *init_pkt;
-	uint32_t ndis_version;
 	uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1,
 	    NVSP_PROTOCOL_VERSION_2,
 	    NVSP_PROTOCOL_VERSION_4,
@@ -558,6 +582,7 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
 	int ret = 0;
 	device_t dev = sc->hn_dev;
 	struct ifnet *ifp = sc->arpcom.ac_ifp;
+	struct hn_nvs_ndis_init ndis;
 
 	net_dev = hv_nv_get_outbound_net_device(sc);
 
@@ -590,37 +615,23 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
 		ret = hv_nv_send_ndis_config(sc, ifp->if_mtu);
 
 	/*
-	 * Send the NDIS version
+	 * Initialize NDIS.
 	 */
-	init_pkt = &net_dev->channel_init_packet;
-
-	memset(init_pkt, 0, sizeof(nvsp_msg));
-
-	if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_4) {
-		ndis_version = NDIS_VERSION_6_1;
-	} else {
-		ndis_version = NDIS_VERSION_6_30;
-	}
-
-	init_pkt->hdr.msg_type = nvsp_msg_1_type_send_ndis_vers;
-	init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_major_vers =
-	    (ndis_version & 0xFFFF0000) >> 16;
-	init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_minor_vers =
-	    ndis_version & 0xFFFF;
 
-	/* Send the init request */
+	memset(&ndis, 0, sizeof(ndis));
+	ndis.nvs_type = HN_NVS_TYPE_NDIS_INIT;
+	ndis.nvs_ndis_major = NDIS_VERSION_MAJOR_6;
+	if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_4)
+		ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_1;
+	else
+		ndis.nvs_ndis_minor = NDIS_VERSION_MINOR_30;
 
 	ret = vmbus_chan_send(sc->hn_prichan, VMBUS_CHANPKT_TYPE_INBAND, 0,
-	    init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&hn_send_ctx_none);
+	    &ndis, sizeof(ndis), (uint64_t)(uintptr_t)&hn_send_ctx_none);
 	if (ret != 0) {
+		if_printf(sc->hn_ifp, "send nvs ndis init failed: %d\n", ret);
 		goto cleanup;
 	}
-	/*
-	 * TODO:  BUGBUG - We have to wait for the above msg since the netvsp
-	 * uses KMCL which acknowledges packet (completion packet) 
-	 * since our Vmbus always set the VMBUS_CHANPKT_FLAG_RC flag
-	 */
-	/* sema_wait(&NetVscChannel->channel_init_sema); */
 
 	/* Post the big receive buffer to NetVSP */
 	if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_2)
@@ -741,19 +752,18 @@ hv_nv_on_device_remove(struct hn_softc *
 }
 
 void
-hn_nvs_sent_wakeup(struct hn_send_ctx *sndc __unused,
-    struct netvsc_dev_ *net_dev, struct vmbus_channel *chan __unused,
-    const struct nvsp_msg_ *msg)
-{
-	/* Copy the response back */
-	memcpy(&net_dev->channel_init_packet, msg, sizeof(nvsp_msg));
-	sema_post(&net_dev->channel_init_sema);
+hn_nvs_sent_xact(struct hn_send_ctx *sndc,
+    struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused,
+    const struct nvsp_msg_ *msg, int dlen)
+{
+
+	vmbus_xact_wakeup(sndc->hn_cbarg, msg, dlen);
 }
 
 static void
 hn_nvs_sent_none(struct hn_send_ctx *sndc __unused,
     struct netvsc_dev_ *net_dev __unused, struct vmbus_channel *chan __unused,
-    const struct nvsp_msg_ *msg __unused)
+    const struct nvsp_msg_ *msg __unused, int dlen __unused)
 {
 	/* EMPTY */
 }
@@ -787,7 +797,8 @@ hv_nv_on_send_completion(netvsc_dev *net
 	struct hn_send_ctx *sndc;
 
 	sndc = (struct hn_send_ctx *)(uintptr_t)pkt->cph_xactid;
-	sndc->hn_cb(sndc, net_dev, chan, VMBUS_CHANPKT_CONST_DATA(pkt));
+	sndc->hn_cb(sndc, net_dev, chan, VMBUS_CHANPKT_CONST_DATA(pkt),
+	    VMBUS_CHANPKT_DATALEN(pkt));
 	/*
 	 * NOTE:
 	 * 'sndc' CAN NOT be accessed anymore, since it can be freed by

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Thu Oct 13 02:06:23 2016	(r307163)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Thu Oct 13 02:28:40 2016	(r307164)
@@ -1060,7 +1060,6 @@ typedef struct netvsc_dev_ {
 	uint32_t				rx_buf_size;
 	uint32_t				rx_buf_gpadl_handle;
 	uint32_t				rx_section_count;
-	nvsp_1_rx_buf_section			*rx_sections;
 
 	/* Used for NetVSP initialization protocol */
 	struct sema				channel_init_sema;
@@ -1244,6 +1243,7 @@ typedef struct hn_softc {
 	struct taskqueue *hn_tx_taskq;
 	struct sysctl_oid *hn_tx_sysctl_tree;
 	struct sysctl_oid *hn_rx_sysctl_tree;
+	struct vmbus_xact_ctx *hn_xact;
 } hn_softc_t;
 
 /*

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Thu Oct 13 02:06:23 2016	(r307163)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Thu Oct 13 02:28:40 2016	(r307164)
@@ -117,6 +117,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/hyperv/include/hyperv.h>
 #include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/include/vmbus_xact.h>
 
 #include "hv_net_vsc.h"
 #include "hv_rndis.h"
@@ -126,6 +127,9 @@ __FBSDID("$FreeBSD$");
 /* Short for Hyper-V network interface */
 #define NETVSC_DEVNAME    "hn"
 
+#define HN_XACT_REQ_SIZE		(2 * PAGE_SIZE)
+#define HN_XACT_RESP_SIZE		(2 * PAGE_SIZE)
+
 /*
  * It looks like offset 0 of buf is reserved to hold the softc pointer.
  * The sc pointer evidently not needed, and is not presently populated.
@@ -558,6 +562,11 @@ netvsc_attach(device_t dev)
 	    IFCAP_LRO;
 	ifp->if_hwassist = sc->hn_tx_ring[0].hn_csum_assist | CSUM_TSO;
 
+	sc->hn_xact = vmbus_xact_ctx_create(bus_get_dma_tag(dev),
+	    HN_XACT_REQ_SIZE, HN_XACT_RESP_SIZE, 0);
+	if (sc->hn_xact == NULL)
+		goto failed;
+
 	error = hv_rf_on_device_add(sc, &device_info, ring_cnt,
 	    &sc->hn_rx_ring[0]);
 	if (error)
@@ -655,6 +664,7 @@ netvsc_detach(device_t dev)
 	if (sc->hn_tx_taskq != hn_tx_taskq)
 		taskqueue_free(sc->hn_tx_taskq);
 
+	vmbus_xact_ctx_destroy(sc->hn_xact);
 	return (0);
 }
 
@@ -794,7 +804,8 @@ hn_txeof(struct hn_tx_ring *txr)
 
 static void
 hn_tx_done(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
-    struct vmbus_channel *chan, const struct nvsp_msg_ *msg __unused)
+    struct vmbus_channel *chan, const struct nvsp_msg_ *msg __unused,
+    int dlen __unused)
 {
 	struct hn_txdesc *txd = sndc->hn_cbarg;
 	struct hn_tx_ring *txr;

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis.h	Thu Oct 13 02:06:23 2016	(r307163)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis.h	Thu Oct 13 02:28:40 2016	(r307164)
@@ -41,6 +41,10 @@
 #define NDIS_VERSION_6_1                        0x00060001
 #define NDIS_VERSION_6_30                       0x0006001e
 
+#define NDIS_VERSION_MAJOR_6			6
+#define NDIS_VERSION_MINOR_1			1
+#define NDIS_VERSION_MINOR_30			30
+
 #define NDIS_VERSION                            (NDIS_VERSION_5_1)
 
 /*

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Thu Oct 13 02:06:23 2016	(r307163)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Thu Oct 13 02:28:40 2016	(r307164)
@@ -47,9 +47,11 @@ __FBSDID("$FreeBSD$");
 #include <vm/pmap.h>
 
 #include <dev/hyperv/include/hyperv.h>
-#include "hv_net_vsc.h"
-#include "hv_rndis.h"
-#include "hv_rndis_filter.h"
+#include <dev/hyperv/include/vmbus_xact.h>
+#include <dev/hyperv/netvsc/hv_net_vsc.h>
+#include <dev/hyperv/netvsc/hv_rndis.h>
+#include <dev/hyperv/netvsc/hv_rndis_filter.h>
+#include <dev/hyperv/netvsc/if_hnreg.h>
 
 struct hv_rf_recvinfo {
 	const ndis_8021q_info		*vlan_info;
@@ -92,10 +94,10 @@ hv_rf_send_offload_request(struct hn_sof
 
 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
     struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
-    const struct nvsp_msg_ *msg);
+    const struct nvsp_msg_ *msg, int dlen);
 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
     struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
-    const struct nvsp_msg_ *msg);
+    const struct nvsp_msg_ *msg, int dlen);
 
 /*
  * Set the Per-Packet-Info with the specified type
@@ -1061,12 +1063,16 @@ hv_rf_on_device_add(struct hn_softc *sc,
 	int ret;
 	netvsc_dev *net_dev;
 	rndis_device *rndis_dev;
-	nvsp_msg *init_pkt;
 	rndis_offload_params offloads;
 	struct rndis_recv_scale_cap rsscaps;
 	uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
 	netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
 	device_t dev = sc->hn_dev;
+	struct hn_nvs_subch_req *req;
+	const struct hn_nvs_subch_resp *resp;
+	size_t resp_len;
+	struct vmbus_xact *xact;
+	uint32_t status, nsubch;
 
 	rndis_dev = hv_get_rndis_device();
 	if (rndis_dev == NULL) {
@@ -1154,36 +1160,65 @@ hv_rf_on_device_add(struct hn_softc *sc,
 		goto out;
 	}
 	
-	/* request host to create sub channels */
-	init_pkt = &net_dev->channel_init_packet;
-	memset(init_pkt, 0, sizeof(nvsp_msg));
-
-	init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
-	init_pkt->msgs.vers_5_msgs.subchannel_request.op =
-	    NVSP_SUBCHANNE_ALLOCATE;
-	init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
-	    net_dev->num_channel - 1;
+	/*
+	 * Ask NVS to allocate sub-channels.
+	 */
+	xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
+	if (xact == NULL) {
+		if_printf(sc->hn_ifp, "no xact for nvs subch req\n");
+		ret = ENXIO;
+		goto out;
+	}
+
+	req = vmbus_xact_req_data(xact);
+	req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
+	req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
+	req->nvs_nsubch = net_dev->num_channel - 1;
+
+	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
+	vmbus_xact_activate(xact);
 
-	hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
 	ret = vmbus_chan_send(sc->hn_prichan,
 	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
-	    init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
+	    req, sizeof(*req), (uint64_t)(uintptr_t)&sndc);
 	if (ret != 0) {
-		device_printf(dev, "Fail to allocate subchannel\n");
+		if_printf(sc->hn_ifp, "send nvs subch req failed: %d\n", ret);
+		vmbus_xact_deactivate(xact);
+		vmbus_xact_put(xact);
 		goto out;
 	}
 
-	sema_wait(&net_dev->channel_init_sema);
-
-	if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
-	    nvsp_status_success) {
-		ret = ENODEV;
-		device_printf(dev, "sub channel complete error\n");
+	resp = vmbus_xact_wait(xact, &resp_len);
+	if (resp_len < sizeof(*resp)) {
+		if_printf(sc->hn_ifp, "invalid subch resp length %zu\n",
+		    resp_len);
+		vmbus_xact_put(xact);
+		ret = EINVAL;
+		goto out;
+	}
+	if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) {
+		if_printf(sc->hn_ifp, "not subch resp, type %u\n",
+		    resp->nvs_type);
+		vmbus_xact_put(xact);
+		ret = EINVAL;
 		goto out;
 	}
 
-	net_dev->num_channel = 1 +
-	    init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
+	status = resp->nvs_status;
+	nsubch = resp->nvs_nsubch;
+	vmbus_xact_put(xact);
+
+	if (status != HN_NVS_STATUS_OK) {
+		if_printf(sc->hn_ifp, "subch req failed: %x\n", status);
+		ret = EIO;
+		goto out;
+	}
+	if (nsubch > net_dev->num_channel - 1) {
+		if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n",
+		    nsubch, net_dev->num_channel - 1);
+		nsubch = net_dev->num_channel - 1;
+	}
+	net_dev->num_channel = nsubch + 1;
 
 	ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
 
@@ -1240,7 +1275,8 @@ hv_rf_on_close(struct hn_softc *sc)
 
 static void
 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
-    struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused)
+    struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused,
+    int dlen __unused)
 {
 	if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
 		hn_chim_free(net_dev, sndc->hn_chim_idx);
@@ -1248,7 +1284,8 @@ hn_rndis_sent_cb(struct hn_send_ctx *snd
 
 static void
 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
-    struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused)
+    struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused,
+    int dlen __unused)
 {
 	rndis_request *request = sndc->hn_cbarg;
 

Copied and modified: stable/10/sys/dev/hyperv/netvsc/if_hnreg.h (from r303948, head/sys/dev/hyperv/netvsc/if_hnreg.h)
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hnreg.h	Thu Aug 11 06:14:54 2016	(r303948, copy source)
+++ stable/10/sys/dev/hyperv/netvsc/if_hnreg.h	Thu Oct 13 02:28:40 2016	(r307164)
@@ -32,10 +32,23 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 
+#define HN_NVS_RXBUF_SIG		0xcafe
+#define HN_NVS_CHIM_SIG			0xface
+
 #define HN_NVS_STATUS_OK		1
 
 #define HN_NVS_TYPE_INIT		1
 #define HN_NVS_TYPE_INIT_RESP		2
+#define HN_NVS_TYPE_NDIS_INIT		100
+#define HN_NVS_TYPE_RXBUF_CONN		101
+#define HN_NVS_TYPE_RXBUF_CONNRESP	102
+#define HN_NVS_TYPE_RXBUF_DISCONN	103
+#define HN_NVS_TYPE_CHIM_CONN		104
+#define HN_NVS_TYPE_CHIM_CONNRESP	105
+#define HN_NVS_TYPE_CHIM_DISCONN	106
+#define HN_NVS_TYPE_NDIS_CONF		125
+#define HN_NVS_TYPE_SUBCH_REQ		133
+#define HN_NVS_TYPE_SUBCH_RESP		133	/* same as SUBCH_REQ */
 
 /*
  * Any size less than this one will _not_ work, e.g. hn_nvs_init
@@ -59,4 +72,94 @@ struct hn_nvs_init_resp {
 	uint32_t	nvs_status;	/* HN_NVS_STATUS_ */

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



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