Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Oct 2016 09:11:23 +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: r307034 - in stable/10/sys/dev/hyperv: include netvsc storvsc utilities vmbus
Message-ID:  <201610110911.u9B9BNmd048898@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Tue Oct 11 09:11:23 2016
New Revision: 307034
URL: https://svnweb.freebsd.org/changeset/base/307034

Log:
  MFC 302875,302876,302878-302881
  
  302875
      hyperv/vmbus: Redefine channel packet.
  
      The channel packet header will be shared w/ PRP (physical region page)
      list channel packet and SG (scatter gather) list channel packet.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7155
  
  302876
      hyperv/vmbus: Rework sglist sending.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7156
  
  302878
      hyeprv/vmbus: Rework prplist sending.
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7175
  
  302879
      hyperv/vmbus: Move channel packet flags definition to vmbus.h
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7176
  
  302880
      hyperv/vmbus: Move channel packet types definition to vmbus.h
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7177
  
  302881
      hyperv/vmbus: Cleanup channel sending
  
      Sponsored by:   Microsoft OSTC
      Differential Revision:  https://reviews.freebsd.org/D7178

Added:
  stable/10/sys/dev/hyperv/include/vmbus.h
     - copied, changed from r302876, head/sys/dev/hyperv/include/vmbus.h
Modified:
  stable/10/sys/dev/hyperv/include/hyperv.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_filter.c
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h
  stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/utilities/hv_heartbeat.c
  stable/10/sys/dev/hyperv/utilities/hv_kvp.c
  stable/10/sys/dev/hyperv/utilities/hv_shutdown.c
  stable/10/sys/dev/hyperv/utilities/hv_timesync.c
  stable/10/sys/dev/hyperv/vmbus/hv_channel.c
  stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
  stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/hyperv.h	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/include/hyperv.h	Tue Oct 11 09:11:23 2016	(r307034)
@@ -82,19 +82,6 @@ typedef uint8_t	hv_bool_uint8_t;
 #define VMBUS_VERSION_MAJOR(ver)	(((uint32_t)(ver)) >> 16)
 #define VMBUS_VERSION_MINOR(ver)	(((uint32_t)(ver)) & 0xffff)
 
-#define HV_MAX_PAGE_BUFFER_COUNT	32
-#define HV_MAX_MULTIPAGE_BUFFER_COUNT	32
-
-#define HV_ALIGN_UP(value, align)					\
-		(((value) & (align-1)) ?				\
-		    (((value) + (align-1)) & ~(align-1) ) : (value))
-
-#define HV_ALIGN_DOWN(value, align) ( (value) & ~(align-1) )
-
-#define HV_NUM_PAGES_SPANNED(addr, len)					\
-		((HV_ALIGN_UP(addr+len, PAGE_SIZE) -			\
-		    HV_ALIGN_DOWN(addr, PAGE_SIZE)) >> PAGE_SHIFT )
-
 struct hyperv_guid {
 	uint8_t		hv_guid[16];
 } __packed;
@@ -125,25 +112,6 @@ typedef struct {
 	hv_vm_transfer_page	ranges[1];
 } __packed hv_vm_transfer_page_packet_header;
 
-typedef enum {
-	HV_VMBUS_PACKET_TYPE_INVALID				= 0x0,
-	HV_VMBUS_PACKET_TYPES_SYNCH				= 0x1,
-	HV_VMBUS_PACKET_TYPE_ADD_TRANSFER_PAGE_SET		= 0x2,
-	HV_VMBUS_PACKET_TYPE_REMOVE_TRANSFER_PAGE_SET		= 0x3,
-	HV_VMBUS_PACKET_TYPE_ESTABLISH_GPADL			= 0x4,
-	HV_VMBUS_PACKET_TYPE_TEAR_DOWN_GPADL			= 0x5,
-	HV_VMBUS_PACKET_TYPE_DATA_IN_BAND			= 0x6,
-	HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES		= 0x7,
-	HV_VMBUS_PACKET_TYPE_DATA_USING_GPADL			= 0x8,
-	HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT		= 0x9,
-	HV_VMBUS_PACKET_TYPE_CANCEL_REQUEST			= 0xa,
-	HV_VMBUS_PACKET_TYPE_COMPLETION				= 0xb,
-	HV_VMBUS_PACKET_TYPE_DATA_USING_ADDITIONAL_PACKETS	= 0xc,
-	HV_VMBUS_PACKET_TYPE_ADDITIONAL_DATA = 0xd
-} hv_vmbus_packet_type;
-
-#define HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED    1
-
 #define HW_MACADDR_LEN	6
 
 /*
@@ -225,18 +193,6 @@ typedef struct {
 } __packed hv_vmbus_ring_buffer;
 
 typedef struct {
-	int		length;
-	int		offset;
-	uint64_t	pfn;
-} __packed hv_vmbus_page_buffer;
-
-typedef struct {
-	int		length;
-	int		offset;
-	uint64_t	pfn_array[HV_MAX_MULTIPAGE_BUFFER_COUNT];
-} __packed hv_vmbus_multipage_buffer;
-
-typedef struct {
 	hv_vmbus_ring_buffer*	ring_buffer;
 	struct mtx		ring_lock;
 	uint32_t		ring_data_size;	/* ring_size */
