Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Jul 2016 06:29:19 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r302876 - in head/sys/dev/hyperv: include netvsc vmbus
Message-ID:  <201607150629.u6F6TJOG098098@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Fri Jul 15 06:29:19 2016
New Revision: 302876
URL: https://svnweb.freebsd.org/changeset/base/302876

Log:
  hyperv/vmbus: Rework sglist sending.
  
  MFC after:	1 week
  Sponsored by:	Microsoft OSTC
  Differential Revision:	https://reviews.freebsd.org/D7156

Added:
  head/sys/dev/hyperv/include/vmbus.h   (contents, props changed)
Modified:
  head/sys/dev/hyperv/include/hyperv.h
  head/sys/dev/hyperv/netvsc/hv_net_vsc.c
  head/sys/dev/hyperv/netvsc/hv_net_vsc.h
  head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  head/sys/dev/hyperv/netvsc/hv_rndis_filter.h
  head/sys/dev/hyperv/vmbus/hv_channel.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
  head/sys/dev/hyperv/vmbus/vmbus_reg.h

Modified: head/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- head/sys/dev/hyperv/include/hyperv.h	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/include/hyperv.h	Fri Jul 15 06:29:19 2016	(r302876)
@@ -82,7 +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)					\
@@ -227,12 +226,6 @@ typedef struct {
 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;
 
@@ -375,14 +368,6 @@ int		hv_vmbus_channel_send_packet(
 				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,

Added: head/sys/dev/hyperv/include/vmbus.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/hyperv/include/vmbus.h	Fri Jul 15 06:29:19 2016	(r302876)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMBUS_H_
+#define _VMBUS_H_
+
+#include <sys/param.h>
+
+/* This is actually vmbus_gpa_range.gpa_page[1] */
+struct vmbus_gpa {
+	uint32_t	gpa_len;
+	uint32_t	gpa_ofs;
+	uint64_t	gpa_page;
+} __packed;
+
+#define VMBUS_CHAN_SGLIST_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);
+
+#endif	/* !_VMBUS_H_ */

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.c	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.c	Fri Jul 15 06:29:19 2016	(r302876)
@@ -816,9 +816,8 @@ 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,

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h	Fri Jul 15 06:29:19 2016	(r302876)
@@ -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: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Jul 15 06:29:19 2016	(r302876)
@@ -154,7 +154,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
 
@@ -998,7 +998,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;
 		}
@@ -1024,24 +1024,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: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Fri Jul 15 06:29:19 2016	(r302876)
@@ -248,26 +248,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 */
@@ -289,7 +286,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 */

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.h	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.h	Fri Jul 15 06:29:19 2016	(r302876)
@@ -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: head/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_channel.c	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/vmbus/hv_channel.c	Fri Jul 15 06:29:19 2016	(r302876)
@@ -672,70 +672,44 @@ hv_vmbus_channel_send_packet(
 	return (ret);
 }
 
-/**
- * @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 = HV_VMBUS_PACKET_TYPE_DATA_USING_GPA_DIRECT;
+	pkt.cp_hdr.cph_flags = HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+	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;
 }
 
 /**

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h	Fri Jul 15 06:29:19 2016	(r302876)
@@ -44,20 +44,6 @@ struct vmbus_softc;
 /*
  * The format must be the same as hv_vm_data_gpa_direct
  */
-typedef struct hv_vmbus_channel_packet_page_buffer {
-	uint16_t		type;
-	uint16_t		data_offset8;
-	uint16_t		length8;
-	uint16_t		flags;
-	uint64_t		transaction_id;
-	uint32_t		reserved;
-	uint32_t		range_count;
-	hv_vmbus_page_buffer	range[HV_MAX_PAGE_BUFFER_COUNT];
-} __packed hv_vmbus_channel_packet_page_buffer;
-
-/*
- * The format must be the same as hv_vm_data_gpa_direct
- */
 typedef struct hv_vmbus_channel_packet_multipage_buffer {
 	uint16_t 			type;
 	uint16_t 			data_offset8;

Modified: head/sys/dev/hyperv/vmbus/vmbus_reg.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/vmbus_reg.h	Fri Jul 15 06:16:39 2016	(r302875)
+++ head/sys/dev/hyperv/vmbus/vmbus_reg.h	Fri Jul 15 06:29:19 2016	(r302876)
@@ -30,8 +30,9 @@
 #define _VMBUS_REG_H_
 
 #include <sys/param.h>
-#include <dev/hyperv/vmbus/hyperv_reg.h>
 #include <dev/hyperv/include/hyperv.h> /* XXX for hyperv_guid */
+#include <dev/hyperv/include/vmbus.h>
+#include <dev/hyperv/vmbus/hyperv_reg.h>
 
 /*
  * Hyper-V SynIC message format.
@@ -135,6 +136,13 @@ struct vmbus_chanpkt {
 	struct vmbus_chanpkt_hdr cp_hdr;
 } __packed;
 
+struct vmbus_chanpkt_sglist {
+	struct vmbus_chanpkt_hdr cp_hdr;
+	uint32_t	cp_rsvd;
+	uint32_t	cp_gpa_cnt;
+	struct vmbus_gpa cp_gpa[];
+} __packed;
+
 /*
  * Channel messages
  * - Embedded in vmbus_message.msg_data, e.g. response and notification.



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