@@ -372,23 +328,8 @@ int		hv_vmbus_channel_send_packet(
 				void*			buffer,
 				uint32_t		buffer_len,
 				uint64_t		request_id,
-				hv_vmbus_packet_type	type,
-				uint32_t		flags);
-
-int		hv_vmbus_channel_send_packet_pagebuffer(
-				hv_vmbus_channel*	channel,
-				hv_vmbus_page_buffer	page_buffers[],
-				uint32_t		page_count,
-				void*			buffer,
-				uint32_t		buffer_len,
-				uint64_t		request_id);
-
-int		hv_vmbus_channel_send_packet_multipagebuffer(
-				hv_vmbus_channel*	    channel,
-				hv_vmbus_multipage_buffer*  multi_page_buffer,
-				void*			    buffer,
-				uint32_t		    buffer_len,
-				uint64_t		    request_id);
+				uint16_t		type,
+				uint16_t		flags);
 
 int		hv_vmbus_channel_establish_gpadl(
 				hv_vmbus_channel*	channel,

Copied and modified: stable/10/sys/dev/hyperv/include/vmbus.h (from r302876, head/sys/dev/hyperv/include/vmbus.h)
==============================================================================
--- head/sys/dev/hyperv/include/vmbus.h	Fri Jul 15 06:29:19 2016	(r302876, copy source)
+++ stable/10/sys/dev/hyperv/include/vmbus.h	Tue Oct 11 09:11:23 2016	(r307034)
@@ -31,6 +31,15 @@
 
 #include <sys/param.h>
 
+/*
+ * GPA stuffs.
+ */
+struct vmbus_gpa_range {
+	uint32_t	gpa_len;
+	uint32_t	gpa_ofs;
+	uint64_t	gpa_page[0];
+} __packed;
+
 /* This is actually vmbus_gpa_range.gpa_page[1] */
 struct vmbus_gpa {
 	uint32_t	gpa_len;
@@ -38,12 +47,23 @@ struct vmbus_gpa {
 	uint64_t	gpa_page;
 } __packed;
 
-#define VMBUS_CHAN_SGLIST_MAX	32
+#define VMBUS_CHANPKT_TYPE_INBAND	0x0006
+#define VMBUS_CHANPKT_TYPE_RXBUF	0x0007
+#define VMBUS_CHANPKT_TYPE_GPA		0x0009
+#define VMBUS_CHANPKT_TYPE_COMP		0x000b
+
+#define VMBUS_CHANPKT_FLAG_RC		0x0001	/* report completion */
+
+#define VMBUS_CHAN_SGLIST_MAX		32
+#define VMBUS_CHAN_PRPLIST_MAX		32
 
 struct hv_vmbus_channel;
 
 int	vmbus_chan_send_sglist(struct hv_vmbus_channel *chan,
 	    struct vmbus_gpa sg[], int sglen, void *data, int dlen,
 	    uint64_t xactid);
+int	vmbus_chan_send_prplist(struct hv_vmbus_channel *chan,
+	    struct vmbus_gpa_range *prp, int prp_cnt, void *data, int dlen,
+	    uint64_t xactid);
 
 #endif	/* !_VMBUS_H_ */

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -184,8 +184,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct
 
 	ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt,
 	    sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
-	    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-	    HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC);
 	if (ret != 0) {
 		goto cleanup;
 	}
@@ -278,8 +277,7 @@ hv_nv_init_send_buffer_with_net_vsp(stru
 
 	ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt,
   	    sizeof(nvsp_msg), (uint64_t)init_pkt,
-	    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-	    HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC);
 	if (ret != 0) {
 		goto cleanup;
 	}
@@ -339,7 +337,7 @@ hv_nv_destroy_rx_buffer(netvsc_dev *net_
 		ret = hv_vmbus_channel_send_packet(net_dev->sc->hn_prichan,
 		    revoke_pkt, sizeof(nvsp_msg),
 		    (uint64_t)(uintptr_t)revoke_pkt,
-		    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
+		    VMBUS_CHANPKT_TYPE_INBAND, 0);
 
 		/*
 		 * If we failed here, we might as well return and have a leak 
@@ -407,7 +405,7 @@ hv_nv_destroy_send_buffer(netvsc_dev *ne
 		ret = hv_vmbus_channel_send_packet(net_dev->sc->hn_prichan,
 		    revoke_pkt, sizeof(nvsp_msg),
 		    (uint64_t)(uintptr_t)revoke_pkt,
-		    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
+		    VMBUS_CHANPKT_TYPE_INBAND, 0);
 		/*
 		 * If we failed here, we might as well return and have a leak 
 		 * rather than continue and a bugchk
@@ -473,8 +471,7 @@ hv_nv_negotiate_nvsp_protocol(struct hn_
 	/* Send the init request */
 	ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt,
 	    sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
-	    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-	    HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC);
 	if (ret != 0)
 		return (-1);
 
@@ -517,7 +514,7 @@ hv_nv_send_ndis_config(struct hn_softc *
 	/* Send the configuration packet */
 	ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt,
 	    sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
-	    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
+	    VMBUS_CHANPKT_TYPE_INBAND, 0);
 	if (ret != 0)
 		return (-EINVAL);
 
@@ -596,15 +593,14 @@ hv_nv_connect_to_vsp(struct hn_softc *sc
 
 	ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt,
 	    sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
-	    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
+	    VMBUS_CHANPKT_TYPE_INBAND, 0);
 	if (ret != 0) {
 		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
-	 * HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
+	 * since our Vmbus always set the VMBUS_CHANPKT_FLAG_RC flag
 	 */
 	/* sema_wait(&NetVscChannel->channel_init_sema); */
 
@@ -815,15 +811,13 @@ hv_nv_on_send(struct hv_vmbus_channel *c
 	send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size =
 	    pkt->send_buf_section_size;
 
-	if (pkt->page_buf_count) {
-		ret = hv_vmbus_channel_send_packet_pagebuffer(chan,
-		    pkt->page_buffers, pkt->page_buf_count,
+	if (pkt->gpa_cnt) {
+		ret = vmbus_chan_send_sglist(chan, pkt->gpa, pkt->gpa_cnt,
 		    &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt);
 	} else {
 		ret = hv_vmbus_channel_send_packet(chan,
 		    &send_msg, sizeof(nvsp_msg), (uint64_t)(uintptr_t)pkt,
-		    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-		    HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+		    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC);
 	}
 
 	return (ret);
@@ -852,7 +846,7 @@ hv_nv_on_receive(netvsc_dev *net_dev, st
 	 * All inbound packets other than send completion should be
 	 * xfer page packet.
 	 */
-	if (pkt->type != HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES) {
+	if (pkt->type != VMBUS_CHANPKT_TYPE_RXBUF) {
 		device_printf(dev, "packet type %d is invalid!\n", pkt->type);
 		return;
 	}
@@ -923,7 +917,7 @@ hv_nv_on_receive_completion(struct hv_vm
 retry_send_cmplt:
 	/* Send the completion */
 	ret = hv_vmbus_channel_send_packet(chan, &rx_comp_msg,
-	    sizeof(nvsp_msg), tid, HV_VMBUS_PACKET_TYPE_COMPLETION, 0);
+	    sizeof(nvsp_msg), tid, VMBUS_CHANPKT_TYPE_COMP, 0);
 	if (ret == 0) {
 		/* success */
 		/* no-op */
@@ -1008,14 +1002,14 @@ hv_nv_on_channel_callback(void *xchan)
 			if (bytes_rxed > 0) {
 				desc = (hv_vm_packet_descriptor *)buffer;
 				switch (desc->type) {
-				case HV_VMBUS_PACKET_TYPE_COMPLETION:
+				case VMBUS_CHANPKT_TYPE_COMP:
 					hv_nv_on_send_completion(net_dev, chan,
 					    desc);
 					break;
-				case HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES:
+				case VMBUS_CHANPKT_TYPE_RXBUF:
 					hv_nv_on_receive(net_dev, sc, chan, desc);
 					break;
-				case HV_VMBUS_PACKET_TYPE_DATA_IN_BAND:
+				case VMBUS_CHANPKT_TYPE_INBAND:
 					hv_nv_send_table(sc, desc);
 					break;
 				default:

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h	Tue Oct 11 09:11:23 2016	(r307034)
@@ -57,6 +57,7 @@
 #include <net/if_media.h>
 
 #include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/vmbus.h>
 
 #define HN_USE_TXDESC_BUFRING
 
@@ -1082,8 +1083,6 @@ struct hv_vmbus_channel;
 typedef void (*pfn_on_send_rx_completion)(struct hv_vmbus_channel *, void *);
 
 #define NETVSC_DEVICE_RING_BUFFER_SIZE	(128 * PAGE_SIZE)
-#define NETVSC_PACKET_MAXPAGE		32 
-
 
 #define NETVSC_VLAN_PRIO_MASK		0xe000
 #define NETVSC_VLAN_PRIO_SHIFT		13
@@ -1132,8 +1131,8 @@ typedef struct netvsc_packet_ {
 	void		*rndis_mesg;
 	uint32_t	tot_data_buf_len;
 	void		*data;
-	uint32_t	page_buf_count;
-	hv_vmbus_page_buffer	page_buffers[NETVSC_PACKET_MAXPAGE];
+	uint32_t	gpa_cnt;
+	struct vmbus_gpa gpa[VMBUS_CHAN_SGLIST_MAX];
 } netvsc_packet;
 
 typedef struct {

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -156,7 +156,7 @@ __FBSDID("$FreeBSD$");
 #define HN_TX_DATA_MAXSIZE		IP_MAXPACKET
 #define HN_TX_DATA_SEGSIZE		PAGE_SIZE
 #define HN_TX_DATA_SEGCNT_MAX		\
-    (NETVSC_PACKET_MAXPAGE - HV_RF_NUM_TX_RESERVED_PAGE_BUFS)
+    (VMBUS_CHAN_SGLIST_MAX - HV_RF_NUM_TX_RESERVED_PAGE_BUFS)
 
 #define HN_DIRECT_TX_SIZE_DEF		128
 
@@ -1015,7 +1015,7 @@ hn_encap(struct hn_tx_ring *txr, struct 
 			packet->send_buf_section_idx = send_buf_section_idx;
 			packet->send_buf_section_size =
 			    packet->tot_data_buf_len;
-			packet->page_buf_count = 0;
+			packet->gpa_cnt = 0;
 			txr->hn_tx_chimney++;
 			goto done;
 		}
@@ -1041,24 +1041,24 @@ hn_encap(struct hn_tx_ring *txr, struct 
 	}
 	*m_head0 = m_head;
 
-	packet->page_buf_count = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS;
+	packet->gpa_cnt = nsegs + HV_RF_NUM_TX_RESERVED_PAGE_BUFS;
 
 	/* send packet with page buffer */
-	packet->page_buffers[0].pfn = atop(txd->rndis_msg_paddr);
-	packet->page_buffers[0].offset = txd->rndis_msg_paddr & PAGE_MASK;
-	packet->page_buffers[0].length = rndis_msg_size;
+	packet->gpa[0].gpa_page = atop(txd->rndis_msg_paddr);
+	packet->gpa[0].gpa_ofs = txd->rndis_msg_paddr & PAGE_MASK;
+	packet->gpa[0].gpa_len = rndis_msg_size;
 
 	/*
 	 * Fill the page buffers with mbuf info starting at index
 	 * HV_RF_NUM_TX_RESERVED_PAGE_BUFS.
 	 */
 	for (i = 0; i < nsegs; ++i) {
-		hv_vmbus_page_buffer *pb = &packet->page_buffers[
+		struct vmbus_gpa *gpa = &packet->gpa[
 		    i + HV_RF_NUM_TX_RESERVED_PAGE_BUFS];
 
-		pb->pfn = atop(segs[i].ds_addr);
-		pb->offset = segs[i].ds_addr & PAGE_MASK;
-		pb->length = segs[i].ds_len;
+		gpa->gpa_page = atop(segs[i].ds_addr);
+		gpa->gpa_ofs = segs[i].ds_addr & PAGE_MASK;
+		gpa->gpa_len = segs[i].ds_len;
 	}
 
 	packet->send_buf_section_idx =

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -249,26 +249,23 @@ hv_rf_send_request(rndis_device *device,
 	
 	packet->is_data_pkt = FALSE;
 	packet->tot_data_buf_len = request->request_msg.msg_len;
-	packet->page_buf_count = 1;
+	packet->gpa_cnt = 1;
 
-	packet->page_buffers[0].pfn =
+	packet->gpa[0].gpa_page =
 	    hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
-	packet->page_buffers[0].length = request->request_msg.msg_len;
-	packet->page_buffers[0].offset =
+	packet->gpa[0].gpa_len = request->request_msg.msg_len;
+	packet->gpa[0].gpa_ofs =
 	    (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
 
-	if (packet->page_buffers[0].offset +
-		packet->page_buffers[0].length > PAGE_SIZE) {
-		packet->page_buf_count = 2;
-		packet->page_buffers[0].length =
-		        PAGE_SIZE - packet->page_buffers[0].offset;
-		packet->page_buffers[1].pfn =
+	if (packet->gpa[0].gpa_ofs + packet->gpa[0].gpa_len > PAGE_SIZE) {
+		packet->gpa_cnt = 2;
+		packet->gpa[0].gpa_len = PAGE_SIZE - packet->gpa[0].gpa_ofs;
+		packet->gpa[1].gpa_page =
 		        hv_get_phys_addr((char*)&request->request_msg +
-                		packet->page_buffers[0].length) >> PAGE_SHIFT;
-		packet->page_buffers[1].offset = 0;
-		packet->page_buffers[1].length =
-		        request->request_msg.msg_len -
-			        packet->page_buffers[0].length;
+                		packet->gpa[0].gpa_len) >> PAGE_SHIFT;
+		packet->gpa[1].gpa_ofs = 0;
+		packet->gpa[1].gpa_len = request->request_msg.msg_len -
+		    packet->gpa[0].gpa_len;
 	}
 
 	packet->compl.send.send_completion_context = request; /* packet */
@@ -290,7 +287,7 @@ hv_rf_send_request(rndis_device *device,
 			memcpy(dest, &request->request_msg, request->request_msg.msg_len);
 			packet->send_buf_section_idx = send_buf_section_idx;
 			packet->send_buf_section_size = packet->tot_data_buf_len;
-			packet->page_buf_count = 0;
+			packet->gpa_cnt = 0;
 			goto sendit;
 		}
 		/* Failed to allocate chimney send buffer; move on */
@@ -1172,8 +1169,7 @@ hv_rf_on_device_add(struct hn_softc *sc,
 
 	ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt,
 	    sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
-	    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-	    HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	    VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC);
 	if (ret != 0) {
 		device_printf(dev, "Fail to allocate subchannel\n");
 		goto out;

Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.h	Tue Oct 11 09:11:23 2016	(r307034)
@@ -74,7 +74,6 @@ typedef struct rndis_request_ {
 
 	/* Simplify allocation by having a netvsc packet inline */
 	netvsc_packet			pkt;
-	hv_vmbus_page_buffer		buffer;
 
 	/*
 	 * The max request size is sizeof(rndis_msg) + PAGE_SIZE.

Modified: stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
 #include <cam/scsi/scsi_message.h>
 
 #include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/vmbus.h>
 
 #include "hv_vstorage.h"
 #include "vmbus_if.h"
@@ -100,7 +101,7 @@ struct hv_sgl_page_pool{
 	boolean_t                is_init;
 } g_hv_sgl_page_pool;
 
-#define STORVSC_MAX_SG_PAGE_CNT STORVSC_MAX_IO_REQUESTS * HV_MAX_MULTIPAGE_BUFFER_COUNT
+#define STORVSC_MAX_SG_PAGE_CNT STORVSC_MAX_IO_REQUESTS * VMBUS_CHAN_PRPLIST_MAX
 
 enum storvsc_request_type {
 	WRITE_TYPE,
@@ -108,10 +109,16 @@ enum storvsc_request_type {
 	UNKNOWN_TYPE
 };
 
+struct hvs_gpa_range {
+	struct vmbus_gpa_range	gpa_range;
+	uint64_t		gpa_page[VMBUS_CHAN_PRPLIST_MAX];
+} __packed;
+
 struct hv_storvsc_request {
 	LIST_ENTRY(hv_storvsc_request) link;
 	struct vstor_packet	vstor_packet;
-	hv_vmbus_multipage_buffer data_buf;
+	int prp_cnt;
+	struct hvs_gpa_range prp_list;
 	void *sense_data;
 	uint8_t sense_info_len;
 	uint8_t retries;
@@ -354,8 +361,8 @@ storvsc_send_multichannel_request(struct
 	    vstor_packet,
 	    VSTOR_PKT_SIZE,
 	    (uint64_t)(uintptr_t)request,
-	    HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-	    HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	    VMBUS_CHANPKT_TYPE_INBAND,
+	    VMBUS_CHANPKT_FLAG_RC);
 
 	/* wait for 5 seconds */
 	ret = sema_timedwait(&request->synch_sema, 5 * hz);
@@ -425,8 +432,8 @@ hv_storvsc_channel_init(struct storvsc_s
 			vstor_packet,
 			VSTOR_PKT_SIZE,
 			(uint64_t)(uintptr_t)request,
-			HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-			HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+			VMBUS_CHANPKT_TYPE_INBAND,
+			VMBUS_CHANPKT_FLAG_RC);
 
 	if (ret != 0)
 		goto cleanup;
@@ -459,8 +466,8 @@ hv_storvsc_channel_init(struct storvsc_s
 			vstor_packet,
 			VSTOR_PKT_SIZE,
 			(uint64_t)(uintptr_t)request,
-			HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-			HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+			VMBUS_CHANPKT_TYPE_INBAND,
+			VMBUS_CHANPKT_FLAG_RC);
 
 		if (ret != 0)
 			goto cleanup;
@@ -502,8 +509,8 @@ hv_storvsc_channel_init(struct storvsc_s
 				vstor_packet,
 				VSTOR_PKT_SIZE,
 				(uint64_t)(uintptr_t)request,
-				HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-				HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+				VMBUS_CHANPKT_TYPE_INBAND,
+				VMBUS_CHANPKT_FLAG_RC);
 
 	if ( ret != 0)
 		goto cleanup;
@@ -538,8 +545,8 @@ hv_storvsc_channel_init(struct storvsc_s
 			vstor_packet,
 			VSTOR_PKT_SIZE,
 			(uint64_t)(uintptr_t)request,
-			HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-			HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+			VMBUS_CHANPKT_TYPE_INBAND,
+			VMBUS_CHANPKT_FLAG_RC);
 
 	if (ret != 0) {
 		goto cleanup;
@@ -628,8 +635,8 @@ hv_storvsc_host_reset(struct storvsc_sof
 			vstor_packet,
 			VSTOR_PKT_SIZE,
 			(uint64_t)(uintptr_t)&sc->hs_reset_req,
-			HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-			HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+			VMBUS_CHANPKT_TYPE_INBAND,
+			VMBUS_CHANPKT_FLAG_RC);
 
 	if (ret != 0) {
 		goto cleanup;
@@ -675,29 +682,26 @@ hv_storvsc_io_request(struct storvsc_sof
 	
 	vstor_packet->u.vm_srb.sense_info_len = sense_buffer_size;
 
-	vstor_packet->u.vm_srb.transfer_len = request->data_buf.length;
+	vstor_packet->u.vm_srb.transfer_len =
+	    request->prp_list.gpa_range.gpa_len;
 
 	vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB;
 
 	outgoing_channel = vmbus_select_outgoing_channel(sc->hs_chan);
 
 	mtx_unlock(&request->softc->hs_lock);
-	if (request->data_buf.length) {
-		ret = hv_vmbus_channel_send_packet_multipagebuffer(
-				outgoing_channel,
-				&request->data_buf,
-				vstor_packet,
-				VSTOR_PKT_SIZE,
-				(uint64_t)(uintptr_t)request);
-
+	if (request->prp_list.gpa_range.gpa_len) {
+		ret = vmbus_chan_send_prplist(outgoing_channel,
+		    &request->prp_list.gpa_range, request->prp_cnt,
+		    vstor_packet, VSTOR_PKT_SIZE, (uint64_t)(uintptr_t)request);
 	} else {
 		ret = hv_vmbus_channel_send_packet(
 			outgoing_channel,
 			vstor_packet,
 			VSTOR_PKT_SIZE,
 			(uint64_t)(uintptr_t)request,
-			HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
-			HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+			VMBUS_CHANPKT_TYPE_INBAND,
+			VMBUS_CHANPKT_FLAG_RC);
 	}
 	mtx_lock(&request->softc->hs_lock);
 
@@ -956,7 +960,7 @@ storvsc_attach(device_t dev)
 
 		/*
 		 * Pre-create SG list, each SG list with
-		 * HV_MAX_MULTIPAGE_BUFFER_COUNT segments, each
+		 * VMBUS_CHAN_PRPLIST_MAX segments, each
 		 * segment has one page buffer
 		 */
 		for (i = 0; i < STORVSC_MAX_IO_REQUESTS; i++) {
@@ -964,10 +968,10 @@ storvsc_attach(device_t dev)
 			    M_DEVBUF, M_WAITOK|M_ZERO);
 
 			sgl_node->sgl_data =
-			    sglist_alloc(HV_MAX_MULTIPAGE_BUFFER_COUNT,
+			    sglist_alloc(VMBUS_CHAN_PRPLIST_MAX,
 			    M_WAITOK|M_ZERO);
 
-			for (j = 0; j < HV_MAX_MULTIPAGE_BUFFER_COUNT; j++) {
+			for (j = 0; j < VMBUS_CHAN_PRPLIST_MAX; j++) {
 				tmp_buff = malloc(PAGE_SIZE,
 				    M_DEVBUF, M_WAITOK|M_ZERO);
 
@@ -1054,7 +1058,7 @@ cleanup:
 	while (!LIST_EMPTY(&g_hv_sgl_page_pool.free_sgl_list)) {
 		sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list);
 		LIST_REMOVE(sgl_node, link);
-		for (j = 0; j < HV_MAX_MULTIPAGE_BUFFER_COUNT; j++) {
+		for (j = 0; j < VMBUS_CHAN_PRPLIST_MAX; j++) {
 			if (NULL !=
 			    (void*)sgl_node->sgl_data->sg_segs[j].ss_paddr) {
 				free((void*)sgl_node->sgl_data->sg_segs[j].ss_paddr, M_DEVBUF);
@@ -1117,7 +1121,7 @@ storvsc_detach(device_t dev)
 	while (!LIST_EMPTY(&g_hv_sgl_page_pool.free_sgl_list)) {
 		sgl_node = LIST_FIRST(&g_hv_sgl_page_pool.free_sgl_list);
 		LIST_REMOVE(sgl_node, link);
-		for (j = 0; j < HV_MAX_MULTIPAGE_BUFFER_COUNT; j++){
+		for (j = 0; j < VMBUS_CHAN_PRPLIST_MAX; j++){
 			if (NULL !=
 			    (void*)sgl_node->sgl_data->sg_segs[j].ss_paddr) {
 				free((void*)sgl_node->sgl_data->sg_segs[j].ss_paddr, M_DEVBUF);
@@ -1668,6 +1672,7 @@ create_storvsc_request(union ccb *ccb, s
 	uint32_t pfn_num = 0;
 	uint32_t pfn;
 	uint64_t not_aligned_seg_bits = 0;
+	struct hvs_gpa_range *prplist;
 	
 	/* refer to struct vmscsi_req for meanings of these two fields */
 	reqp->vstor_packet.u.vm_srb.port =
@@ -1711,22 +1716,23 @@ create_storvsc_request(union ccb *ccb, s
 		return (0);
 	}
 
-	reqp->data_buf.length = csio->dxfer_len;
+	prplist = &reqp->prp_list;
+	prplist->gpa_range.gpa_len = csio->dxfer_len;
 
 	switch (ccb->ccb_h.flags & CAM_DATA_MASK) {
 	case CAM_DATA_VADDR:
 	{
 		bytes_to_copy = csio->dxfer_len;
 		phys_addr = vtophys(csio->data_ptr);
-		reqp->data_buf.offset = phys_addr & PAGE_MASK;
+		prplist->gpa_range.gpa_ofs = phys_addr & PAGE_MASK;
 		
 		while (bytes_to_copy != 0) {
 			int bytes, page_offset;
 			phys_addr =
-			    vtophys(&csio->data_ptr[reqp->data_buf.length -
+			    vtophys(&csio->data_ptr[prplist->gpa_range.gpa_len -
 			    bytes_to_copy]);
 			pfn = phys_addr >> PAGE_SHIFT;
-			reqp->data_buf.pfn_array[pfn_num] = pfn;
+			prplist->gpa_page[pfn_num] = pfn;
 			page_offset = phys_addr & PAGE_MASK;
 
 			bytes = min(PAGE_SIZE - page_offset, bytes_to_copy);
@@ -1734,6 +1740,7 @@ create_storvsc_request(union ccb *ccb, s
 			bytes_to_copy -= bytes;
 			pfn_num++;
 		}
+		reqp->prp_cnt = pfn_num;
 		break;
 	}
 
@@ -1750,10 +1757,10 @@ create_storvsc_request(union ccb *ccb, s
 		printf("Storvsc: get SG I/O operation, %d\n",
 		    reqp->vstor_packet.u.vm_srb.data_in);
 
-		if (storvsc_sg_count > HV_MAX_MULTIPAGE_BUFFER_COUNT){
+		if (storvsc_sg_count > VMBUS_CHAN_PRPLIST_MAX){
 			printf("Storvsc: %d segments is too much, "
 			    "only support %d segments\n",
-			    storvsc_sg_count, HV_MAX_MULTIPAGE_BUFFER_COUNT);
+			    storvsc_sg_count, VMBUS_CHAN_PRPLIST_MAX);
 			return (EINVAL);
 		}
 
@@ -1806,10 +1813,10 @@ create_storvsc_request(union ccb *ccb, s
  				phys_addr =
 					vtophys(storvsc_sglist[0].ds_addr);
 			}
-			reqp->data_buf.offset = phys_addr & PAGE_MASK;
+			prplist->gpa_range.gpa_ofs = phys_addr & PAGE_MASK;
 
 			pfn = phys_addr >> PAGE_SHIFT;
-			reqp->data_buf.pfn_array[0] = pfn;
+			prplist->gpa_page[0] = pfn;
 			
 			for (i = 1; i < storvsc_sg_count; i++) {
 				if (reqp->not_aligned_seg_bits & (1 << i)) {
@@ -1821,27 +1828,31 @@ create_storvsc_request(union ccb *ccb, s
 				}
 
 				pfn = phys_addr >> PAGE_SHIFT;
-				reqp->data_buf.pfn_array[i] = pfn;
+				prplist->gpa_page[i] = pfn;
 			}
+			reqp->prp_cnt = i;
 		} else {
 			phys_addr = vtophys(storvsc_sglist[0].ds_addr);
 
-			reqp->data_buf.offset = phys_addr & PAGE_MASK;
+			prplist->gpa_range.gpa_ofs = phys_addr & PAGE_MASK;
 
 			for (i = 0; i < storvsc_sg_count; i++) {
 				phys_addr = vtophys(storvsc_sglist[i].ds_addr);
 				pfn = phys_addr >> PAGE_SHIFT;
-				reqp->data_buf.pfn_array[i] = pfn;
+				prplist->gpa_page[i] = pfn;
 			}
+			reqp->prp_cnt = i;
 
 			/* check the last segment cross boundary or not */
 			offset = phys_addr & PAGE_MASK;
 			if (offset) {
+				/* Add one more PRP entry */
 				phys_addr =
 				    vtophys(storvsc_sglist[i-1].ds_addr +
 				    PAGE_SIZE - offset);
 				pfn = phys_addr >> PAGE_SHIFT;
-				reqp->data_buf.pfn_array[i] = pfn;
+				prplist->gpa_page[i] = pfn;
+				reqp->prp_cnt++;
 			}
 			
 			reqp->bounce_sgl_count = 0;

Modified: stable/10/sys/dev/hyperv/utilities/hv_heartbeat.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/hv_heartbeat.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/utilities/hv_heartbeat.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -35,6 +35,7 @@
 #include <sys/syscallsubr.h>
 
 #include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/vmbus.h>
 #include "hv_util.h"
 #include "vmbus_if.h"
 
@@ -87,7 +88,7 @@ hv_heartbeat_cb(void *context)
 				 HV_ICMSGHDRFLAG_RESPONSE;
 
 	    hv_vmbus_channel_send_packet(channel, buf, recvlen, requestid,
-		HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
+		VMBUS_CHANPKT_TYPE_INBAND, 0);
 	}
 }
 

Modified: stable/10/sys/dev/hyperv/utilities/hv_kvp.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/hv_kvp.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/utilities/hv_kvp.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -578,7 +578,7 @@ hv_kvp_respond_host(hv_kvp_sc *sc, int e
 	error = hv_vmbus_channel_send_packet(sc->util_sc.channel,
 			sc->rcv_buf,
 			sc->host_msg_len, sc->host_msg_id,
-			HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
+			VMBUS_CHANPKT_TYPE_INBAND, 0);
 
 	if (error)
 		hv_kvp_log_info("%s: hv_kvp_respond_host: sendpacket error:%d\n",

Modified: stable/10/sys/dev/hyperv/utilities/hv_shutdown.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/hv_shutdown.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/utilities/hv_shutdown.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -40,6 +40,7 @@
 #include <sys/syscallsubr.h>
 
 #include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/vmbus.h>
 #include "hv_util.h"
 #include "vmbus_if.h"
 
@@ -106,7 +107,7 @@ hv_shutdown_cb(void *context)
 
 	    hv_vmbus_channel_send_packet(channel, buf,
 					recv_len, request_id,
-					HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
+					VMBUS_CHANPKT_TYPE_INBAND, 0);
 	}
 
 	if (execute_shutdown)

Modified: stable/10/sys/dev/hyperv/utilities/hv_timesync.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/hv_timesync.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/utilities/hv_timesync.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -40,6 +40,7 @@
 #include <sys/syscallsubr.h>
 
 #include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/vmbus.h>
 #include "hv_util.h"
 #include "vmbus_if.h"
 
@@ -164,7 +165,7 @@ hv_timesync_cb(void *context)
 
 	    hv_vmbus_channel_send_packet(channel, time_buf,
 		recvlen, requestId,
-		HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
+		VMBUS_CHANPKT_TYPE_INBAND, 0);
 	}
 }
 

Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Tue Oct 11 09:02:55 2016	(r307033)
+++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c	Tue Oct 11 09:11:23 2016	(r307034)
@@ -621,194 +621,119 @@ hv_vmbus_channel_close(struct hv_vmbus_c
 	hv_vmbus_channel_close_internal(chan);
 }
 
-/**
- * @brief Send the specified buffer on the given channel
- */
 int
-hv_vmbus_channel_send_packet(
-	hv_vmbus_channel*	channel,
-	void*			buffer,
-	uint32_t		buffer_len,
-	uint64_t		request_id,
-	hv_vmbus_packet_type	type,
-	uint32_t		flags)
+hv_vmbus_channel_send_packet(struct hv_vmbus_channel *chan,
+    void *data, uint32_t dlen, uint64_t xactid, uint16_t type, uint16_t flags)
 {
-	int			ret = 0;
-	hv_vm_packet_descriptor	desc;
-	uint32_t		packet_len;
-	uint64_t		aligned_data;
-	uint32_t		packet_len_aligned;
-	boolean_t		need_sig;
-	struct iovec		iov[3];
-
-	packet_len = sizeof(hv_vm_packet_descriptor) + buffer_len;
-	packet_len_aligned = HV_ALIGN_UP(packet_len, sizeof(uint64_t));
-	aligned_data = 0;
-
-	/* Setup the descriptor */
-	desc.type = type;   /* HV_VMBUS_PACKET_TYPE_DATA_IN_BAND;             */
-	desc.flags = flags; /* HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED */
-			    /* in 8-bytes granularity */
-	desc.data_offset8 = sizeof(hv_vm_packet_descriptor) >> 3;
-	desc.length8 = (uint16_t) (packet_len_aligned >> 3);
-	desc.transaction_id = request_id;
-
-	iov[0].iov_base = &desc;
-	iov[0].iov_len = sizeof(hv_vm_packet_descriptor);
-
-	iov[1].iov_base = buffer;
-	iov[1].iov_len = buffer_len;
-
-	iov[2].iov_base = &aligned_data;
-	iov[2].iov_len = packet_len_aligned - packet_len;
-
-	ret = hv_ring_buffer_write(&channel->outbound, iov, 3, &need_sig);
-
-	/* TODO: We should determine if this is optional */
-	if (ret == 0 && need_sig)
-		vmbus_chan_send_event(channel);
-
-	return (ret);
+	struct vmbus_chanpkt pkt;
+	int pktlen, pad_pktlen, hlen, error;
+	uint64_t pad = 0;
+	struct iovec iov[3];
+	boolean_t send_evt;
+
+	hlen = sizeof(pkt);
+	pktlen = hlen + dlen;
+	pad_pktlen = roundup2(pktlen, VMBUS_CHANPKT_SIZE_ALIGN);
+
+	pkt.cp_hdr.cph_type = type;
+	pkt.cp_hdr.cph_flags = flags;
+	pkt.cp_hdr.cph_data_ofs = hlen >> VMBUS_CHANPKT_SIZE_SHIFT;
+	pkt.cp_hdr.cph_len = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT;
+	pkt.cp_hdr.cph_xactid = xactid;
+
+	iov[0].iov_base = &pkt;
+	iov[0].iov_len = hlen;
+	iov[1].iov_base = data;
+	iov[1].iov_len = dlen;
+	iov[2].iov_base = &pad;
+	iov[2].iov_len = pad_pktlen - pktlen;
+
+	error = hv_ring_buffer_write(&chan->outbound, iov, 3, &send_evt);
+	if (!error && send_evt)
+		vmbus_chan_send_event(chan);
+	return error;
 }
 
-/**
- * @brief Send a range of single-page buffer packets using
- * a GPADL Direct packet type
- */
 int
-hv_vmbus_channel_send_packet_pagebuffer(
-	hv_vmbus_channel*	channel,
-	hv_vmbus_page_buffer	page_buffers[],
-	uint32_t		page_count,
-	void*			buffer,
-	uint32_t		buffer_len,
-	uint64_t		request_id)
+vmbus_chan_send_sglist(struct hv_vmbus_channel *chan,
+    struct vmbus_gpa sg[], int sglen, void *data, int dlen, uint64_t xactid)
 {
-
-	int					ret = 0;
-	boolean_t				need_sig;
-	uint32_t				packet_len;
-	uint32_t				page_buflen;
-	uint32_t				packetLen_aligned;
-	struct iovec				iov[4];
-	hv_vmbus_channel_packet_page_buffer	desc;
-	uint32_t				descSize;
-	uint64_t				alignedData = 0;
-
-	if (page_count > HV_MAX_PAGE_BUFFER_COUNT)
-		return (EINVAL);
-
-	/*
-	 * Adjust the size down since hv_vmbus_channel_packet_page_buffer
-	 *  is the largest size we support
-	 */
-	descSize = __offsetof(hv_vmbus_channel_packet_page_buffer, range);
-	page_buflen = sizeof(hv_vmbus_page_buffer) * page_count;
-	packet_len = descSize + page_buflen + buffer_len;
-	packetLen_aligned = HV_ALIGN_UP(packet_len, sizeof(uint64_t));
-
-	/* Setup the descriptor */
-	desc.type = HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT;
-	desc.flags = HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
-	/* in 8-bytes granularity */
-	desc.data_offset8 = (descSize + page_buflen) >> 3;
-	desc.length8 = (uint16_t) (packetLen_aligned >> 3);
-	desc.transaction_id = request_id;
-	desc.range_count = page_count;
-
-	iov[0].iov_base = &desc;
-	iov[0].iov_len = descSize;
-
-	iov[1].iov_base = page_buffers;
-	iov[1].iov_len = page_buflen;
-
-	iov[2].iov_base = buffer;
-	iov[2].iov_len = buffer_len;
-
-	iov[3].iov_base = &alignedData;
-	iov[3].iov_len = packetLen_aligned - packet_len;
-
-	ret = hv_ring_buffer_write(&channel->outbound, iov, 4, &need_sig);
-
-	/* TODO: We should determine if this is optional */
-	if (ret == 0 && need_sig)
-		vmbus_chan_send_event(channel);
-
-	return (ret);
+	struct vmbus_chanpkt_sglist pkt;
+	int pktlen, pad_pktlen, hlen, error;
+	struct iovec iov[4];
+	boolean_t send_evt;
+	uint64_t pad = 0;
+
+	KASSERT(sglen < VMBUS_CHAN_SGLIST_MAX,
+	    ("invalid sglist len %d", sglen));
+
+	hlen = __offsetof(struct vmbus_chanpkt_sglist, cp_gpa[sglen]);
+	pktlen = hlen + dlen;
+	pad_pktlen = roundup2(pktlen, VMBUS_CHANPKT_SIZE_ALIGN);
+
+	pkt.cp_hdr.cph_type = VMBUS_CHANPKT_TYPE_GPA;
+	pkt.cp_hdr.cph_flags = VMBUS_CHANPKT_FLAG_RC;
+	pkt.cp_hdr.cph_data_ofs = hlen >> VMBUS_CHANPKT_SIZE_SHIFT;
+	pkt.cp_hdr.cph_len = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT;
+	pkt.cp_hdr.cph_xactid = xactid;
+	pkt.cp_rsvd = 0;
+	pkt.cp_gpa_cnt = sglen;
+
+	iov[0].iov_base = &pkt;
+	iov[0].iov_len = sizeof(pkt);
+	iov[1].iov_base = sg;
+	iov[1].iov_len = sizeof(struct vmbus_gpa) * sglen;
+	iov[2].iov_base = data;
+	iov[2].iov_len = dlen;
+	iov[3].iov_base = &pad;
+	iov[3].iov_len = pad_pktlen - pktlen;
+
+	error = hv_ring_buffer_write(&chan->outbound, iov, 4, &send_evt);
+	if (!error && send_evt)
+		vmbus_chan_send_event(chan);
+	return error;
 }
 
-/**
- * @brief Send a multi-page buffer packet using a GPADL Direct packet type
- */
 int
-hv_vmbus_channel_send_packet_multipagebuffer(
-	hv_vmbus_channel*		channel,
-	hv_vmbus_multipage_buffer*	multi_page_buffer,
-	void*				buffer,
-	uint32_t			buffer_len,
-	uint64_t			request_id)
-{
-
-	int			ret = 0;
-	uint32_t		desc_size;
-	boolean_t		need_sig;
-	uint32_t		packet_len;
-	uint32_t		packet_len_aligned;
-	uint32_t		pfn_count;
-	uint64_t		aligned_data = 0;
-	struct iovec		iov[3];
-	hv_vmbus_channel_packet_multipage_buffer desc;
-
-	pfn_count =
-	    HV_NUM_PAGES_SPANNED(
-		    multi_page_buffer->offset,
-		    multi_page_buffer->length);
-
-	if ((pfn_count == 0) || (pfn_count > HV_MAX_MULTIPAGE_BUFFER_COUNT))
-	    return (EINVAL);
-	/*
-	 * Adjust the size down since hv_vmbus_channel_packet_multipage_buffer
-	 * is the largest size we support
-	 */
-	desc_size =
-	    sizeof(hv_vmbus_channel_packet_multipage_buffer) -
-		    ((HV_MAX_MULTIPAGE_BUFFER_COUNT - pfn_count) *
-			sizeof(uint64_t));

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



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